Add support for alpha channel in colours in wxSVGFileDC.

Use stroke-opacity and fill-opacity SVG attributes to handle pens and brushes
created from colours with alpha channel in wxSVGFileDC.

Closes #13086.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67373 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2011-04-02 16:37:54 +00:00
parent b72ed64277
commit 403695b323
3 changed files with 71 additions and 49 deletions

View File

@@ -499,6 +499,7 @@ All (GUI):
- wxComboCtrl, wxOwnerDrawnComboBox: better support for themed and custom
panel backgrounds, especially on OS X.
- Add WXK_CONTROL_A..WXK_CONTROL_Z constants (Jan van Dijk).
- Add support for alpha channel in colours in wxSVGFileDC (snowleopard).
GTK:

View File

@@ -153,9 +153,14 @@ struct wxFontMetrics
@section dc_alpha_support Support for Transparency / Alpha Channel
On Mac OS X colours with alpha channel are supported. Instances of wxPen
or wxBrush that are built from wxColour use the colour's alpha values
when stroking or filling.
In general wxDC methods don't support alpha transparency and the alpha
component of wxColour is simply ignored and you need to use wxGraphicsContext
for full transparency support. There are, however, a few exceptions: first,
under Mac OS X colours with alpha channel are supported in all the normal
wxDC-derived classes as they use wxGraphicsContext internally. Second,
under all platforms wxSVGFileDC also fully supports alpha channel. In both
of these cases the instances of wxPen or wxBrush that are built from
wxColour use the colour's alpha values when stroking or filling.
@library{wxcore}

View File

@@ -40,9 +40,52 @@ namespace
inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
wxString wxBrushString ( wxColour c, int style )
// This function returns a string representation of a floating point number in
// C locale (i.e. always using "." for the decimal separator) and with the
// fixed precision (which is 2 for some unknown reason but this is what it was
// in this code originally).
inline wxString NumStr(double f)
{
return wxString::FromCDouble(f, 2);
}
wxString wxPenString(wxColour c, int style = wxPENSTYLE_SOLID)
{
wxString s = wxT("stroke:") + c.GetAsString(wxC2S_HTML_SYNTAX) + wxT("; ");
// Use the color's alpha value (if not opaque) for the opacity.
// Note that a transparent pen will override the alpha value.
if (c.Alpha() != wxALPHA_OPAQUE && style != wxPENSTYLE_TRANSPARENT)
{
s = s + wxString::Format(wxT("stroke-opacity:%s; "), NumStr(c.Alpha()/255.));
}
else
{
switch ( style )
{
case wxPENSTYLE_SOLID:
s = s + wxT("stroke-opacity:1.0; ");
break;
case wxPENSTYLE_TRANSPARENT:
s = s + wxT("stroke-opacity:0.0; ");
break;
default :
wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Pen Style not available"));
}
}
return s;
}
wxString wxBrushString(wxColour c, int style = wxBRUSHSTYLE_SOLID)
{
wxString s = wxT("fill:") + c.GetAsString(wxC2S_HTML_SYNTAX) + wxT("; ");
// Use the color's alpha value (if not opaque) for the opacity.
// Note that a transparent brush will override the alpha value.
if (c.Alpha() != wxALPHA_OPAQUE && style != wxBRUSHSTYLE_TRANSPARENT)
{
s = s + wxString::Format(wxT("fill-opacity:%s; "), NumStr(c.Alpha()/255.));
}
else
{
switch ( style )
{
case wxBRUSHSTYLE_SOLID:
@@ -51,24 +94,13 @@ wxString wxBrushString ( wxColour c, int style )
case wxBRUSHSTYLE_TRANSPARENT:
s = s + wxT("fill-opacity:0.0; ");
break;
default :
wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available"));
}
s = s + wxT("\n");
}
return s;
}
// This function returns a string representation of a floating point number in
// C locale (i.e. always using "." for the decimal separator) and with the
// fixed precision (which is 2 for some unknown reason but this is what it was
// in this code originally).
inline wxString NumStr(double f)
{
return wxString::FromCDouble(f, 2);
}
} // anonymous namespace
// ----------------------------------------------------------
@@ -231,9 +263,9 @@ void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoor
wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background"));
sTmp.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x,y+desc-h, w, h );
s = sTmp + wxT("style=\"fill:") + m_textBackgroundColour.GetAsString(wxC2S_HTML_SYNTAX) + wxT("; ");
s = s + wxT("stroke-width:1; stroke:") + m_textBackgroundColour.GetAsString(wxC2S_HTML_SYNTAX) + wxT("; ");
sTmp.Printf ( wxT("\" transform=\"rotate( %s %d %d ) \">"), NumStr(-angle), x,y );
s = sTmp + wxT("style=\"") + wxBrushString(m_textBackgroundColour);
s = s + wxT("stroke-width:1; ") + wxPenString(m_textBackgroundColour);
sTmp.Printf ( wxT("\" transform=\"rotate( %s %d %d ) \" />"), NumStr(-angle), x,y );
s = s + sTmp + wxT("\n");
write(s);
}
@@ -250,9 +282,10 @@ void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoor
wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
s = s + wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + wxT("; ");
sTmp.Printf (wxT("font-size:%dpt; fill:"), m_font.GetPointSize () );
sTmp.Printf (wxT("font-size:%dpt; "), m_font.GetPointSize () );
s = s + sTmp;
s = s + m_textForegroundColour.GetAsString(wxC2S_HTML_SYNTAX) + wxT("; stroke:") + m_textForegroundColour.GetAsString(wxC2S_HTML_SYNTAX) + wxT("; ");
//text will be solid, unless alpha value isn't opaque in the foreground colour
s = s + wxBrushString(m_textForegroundColour) + wxPenString(m_textForegroundColour);
sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %s %d %d ) \" >"), NumStr(-angle), x,y );
s = s + sTmp + sText + wxT("</text> ") + wxT("\n");
if (m_OK)
@@ -516,14 +549,10 @@ void wxSVGFileDCImpl::SetPen(const wxPen& pen)
void wxSVGFileDCImpl::NewGraphics ()
{
int w = m_pen.GetWidth ();
wxColour c = m_pen.GetColour ();
wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () )
+ wxT(" stroke:") + c.GetAsString(wxC2S_HTML_SYNTAX) + wxT("; ");
+ wxPenString(m_pen.GetColour(), m_pen.GetStyle());
switch ( m_pen.GetCap () )
{
@@ -550,21 +579,8 @@ void wxSVGFileDCImpl::NewGraphics ()
sPenJoin = wxT("stroke-linejoin:round; ");
};
switch ( m_pen.GetStyle () )
{
case wxPENSTYLE_SOLID :
sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ");
break;
case wxPENSTYLE_TRANSPARENT :
sPenStyle = wxT("stroke-opacity:0.0; stroke-opacity:0.0; ");
break;
default :
wxASSERT_MSG(false, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available"));
sWarn = sWarn + wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n");
}
sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%s %s) scale(%s %s)\">"),
w, NumStr(m_logicalOriginX), NumStr(m_logicalOriginY), NumStr(m_scaleX), NumStr(m_scaleY) );
m_pen.GetWidth(), NumStr(m_logicalOriginX), NumStr(m_logicalOriginY), NumStr(m_scaleX), NumStr(m_scaleY) );
s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + wxT("\n") + sWarn;
write(s);