1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/svg.cpp
4 // Author: Chris Elliott
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
21 #include "wx/dcmemory.h"
22 #include "wx/dcscreen.h"
28 #include "wx/wfstream.h"
29 #include "wx/filename.h"
31 #define wxSVG_DEBUG false
32 // or true to see the calls being executed
34 // ----------------------------------------------------------
36 // ----------------------------------------------------------
41 inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
43 wxString
wxBrushString ( wxColour c
, int style
)
45 wxString s
= wxT("fill:") + c
.GetAsString(wxC2S_HTML_SYNTAX
) + wxT("; ");
48 case wxBRUSHSTYLE_SOLID
:
49 s
= s
+ wxT("fill-opacity:1.0; ");
51 case wxBRUSHSTYLE_TRANSPARENT
:
52 s
= s
+ wxT("fill-opacity:0.0; ");
56 wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available"));
63 // This function returns a string representation of a floating point number in
64 // C locale (i.e. always using "." for the decimal separator) and with the
65 // fixed precision (which is 2 for some unknown reason but this is what it was
66 // in this code originally).
67 inline wxString
NumStr(double f
)
69 return wxString::FromCDouble(f
, 2);
72 } // anonymous namespace
74 // ----------------------------------------------------------
76 // ----------------------------------------------------------
78 IMPLEMENT_ABSTRACT_CLASS(wxSVGFileDCImpl
, wxDC
)
80 wxSVGFileDCImpl::wxSVGFileDCImpl( wxSVGFileDC
*owner
, const wxString
&filename
,
81 int width
, int height
, double dpi
) :
84 Init( filename
, width
, height
, dpi
);
87 void wxSVGFileDCImpl::Init (const wxString
&filename
, int Width
, int Height
, double dpi
)
96 m_mm_to_pix_x
= dpi
/25.4;
97 m_mm_to_pix_y
= dpi
/25.4;
99 m_backgroundBrush
= *wxTRANSPARENT_BRUSH
;
100 m_textForegroundColour
= *wxBLACK
;
101 m_textBackgroundColour
= *wxWHITE
;
102 m_colour
= wxColourDisplay();
104 m_pen
= *wxBLACK_PEN
;
105 m_font
= *wxNORMAL_FONT
;
106 m_brush
= *wxWHITE_BRUSH
;
108 m_graphics_changed
= true;
110 ////////////////////code here
112 m_outfile
= new wxFileOutputStream(filename
);
113 m_OK
= m_outfile
->Ok ();
116 m_filename
= filename
;
119 s
= wxT("<?xml version=\"1.0\" standalone=\"no\"?>") + wxString(wxT("\n"));
121 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + wxString(wxT("\n"));
123 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ") + wxString(wxT("\n"));
125 s
= wxT("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ") + wxString(wxT("\n"));
127 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
);
129 s
= wxT("<title>SVG Picture created as ") + wxFileName(filename
).GetFullName() + wxT(" </title>") + wxT("\n");
131 s
= wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion
+ wxT(" </desc>")+ wxT("\n");
133 s
= wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + wxString(wxT("\n"));
138 wxSVGFileDCImpl::~wxSVGFileDCImpl()
140 wxString s
= wxT("</g> \n</svg> \n");
145 void wxSVGFileDCImpl::DoGetSizeMM( int *width
, int *height
) const
148 *width
= wxRound( (double)m_width
/ m_mm_to_pix_x
);
151 *height
= wxRound( (double)m_height
/ m_mm_to_pix_y
);
154 wxSize
wxSVGFileDCImpl::GetPPI() const
156 return wxSize( wxRound(m_dpi
), wxRound(m_dpi
) );
159 void wxSVGFileDCImpl::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
161 if (m_graphics_changed
) NewGraphics ();
163 s
.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1
,y1
,x2
,y2
);
168 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawLine Call executed"));
169 CalcBoundingBox(x1
, y1
);
170 CalcBoundingBox(x2
, y2
);
174 void wxSVGFileDCImpl::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
176 for ( int i
= 1; i
< n
; i
++ )
178 DoDrawLine ( points
[i
-1].x
+ xoffset
, points
[i
-1].y
+ yoffset
,
179 points
[ i
].x
+ xoffset
, points
[ i
].y
+ yoffset
);
183 void wxSVGFileDCImpl::DoDrawPoint (wxCoord x1
, wxCoord y1
)
186 if (m_graphics_changed
) NewGraphics ();
187 s
= wxT("<g style = \"stroke-linecap:round;\" > ") + wxString(wxT("\n"));
189 DoDrawLine ( x1
,y1
,x1
,y1
);
194 void wxSVGFileDCImpl::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
196 wxDCImpl::DoDrawCheckMark (x1
,y1
,width
,height
);
199 void wxSVGFileDCImpl::DoDrawText(const wxString
& text
, wxCoord x1
, wxCoord y1
)
201 DoDrawRotatedText(text
, x1
,y1
,0.0);
202 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawText Call executed"));
205 void wxSVGFileDCImpl::DoDrawRotatedText(const wxString
& sText
, wxCoord x
, wxCoord y
, double angle
)
207 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
208 if (m_graphics_changed
) NewGraphics ();
211 // calculate bounding box
213 DoGetTextExtent(sText
, &w
, &h
, &desc
);
215 double rad
= DegToRad(angle
);
217 // wxT("upper left") and wxT("upper right")
218 CalcBoundingBox(x
, y
);
219 CalcBoundingBox((wxCoord
)(x
+ w
*cos(rad
)), (wxCoord
)(y
- h
*sin(rad
)));
221 // wxT("bottom left") and wxT("bottom right")
222 x
+= (wxCoord
)(h
*sin(rad
));
223 y
+= (wxCoord
)(h
*cos(rad
));
224 CalcBoundingBox(x
, y
);
225 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
)), (wxCoord
)(y
+ h
*cos(rad
)));
227 if (m_backgroundMode
== wxBRUSHSTYLE_SOLID
)
229 // draw background first
230 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
232 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background"));
233 sTmp
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x
,y
+desc
-h
, w
, h
);
234 s
= sTmp
+ wxT("style=\"fill:") + m_textBackgroundColour
.GetAsString(wxC2S_HTML_SYNTAX
) + wxT("; ");
235 s
= s
+ wxT("stroke-width:1; stroke:") + m_textBackgroundColour
.GetAsString(wxC2S_HTML_SYNTAX
) + wxT("; ");
236 sTmp
.Printf ( wxT("\" transform=\"rotate( %s %d %d ) \">"), NumStr(-angle
), x
,y
);
237 s
= s
+ sTmp
+ wxT("\n");
240 //now do the text itself
241 s
.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x
,y
);
243 sTmp
= m_font
.GetFaceName ();
244 if (sTmp
.Len () > 0) s
= s
+ wxT("style=\"font-family:") + sTmp
+ wxT("; ");
245 else s
= s
+ wxT("style=\" ");
247 wxString fontweights
[3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
248 s
= s
+ wxT("font-weight:") + fontweights
[m_font
.GetWeight() - wxNORMAL
] + wxT("; ");
250 wxString fontstyles
[5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
251 s
= s
+ wxT("font-style:") + fontstyles
[m_font
.GetStyle() - wxNORMAL
] + wxT("; ");
253 sTmp
.Printf (wxT("font-size:%dpt; fill:"), m_font
.GetPointSize () );
255 s
= s
+ m_textForegroundColour
.GetAsString(wxC2S_HTML_SYNTAX
) + wxT("; stroke:") + m_textForegroundColour
.GetAsString(wxC2S_HTML_SYNTAX
) + wxT("; ");
256 sTmp
.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %s %d %d ) \" >"), NumStr(-angle
), x
,y
);
257 s
= s
+ sTmp
+ sText
+ wxT("</text> ") + wxT("\n");
262 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawRotatedText Call executed"));
265 void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
267 DoDrawRoundedRectangle(x
, y
, width
, height
, 0);
270 void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
273 if (m_graphics_changed
) NewGraphics ();
276 s
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" "),
277 x
, y
, width
, height
, NumStr(radius
) );
279 s
= s
+ wxT(" /> \n");
282 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed"));
283 CalcBoundingBox(x
, y
);
284 CalcBoundingBox(x
+ width
, y
+ height
);
287 void wxSVGFileDCImpl::DoDrawPolygon(int n
, wxPoint points
[],
288 wxCoord xoffset
, wxCoord yoffset
,
289 wxPolygonFillMode fillStyle
)
291 if (m_graphics_changed
) NewGraphics ();
293 s
= wxT("<polygon style=\"");
294 if ( fillStyle
== wxODDEVEN_RULE
)
295 s
= s
+ wxT("fill-rule:evenodd; ");
297 s
= s
+ wxT("fill-rule:nonzero; ");
299 s
= s
+ wxT("\" \npoints=\"");
301 for (int i
= 0; i
< n
; i
++)
303 sTmp
.Printf ( wxT("%d,%d"), points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
304 s
= s
+ sTmp
+ wxT("\n");
305 CalcBoundingBox ( points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
307 s
= s
+ wxT("\" /> \n");
310 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawPolygon Call executed"));
313 void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
316 if (m_graphics_changed
) NewGraphics ();
322 s
.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x
+rw
,y
+rh
, rw
, rh
);
323 s
= s
+ wxT(" /> \n");
327 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipse Call executed"));
328 CalcBoundingBox(x
, y
);
329 CalcBoundingBox(x
+ width
, y
+ height
);
332 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
334 /* Draws an arc of a circle, centred on (xc, yc), with starting point
335 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
336 and the current brush for filling the shape.
338 The arc is drawn in an anticlockwise direction from the start point to
341 Might be better described as Pie drawing */
343 if (m_graphics_changed
) NewGraphics ();
346 // we need the radius of the circle which has two estimates
347 double r1
= sqrt ( double( (x1
-xc
)*(x1
-xc
) ) + double( (y1
-yc
)*(y1
-yc
) ) );
348 double r2
= sqrt ( double( (x2
-xc
)*(x2
-xc
) ) + double( (y2
-yc
)*(y2
-yc
) ) );
350 wxASSERT_MSG( (fabs ( r2
-r1
) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle"));
351 if ( fabs ( r2
-r1
) > 3 ) //pixels
353 s
= wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n");
357 double theta1
= atan2((double)(yc
-y1
),(double)(x1
-xc
));
358 if ( theta1
< 0 ) theta1
= theta1
+ M_PI
* 2;
359 double theta2
= atan2((double)(yc
-y2
), (double)(x2
-xc
));
360 if ( theta2
< 0 ) theta2
= theta2
+ M_PI
* 2;
361 if ( theta2
< theta1
) theta2
= theta2
+ M_PI
*2;
363 int fArc
; // flag for large or small arc 0 means less than 180 degrees
364 if ( fabs(theta2
- theta1
) > M_PI
) fArc
= 1; else fArc
= 0;
366 int fSweep
= 0; // flag for sweep always 0
368 s
.Printf ( wxT("<path d=\"M%d %d A%s %s 0.0 %d %d %d %d L%d %d z "),
369 x1
,y1
, NumStr(r1
), NumStr(r2
), fArc
, fSweep
, x2
, y2
, xc
, yc
);
371 // the z means close the path and fill
372 s
= s
+ wxT(" \" /> \n");
380 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawArc Call executed"));
383 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
386 Draws an arc of an ellipse. The current pen is used for drawing the arc
387 and the current brush is used for drawing the pie. This function is
388 currently only available for X window and PostScript device contexts.
390 x and y specify the x and y coordinates of the upper-left corner of the
391 rectangle that contains the ellipse.
393 width and height specify the width and height of the rectangle that
394 contains the ellipse.
396 start and end specify the start and end of the arc relative to the
397 three-o'clock position from the center of the rectangle. Angles are
398 specified in degrees (360 is a complete circle). Positive values mean
399 counter-clockwise motion. If start is equal to end, a complete ellipse
402 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
404 if (m_graphics_changed
) NewGraphics ();
414 double xs
, ys
, xe
, ye
;
415 xs
= xc
+ rx
* cos (DegToRad(sa
));
416 xe
= xc
+ rx
* cos (DegToRad(ea
));
417 ys
= yc
- ry
* sin (DegToRad(sa
));
418 ye
= yc
- ry
* sin (DegToRad(ea
));
420 ///now same as circle arc...
422 double theta1
= atan2(ys
-yc
, xs
-xc
);
423 double theta2
= atan2(ye
-yc
, xe
-xc
);
425 int fArc
; // flag for large or small arc 0 means less than 180 degrees
426 if ( (theta2
- theta1
) > 0 ) fArc
= 1; else fArc
= 0;
429 if ( fabs(theta2
- theta1
) > M_PI
) fSweep
= 1; else fSweep
= 0;
431 s
.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
432 int(xs
), int(ys
), int(rx
), int(ry
),
433 fArc
, fSweep
, int(xe
), int(ye
), int(xc
), int(yc
) );
435 s
= s
+ wxT(" \" /> \n");
442 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed"));
445 void wxSVGFileDCImpl::DoGetTextExtent(const wxString
& string
, wxCoord
*w
, wxCoord
*h
, wxCoord
*descent
, wxCoord
*externalLeading
, const wxFont
*font
) const
450 sDC
.SetFont (m_font
);
451 if ( font
!= NULL
) sDC
.SetFont ( *font
);
452 sDC
.GetTextExtent(string
, w
, h
, descent
, externalLeading
);
453 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetTextExtent Call executed"));
456 wxCoord
wxSVGFileDCImpl::GetCharHeight() const
460 sDC
.SetFont (m_font
);
462 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharHeight Call executing"));
463 return ( sDC
.GetCharHeight() );
467 wxCoord
wxSVGFileDCImpl::GetCharWidth() const
470 sDC
.SetFont (m_font
);
472 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharWidth Call executing"));
473 return ( sDC
.GetCharWidth() );
478 // ----------------------------------------------------------
479 // wxSVGFileDCImpl - set functions
480 // ----------------------------------------------------------
482 void wxSVGFileDCImpl::SetBackground( const wxBrush
&brush
)
485 m_backgroundBrush
= brush
;
490 void wxSVGFileDCImpl::SetBackgroundMode( int mode
)
492 m_backgroundMode
= mode
;
497 void wxSVGFileDCImpl::SetBrush(const wxBrush
& brush
)
502 m_graphics_changed
= true;
503 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetBrush Call executed"));
507 void wxSVGFileDCImpl::SetPen(const wxPen
& pen
)
509 // width, color, ends, joins : currently implemented
510 // dashes, stipple : not implemented
513 m_graphics_changed
= true;
514 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetPen Call executed"));
517 void wxSVGFileDCImpl::NewGraphics ()
520 int w
= m_pen
.GetWidth ();
521 wxColour c
= m_pen
.GetColour ();
523 wxString s
, sBrush
, sPenCap
, sPenJoin
, sPenStyle
, sLast
, sWarn
;
525 sBrush
= wxT("</g>\n<g style=\"") + wxBrushString ( m_brush
.GetColour (), m_brush
.GetStyle () )
526 + wxT(" stroke:") + c
.GetAsString(wxC2S_HTML_SYNTAX
) + wxT("; ");
528 switch ( m_pen
.GetCap () )
530 case wxCAP_PROJECTING
:
531 sPenCap
= wxT("stroke-linecap:square; ");
534 sPenCap
= wxT("stroke-linecap:butt; ");
538 sPenCap
= wxT("stroke-linecap:round; ");
540 switch ( m_pen
.GetJoin () )
543 sPenJoin
= wxT("stroke-linejoin:bevel; ");
546 sPenJoin
= wxT("stroke-linejoin:miter; ");
550 sPenJoin
= wxT("stroke-linejoin:round; ");
553 switch ( m_pen
.GetStyle () )
555 case wxPENSTYLE_SOLID
:
556 sPenStyle
= wxT("stroke-opacity:1.0; stroke-opacity:1.0; ");
558 case wxPENSTYLE_TRANSPARENT
:
559 sPenStyle
= wxT("stroke-opacity:0.0; stroke-opacity:0.0; ");
562 wxASSERT_MSG(false, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available"));
563 sWarn
= sWarn
+ wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n");
566 sLast
.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%s %s) scale(%s %s)\">"),
567 w
, NumStr(m_logicalOriginX
), NumStr(m_logicalOriginY
), NumStr(m_scaleX
), NumStr(m_scaleY
) );
569 s
= sBrush
+ sPenCap
+ sPenJoin
+ sPenStyle
+ sLast
+ wxT("\n") + sWarn
;
571 m_graphics_changed
= false;
572 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::NewGraphics Call executed"));
576 void wxSVGFileDCImpl::SetFont(const wxFont
& font
)
581 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetFont Call executed"));
584 // export a bitmap as a raster image in png
585 bool wxSVGFileDCImpl::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
586 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
587 wxRasterOperationMode logicalFunc
/*= wxCOPY*/, bool useMask
/*= false*/,
588 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
590 if (logicalFunc
!= wxCOPY
)
592 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible"));
595 if (useMask
!= false)
597 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested false mask; this is not possible"));
600 wxBitmap
myBitmap (width
, height
);
602 memDC
.SelectObject( myBitmap
);
603 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
604 memDC
.SelectObject( wxNullBitmap
);
605 DoDrawBitmap(myBitmap
, xdest
, ydest
);
606 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoBlit Call executed"));
610 void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
612 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() );
614 memDC
.SelectObject( myBitmap
);
615 memDC
.DrawIcon(myIcon
,0,0);
616 memDC
.SelectObject( wxNullBitmap
);
617 DoDrawBitmap(myBitmap
, x
, y
);
618 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawIcon Call executed"));
622 void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
624 if (m_graphics_changed
) NewGraphics ();
626 wxString sTmp
, s
, sPNG
;
627 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) == NULL
)
628 wxImage::AddHandler(new wxPNGHandler
);
630 // create suitable file name
631 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
632 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
633 while (wxFile::Exists(sPNG
) )
636 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
637 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
640 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
641 wxBitmap myBitmap
= bmp
;
643 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
645 // reference the bitmap from the SVG doc
646 // only use filename & ext
647 sPNG
= sPNG
.AfterLast(wxFileName::GetPathSeparator());
649 // reference the bitmap from the SVG doc
650 int w
= myBitmap
.GetWidth();
651 int h
= myBitmap
.GetHeight();
652 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
654 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
655 s
= s
+ sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + wxT("\n");
661 m_OK
= m_outfile
->Ok () && bPNG_OK
;
662 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawBitmap Call executed"));
667 void wxSVGFileDCImpl::write(const wxString
&s
)
669 const wxCharBuffer buf
= s
.utf8_str();
670 m_outfile
->Write(buf
, strlen((const char *)buf
));
671 m_OK
= m_outfile
->Ok();