X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/13cfc51d63509eb0da7d1cc1b9b291a4a701119f..769c3372a2bd68c45d1a4afc8462d3b7939decb1:/src/common/dcsvg.cpp?ds=sidebyside diff --git a/src/common/dcsvg.cpp b/src/common/dcsvg.cpp index 7397e43725..449ad4791a 100644 --- a/src/common/dcsvg.cpp +++ b/src/common/dcsvg.cpp @@ -1,10 +1,10 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: svg.cpp +// Name: src/common/svg.cpp // Purpose: SVG sample // Author: Chris Elliott // Modified by: // RCS-ID: $Id$ -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// @@ -28,54 +28,78 @@ #include "wx/wfstream.h" #include "wx/filename.h" -#define wxSVG_DEBUG false -// or true to see the calls being executed - -#define newline wxString(wxT("\n")) -#define space wxString(wxT(" ")) -#define semicolon wxString(wxT(";")) -#define wx_round(a) (int)((a)+.5) - - // ---------------------------------------------------------- // Global utilities // ---------------------------------------------------------- -static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } +namespace +{ + +inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } -wxString wxColStr ( wxColour c ) +// 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) { - unsigned char r, g, b; - r = c.Red (); - g = c.Green (); - b = c. Blue (); + return wxString::FromCDouble(f, 2); +} - // possible Unicode bug here - wxString s = wxDecToHex(r) + wxDecToHex(g) + wxDecToHex(b); +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 += wxString::Format(wxT("stroke-opacity:%s; "), NumStr(c.Alpha()/255.)); + } + else + { + switch ( style ) + { + case wxPENSTYLE_SOLID: + s += wxT("stroke-opacity:1.0; "); + break; + case wxPENSTYLE_TRANSPARENT: + 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 ) +wxString wxBrushString(wxColour c, int style = wxBRUSHSTYLE_SOLID) { - wxString s = wxT("fill:#") + wxColStr (c) + semicolon + space; - switch ( style ) + 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) { - case wxBRUSHSTYLE_SOLID : - s = s + wxT("fill-opacity:1.0; "); - break; - case wxBRUSHSTYLE_TRANSPARENT: - s = s + wxT("fill-opacity:0.0; "); - break; - - default : - wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available")); - + s += wxString::Format(wxT("fill-opacity:%s; "), NumStr(c.Alpha()/255.)); + } + else + { + switch ( style ) + { + case wxBRUSHSTYLE_SOLID: + s += wxT("fill-opacity:1.0; "); + break; + case wxBRUSHSTYLE_TRANSPARENT: + s += wxT("fill-opacity:0.0; "); + break; + default : + wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available")); + } } - s = s + newline; return s; } +} // anonymous namespace + // ---------------------------------------------------------- // wxSVGFileDCImpl // ---------------------------------------------------------- @@ -115,27 +139,27 @@ void wxSVGFileDCImpl::Init (const wxString &filename, int Width, int Height, dou ////////////////////code here m_outfile = new wxFileOutputStream(filename); - m_OK = m_outfile->Ok (); + m_OK = m_outfile->IsOk(); if (m_OK) { m_filename = filename; m_sub_images = 0; wxString s; - s = wxT(""); s = s + newline; + s = wxT("") + wxString(wxT("\n")); write(s); - s = wxT(" ") + newline; + s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ") + wxString(wxT("\n")); write(s); - s = wxT(" \n"), float(Width)/dpi*2.54, float(Height)/dpi*2.54, Width, Height ); + s.Printf( wxT(" width=\"%scm\" height=\"%scm\" viewBox=\"0 0 %d %d \"> \n"), NumStr(float(Width)/dpi*2.54), NumStr(float(Height)/dpi*2.54), Width, Height ); write(s); - s = wxT("SVG Picture created as ") + wxFileName(filename).GetFullName() + wxT(" ") + newline; + s = wxT("SVG Picture created as ") + wxFileName(filename).GetFullName() + wxT(" ") + wxT("\n"); write(s); - s = wxString (wxT("Picture generated by wxSVG ")) + wxSVGVersion + wxT(" ")+ newline; + s = wxString (wxT("Picture generated by wxSVG ")) + wxSVGVersion + wxT(" ")+ wxT("\n"); write(s); - s = wxT("") + newline; + s = wxT("") + wxString(wxT("\n")); write(s); } } @@ -163,17 +187,15 @@ wxSize wxSVGFileDCImpl::GetPPI() const void wxSVGFileDCImpl::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2) { - if (m_graphics_changed) NewGraphics (); + if (m_graphics_changed) NewGraphics(); wxString s; s.Printf ( wxT(" \n"), x1,y1,x2,y2 ); if (m_OK) { write(s); } - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")); CalcBoundingBox(x1, y1); CalcBoundingBox(x2, y2); - return; } void wxSVGFileDCImpl::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset ) @@ -188,8 +210,8 @@ void wxSVGFileDCImpl::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxC void wxSVGFileDCImpl::DoDrawPoint (wxCoord x1, wxCoord y1) { wxString s; - if (m_graphics_changed) NewGraphics (); - s = wxT(" ") + newline; + if (m_graphics_changed) NewGraphics(); + s = wxT(" ") + wxString(wxT("\n")); write(s); DoDrawLine ( x1,y1,x1,y1 ); s = wxT(""); @@ -204,13 +226,12 @@ void wxSVGFileDCImpl::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxC void wxSVGFileDCImpl::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1) { DoDrawRotatedText(text, x1,y1,0.0); - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawText Call executed")); } void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle) { //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW - if (m_graphics_changed) NewGraphics (); + if (m_graphics_changed) NewGraphics(); wxString s, sTmp; // calculate bounding box @@ -234,37 +255,36 @@ void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoor // draw background first // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")); - sTmp.Printf ( wxT(" "), -angle, x,y ); - s = s + sTmp + newline; + sTmp.Printf ( wxT(" "), NumStr(-angle), x,y ); + s += sTmp + wxT("\n"); write(s); } //now do the text itself s.Printf (wxT(" 0) s = s + wxT("style=\"font-family:") + sTmp + wxT("; "); - else s = s + wxT("style=\" "); + sTmp = m_font.GetFaceName(); + if (sTmp.Len() > 0) s += wxT("style=\"font-family:") + sTmp + wxT("; "); + else s += wxT("style=\" "); wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") }; - s = s + wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space; + s += wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + wxT("; "); 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] + semicolon + space; - - sTmp.Printf (wxT("font-size:%dpt; fill:#"), m_font.GetPointSize () ); - s = s + sTmp; - s = s + wxColStr (m_textForegroundColour) + wxT("; stroke:#") + wxColStr (m_textForegroundColour) + wxT("; "); - sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle, x,y ); - s = s + sTmp + sText + wxT(" ") + newline; + s += wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + wxT("; "); + + sTmp.Printf (wxT("font-size:%dpt; "), m_font.GetPointSize() ); + s += sTmp; + //text will be solid, unless alpha value isn't opaque in the foreground colour + s += wxBrushString(m_textForegroundColour) + wxPenString(m_textForegroundColour); + sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %s %d %d ) \" >"), NumStr(-angle), x,y ); + s += sTmp + sText + wxT(" ") + wxT("\n"); if (m_OK) { write(s); } - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")); } void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height) @@ -275,60 +295,57 @@ void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoo void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius ) { - if (m_graphics_changed) NewGraphics (); + if (m_graphics_changed) NewGraphics(); wxString s; - s.Printf ( wxT(" ") + newline; + s += wxT(" /> \n"); write(s); - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")); CalcBoundingBox(x, y); CalcBoundingBox(x + width, y + height); } -void wxSVGFileDCImpl::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle) +void wxSVGFileDCImpl::DoDrawPolygon(int n, wxPoint points[], + wxCoord xoffset, wxCoord yoffset, + wxPolygonFillMode fillStyle) { - if (m_graphics_changed) NewGraphics (); + if (m_graphics_changed) NewGraphics(); wxString s, sTmp; s = wxT(" "); - s = s + newline; + s += wxT("\" /> \n"); write(s); - - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")); } void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height) { - if (m_graphics_changed) NewGraphics (); + if (m_graphics_changed) NewGraphics(); int rh = height /2; int rw = width /2; wxString s; s.Printf ( wxT(" ") + newline; + s += wxT(" /> \n"); write(s); - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")); CalcBoundingBox(x, y); CalcBoundingBox(x + width, y + height); } @@ -344,7 +361,7 @@ void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, Might be better described as Pie drawing */ - if (m_graphics_changed) NewGraphics (); + if (m_graphics_changed) NewGraphics(); wxString s; // we need the radius of the circle which has two estimates @@ -369,19 +386,17 @@ void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, int fSweep = 0; // flag for sweep always 0 - s.Printf ( wxT(" ") + newline; + s += wxT(" \" /> \n"); if (m_OK) { write(s); } - - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")); } void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea) @@ -405,7 +420,7 @@ void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h, //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW - if (m_graphics_changed) NewGraphics (); + if (m_graphics_changed) NewGraphics(); wxString s; //radius @@ -436,15 +451,12 @@ void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h, int(xs), int(ys), int(rx), int(ry), fArc, fSweep, int(xe), int(ye), int(xc), int(yc) ); - - s = s + wxT(" \" /> ") + newline; + s += wxT(" \" /> \n"); if (m_OK) { write(s); } - - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")); } void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const @@ -455,17 +467,14 @@ void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoor sDC.SetFont (m_font); if ( font != NULL ) sDC.SetFont ( *font ); sDC.GetTextExtent(string, w, h, descent, externalLeading ); - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed")); } wxCoord wxSVGFileDCImpl::GetCharHeight() const - { wxScreenDC sDC; sDC.SetFont (m_font); - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing")); - return ( sDC.GetCharHeight() ); + return sDC.GetCharHeight(); } @@ -474,9 +483,7 @@ wxCoord wxSVGFileDCImpl::GetCharWidth() const wxScreenDC sDC; sDC.SetFont (m_font); - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing")); - return ( sDC.GetCharWidth() ); - + return sDC.GetCharWidth(); } @@ -486,16 +493,13 @@ wxCoord wxSVGFileDCImpl::GetCharWidth() const void wxSVGFileDCImpl::SetBackground( const wxBrush &brush ) { - m_backgroundBrush = brush; - return; } void wxSVGFileDCImpl::SetBackgroundMode( int mode ) { m_backgroundMode = mode; - return; } @@ -505,7 +509,6 @@ void wxSVGFileDCImpl::SetBrush(const wxBrush& brush) m_brush = brush; m_graphics_changed = true; - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed")); } @@ -516,21 +519,16 @@ void wxSVGFileDCImpl::SetPen(const wxPen& pen) m_pen = pen; m_graphics_changed = true; - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")); } -void wxSVGFileDCImpl::NewGraphics () +void wxSVGFileDCImpl::NewGraphics() { - - int w = m_pen.GetWidth (); - wxColour c = m_pen.GetColour (); - wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn; - sBrush = wxT("\n\n \n"); } - sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"), - w, double(m_logicalOriginX), double(m_logicalOriginY), m_scaleX, m_scaleY ); + sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%s %s) scale(%s %s)\">"), + m_pen.GetWidth(), NumStr(m_logicalOriginX), NumStr(m_logicalOriginY), NumStr(m_scaleX), NumStr(m_scaleY) ); - s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn; + s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + wxT("\n") + sWarn; write(s); m_graphics_changed = false; - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")); } @@ -582,14 +567,12 @@ void wxSVGFileDCImpl::SetFont(const wxFont& font) { m_font = font; - - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")); } // export a bitmap as a raster image in png bool wxSVGFileDCImpl::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height, wxDC* source, wxCoord xsrc, wxCoord ysrc, - int logicalFunc /*= wxCOPY*/, bool useMask /*= false*/, + wxRasterOperationMode logicalFunc /*= wxCOPY*/, bool useMask /*= false*/, wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/) { if (logicalFunc != wxCOPY) @@ -608,7 +591,6 @@ bool wxSVGFileDCImpl::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoor memDC.Blit(0, 0, width, height, source, xsrc, ysrc); memDC.SelectObject( wxNullBitmap ); DoDrawBitmap(myBitmap, xdest, ydest); - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed")); return false; } @@ -620,13 +602,11 @@ void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord memDC.DrawIcon(myIcon,0,0); memDC.SelectObject( wxNullBitmap ); DoDrawBitmap(myBitmap, x, y); - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed")); - return; } void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ ) { - if (m_graphics_changed) NewGraphics (); + if (m_graphics_changed) NewGraphics(); wxString sTmp, s, sPNG; if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG) == NULL ) @@ -655,25 +635,22 @@ void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoor int w = myBitmap.GetWidth(); int h = myBitmap.GetHeight(); sTmp.Printf ( wxT(" \n"), sPNG.c_str() ); - s = s + sTmp + wxT("Image from wxSVG ") + newline; + s += sTmp + wxT("Image from wxSVG ") + wxT("\n"); if (m_OK && bPNG_OK) { write(s); } - m_OK = m_outfile->Ok () && bPNG_OK; - wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed")); - - return; + m_OK = m_outfile->IsOk() && bPNG_OK; } void wxSVGFileDCImpl::write(const wxString &s) { const wxCharBuffer buf = s.utf8_str(); m_outfile->Write(buf, strlen((const char *)buf)); - m_OK = m_outfile->Ok(); + m_OK = m_outfile->IsOk(); }