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 // ----------------------------------------------------------
33 // ----------------------------------------------------------
38 inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
40 // This function returns a string representation of a floating point number in
41 // C locale (i.e. always using "." for the decimal separator) and with the
42 // fixed precision (which is 2 for some unknown reason but this is what it was
43 // in this code originally).
44 inline wxString
NumStr(double f
)
46 return wxString::FromCDouble(f
, 2);
49 // Return the colour representation as HTML-like "#rrggbb" string and also
50 // returns its alpha as opacity number in 0..1 range.
51 wxString
Col2SVG(wxColour c
, float *opacity
)
53 if ( c
.Alpha() != wxALPHA_OPAQUE
)
55 *opacity
= c
.Alpha()/255.;
57 // Remove the alpha before using GetAsString(wxC2S_HTML_SYNTAX) as it
58 // doesn't support colours with alpha channel.
59 c
= wxColour(c
.GetRGB());
66 return c
.GetAsString(wxC2S_HTML_SYNTAX
);
69 wxString
wxPenString(wxColour c
, int style
= wxPENSTYLE_SOLID
)
72 wxString s
= wxT("stroke:") + Col2SVG(c
, &opacity
) + wxT("; ");
76 case wxPENSTYLE_SOLID
:
77 s
+= wxString::Format(wxT("stroke-opacity:%s; "), NumStr(opacity
));
79 case wxPENSTYLE_TRANSPARENT
:
80 s
+= wxT("stroke-opacity:0.0; ");
83 wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Pen Style not available"));
89 wxString
wxBrushString(wxColour c
, int style
= wxBRUSHSTYLE_SOLID
)
92 wxString s
= wxT("fill:") + Col2SVG(c
, &opacity
) + wxT("; ");
96 case wxBRUSHSTYLE_SOLID
:
97 s
+= wxString::Format(wxT("fill-opacity:%s; "), NumStr(opacity
));
99 case wxBRUSHSTYLE_TRANSPARENT
:
100 s
+= wxT("fill-opacity:0.0; ");
103 wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available"));
109 } // anonymous namespace
111 // ----------------------------------------------------------
113 // ----------------------------------------------------------
115 IMPLEMENT_ABSTRACT_CLASS(wxSVGFileDCImpl
, wxDC
)
117 wxSVGFileDCImpl::wxSVGFileDCImpl( wxSVGFileDC
*owner
, const wxString
&filename
,
118 int width
, int height
, double dpi
) :
121 Init( filename
, width
, height
, dpi
);
124 void wxSVGFileDCImpl::Init (const wxString
&filename
, int Width
, int Height
, double dpi
)
134 m_clipNestingLevel
= 0;
136 m_mm_to_pix_x
= dpi
/25.4;
137 m_mm_to_pix_y
= dpi
/25.4;
139 m_backgroundBrush
= *wxTRANSPARENT_BRUSH
;
140 m_textForegroundColour
= *wxBLACK
;
141 m_textBackgroundColour
= *wxWHITE
;
142 m_colour
= wxColourDisplay();
144 m_pen
= *wxBLACK_PEN
;
145 m_font
= *wxNORMAL_FONT
;
146 m_brush
= *wxWHITE_BRUSH
;
148 m_graphics_changed
= true;
150 ////////////////////code here
152 m_outfile
= new wxFileOutputStream(filename
);
153 m_OK
= m_outfile
->IsOk();
156 m_filename
= filename
;
159 s
= wxT("<?xml version=\"1.0\" standalone=\"no\"?>\n");
161 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\"\n");
163 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n");
165 s
= wxT("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n");
167 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
);
169 s
= wxT("<title>SVG Picture created as ") + wxFileName(filename
).GetFullName() + wxT(" </title>\n");
171 s
= wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion
+ wxT(" </desc>\n");
173 s
= wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">\n");
178 wxSVGFileDCImpl::~wxSVGFileDCImpl()
180 wxString s
= wxT("</g> \n</svg> \n");
185 void wxSVGFileDCImpl::DoGetSizeMM( int *width
, int *height
) const
188 *width
= wxRound( (double)m_width
/ m_mm_to_pix_x
);
191 *height
= wxRound( (double)m_height
/ m_mm_to_pix_y
);
194 wxSize
wxSVGFileDCImpl::GetPPI() const
196 return wxSize( wxRound(m_dpi
), wxRound(m_dpi
) );
199 void wxSVGFileDCImpl::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
201 NewGraphicsIfNeeded();
203 s
.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1
,y1
,x2
,y2
);
208 CalcBoundingBox(x1
, y1
);
209 CalcBoundingBox(x2
, y2
);
212 void wxSVGFileDCImpl::DoDrawLines(int n
, const wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
214 for ( int i
= 1; i
< n
; i
++ )
216 DoDrawLine ( points
[i
-1].x
+ xoffset
, points
[i
-1].y
+ yoffset
,
217 points
[ i
].x
+ xoffset
, points
[ i
].y
+ yoffset
);
221 void wxSVGFileDCImpl::DoDrawPoint (wxCoord x1
, wxCoord y1
)
224 NewGraphicsIfNeeded();
225 s
= wxT("<g style = \"stroke-linecap:round;\" > \n");
227 DoDrawLine ( x1
,y1
,x1
,y1
);
232 void wxSVGFileDCImpl::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
234 wxDCImpl::DoDrawCheckMark (x1
,y1
,width
,height
);
237 void wxSVGFileDCImpl::DoDrawText(const wxString
& text
, wxCoord x1
, wxCoord y1
)
239 DoDrawRotatedText(text
, x1
,y1
,0.0);
242 void wxSVGFileDCImpl::DoDrawRotatedText(const wxString
& sText
, wxCoord x
, wxCoord y
, double angle
)
244 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
245 NewGraphicsIfNeeded();
248 // calculate bounding box
250 DoGetTextExtent(sText
, &w
, &h
, &desc
);
252 double rad
= DegToRad(angle
);
254 // wxT("upper left") and wxT("upper right")
255 CalcBoundingBox(x
, y
);
256 CalcBoundingBox((wxCoord
)(x
+ w
*cos(rad
)), (wxCoord
)(y
- h
*sin(rad
)));
258 // wxT("bottom left") and wxT("bottom right")
259 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
)), (wxCoord
)(y
+ h
*cos(rad
)));
260 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
) + w
*cos(rad
)), (wxCoord
)(y
+ h
*cos(rad
) - w
*sin(rad
)));
262 if (m_backgroundMode
== wxBRUSHSTYLE_SOLID
)
264 // draw background first
265 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
267 sTmp
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x
, y
, w
, h
);
268 s
= sTmp
+ wxT("style=\"") + wxBrushString(m_textBackgroundColour
);
269 s
+= wxT("stroke-width:1; ") + wxPenString(m_textBackgroundColour
);
270 sTmp
.Printf ( wxT("\" transform=\"rotate( %s %d %d ) \" />"), NumStr(-angle
), x
,y
);
271 s
+= sTmp
+ wxT("\n");
275 // convert x,y to SVG text x,y (the coordinates of the text baseline)
276 x
= (wxCoord
)(x
+ (h
-desc
)*sin(rad
));
277 y
= (wxCoord
)(y
+ (h
-desc
)*cos(rad
));
279 //now do the text itself
280 s
.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x
,y
);
282 sTmp
= m_font
.GetFaceName();
283 if (sTmp
.Len() > 0) s
+= wxT("style=\"font-family:") + sTmp
+ wxT("; ");
284 else s
+= wxT("style=\" ");
286 wxString fontweights
[3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
287 s
+= wxT("font-weight:") + fontweights
[m_font
.GetWeight() - wxNORMAL
] + wxT("; ");
289 wxString fontstyles
[5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
290 s
+= wxT("font-style:") + fontstyles
[m_font
.GetStyle() - wxNORMAL
] + wxT("; ");
292 sTmp
.Printf (wxT("font-size:%dpt; "), m_font
.GetPointSize() );
294 //text will be solid, unless alpha value isn't opaque in the foreground colour
295 s
+= wxBrushString(m_textForegroundColour
) + wxPenString(m_textForegroundColour
);
296 sTmp
.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %s %d %d ) \" >"), NumStr(-angle
), x
,y
);
297 s
+= sTmp
+ sText
+ wxT("</text> ") + wxT("\n");
304 void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
306 DoDrawRoundedRectangle(x
, y
, width
, height
, 0);
309 void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
312 NewGraphicsIfNeeded();
315 s
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" "),
316 x
, y
, width
, height
, NumStr(radius
) );
321 CalcBoundingBox(x
, y
);
322 CalcBoundingBox(x
+ width
, y
+ height
);
325 void wxSVGFileDCImpl::DoDrawPolygon(int n
, const wxPoint points
[],
326 wxCoord xoffset
, wxCoord yoffset
,
327 wxPolygonFillMode fillStyle
)
329 NewGraphicsIfNeeded();
331 s
= wxT("<polygon style=\"");
332 if ( fillStyle
== wxODDEVEN_RULE
)
333 s
+= wxT("fill-rule:evenodd; ");
335 s
+= wxT("fill-rule:nonzero; ");
337 s
+= wxT("\" \npoints=\"");
339 for (int i
= 0; i
< n
; i
++)
341 sTmp
.Printf ( wxT("%d,%d"), points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
342 s
+= sTmp
+ wxT("\n");
343 CalcBoundingBox ( points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
345 s
+= wxT("\" /> \n");
349 void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
352 NewGraphicsIfNeeded();
358 s
.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x
+rw
,y
+rh
, rw
, rh
);
363 CalcBoundingBox(x
, y
);
364 CalcBoundingBox(x
+ width
, y
+ height
);
367 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
369 /* Draws an arc of a circle, centred on (xc, yc), with starting point
370 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
371 and the current brush for filling the shape.
373 The arc is drawn in an anticlockwise direction from the start point to
376 Might be better described as Pie drawing */
378 NewGraphicsIfNeeded();
381 // we need the radius of the circle which has two estimates
382 double r1
= sqrt ( double( (x1
-xc
)*(x1
-xc
) ) + double( (y1
-yc
)*(y1
-yc
) ) );
383 double r2
= sqrt ( double( (x2
-xc
)*(x2
-xc
) ) + double( (y2
-yc
)*(y2
-yc
) ) );
385 wxASSERT_MSG( (fabs ( r2
-r1
) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle"));
386 if ( fabs ( r2
-r1
) > 3 ) //pixels
388 s
= wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n");
392 double theta1
= atan2((double)(yc
-y1
),(double)(x1
-xc
));
393 if ( theta1
< 0 ) theta1
= theta1
+ M_PI
* 2;
394 double theta2
= atan2((double)(yc
-y2
), (double)(x2
-xc
));
395 if ( theta2
< 0 ) theta2
= theta2
+ M_PI
* 2;
396 if ( theta2
< theta1
) theta2
= theta2
+ M_PI
*2;
398 int fArc
; // flag for large or small arc 0 means less than 180 degrees
399 if ( fabs(theta2
- theta1
) > M_PI
) fArc
= 1; else fArc
= 0;
401 int fSweep
= 0; // flag for sweep always 0
403 s
.Printf ( wxT("<path d=\"M%d %d A%s %s 0.0 %d %d %d %d L%d %d z "),
404 x1
,y1
, NumStr(r1
), NumStr(r2
), fArc
, fSweep
, x2
, y2
, xc
, yc
);
406 // the z means close the path and fill
407 s
+= wxT(" \" /> \n");
416 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
419 Draws an arc of an ellipse. The current pen is used for drawing the arc
420 and the current brush is used for drawing the pie. This function is
421 currently only available for X window and PostScript device contexts.
423 x and y specify the x and y coordinates of the upper-left corner of the
424 rectangle that contains the ellipse.
426 width and height specify the width and height of the rectangle that
427 contains the ellipse.
429 start and end specify the start and end of the arc relative to the
430 three-o'clock position from the center of the rectangle. Angles are
431 specified in degrees (360 is a complete circle). Positive values mean
432 counter-clockwise motion. If start is equal to end, a complete ellipse
435 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
437 NewGraphicsIfNeeded();
447 double xs
, ys
, xe
, ye
;
448 xs
= xc
+ rx
* cos (DegToRad(sa
));
449 xe
= xc
+ rx
* cos (DegToRad(ea
));
450 ys
= yc
- ry
* sin (DegToRad(sa
));
451 ye
= yc
- ry
* sin (DegToRad(ea
));
453 ///now same as circle arc...
455 double theta1
= atan2(ys
-yc
, xs
-xc
);
456 double theta2
= atan2(ye
-yc
, xe
-xc
);
458 int fArc
; // flag for large or small arc 0 means less than 180 degrees
459 if ( (theta2
- theta1
) > 0 ) fArc
= 1; else fArc
= 0;
462 if ( fabs(theta2
- theta1
) > M_PI
) fSweep
= 1; else fSweep
= 0;
464 s
.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
465 int(xs
), int(ys
), int(rx
), int(ry
),
466 fArc
, fSweep
, int(xe
), int(ye
), int(xc
), int(yc
) );
468 s
+= wxT(" \" /> \n");
476 void wxSVGFileDCImpl::DoSetClippingRegion( int x
, int y
, int width
, int height
)
480 // End current graphics group to ensure proper xml nesting (e.g. so that
481 // graphics can be subsequently changed inside the clipping region)
484 "<clipPath id=\"clip" << m_clipNestingLevel
<< "\">\n"
485 "<rect id=\"cliprect" << m_clipNestingLevel
<< "\" "
488 "width=\"" << width
<< "\" "
489 "height=\"" << height
<< "\" "
490 "style=\"stroke: gray; fill: none;\"/>\n"
493 "<g style=\"clip-path: url(#clip" << m_clipNestingLevel
<< ");\">\n";
497 // Re-apply current graphics to ensure proper xml nesting
498 DoStartNewGraphics();
501 m_clipNestingLevel
++;
504 void wxSVGFileDCImpl::DestroyClippingRegion()
508 // End current graphics element to ensure proper xml nesting (e.g. graphics
509 // might have been changed inside the clipping region)
512 // Close clipping group elements
513 for ( size_t i
= 0; i
< m_clipUniqueId
; i
++ )
521 // Re-apply current graphics (e.g. brush may have been changed inside one
522 // of the clipped regions - that change will have been lost after xml
523 // elements for the clipped region have been closed).
524 DoStartNewGraphics();
529 void wxSVGFileDCImpl::DoGetTextExtent(const wxString
& string
, wxCoord
*w
, wxCoord
*h
, wxCoord
*descent
, wxCoord
*externalLeading
, const wxFont
*font
) const
534 sDC
.SetFont (m_font
);
535 if ( font
!= NULL
) sDC
.SetFont ( *font
);
536 sDC
.GetTextExtent(string
, w
, h
, descent
, externalLeading
);
539 wxCoord
wxSVGFileDCImpl::GetCharHeight() const
542 sDC
.SetFont (m_font
);
544 return sDC
.GetCharHeight();
548 wxCoord
wxSVGFileDCImpl::GetCharWidth() const
551 sDC
.SetFont (m_font
);
553 return sDC
.GetCharWidth();
557 // ----------------------------------------------------------
558 // wxSVGFileDCImpl - set functions
559 // ----------------------------------------------------------
561 void wxSVGFileDCImpl::SetBackground( const wxBrush
&brush
)
563 m_backgroundBrush
= brush
;
567 void wxSVGFileDCImpl::SetBackgroundMode( int mode
)
569 m_backgroundMode
= mode
;
573 void wxSVGFileDCImpl::SetBrush(const wxBrush
& brush
)
577 m_graphics_changed
= true;
581 void wxSVGFileDCImpl::SetPen(const wxPen
& pen
)
583 // width, color, ends, joins : currently implemented
584 // dashes, stipple : not implemented
587 m_graphics_changed
= true;
590 void wxSVGFileDCImpl::NewGraphicsIfNeeded()
592 if ( !m_graphics_changed
)
595 m_graphics_changed
= false;
597 write(wxS("</g>\n"));
599 DoStartNewGraphics();
602 void wxSVGFileDCImpl::DoStartNewGraphics()
604 wxString s
, sBrush
, sPenCap
, sPenJoin
, sPenStyle
, sLast
;
606 sBrush
= wxS("<g style=\"") + wxBrushString ( m_brush
.GetColour(), m_brush
.GetStyle() )
607 + wxPenString(m_pen
.GetColour(), m_pen
.GetStyle());
609 switch ( m_pen
.GetCap() )
611 case wxCAP_PROJECTING
:
612 sPenCap
= wxT("stroke-linecap:square; ");
615 sPenCap
= wxT("stroke-linecap:butt; ");
619 sPenCap
= wxT("stroke-linecap:round; ");
622 switch ( m_pen
.GetJoin() )
625 sPenJoin
= wxT("stroke-linejoin:bevel; ");
628 sPenJoin
= wxT("stroke-linejoin:miter; ");
632 sPenJoin
= wxT("stroke-linejoin:round; ");
635 sLast
.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%s %s) scale(%s %s)\">"),
636 m_pen
.GetWidth(), NumStr(m_logicalOriginX
), NumStr(m_logicalOriginY
), NumStr(m_scaleX
), NumStr(m_scaleY
) );
638 s
= sBrush
+ sPenCap
+ sPenJoin
+ sPenStyle
+ sLast
+ wxT("\n");
643 void wxSVGFileDCImpl::SetFont(const wxFont
& font
)
649 // export a bitmap as a raster image in png
650 bool wxSVGFileDCImpl::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
651 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
652 wxRasterOperationMode logicalFunc
/*= wxCOPY*/, bool useMask
/*= false*/,
653 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
655 if (logicalFunc
!= wxCOPY
)
657 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible"));
660 if (useMask
!= false)
662 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested false mask; this is not possible"));
665 wxBitmap
myBitmap (width
, height
);
667 memDC
.SelectObject( myBitmap
);
668 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
669 memDC
.SelectObject( wxNullBitmap
);
670 DoDrawBitmap(myBitmap
, xdest
, ydest
);
674 void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
676 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() );
678 memDC
.SelectObject( myBitmap
);
679 memDC
.DrawIcon(myIcon
,0,0);
680 memDC
.SelectObject( wxNullBitmap
);
681 DoDrawBitmap(myBitmap
, x
, y
);
684 void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
686 NewGraphicsIfNeeded();
688 wxString sTmp
, s
, sPNG
;
689 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) == NULL
)
690 wxImage::AddHandler(new wxPNGHandler
);
692 // create suitable file name
693 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
694 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
695 while (wxFile::Exists(sPNG
) )
698 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
699 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
702 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
703 wxBitmap myBitmap
= bmp
;
705 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
707 // reference the bitmap from the SVG doc
708 // only use filename & ext
709 sPNG
= sPNG
.AfterLast(wxFileName::GetPathSeparator());
711 // reference the bitmap from the SVG doc
712 int w
= myBitmap
.GetWidth();
713 int h
= myBitmap
.GetHeight();
714 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
716 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
717 s
+= sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + wxT("\n");
723 m_OK
= m_outfile
->IsOk() && bPNG_OK
;
726 void wxSVGFileDCImpl::write(const wxString
&s
)
728 const wxCharBuffer buf
= s
.utf8_str();
729 m_outfile
->Write(buf
, strlen((const char *)buf
));
730 m_OK
= m_outfile
->IsOk();