]>
git.saurik.com Git - wxWidgets.git/blob - src/common/dcsvg.cpp
15781af016d53e8c34344bd25c9deb52257ea746
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"
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)
39 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
41 wxString
wxColStr ( wxColour c
)
43 unsigned char r
, g
, b
;
48 // possible Unicode bug here
49 wxString s
= wxDecToHex(r
) + wxDecToHex(g
) + wxDecToHex(b
) ;
54 wxString
wxBrushString ( wxColour c
, int style
)
56 wxString s
= wxT("fill:#") + wxColStr (c
) + semicolon
+ space
;
59 case wxBRUSHSTYLE_SOLID
:
60 s
= s
+ wxT("fill-opacity:1.0; ");
62 case wxBRUSHSTYLE_TRANSPARENT
:
63 s
= s
+ wxT("fill-opacity:0.0; ");
67 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::Requested Brush Style not available")) ;
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\"?>") ; s
= s
+ newline
;
121 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline
;
123 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ") + newline
;
125 s
= wxT("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ") + newline
;
127 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
);
129 s
= wxT("<title>SVG Picture created as ") + wxFileNameFromPath(filename
) + wxT(" </title>") + newline
;
131 s
= wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion
+ wxT(" </desc>")+ newline
;
133 s
= wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline
;
141 wxSVGFileDCImpl::~wxSVGFileDCImpl()
143 wxString s
= wxT("</g> \n</svg> \n") ;
148 void wxSVGFileDCImpl::DoGetSizeMM( int *width
, int *height
) const
151 *width
= wxRound( (double)m_width
/ m_mm_to_pix_x
);
154 *height
= wxRound( (double)m_height
/ m_mm_to_pix_y
);
157 wxSize
wxSVGFileDCImpl::GetPPI() const
159 return wxSize( wxRound(m_dpi
), wxRound(m_dpi
) );
162 void wxSVGFileDCImpl::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
164 if (m_graphics_changed
) NewGraphics ();
166 s
.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1
,y1
,x2
,y2
);
171 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawLine Call executed")) ;
172 CalcBoundingBox(x1
, y1
) ;
173 CalcBoundingBox(x2
, y2
) ;
177 void wxSVGFileDCImpl::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
179 for ( int i
= 1; i
< n
; i
++ )
181 DoDrawLine ( points
[i
-1].x
+ xoffset
, points
[i
-1].y
+ yoffset
,
182 points
[ i
].x
+ xoffset
, points
[ i
].y
+ yoffset
) ;
187 void wxSVGFileDCImpl::DoDrawPoint (wxCoord x1
, wxCoord y1
)
190 if (m_graphics_changed
) NewGraphics ();
191 s
= wxT("<g style = \"stroke-linecap:round;\" > ") + newline
;
193 DoDrawLine ( x1
,y1
,x1
,y1
);
199 void wxSVGFileDCImpl::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
201 wxDCImpl::DoDrawCheckMark (x1
,y1
,width
,height
) ;
205 void wxSVGFileDCImpl::DoDrawText(const wxString
& text
, wxCoord x1
, wxCoord y1
)
207 DoDrawRotatedText(text
, x1
,y1
,0.0);
208 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawText Call executed")) ;
212 void wxSVGFileDCImpl::DoDrawRotatedText(const wxString
& sText
, wxCoord x
, wxCoord y
, double angle
)
214 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
215 if (m_graphics_changed
) NewGraphics ();
218 // calculate bounding box
220 DoGetTextExtent(sText
, &w
, &h
, &desc
);
222 double rad
= DegToRad(angle
);
224 // wxT("upper left") and wxT("upper right")
225 CalcBoundingBox(x
, y
);
226 CalcBoundingBox((wxCoord
)(x
+ w
*cos(rad
)), (wxCoord
)(y
- h
*sin(rad
)));
228 // wxT("bottom left") and wxT("bottom right")
229 x
+= (wxCoord
)(h
*sin(rad
));
230 y
+= (wxCoord
)(h
*cos(rad
));
231 CalcBoundingBox(x
, y
);
232 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
)), (wxCoord
)(y
+ h
*cos(rad
)));
234 if (m_backgroundMode
== wxBRUSHSTYLE_SOLID
)
236 // draw background first
237 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
239 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ;
240 sTmp
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x
,y
+desc
-h
, w
, h
);
241 s
= sTmp
+ wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour
) + wxT("; ") ;
242 s
= s
+ wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour
) + wxT("; ") ;
243 sTmp
.Printf ( wxT("\" transform=\"rotate( %.2g %d %d ) \">"), -angle
, x
,y
) ;
244 s
= s
+ sTmp
+ newline
;
247 //now do the text itself
248 s
.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x
,y
);
250 sTmp
= m_font
.GetFaceName () ;
251 if (sTmp
.Len () > 0) s
= s
+ wxT("style=\"font-family:") + sTmp
+ wxT("; ");
252 else s
= s
+ wxT("style=\" ") ;
254 wxString fontweights
[3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
255 s
= s
+ wxT("font-weight:") + fontweights
[m_font
.GetWeight() - wxNORMAL
] + semicolon
+ space
;
257 wxString fontstyles
[5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
258 s
= s
+ wxT("font-style:") + fontstyles
[m_font
.GetStyle() - wxNORMAL
] + semicolon
+ space
;
260 sTmp
.Printf (wxT("font-size:%dpt; fill:#"), m_font
.GetPointSize () );
262 s
= s
+ wxColStr (m_textForegroundColour
) + wxT("; stroke:#") + wxColStr (m_textForegroundColour
) + wxT("; ") ;
263 sTmp
.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle
, x
,y
) ;
264 s
= s
+ sTmp
+ sText
+ wxT("</text> ") + newline
;
269 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
274 void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
276 DoDrawRoundedRectangle(x
, y
, width
, height
, 0) ;
280 void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
283 if (m_graphics_changed
) NewGraphics ();
286 s
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "),
287 x
, y
, width
, height
, radius
);
289 s
= s
+ wxT(" /> ") + newline
;
292 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ;
293 CalcBoundingBox(x
, y
) ;
294 CalcBoundingBox(x
+ width
, y
+ height
) ;
299 void wxSVGFileDCImpl::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
,int fillStyle
)
301 if (m_graphics_changed
) NewGraphics ();
303 s
= wxT("<polygon style=\"") ;
304 if ( fillStyle
== wxODDEVEN_RULE
)
305 s
= s
+ wxT("fill-rule:evenodd; ");
307 s
= s
+ wxT("fill-rule:nonzero; ");
309 s
= s
+ wxT("\" \npoints=\"") ;
311 for (int i
= 0; i
< n
; i
++)
313 sTmp
.Printf ( wxT("%d,%d"), points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
314 s
= s
+ sTmp
+ newline
;
315 CalcBoundingBox ( points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
317 s
= s
+ wxT("\" /> ") ;
321 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
325 void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
328 if (m_graphics_changed
) NewGraphics ();
334 s
.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x
+rw
,y
+rh
, rw
, rh
);
335 s
= s
+ wxT(" /> ") + newline
;
339 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
340 CalcBoundingBox(x
, y
) ;
341 CalcBoundingBox(x
+ width
, y
+ height
) ;
345 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
347 /* Draws an arc of a circle, centred on (xc, yc), with starting point
348 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
349 and the current brush for filling the shape.
351 The arc is drawn in an anticlockwise direction from the start point to
354 Might be better described as Pie drawing */
356 if (m_graphics_changed
) NewGraphics ();
359 // we need the radius of the circle which has two estimates
360 double r1
= sqrt ( double( (x1
-xc
)*(x1
-xc
) ) + double( (y1
-yc
)*(y1
-yc
) ) );
361 double r2
= sqrt ( double( (x2
-xc
)*(x2
-xc
) ) + double( (y2
-yc
)*(y2
-yc
) ) );
363 wxASSERT_MSG( (fabs ( r2
-r1
) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ;
364 if ( fabs ( r2
-r1
) > 3 ) //pixels
366 s
= wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n") ;
370 double theta1
= atan2((double)(yc
-y1
),(double)(x1
-xc
));
371 if ( theta1
< 0 ) theta1
= theta1
+ M_PI
* 2;
372 double theta2
= atan2((double)(yc
-y2
), (double)(x2
-xc
));
373 if ( theta2
< 0 ) theta2
= theta2
+ M_PI
* 2;
374 if ( theta2
< theta1
) theta2
= theta2
+ M_PI
*2 ;
376 int fArc
; // flag for large or small arc 0 means less than 180 degrees
377 if ( fabs(theta2
- theta1
) > M_PI
) fArc
= 1; else fArc
= 0 ;
379 int fSweep
= 0 ; // flag for sweep always 0
381 s
.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
382 x1
,y1
, r1
, r2
, fArc
, fSweep
, x2
, y2
, xc
, yc
);
384 // the z means close the path and fill
385 s
= s
+ wxT(" \" /> ") + newline
;
393 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
397 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
400 Draws an arc of an ellipse. The current pen is used for drawing the arc
401 and the current brush is used for drawing the pie. This function is
402 currently only available for X window and PostScript device contexts.
404 x and y specify the x and y coordinates of the upper-left corner of the
405 rectangle that contains the ellipse.
407 width and height specify the width and height of the rectangle that
408 contains the ellipse.
410 start and end specify the start and end of the arc relative to the
411 three-o'clock position from the center of the rectangle. Angles are
412 specified in degrees (360 is a complete circle). Positive values mean
413 counter-clockwise motion. If start is equal to end, a complete ellipse
416 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
418 if (m_graphics_changed
) NewGraphics ();
428 double xs
, ys
, xe
, ye
;
429 xs
= xc
+ rx
* cos (DegToRad(sa
)) ;
430 xe
= xc
+ rx
* cos (DegToRad(ea
)) ;
431 ys
= yc
- ry
* sin (DegToRad(sa
)) ;
432 ye
= yc
- ry
* sin (DegToRad(ea
)) ;
434 ///now same as circle arc...
436 double theta1
= atan2(ys
-yc
, xs
-xc
);
437 double theta2
= atan2(ye
-yc
, xe
-xc
);
439 int fArc
; // flag for large or small arc 0 means less than 180 degrees
440 if ( (theta2
- theta1
) > 0 ) fArc
= 1; else fArc
= 0 ;
443 if ( fabs(theta2
- theta1
) > M_PI
) fSweep
= 1; else fSweep
= 0 ;
445 s
.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
446 int(xs
), int(ys
), int(rx
), int(ry
),
447 fArc
, fSweep
, int(xe
), int(ye
), int(xc
), int(yc
) );
450 s
= s
+ wxT(" \" /> ") + newline
;
457 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ;
461 void wxSVGFileDCImpl::DoGetTextExtent(const wxString
& string
, wxCoord
*w
, wxCoord
*h
, wxCoord
*descent
, wxCoord
*externalLeading
, const wxFont
*font
) const
466 sDC
.SetFont (m_font
);
467 if ( font
!= NULL
) sDC
.SetFont ( *font
);
468 sDC
.GetTextExtent(string
, w
, h
, descent
, externalLeading
);
469 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetTextExtent Call executed")) ;
473 wxCoord
wxSVGFileDCImpl::GetCharHeight() const
477 sDC
.SetFont (m_font
);
479 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
480 return ( sDC
.GetCharHeight() );
485 wxCoord
wxSVGFileDCImpl::GetCharWidth() const
488 sDC
.SetFont (m_font
);
490 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharWidth Call executing")) ;
491 return ( sDC
.GetCharWidth() ) ;
496 /// Set Functions /////////////////////////////////////////////////////////////////
497 void wxSVGFileDCImpl::SetBackground( const wxBrush
&brush
)
500 m_backgroundBrush
= brush
;
505 void wxSVGFileDCImpl::SetBackgroundMode( int mode
)
507 m_backgroundMode
= mode
;
512 void wxSVGFileDCImpl::SetBrush(const wxBrush
& brush
)
517 m_graphics_changed
= TRUE
;
518 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetBrush Call executed")) ;
522 void wxSVGFileDCImpl::SetPen(const wxPen
& pen
)
524 // width, color, ends, joins : currently implemented
525 // dashes, stipple : not implemented
528 m_graphics_changed
= TRUE
;
529 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetPen Call executed")) ;
532 void wxSVGFileDCImpl::NewGraphics ()
535 int w
= m_pen
.GetWidth ();
536 wxColour c
= m_pen
.GetColour () ;
538 wxString s
, sBrush
, sPenCap
, sPenJoin
, sPenStyle
, sLast
, sWarn
;
540 sBrush
= wxT("</g>\n<g style=\"") + wxBrushString ( m_brush
.GetColour (), m_brush
.GetStyle () )
541 + wxT(" stroke:#") + wxColStr (c
) + wxT("; ") ;
543 switch ( m_pen
.GetCap () )
545 case wxCAP_PROJECTING
:
546 sPenCap
= wxT("stroke-linecap:square; ") ;
549 sPenCap
= wxT("stroke-linecap:butt; ") ;
553 sPenCap
= wxT("stroke-linecap:round; ") ;
555 switch ( m_pen
.GetJoin () )
558 sPenJoin
= wxT("stroke-linejoin:bevel; ") ;
561 sPenJoin
= wxT("stroke-linejoin:miter; ") ;
565 sPenJoin
= wxT("stroke-linejoin:round; ") ;
568 switch ( m_pen
.GetStyle () )
570 case wxPENSTYLE_SOLID
:
571 sPenStyle
= wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
573 case wxPENSTYLE_TRANSPARENT
:
574 sPenStyle
= wxT("stroke-opacity:0.0; stroke-opacity:0.0; ") ;
577 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available")) ;
578 sWarn
= sWarn
+ wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n") ;
581 sLast
.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
582 w
, (double)m_logicalOriginX
, m_logicalOriginY
, m_scaleX
, m_scaleY
);
584 s
= sBrush
+ sPenCap
+ sPenJoin
+ sPenStyle
+ sLast
+ newline
+ sWarn
;
586 m_graphics_changed
= FALSE
;
587 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::NewGraphics Call executed")) ;
591 void wxSVGFileDCImpl::SetFont(const wxFont
& font
)
596 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetFont Call executed")) ;
600 // export a bitmap as a raster image in png
601 bool wxSVGFileDCImpl::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
602 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
603 int logicalFunc
/*= wxCOPY*/, bool useMask
/*= FALSE*/,
604 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
606 if (logicalFunc
!= wxCOPY
)
608 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
611 if (useMask
!= FALSE
)
613 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
616 wxBitmap
myBitmap (width
, height
) ;
618 memDC
.SelectObject( myBitmap
);
619 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
620 memDC
.SelectObject( wxNullBitmap
);
621 DoDrawBitmap(myBitmap
, xdest
, ydest
);
622 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoBlit Call executed")) ;
626 void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
628 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() ) ;
630 memDC
.SelectObject( myBitmap
);
631 memDC
.DrawIcon(myIcon
,0,0);
632 memDC
.SelectObject( wxNullBitmap
);
633 DoDrawBitmap(myBitmap
, x
, y
);
634 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
638 void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
640 if (m_graphics_changed
) NewGraphics ();
642 wxString sTmp
, s
, sPNG
;
643 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG
) == NULL
)
644 wxImage::AddHandler(new wxPNGHandler
);
646 // create suitable file name
647 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
648 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
649 while (wxFile::Exists(sPNG
) )
652 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
653 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
656 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
657 wxBitmap myBitmap
= bmp
;
659 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
661 // reference the bitmap from the SVG doc
662 // only use filename & ext
663 sPNG
= sPNG
.AfterLast(wxFileName::GetPathSeparator());
665 // refrence the bitmap from the SVG doc
666 int w
= myBitmap
.GetWidth();
667 int h
= myBitmap
.GetHeight();
668 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
670 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
671 s
= s
+ sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + newline
;
677 m_OK
= m_outfile
->Ok () && bPNG_OK
;
678 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
683 void wxSVGFileDCImpl::write(const wxString
&s
)
685 const wxCharBuffer buf
= s
.utf8_str();
686 m_outfile
->Write(buf
, strlen((const char *)buf
));
687 m_OK
= m_outfile
->Ok();