]>
git.saurik.com Git - wxWidgets.git/blob - src/common/dcsvg.cpp
1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Chris Elliott
7 // Licence: wxWindows license
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"
30 #define wxSVG_DEBUG FALSE
31 // or TRUE to see the calls being executed
33 #define newline wxString(wxT("\n"))
34 #define space wxString(wxT(" "))
35 #define semicolon wxString(wxT(";"))
36 #define wx_round(a) (int)((a)+.5)
38 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
40 wxString
wxColStr ( wxColour c
)
42 unsigned char r
, g
, b
;
47 // possible Unicode bug here
48 wxString s
= wxDecToHex(r
) + wxDecToHex(g
) + wxDecToHex(b
) ;
53 wxString
wxBrushString ( wxColour c
, int style
)
55 wxString s
= wxT("fill:#") + wxColStr (c
) + semicolon
+ space
;
58 case wxBRUSHSTYLE_SOLID
:
59 s
= s
+ wxT("fill-opacity:1.0; ");
61 case wxBRUSHSTYLE_TRANSPARENT
:
62 s
= s
+ wxT("fill-opacity:0.0; ");
66 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::Requested Brush Style not available")) ;
73 // ----------------------------------------------------------
75 // ----------------------------------------------------------
77 IMPLEMENT_ABSTRACT_CLASS(wxSVGFileDCImpl
, wxDC
)
79 wxSVGFileDCImpl::wxSVGFileDCImpl( wxSVGFileDC
*owner
, const wxString
&filename
,
80 int width
, int height
, double dpi
) :
83 Init( filename
, width
, height
, dpi
);
86 void wxSVGFileDCImpl::Init (const wxString
&filename
, int Width
, int Height
, double dpi
)
95 m_mm_to_pix_x
= dpi
/25.4;
96 m_mm_to_pix_y
= dpi
/25.4;
98 m_backgroundBrush
= *wxTRANSPARENT_BRUSH
;
99 m_textForegroundColour
= *wxBLACK
;
100 m_textBackgroundColour
= *wxWHITE
;
101 m_colour
= wxColourDisplay();
103 m_pen
= *wxBLACK_PEN
;
104 m_font
= *wxNORMAL_FONT
;
105 m_brush
= *wxWHITE_BRUSH
;
107 m_graphics_changed
= TRUE
;
109 ////////////////////code here
111 m_outfile
= new wxFileOutputStream(filename
) ;
112 m_OK
= m_outfile
->Ok ();
115 m_filename
= filename
;
118 s
= wxT("<?xml version=\"1.0\" standalone=\"no\"?>") ; s
= s
+ newline
;
120 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline
;
122 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ") + newline
;
124 s
= wxT("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ") + newline
;
126 s
.Printf( wxT(" width=\"%.2gcm\" height=\"%.2gcm\" viewBox=\"0 0 %d %d \"> \n"), float(Width
)/dpi
*2.54, float(Height
)/dpi
*2.54, Width
, Height
);
128 s
= wxT("<title>SVG Picture created as ") + wxFileNameFromPath(filename
) + wxT(" </title>") + newline
;
130 s
= wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion
+ wxT(" </desc>")+ newline
;
132 s
= wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline
;
140 wxSVGFileDCImpl::~wxSVGFileDCImpl()
142 wxString s
= wxT("</g> \n</svg> \n") ;
147 void wxSVGFileDCImpl::DoGetSizeMM( int *width
, int *height
) const
150 *width
= wxRound( (double)m_width
/ m_mm_to_pix_x
);
153 *height
= wxRound( (double)m_height
/ m_mm_to_pix_y
);
156 wxSize
wxSVGFileDCImpl::GetPPI() const
158 return wxSize( wxRound(m_dpi
), wxRound(m_dpi
) );
161 void wxSVGFileDCImpl::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
163 if (m_graphics_changed
) NewGraphics ();
165 s
.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1
,y1
,x2
,y2
);
170 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawLine Call executed")) ;
171 CalcBoundingBox(x1
, y1
) ;
172 CalcBoundingBox(x2
, y2
) ;
176 void wxSVGFileDCImpl::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
178 for ( int i
= 1; i
< n
; i
++ )
180 DoDrawLine ( points
[i
-1].x
+ xoffset
, points
[i
-1].y
+ yoffset
,
181 points
[ i
].x
+ xoffset
, points
[ i
].y
+ yoffset
) ;
186 void wxSVGFileDCImpl::DoDrawPoint (wxCoord x1
, wxCoord y1
)
189 if (m_graphics_changed
) NewGraphics ();
190 s
= wxT("<g style = \"stroke-linecap:round;\" > ") + newline
;
192 DoDrawLine ( x1
,y1
,x1
,y1
);
198 void wxSVGFileDCImpl::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
200 wxDCImpl::DoDrawCheckMark (x1
,y1
,width
,height
) ;
204 void wxSVGFileDCImpl::DoDrawText(const wxString
& text
, wxCoord x1
, wxCoord y1
)
206 DoDrawRotatedText(text
, x1
,y1
,0.0);
207 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawText Call executed")) ;
211 void wxSVGFileDCImpl::DoDrawRotatedText(const wxString
& sText
, wxCoord x
, wxCoord y
, double angle
)
213 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
214 if (m_graphics_changed
) NewGraphics ();
217 // calculate bounding box
219 DoGetTextExtent(sText
, &w
, &h
, &desc
);
221 double rad
= DegToRad(angle
);
223 // wxT("upper left") and wxT("upper right")
224 CalcBoundingBox(x
, y
);
225 CalcBoundingBox((wxCoord
)(x
+ w
*cos(rad
)), (wxCoord
)(y
- h
*sin(rad
)));
227 // wxT("bottom left") and wxT("bottom right")
228 x
+= (wxCoord
)(h
*sin(rad
));
229 y
+= (wxCoord
)(h
*cos(rad
));
230 CalcBoundingBox(x
, y
);
231 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
)), (wxCoord
)(y
+ h
*cos(rad
)));
233 if (m_backgroundMode
== wxBRUSHSTYLE_SOLID
)
235 // draw background first
236 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
238 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ;
239 sTmp
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x
,y
+desc
-h
, w
, h
);
240 s
= sTmp
+ wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour
) + wxT("; ") ;
241 s
= s
+ wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour
) + wxT("; ") ;
242 sTmp
.Printf ( wxT("\" transform=\"rotate( %.2g %d %d ) \">"), -angle
, x
,y
) ;
243 s
= s
+ sTmp
+ newline
;
246 //now do the text itself
247 s
.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x
,y
);
249 sTmp
= m_font
.GetFaceName () ;
250 if (sTmp
.Len () > 0) s
= s
+ wxT("style=\"font-family:") + sTmp
+ wxT("; ");
251 else s
= s
+ wxT("style=\" ") ;
253 wxString fontweights
[3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
254 s
= s
+ wxT("font-weight:") + fontweights
[m_font
.GetWeight() - wxNORMAL
] + semicolon
+ space
;
256 wxString fontstyles
[5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
257 s
= s
+ wxT("font-style:") + fontstyles
[m_font
.GetStyle() - wxNORMAL
] + semicolon
+ space
;
259 sTmp
.Printf (wxT("font-size:%dpt; fill:#"), m_font
.GetPointSize () );
261 s
= s
+ wxColStr (m_textForegroundColour
) + wxT("; stroke:#") + wxColStr (m_textForegroundColour
) + wxT("; ") ;
262 sTmp
.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle
, x
,y
) ;
263 s
= s
+ sTmp
+ sText
+ wxT("</text> ") + newline
;
268 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
273 void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
275 DoDrawRoundedRectangle(x
, y
, width
, height
, 0) ;
279 void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
282 if (m_graphics_changed
) NewGraphics ();
285 s
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "),
286 x
, y
, width
, height
, radius
);
288 s
= s
+ wxT(" /> ") + newline
;
291 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ;
292 CalcBoundingBox(x
, y
) ;
293 CalcBoundingBox(x
+ width
, y
+ height
) ;
298 void wxSVGFileDCImpl::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
,int fillStyle
)
300 if (m_graphics_changed
) NewGraphics ();
302 s
= wxT("<polygon style=\"") ;
303 if ( fillStyle
== wxODDEVEN_RULE
)
304 s
= s
+ wxT("fill-rule:evenodd; ");
306 s
= s
+ wxT("fill-rule:nonzero; ");
308 s
= s
+ wxT("\" \npoints=\"") ;
310 for (int i
= 0; i
< n
; i
++)
312 sTmp
.Printf ( wxT("%d,%d"), points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
313 s
= s
+ sTmp
+ newline
;
314 CalcBoundingBox ( points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
316 s
= s
+ wxT("\" /> ") ;
320 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
324 void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
327 if (m_graphics_changed
) NewGraphics ();
333 s
.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x
+rw
,y
+rh
, rw
, rh
);
334 s
= s
+ wxT(" /> ") + newline
;
338 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
339 CalcBoundingBox(x
, y
) ;
340 CalcBoundingBox(x
+ width
, y
+ height
) ;
344 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
346 /* Draws an arc of a circle, centred on (xc, yc), with starting point
347 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
348 and the current brush for filling the shape.
350 The arc is drawn in an anticlockwise direction from the start point to
353 Might be better described as Pie drawing */
355 if (m_graphics_changed
) NewGraphics ();
358 // we need the radius of the circle which has two estimates
359 double r1
= sqrt ( double( (x1
-xc
)*(x1
-xc
) ) + double( (y1
-yc
)*(y1
-yc
) ) );
360 double r2
= sqrt ( double( (x2
-xc
)*(x2
-xc
) ) + double( (y2
-yc
)*(y2
-yc
) ) );
362 wxASSERT_MSG( (fabs ( r2
-r1
) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ;
363 if ( fabs ( r2
-r1
) > 3 ) //pixels
365 s
= wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n") ;
369 double theta1
= atan2((double)(yc
-y1
),(double)(x1
-xc
));
370 if ( theta1
< 0 ) theta1
= theta1
+ M_PI
* 2;
371 double theta2
= atan2((double)(yc
-y2
), (double)(x2
-xc
));
372 if ( theta2
< 0 ) theta2
= theta2
+ M_PI
* 2;
373 if ( theta2
< theta1
) theta2
= theta2
+ M_PI
*2 ;
375 int fArc
; // flag for large or small arc 0 means less than 180 degrees
376 if ( fabs(theta2
- theta1
) > M_PI
) fArc
= 1; else fArc
= 0 ;
378 int fSweep
= 0 ; // flag for sweep always 0
380 s
.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
381 x1
,y1
, r1
, r2
, fArc
, fSweep
, x2
, y2
, xc
, yc
);
383 // the z means close the path and fill
384 s
= s
+ wxT(" \" /> ") + newline
;
392 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
396 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
399 Draws an arc of an ellipse. The current pen is used for drawing the arc
400 and the current brush is used for drawing the pie. This function is
401 currently only available for X window and PostScript device contexts.
403 x and y specify the x and y coordinates of the upper-left corner of the
404 rectangle that contains the ellipse.
406 width and height specify the width and height of the rectangle that
407 contains the ellipse.
409 start and end specify the start and end of the arc relative to the
410 three-o'clock position from the center of the rectangle. Angles are
411 specified in degrees (360 is a complete circle). Positive values mean
412 counter-clockwise motion. If start is equal to end, a complete ellipse
415 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
417 if (m_graphics_changed
) NewGraphics ();
427 double xs
, ys
, xe
, ye
;
428 xs
= xc
+ rx
* cos (DegToRad(sa
)) ;
429 xe
= xc
+ rx
* cos (DegToRad(ea
)) ;
430 ys
= yc
- ry
* sin (DegToRad(sa
)) ;
431 ye
= yc
- ry
* sin (DegToRad(ea
)) ;
433 ///now same as circle arc...
435 double theta1
= atan2(ys
-yc
, xs
-xc
);
436 double theta2
= atan2(ye
-yc
, xe
-xc
);
438 int fArc
; // flag for large or small arc 0 means less than 180 degrees
439 if ( (theta2
- theta1
) > 0 ) fArc
= 1; else fArc
= 0 ;
442 if ( fabs(theta2
- theta1
) > M_PI
) fSweep
= 1; else fSweep
= 0 ;
444 s
.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
445 int(xs
), int(ys
), int(rx
), int(ry
),
446 fArc
, fSweep
, int(xe
), int(ye
), int(xc
), int(yc
) );
449 s
= s
+ wxT(" \" /> ") + newline
;
456 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ;
460 void wxSVGFileDCImpl::DoGetTextExtent(const wxString
& string
, wxCoord
*w
, wxCoord
*h
, wxCoord
*descent
, wxCoord
*externalLeading
, const wxFont
*font
) const
465 sDC
.SetFont (m_font
);
466 if ( font
!= NULL
) sDC
.SetFont ( *font
);
467 sDC
.GetTextExtent(string
, w
, h
, descent
, externalLeading
);
468 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetTextExtent Call executed")) ;
472 wxCoord
wxSVGFileDCImpl::GetCharHeight() const
476 sDC
.SetFont (m_font
);
478 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
479 return ( sDC
.GetCharHeight() );
484 wxCoord
wxSVGFileDCImpl::GetCharWidth() const
487 sDC
.SetFont (m_font
);
489 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharWidth Call executing")) ;
490 return ( sDC
.GetCharWidth() ) ;
495 /// Set Functions /////////////////////////////////////////////////////////////////
496 void wxSVGFileDCImpl::SetBackground( const wxBrush
&brush
)
499 m_backgroundBrush
= brush
;
504 void wxSVGFileDCImpl::SetBackgroundMode( int mode
)
506 m_backgroundMode
= mode
;
511 void wxSVGFileDCImpl::SetBrush(const wxBrush
& brush
)
516 m_graphics_changed
= TRUE
;
517 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetBrush Call executed")) ;
521 void wxSVGFileDCImpl::SetPen(const wxPen
& pen
)
523 // width, color, ends, joins : currently implemented
524 // dashes, stipple : not implemented
527 m_graphics_changed
= TRUE
;
528 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetPen Call executed")) ;
531 void wxSVGFileDCImpl::NewGraphics ()
534 int w
= m_pen
.GetWidth ();
535 wxColour c
= m_pen
.GetColour () ;
537 wxString s
, sBrush
, sPenCap
, sPenJoin
, sPenStyle
, sLast
, sWarn
;
539 sBrush
= wxT("</g>\n<g style=\"") + wxBrushString ( m_brush
.GetColour (), m_brush
.GetStyle () )
540 + wxT(" stroke:#") + wxColStr (c
) + wxT("; ") ;
542 switch ( m_pen
.GetCap () )
544 case wxCAP_PROJECTING
:
545 sPenCap
= wxT("stroke-linecap:square; ") ;
548 sPenCap
= wxT("stroke-linecap:butt; ") ;
552 sPenCap
= wxT("stroke-linecap:round; ") ;
554 switch ( m_pen
.GetJoin () )
557 sPenJoin
= wxT("stroke-linejoin:bevel; ") ;
560 sPenJoin
= wxT("stroke-linejoin:miter; ") ;
564 sPenJoin
= wxT("stroke-linejoin:round; ") ;
567 switch ( m_pen
.GetStyle () )
569 case wxPENSTYLE_SOLID
:
570 sPenStyle
= wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
572 case wxPENSTYLE_TRANSPARENT
:
573 sPenStyle
= wxT("stroke-opacity:0.0; stroke-opacity:0.0; ") ;
576 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available")) ;
577 sWarn
= sWarn
+ wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n") ;
580 sLast
.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
581 w
, (double)m_logicalOriginX
, m_logicalOriginY
, m_scaleX
, m_scaleY
);
583 s
= sBrush
+ sPenCap
+ sPenJoin
+ sPenStyle
+ sLast
+ newline
+ sWarn
;
585 m_graphics_changed
= FALSE
;
586 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::NewGraphics Call executed")) ;
590 void wxSVGFileDCImpl::SetFont(const wxFont
& font
)
595 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetFont Call executed")) ;
599 // export a bitmap as a raster image in png
600 bool wxSVGFileDCImpl::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
601 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
602 int logicalFunc
/*= wxCOPY*/, bool useMask
/*= FALSE*/,
603 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
605 if (logicalFunc
!= wxCOPY
)
607 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
610 if (useMask
!= FALSE
)
612 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
615 wxBitmap
myBitmap (width
, height
) ;
617 memDC
.SelectObject( myBitmap
);
618 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
619 memDC
.SelectObject( wxNullBitmap
);
620 DoDrawBitmap(myBitmap
, xdest
, ydest
);
621 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoBlit Call executed")) ;
625 void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
627 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() ) ;
629 memDC
.SelectObject( myBitmap
);
630 memDC
.DrawIcon(myIcon
,0,0);
631 memDC
.SelectObject( wxNullBitmap
);
632 DoDrawBitmap(myBitmap
, x
, y
);
633 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
637 void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
639 if (m_graphics_changed
) NewGraphics ();
641 wxString sTmp
, s
, sPNG
;
642 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) == NULL
)
643 wxImage::AddHandler(new wxPNGHandler
);
645 // create suitable file name
646 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
647 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
648 while (wxFile::Exists(sPNG
) )
651 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
652 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
655 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
656 wxBitmap myBitmap
= bmp
;
658 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
660 // refrence the bitmap from the SVG doc
661 int w
= myBitmap
.GetWidth();
662 int h
= myBitmap
.GetHeight();
663 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
665 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
666 s
= s
+ sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + newline
;
672 m_OK
= m_outfile
->Ok () && bPNG_OK
;
673 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
678 void wxSVGFileDCImpl::write(const wxString
&s
)
680 const wxCharBuffer buf
= s
.utf8_str();
681 m_outfile
->Write(buf
, strlen((const char *)buf
));
682 m_OK
= m_outfile
->Ok();