1 /////////////////////////////////////////////////////////////////////////////
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 #define newline wxString(wxT("\n"))
35 #define space wxString(wxT(" "))
36 #define semicolon wxString(wxT(";"))
37 #define wx_round(a) (int)((a)+.5)
40 // ----------------------------------------------------------
42 // ----------------------------------------------------------
47 inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
49 wxString
wxColStr ( wxColour c
)
51 unsigned char r
, g
, b
;
56 // possible Unicode bug here
57 wxString s
= wxDecToHex(r
) + wxDecToHex(g
) + wxDecToHex(b
);
62 wxString
wxBrushString ( wxColour c
, int style
)
64 wxString s
= wxT("fill:#") + wxColStr (c
) + semicolon
+ space
;
67 case wxBRUSHSTYLE_SOLID
:
68 s
= s
+ wxT("fill-opacity:1.0; ");
70 case wxBRUSHSTYLE_TRANSPARENT
:
71 s
= s
+ wxT("fill-opacity:0.0; ");
75 wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available"));
82 // This function returns a string representation of a floating point number in
83 // C locale (i.e. always using "." for the decimal separator) and with the
84 // fixed precision (which is 2 for some unknown reason but this is what it was
85 // in this code originally).
86 inline wxString
NumStr(double f
)
88 return wxString::FromCDouble(f
, 2);
91 } // anonymous namespace
93 // ----------------------------------------------------------
95 // ----------------------------------------------------------
97 IMPLEMENT_ABSTRACT_CLASS(wxSVGFileDCImpl
, wxDC
)
99 wxSVGFileDCImpl::wxSVGFileDCImpl( wxSVGFileDC
*owner
, const wxString
&filename
,
100 int width
, int height
, double dpi
) :
103 Init( filename
, width
, height
, dpi
);
106 void wxSVGFileDCImpl::Init (const wxString
&filename
, int Width
, int Height
, double dpi
)
115 m_mm_to_pix_x
= dpi
/25.4;
116 m_mm_to_pix_y
= dpi
/25.4;
118 m_backgroundBrush
= *wxTRANSPARENT_BRUSH
;
119 m_textForegroundColour
= *wxBLACK
;
120 m_textBackgroundColour
= *wxWHITE
;
121 m_colour
= wxColourDisplay();
123 m_pen
= *wxBLACK_PEN
;
124 m_font
= *wxNORMAL_FONT
;
125 m_brush
= *wxWHITE_BRUSH
;
127 m_graphics_changed
= true;
129 ////////////////////code here
131 m_outfile
= new wxFileOutputStream(filename
);
132 m_OK
= m_outfile
->Ok ();
135 m_filename
= filename
;
138 s
= wxT("<?xml version=\"1.0\" standalone=\"no\"?>"); s
= s
+ newline
;
140 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline
;
142 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ") + newline
;
144 s
= wxT("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ") + newline
;
146 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
);
148 s
= wxT("<title>SVG Picture created as ") + wxFileName(filename
).GetFullName() + wxT(" </title>") + newline
;
150 s
= wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion
+ wxT(" </desc>")+ newline
;
152 s
= wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline
;
157 wxSVGFileDCImpl::~wxSVGFileDCImpl()
159 wxString s
= wxT("</g> \n</svg> \n");
164 void wxSVGFileDCImpl::DoGetSizeMM( int *width
, int *height
) const
167 *width
= wxRound( (double)m_width
/ m_mm_to_pix_x
);
170 *height
= wxRound( (double)m_height
/ m_mm_to_pix_y
);
173 wxSize
wxSVGFileDCImpl::GetPPI() const
175 return wxSize( wxRound(m_dpi
), wxRound(m_dpi
) );
178 void wxSVGFileDCImpl::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
180 if (m_graphics_changed
) NewGraphics ();
182 s
.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1
,y1
,x2
,y2
);
187 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawLine Call executed"));
188 CalcBoundingBox(x1
, y1
);
189 CalcBoundingBox(x2
, y2
);
193 void wxSVGFileDCImpl::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
195 for ( int i
= 1; i
< n
; i
++ )
197 DoDrawLine ( points
[i
-1].x
+ xoffset
, points
[i
-1].y
+ yoffset
,
198 points
[ i
].x
+ xoffset
, points
[ i
].y
+ yoffset
);
202 void wxSVGFileDCImpl::DoDrawPoint (wxCoord x1
, wxCoord y1
)
205 if (m_graphics_changed
) NewGraphics ();
206 s
= wxT("<g style = \"stroke-linecap:round;\" > ") + newline
;
208 DoDrawLine ( x1
,y1
,x1
,y1
);
213 void wxSVGFileDCImpl::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
215 wxDCImpl::DoDrawCheckMark (x1
,y1
,width
,height
);
218 void wxSVGFileDCImpl::DoDrawText(const wxString
& text
, wxCoord x1
, wxCoord y1
)
220 DoDrawRotatedText(text
, x1
,y1
,0.0);
221 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawText Call executed"));
224 void wxSVGFileDCImpl::DoDrawRotatedText(const wxString
& sText
, wxCoord x
, wxCoord y
, double angle
)
226 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
227 if (m_graphics_changed
) NewGraphics ();
230 // calculate bounding box
232 DoGetTextExtent(sText
, &w
, &h
, &desc
);
234 double rad
= DegToRad(angle
);
236 // wxT("upper left") and wxT("upper right")
237 CalcBoundingBox(x
, y
);
238 CalcBoundingBox((wxCoord
)(x
+ w
*cos(rad
)), (wxCoord
)(y
- h
*sin(rad
)));
240 // wxT("bottom left") and wxT("bottom right")
241 x
+= (wxCoord
)(h
*sin(rad
));
242 y
+= (wxCoord
)(h
*cos(rad
));
243 CalcBoundingBox(x
, y
);
244 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
)), (wxCoord
)(y
+ h
*cos(rad
)));
246 if (m_backgroundMode
== wxBRUSHSTYLE_SOLID
)
248 // draw background first
249 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
251 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background"));
252 sTmp
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x
,y
+desc
-h
, w
, h
);
253 s
= sTmp
+ wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour
) + wxT("; ");
254 s
= s
+ wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour
) + wxT("; ");
255 sTmp
.Printf ( wxT("\" transform=\"rotate( %s %d %d ) \">"), NumStr(-angle
), x
,y
);
256 s
= s
+ sTmp
+ newline
;
259 //now do the text itself
260 s
.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x
,y
);
262 sTmp
= m_font
.GetFaceName ();
263 if (sTmp
.Len () > 0) s
= s
+ wxT("style=\"font-family:") + sTmp
+ wxT("; ");
264 else s
= s
+ wxT("style=\" ");
266 wxString fontweights
[3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
267 s
= s
+ wxT("font-weight:") + fontweights
[m_font
.GetWeight() - wxNORMAL
] + semicolon
+ space
;
269 wxString fontstyles
[5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
270 s
= s
+ wxT("font-style:") + fontstyles
[m_font
.GetStyle() - wxNORMAL
] + semicolon
+ space
;
272 sTmp
.Printf (wxT("font-size:%dpt; fill:#"), m_font
.GetPointSize () );
274 s
= s
+ wxColStr (m_textForegroundColour
) + wxT("; stroke:#") + wxColStr (m_textForegroundColour
) + wxT("; ");
275 sTmp
.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %s %d %d ) \" >"), NumStr(-angle
), x
,y
);
276 s
= s
+ sTmp
+ sText
+ wxT("</text> ") + newline
;
281 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawRotatedText Call executed"));
284 void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
286 DoDrawRoundedRectangle(x
, y
, width
, height
, 0);
289 void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
292 if (m_graphics_changed
) NewGraphics ();
295 s
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" "),
296 x
, y
, width
, height
, NumStr(radius
) );
298 s
= s
+ wxT(" /> ") + newline
;
301 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed"));
302 CalcBoundingBox(x
, y
);
303 CalcBoundingBox(x
+ width
, y
+ height
);
306 void wxSVGFileDCImpl::DoDrawPolygon(int n
, wxPoint points
[],
307 wxCoord xoffset
, wxCoord yoffset
,
308 wxPolygonFillMode fillStyle
)
310 if (m_graphics_changed
) NewGraphics ();
312 s
= wxT("<polygon style=\"");
313 if ( fillStyle
== wxODDEVEN_RULE
)
314 s
= s
+ wxT("fill-rule:evenodd; ");
316 s
= s
+ wxT("fill-rule:nonzero; ");
318 s
= s
+ wxT("\" \npoints=\"");
320 for (int i
= 0; i
< n
; i
++)
322 sTmp
.Printf ( wxT("%d,%d"), points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
323 s
= s
+ sTmp
+ newline
;
324 CalcBoundingBox ( points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
326 s
= s
+ wxT("\" /> ");
330 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawPolygon Call executed"));
333 void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
336 if (m_graphics_changed
) NewGraphics ();
342 s
.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x
+rw
,y
+rh
, rw
, rh
);
343 s
= s
+ wxT(" /> ") + newline
;
347 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipse Call executed"));
348 CalcBoundingBox(x
, y
);
349 CalcBoundingBox(x
+ width
, y
+ height
);
352 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
354 /* Draws an arc of a circle, centred on (xc, yc), with starting point
355 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
356 and the current brush for filling the shape.
358 The arc is drawn in an anticlockwise direction from the start point to
361 Might be better described as Pie drawing */
363 if (m_graphics_changed
) NewGraphics ();
366 // we need the radius of the circle which has two estimates
367 double r1
= sqrt ( double( (x1
-xc
)*(x1
-xc
) ) + double( (y1
-yc
)*(y1
-yc
) ) );
368 double r2
= sqrt ( double( (x2
-xc
)*(x2
-xc
) ) + double( (y2
-yc
)*(y2
-yc
) ) );
370 wxASSERT_MSG( (fabs ( r2
-r1
) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle"));
371 if ( fabs ( r2
-r1
) > 3 ) //pixels
373 s
= wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n");
377 double theta1
= atan2((double)(yc
-y1
),(double)(x1
-xc
));
378 if ( theta1
< 0 ) theta1
= theta1
+ M_PI
* 2;
379 double theta2
= atan2((double)(yc
-y2
), (double)(x2
-xc
));
380 if ( theta2
< 0 ) theta2
= theta2
+ M_PI
* 2;
381 if ( theta2
< theta1
) theta2
= theta2
+ M_PI
*2;
383 int fArc
; // flag for large or small arc 0 means less than 180 degrees
384 if ( fabs(theta2
- theta1
) > M_PI
) fArc
= 1; else fArc
= 0;
386 int fSweep
= 0; // flag for sweep always 0
388 s
.Printf ( wxT("<path d=\"M%d %d A%s %s 0.0 %d %d %d %d L%d %d z "),
389 x1
,y1
, NumStr(r1
), NumStr(r2
), fArc
, fSweep
, x2
, y2
, xc
, yc
);
391 // the z means close the path and fill
392 s
= s
+ wxT(" \" /> ") + newline
;
400 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawArc Call executed"));
403 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
406 Draws an arc of an ellipse. The current pen is used for drawing the arc
407 and the current brush is used for drawing the pie. This function is
408 currently only available for X window and PostScript device contexts.
410 x and y specify the x and y coordinates of the upper-left corner of the
411 rectangle that contains the ellipse.
413 width and height specify the width and height of the rectangle that
414 contains the ellipse.
416 start and end specify the start and end of the arc relative to the
417 three-o'clock position from the center of the rectangle. Angles are
418 specified in degrees (360 is a complete circle). Positive values mean
419 counter-clockwise motion. If start is equal to end, a complete ellipse
422 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
424 if (m_graphics_changed
) NewGraphics ();
434 double xs
, ys
, xe
, ye
;
435 xs
= xc
+ rx
* cos (DegToRad(sa
));
436 xe
= xc
+ rx
* cos (DegToRad(ea
));
437 ys
= yc
- ry
* sin (DegToRad(sa
));
438 ye
= yc
- ry
* sin (DegToRad(ea
));
440 ///now same as circle arc...
442 double theta1
= atan2(ys
-yc
, xs
-xc
);
443 double theta2
= atan2(ye
-yc
, xe
-xc
);
445 int fArc
; // flag for large or small arc 0 means less than 180 degrees
446 if ( (theta2
- theta1
) > 0 ) fArc
= 1; else fArc
= 0;
449 if ( fabs(theta2
- theta1
) > M_PI
) fSweep
= 1; else fSweep
= 0;
451 s
.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
452 int(xs
), int(ys
), int(rx
), int(ry
),
453 fArc
, fSweep
, int(xe
), int(ye
), int(xc
), int(yc
) );
456 s
= s
+ wxT(" \" /> ") + newline
;
463 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed"));
466 void wxSVGFileDCImpl::DoGetTextExtent(const wxString
& string
, wxCoord
*w
, wxCoord
*h
, wxCoord
*descent
, wxCoord
*externalLeading
, const wxFont
*font
) const
471 sDC
.SetFont (m_font
);
472 if ( font
!= NULL
) sDC
.SetFont ( *font
);
473 sDC
.GetTextExtent(string
, w
, h
, descent
, externalLeading
);
474 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetTextExtent Call executed"));
477 wxCoord
wxSVGFileDCImpl::GetCharHeight() const
481 sDC
.SetFont (m_font
);
483 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharHeight Call executing"));
484 return ( sDC
.GetCharHeight() );
488 wxCoord
wxSVGFileDCImpl::GetCharWidth() const
491 sDC
.SetFont (m_font
);
493 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharWidth Call executing"));
494 return ( sDC
.GetCharWidth() );
499 // ----------------------------------------------------------
500 // wxSVGFileDCImpl - set functions
501 // ----------------------------------------------------------
503 void wxSVGFileDCImpl::SetBackground( const wxBrush
&brush
)
506 m_backgroundBrush
= brush
;
511 void wxSVGFileDCImpl::SetBackgroundMode( int mode
)
513 m_backgroundMode
= mode
;
518 void wxSVGFileDCImpl::SetBrush(const wxBrush
& brush
)
523 m_graphics_changed
= true;
524 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetBrush Call executed"));
528 void wxSVGFileDCImpl::SetPen(const wxPen
& pen
)
530 // width, color, ends, joins : currently implemented
531 // dashes, stipple : not implemented
534 m_graphics_changed
= true;
535 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetPen Call executed"));
538 void wxSVGFileDCImpl::NewGraphics ()
541 int w
= m_pen
.GetWidth ();
542 wxColour c
= m_pen
.GetColour ();
544 wxString s
, sBrush
, sPenCap
, sPenJoin
, sPenStyle
, sLast
, sWarn
;
546 sBrush
= wxT("</g>\n<g style=\"") + wxBrushString ( m_brush
.GetColour (), m_brush
.GetStyle () )
547 + wxT(" stroke:#") + wxColStr (c
) + wxT("; ");
549 switch ( m_pen
.GetCap () )
551 case wxCAP_PROJECTING
:
552 sPenCap
= wxT("stroke-linecap:square; ");
555 sPenCap
= wxT("stroke-linecap:butt; ");
559 sPenCap
= wxT("stroke-linecap:round; ");
561 switch ( m_pen
.GetJoin () )
564 sPenJoin
= wxT("stroke-linejoin:bevel; ");
567 sPenJoin
= wxT("stroke-linejoin:miter; ");
571 sPenJoin
= wxT("stroke-linejoin:round; ");
574 switch ( m_pen
.GetStyle () )
576 case wxPENSTYLE_SOLID
:
577 sPenStyle
= wxT("stroke-opacity:1.0; stroke-opacity:1.0; ");
579 case wxPENSTYLE_TRANSPARENT
:
580 sPenStyle
= wxT("stroke-opacity:0.0; stroke-opacity:0.0; ");
583 wxASSERT_MSG(false, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available"));
584 sWarn
= sWarn
+ wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n");
587 sLast
.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%s %s) scale(%s %s)\">"),
588 w
, NumStr(m_logicalOriginX
), NumStr(m_logicalOriginY
), NumStr(m_scaleX
), NumStr(m_scaleY
) );
590 s
= sBrush
+ sPenCap
+ sPenJoin
+ sPenStyle
+ sLast
+ newline
+ sWarn
;
592 m_graphics_changed
= false;
593 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::NewGraphics Call executed"));
597 void wxSVGFileDCImpl::SetFont(const wxFont
& font
)
602 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetFont Call executed"));
605 // export a bitmap as a raster image in png
606 bool wxSVGFileDCImpl::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
607 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
608 wxRasterOperationMode logicalFunc
/*= wxCOPY*/, bool useMask
/*= false*/,
609 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
611 if (logicalFunc
!= wxCOPY
)
613 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible"));
616 if (useMask
!= false)
618 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested false mask; this is not possible"));
621 wxBitmap
myBitmap (width
, height
);
623 memDC
.SelectObject( myBitmap
);
624 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
625 memDC
.SelectObject( wxNullBitmap
);
626 DoDrawBitmap(myBitmap
, xdest
, ydest
);
627 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoBlit Call executed"));
631 void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
633 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() );
635 memDC
.SelectObject( myBitmap
);
636 memDC
.DrawIcon(myIcon
,0,0);
637 memDC
.SelectObject( wxNullBitmap
);
638 DoDrawBitmap(myBitmap
, x
, y
);
639 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawIcon Call executed"));
643 void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
645 if (m_graphics_changed
) NewGraphics ();
647 wxString sTmp
, s
, sPNG
;
648 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) == NULL
)
649 wxImage::AddHandler(new wxPNGHandler
);
651 // create suitable file name
652 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
653 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
654 while (wxFile::Exists(sPNG
) )
657 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
658 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
661 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
662 wxBitmap myBitmap
= bmp
;
664 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
666 // reference the bitmap from the SVG doc
667 // only use filename & ext
668 sPNG
= sPNG
.AfterLast(wxFileName::GetPathSeparator());
670 // reference the bitmap from the SVG doc
671 int w
= myBitmap
.GetWidth();
672 int h
= myBitmap
.GetHeight();
673 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
675 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
676 s
= s
+ sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + newline
;
682 m_OK
= m_outfile
->Ok () && bPNG_OK
;
683 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawBitmap Call executed"));
688 void wxSVGFileDCImpl::write(const wxString
&s
)
690 const wxCharBuffer buf
= s
.utf8_str();
691 m_outfile
->Write(buf
, strlen((const char *)buf
));
692 m_OK
= m_outfile
->Ok();