1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/svg.cpp
4 // Author: Chris Elliott
6 // Licence: wxWindows licence
7 /////////////////////////////////////////////////////////////////////////////
10 // For compilers that support precompilation, includes "wx/wx.h".
11 #include "wx/wxprec.h"
20 #include "wx/dcmemory.h"
21 #include "wx/dcscreen.h"
27 #include "wx/wfstream.h"
28 #include "wx/filename.h"
30 // ----------------------------------------------------------
32 // ----------------------------------------------------------
37 inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
39 // This function returns a string representation of a floating point number in
40 // C locale (i.e. always using "." for the decimal separator) and with the
41 // fixed precision (which is 2 for some unknown reason but this is what it was
42 // in this code originally).
43 inline wxString
NumStr(double f
)
45 return wxString::FromCDouble(f
, 2);
48 // Return the colour representation as HTML-like "#rrggbb" string and also
49 // returns its alpha as opacity number in 0..1 range.
50 wxString
Col2SVG(wxColour c
, float *opacity
)
52 if ( c
.Alpha() != wxALPHA_OPAQUE
)
54 *opacity
= c
.Alpha()/255.;
56 // Remove the alpha before using GetAsString(wxC2S_HTML_SYNTAX) as it
57 // doesn't support colours with alpha channel.
58 c
= wxColour(c
.GetRGB());
65 return c
.GetAsString(wxC2S_HTML_SYNTAX
);
68 wxString
wxPenString(wxColour c
, int style
= wxPENSTYLE_SOLID
)
71 wxString s
= wxT("stroke:") + Col2SVG(c
, &opacity
) + wxT("; ");
75 case wxPENSTYLE_SOLID
:
76 s
+= wxString::Format(wxT("stroke-opacity:%s; "), NumStr(opacity
));
78 case wxPENSTYLE_TRANSPARENT
:
79 s
+= wxT("stroke-opacity:0.0; ");
82 wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Pen Style not available"));
88 wxString
wxBrushString(wxColour c
, int style
= wxBRUSHSTYLE_SOLID
)
91 wxString s
= wxT("fill:") + Col2SVG(c
, &opacity
) + wxT("; ");
95 case wxBRUSHSTYLE_SOLID
:
96 s
+= wxString::Format(wxT("fill-opacity:%s; "), NumStr(opacity
));
98 case wxBRUSHSTYLE_TRANSPARENT
:
99 s
+= wxT("fill-opacity:0.0; ");
102 wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available"));
108 } // anonymous namespace
110 // ----------------------------------------------------------
112 // ----------------------------------------------------------
114 IMPLEMENT_ABSTRACT_CLASS(wxSVGFileDCImpl
, wxDC
)
116 wxSVGFileDCImpl::wxSVGFileDCImpl( wxSVGFileDC
*owner
, const wxString
&filename
,
117 int width
, int height
, double dpi
) :
120 Init( filename
, width
, height
, dpi
);
123 void wxSVGFileDCImpl::Init (const wxString
&filename
, int Width
, int Height
, double dpi
)
133 m_clipNestingLevel
= 0;
135 m_mm_to_pix_x
= dpi
/25.4;
136 m_mm_to_pix_y
= dpi
/25.4;
138 m_backgroundBrush
= *wxTRANSPARENT_BRUSH
;
139 m_textForegroundColour
= *wxBLACK
;
140 m_textBackgroundColour
= *wxWHITE
;
141 m_colour
= wxColourDisplay();
143 m_pen
= *wxBLACK_PEN
;
144 m_font
= *wxNORMAL_FONT
;
145 m_brush
= *wxWHITE_BRUSH
;
147 m_graphics_changed
= true;
149 ////////////////////code here
151 m_outfile
= new wxFileOutputStream(filename
);
152 m_OK
= m_outfile
->IsOk();
155 m_filename
= filename
;
158 s
= wxT("<?xml version=\"1.0\" standalone=\"no\"?>\n");
160 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\"\n");
162 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n");
164 s
= wxT("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n");
166 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
);
168 s
= wxT("<title>SVG Picture created as ") + wxFileName(filename
).GetFullName() + wxT(" </title>\n");
170 s
= wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion
+ wxT(" </desc>\n");
172 s
= wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">\n");
177 wxSVGFileDCImpl::~wxSVGFileDCImpl()
179 wxString s
= wxT("</g> \n</svg> \n");
184 void wxSVGFileDCImpl::DoGetSizeMM( int *width
, int *height
) const
187 *width
= wxRound( (double)m_width
/ m_mm_to_pix_x
);
190 *height
= wxRound( (double)m_height
/ m_mm_to_pix_y
);
193 wxSize
wxSVGFileDCImpl::GetPPI() const
195 return wxSize( wxRound(m_dpi
), wxRound(m_dpi
) );
198 void wxSVGFileDCImpl::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
200 NewGraphicsIfNeeded();
202 s
.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1
,y1
,x2
,y2
);
207 CalcBoundingBox(x1
, y1
);
208 CalcBoundingBox(x2
, y2
);
211 void wxSVGFileDCImpl::DoDrawLines(int n
, const wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
213 for ( int i
= 1; i
< n
; i
++ )
215 DoDrawLine ( points
[i
-1].x
+ xoffset
, points
[i
-1].y
+ yoffset
,
216 points
[ i
].x
+ xoffset
, points
[ i
].y
+ yoffset
);
220 void wxSVGFileDCImpl::DoDrawPoint (wxCoord x1
, wxCoord y1
)
223 NewGraphicsIfNeeded();
224 s
= wxT("<g style = \"stroke-linecap:round;\" > \n");
226 DoDrawLine ( x1
,y1
,x1
,y1
);
231 void wxSVGFileDCImpl::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
233 wxDCImpl::DoDrawCheckMark (x1
,y1
,width
,height
);
236 void wxSVGFileDCImpl::DoDrawText(const wxString
& text
, wxCoord x1
, wxCoord y1
)
238 DoDrawRotatedText(text
, x1
,y1
,0.0);
241 void wxSVGFileDCImpl::DoDrawRotatedText(const wxString
& sText
, wxCoord x
, wxCoord y
, double angle
)
243 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
244 NewGraphicsIfNeeded();
247 // calculate bounding box
249 DoGetTextExtent(sText
, &w
, &h
, &desc
);
251 double rad
= DegToRad(angle
);
253 // wxT("upper left") and wxT("upper right")
254 CalcBoundingBox(x
, y
);
255 CalcBoundingBox((wxCoord
)(x
+ w
*cos(rad
)), (wxCoord
)(y
- h
*sin(rad
)));
257 // wxT("bottom left") and wxT("bottom right")
258 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
)), (wxCoord
)(y
+ h
*cos(rad
)));
259 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
) + w
*cos(rad
)), (wxCoord
)(y
+ h
*cos(rad
) - w
*sin(rad
)));
261 if (m_backgroundMode
== wxBRUSHSTYLE_SOLID
)
263 // draw background first
264 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
266 sTmp
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x
, y
, w
, h
);
267 s
= sTmp
+ wxT("style=\"") + wxBrushString(m_textBackgroundColour
);
268 s
+= wxT("stroke-width:1; ") + wxPenString(m_textBackgroundColour
);
269 sTmp
.Printf ( wxT("\" transform=\"rotate( %s %d %d ) \" />"), NumStr(-angle
), x
,y
);
270 s
+= sTmp
+ wxT("\n");
274 // convert x,y to SVG text x,y (the coordinates of the text baseline)
275 x
= (wxCoord
)(x
+ (h
-desc
)*sin(rad
));
276 y
= (wxCoord
)(y
+ (h
-desc
)*cos(rad
));
278 //now do the text itself
279 s
.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x
,y
);
281 sTmp
= m_font
.GetFaceName();
282 if (sTmp
.Len() > 0) s
+= wxT("style=\"font-family:") + sTmp
+ wxT("; ");
283 else s
+= wxT("style=\" ");
285 wxString fontweights
[3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
286 s
+= wxT("font-weight:") + fontweights
[m_font
.GetWeight() - wxNORMAL
] + wxT("; ");
288 wxString fontstyles
[5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
289 s
+= wxT("font-style:") + fontstyles
[m_font
.GetStyle() - wxNORMAL
] + wxT("; ");
291 sTmp
.Printf (wxT("font-size:%dpt; "), m_font
.GetPointSize() );
293 //text will be solid, unless alpha value isn't opaque in the foreground colour
294 s
+= wxBrushString(m_textForegroundColour
) + wxPenString(m_textForegroundColour
);
295 sTmp
.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %s %d %d ) \" >"), NumStr(-angle
), x
,y
);
296 s
+= sTmp
+ sText
+ wxT("</text> ") + wxT("\n");
303 void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
305 DoDrawRoundedRectangle(x
, y
, width
, height
, 0);
308 void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
311 NewGraphicsIfNeeded();
314 s
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" "),
315 x
, y
, width
, height
, NumStr(radius
) );
320 CalcBoundingBox(x
, y
);
321 CalcBoundingBox(x
+ width
, y
+ height
);
324 void wxSVGFileDCImpl::DoDrawPolygon(int n
, const wxPoint points
[],
325 wxCoord xoffset
, wxCoord yoffset
,
326 wxPolygonFillMode fillStyle
)
328 NewGraphicsIfNeeded();
330 s
= wxT("<polygon style=\"");
331 if ( fillStyle
== wxODDEVEN_RULE
)
332 s
+= wxT("fill-rule:evenodd; ");
334 s
+= wxT("fill-rule:nonzero; ");
336 s
+= wxT("\" \npoints=\"");
338 for (int i
= 0; i
< n
; i
++)
340 sTmp
.Printf ( wxT("%d,%d"), points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
341 s
+= sTmp
+ wxT("\n");
342 CalcBoundingBox ( points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
344 s
+= wxT("\" /> \n");
348 void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
351 NewGraphicsIfNeeded();
357 s
.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x
+rw
,y
+rh
, rw
, rh
);
362 CalcBoundingBox(x
, y
);
363 CalcBoundingBox(x
+ width
, y
+ height
);
366 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
368 /* Draws an arc of a circle, centred on (xc, yc), with starting point
369 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
370 and the current brush for filling the shape.
372 The arc is drawn in an anticlockwise direction from the start point to
375 Might be better described as Pie drawing */
377 NewGraphicsIfNeeded();
380 // we need the radius of the circle which has two estimates
381 double r1
= sqrt ( double( (x1
-xc
)*(x1
-xc
) ) + double( (y1
-yc
)*(y1
-yc
) ) );
382 double r2
= sqrt ( double( (x2
-xc
)*(x2
-xc
) ) + double( (y2
-yc
)*(y2
-yc
) ) );
384 wxASSERT_MSG( (fabs ( r2
-r1
) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle"));
385 if ( fabs ( r2
-r1
) > 3 ) //pixels
387 s
= wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n");
391 double theta1
= atan2((double)(yc
-y1
),(double)(x1
-xc
));
392 if ( theta1
< 0 ) theta1
= theta1
+ M_PI
* 2;
393 double theta2
= atan2((double)(yc
-y2
), (double)(x2
-xc
));
394 if ( theta2
< 0 ) theta2
= theta2
+ M_PI
* 2;
395 if ( theta2
< theta1
) theta2
= theta2
+ M_PI
*2;
397 int fArc
; // flag for large or small arc 0 means less than 180 degrees
398 if ( fabs(theta2
- theta1
) > M_PI
) fArc
= 1; else fArc
= 0;
400 int fSweep
= 0; // flag for sweep always 0
402 s
.Printf ( wxT("<path d=\"M%d %d A%s %s 0.0 %d %d %d %d L%d %d z "),
403 x1
,y1
, NumStr(r1
), NumStr(r2
), fArc
, fSweep
, x2
, y2
, xc
, yc
);
405 // the z means close the path and fill
406 s
+= wxT(" \" /> \n");
415 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
418 Draws an arc of an ellipse. The current pen is used for drawing the arc
419 and the current brush is used for drawing the pie. This function is
420 currently only available for X window and PostScript device contexts.
422 x and y specify the x and y coordinates of the upper-left corner of the
423 rectangle that contains the ellipse.
425 width and height specify the width and height of the rectangle that
426 contains the ellipse.
428 start and end specify the start and end of the arc relative to the
429 three-o'clock position from the center of the rectangle. Angles are
430 specified in degrees (360 is a complete circle). Positive values mean
431 counter-clockwise motion. If start is equal to end, a complete ellipse
434 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
436 NewGraphicsIfNeeded();
446 double xs
, ys
, xe
, ye
;
447 xs
= xc
+ rx
* cos (DegToRad(sa
));
448 xe
= xc
+ rx
* cos (DegToRad(ea
));
449 ys
= yc
- ry
* sin (DegToRad(sa
));
450 ye
= yc
- ry
* sin (DegToRad(ea
));
452 ///now same as circle arc...
454 double theta1
= atan2(ys
-yc
, xs
-xc
);
455 double theta2
= atan2(ye
-yc
, xe
-xc
);
457 int fArc
; // flag for large or small arc 0 means less than 180 degrees
458 if ( (theta2
- theta1
) > 0 ) fArc
= 1; else fArc
= 0;
461 if ( fabs(theta2
- theta1
) > M_PI
) fSweep
= 1; else fSweep
= 0;
463 s
.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
464 int(xs
), int(ys
), int(rx
), int(ry
),
465 fArc
, fSweep
, int(xe
), int(ye
), int(xc
), int(yc
) );
467 s
+= wxT(" \" /> \n");
475 void wxSVGFileDCImpl::DoSetClippingRegion( int x
, int y
, int width
, int height
)
479 // End current graphics group to ensure proper xml nesting (e.g. so that
480 // graphics can be subsequently changed inside the clipping region)
483 "<clipPath id=\"clip" << m_clipNestingLevel
<< "\">\n"
484 "<rect id=\"cliprect" << m_clipNestingLevel
<< "\" "
487 "width=\"" << width
<< "\" "
488 "height=\"" << height
<< "\" "
489 "style=\"stroke: gray; fill: none;\"/>\n"
492 "<g style=\"clip-path: url(#clip" << m_clipNestingLevel
<< ");\">\n";
496 // Re-apply current graphics to ensure proper xml nesting
497 DoStartNewGraphics();
500 m_clipNestingLevel
++;
503 void wxSVGFileDCImpl::DestroyClippingRegion()
507 // End current graphics element to ensure proper xml nesting (e.g. graphics
508 // might have been changed inside the clipping region)
511 // Close clipping group elements
512 for ( size_t i
= 0; i
< m_clipUniqueId
; i
++ )
520 // Re-apply current graphics (e.g. brush may have been changed inside one
521 // of the clipped regions - that change will have been lost after xml
522 // elements for the clipped region have been closed).
523 DoStartNewGraphics();
528 void wxSVGFileDCImpl::DoGetTextExtent(const wxString
& string
, wxCoord
*w
, wxCoord
*h
, wxCoord
*descent
, wxCoord
*externalLeading
, const wxFont
*font
) const
533 sDC
.SetFont (m_font
);
534 if ( font
!= NULL
) sDC
.SetFont ( *font
);
535 sDC
.GetTextExtent(string
, w
, h
, descent
, externalLeading
);
538 wxCoord
wxSVGFileDCImpl::GetCharHeight() const
541 sDC
.SetFont (m_font
);
543 return sDC
.GetCharHeight();
547 wxCoord
wxSVGFileDCImpl::GetCharWidth() const
550 sDC
.SetFont (m_font
);
552 return sDC
.GetCharWidth();
556 // ----------------------------------------------------------
557 // wxSVGFileDCImpl - set functions
558 // ----------------------------------------------------------
560 void wxSVGFileDCImpl::SetBackground( const wxBrush
&brush
)
562 m_backgroundBrush
= brush
;
566 void wxSVGFileDCImpl::SetBackgroundMode( int mode
)
568 m_backgroundMode
= mode
;
572 void wxSVGFileDCImpl::SetBrush(const wxBrush
& brush
)
576 m_graphics_changed
= true;
580 void wxSVGFileDCImpl::SetPen(const wxPen
& pen
)
582 // width, color, ends, joins : currently implemented
583 // dashes, stipple : not implemented
586 m_graphics_changed
= true;
589 void wxSVGFileDCImpl::NewGraphicsIfNeeded()
591 if ( !m_graphics_changed
)
594 m_graphics_changed
= false;
596 write(wxS("</g>\n"));
598 DoStartNewGraphics();
601 void wxSVGFileDCImpl::DoStartNewGraphics()
603 wxString s
, sBrush
, sPenCap
, sPenJoin
, sPenStyle
, sLast
;
605 sBrush
= wxS("<g style=\"") + wxBrushString ( m_brush
.GetColour(), m_brush
.GetStyle() )
606 + wxPenString(m_pen
.GetColour(), m_pen
.GetStyle());
608 switch ( m_pen
.GetCap() )
610 case wxCAP_PROJECTING
:
611 sPenCap
= wxT("stroke-linecap:square; ");
614 sPenCap
= wxT("stroke-linecap:butt; ");
618 sPenCap
= wxT("stroke-linecap:round; ");
621 switch ( m_pen
.GetJoin() )
624 sPenJoin
= wxT("stroke-linejoin:bevel; ");
627 sPenJoin
= wxT("stroke-linejoin:miter; ");
631 sPenJoin
= wxT("stroke-linejoin:round; ");
634 sLast
.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%s %s) scale(%s %s)\">"),
635 m_pen
.GetWidth(), NumStr(m_logicalOriginX
), NumStr(m_logicalOriginY
), NumStr(m_scaleX
), NumStr(m_scaleY
) );
637 s
= sBrush
+ sPenCap
+ sPenJoin
+ sPenStyle
+ sLast
+ wxT("\n");
642 void wxSVGFileDCImpl::SetFont(const wxFont
& font
)
648 // export a bitmap as a raster image in png
649 bool wxSVGFileDCImpl::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
650 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
651 wxRasterOperationMode logicalFunc
/*= wxCOPY*/, bool useMask
/*= false*/,
652 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
654 if (logicalFunc
!= wxCOPY
)
656 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible"));
659 if (useMask
!= false)
661 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested false mask; this is not possible"));
664 wxBitmap
myBitmap (width
, height
);
666 memDC
.SelectObject( myBitmap
);
667 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
668 memDC
.SelectObject( wxNullBitmap
);
669 DoDrawBitmap(myBitmap
, xdest
, ydest
);
673 void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
675 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() );
677 memDC
.SelectObject( myBitmap
);
678 memDC
.DrawIcon(myIcon
,0,0);
679 memDC
.SelectObject( wxNullBitmap
);
680 DoDrawBitmap(myBitmap
, x
, y
);
683 void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
685 NewGraphicsIfNeeded();
687 wxString sTmp
, s
, sPNG
;
688 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) == NULL
)
689 wxImage::AddHandler(new wxPNGHandler
);
691 // create suitable file name
692 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
693 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
694 while (wxFile::Exists(sPNG
) )
697 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
698 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
701 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
702 wxBitmap myBitmap
= bmp
;
704 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
706 // reference the bitmap from the SVG doc
707 // only use filename & ext
708 sPNG
= sPNG
.AfterLast(wxFileName::GetPathSeparator());
710 // reference the bitmap from the SVG doc
711 int w
= myBitmap
.GetWidth();
712 int h
= myBitmap
.GetHeight();
713 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
715 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
716 s
+= sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + wxT("\n");
722 m_OK
= m_outfile
->IsOk() && bPNG_OK
;
725 void wxSVGFileDCImpl::write(const wxString
&s
)
727 const wxCharBuffer buf
= s
.utf8_str();
728 m_outfile
->Write(buf
, strlen((const char *)buf
));
729 m_OK
= m_outfile
->IsOk();