]>
git.saurik.com Git - wxWidgets.git/blob - contrib/src/svg/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"
22 #include "wx/svg/dcsvg.h"
26 #define wxSVG_DEBUG FALSE
27 // or TRUE to see the calls being executed
28 #define newline wxString(wxT("\n"))
29 #define space wxString(wxT(" "))
30 #define semicolon wxString(wxT(";"))
31 #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
;
59 s
= s
+ wxT("fill-opacity:1.0; ");
62 s
= s
+ wxT("fill-opacity:0.0; ");
66 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::Requested Brush Style not available")) ;
74 void wxSVGFileDC::Init (wxString f
, int Width
, int Height
, float dpi
)
77 //set up things first wxDCBase does all this?
84 m_mm_to_pix_x
= dpi
/25.4;
85 m_mm_to_pix_y
= dpi
/25.4;
87 m_signX
= m_signY
= 1;
89 m_userScaleX
= m_userScaleY
=
90 m_deviceOriginX
= m_deviceOriginY
= 0;
92 m_OriginX
= m_OriginY
= 0;
93 m_logicalOriginX
= m_logicalOriginY
= 0;
94 m_logicalScaleX
= m_logicalScaleY
= 0 ;
95 m_scaleX
= m_scaleY
= 1.0 ;
97 m_logicalFunction
= wxCOPY
;
98 m_backgroundMode
= wxTRANSPARENT
;
99 m_mappingMode
= wxMM_TEXT
;
101 m_backgroundBrush
= *wxTRANSPARENT_BRUSH
;
102 m_textForegroundColour
= *wxBLACK
;
103 m_textBackgroundColour
= *wxWHITE
;
104 m_colour
= wxColourDisplay();
106 m_pen
= *wxBLACK_PEN
;
107 m_font
= *wxNORMAL_FONT
;
108 m_brush
= *wxWHITE_BRUSH
;
110 m_graphics_changed
= TRUE
;
112 ////////////////////code here
114 m_outfile
= new wxFileOutputStream(f
) ;
115 m_OK
= m_outfile
->Ok ();
121 s
= wxT("<?xml version=\"1.0\" standalone=\"no\"?>") ; s
= s
+ newline
;
123 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline
;
125 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline
;
127 s
.Printf ( wxT("<svg 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(f
) + 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 wxSVGFileDC::wxSVGFileDC (wxString f
)
143 // quarter 640x480 screen display at 72 dpi
144 Init (f
,320,240,72.0);
147 wxSVGFileDC::wxSVGFileDC (wxString f
, int Width
, int Height
)
149 Init (f
,Width
,Height
,72.0);
152 wxSVGFileDC::wxSVGFileDC (wxString f
, int Width
, int Height
, float dpi
)
154 Init (f
,Width
,Height
,dpi
);
157 wxSVGFileDC::~wxSVGFileDC()
159 wxString s
= wxT("</g> \n</svg> \n") ;
165 //////////////////////////////////////////////////////////////////////////////////////////
167 void wxSVGFileDC::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
169 if (m_graphics_changed
) NewGraphics ();
171 s
.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1
,y1
,x2
,y2
);
176 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawLine Call executed")) ;
177 CalcBoundingBox(x1
, y1
) ;
178 CalcBoundingBox(x2
, y2
) ;
182 void wxSVGFileDC::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
184 for ( int i
= 1; i
< n
; i
++ )
186 DoDrawLine ( points
[i
-1].x
+ xoffset
, points
[i
-1].y
+ yoffset
,
187 points
[ i
].x
+ xoffset
, points
[ i
].y
+ yoffset
) ;
192 void wxSVGFileDC::DoDrawPoint (wxCoord x1
, wxCoord y1
)
195 if (m_graphics_changed
) NewGraphics ();
196 s
= wxT("<g style = \"stroke-linecap:round;\" > ") + newline
;
198 DrawLine ( x1
,y1
,x1
,y1
);
204 void wxSVGFileDC::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
206 wxDCBase::DoDrawCheckMark (x1
,y1
,width
,height
) ;
210 void wxSVGFileDC::DoDrawText(const wxString
& text
, wxCoord x1
, wxCoord y1
)
212 DoDrawRotatedText(text
, x1
,y1
,0.0);
213 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawText Call executed")) ;
217 void wxSVGFileDC::DoDrawRotatedText(const wxString
& sText
, wxCoord x
, wxCoord y
, double angle
)
219 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
220 if (m_graphics_changed
) NewGraphics ();
223 // calculate bounding box
225 DoGetTextExtent(sText
, &w
, &h
, &desc
);
227 double rad
= DegToRad(angle
);
229 // wxT("upper left") and wxT("upper right")
230 CalcBoundingBox(x
, y
);
231 CalcBoundingBox((wxCoord
)(x
+ w
*cos(rad
)), (wxCoord
)(y
- h
*sin(rad
)));
233 // wxT("bottom left") and wxT("bottom right")
234 x
+= (wxCoord
)(h
*sin(rad
));
235 y
+= (wxCoord
)(h
*cos(rad
));
236 CalcBoundingBox(x
, y
);
237 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
)), (wxCoord
)(y
+ h
*cos(rad
)));
239 if (m_backgroundMode
== wxSOLID
)
241 // draw background first
242 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
244 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ;
245 sTmp
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x
,y
+desc
-h
, w
, h
);
246 s
= sTmp
+ wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour
) + wxT("; ") ;
247 s
= s
+ wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour
) + wxT("; ") ;
248 sTmp
.Printf ( wxT("\" transform=\"rotate( %.2g %d %d ) \">"), -angle
, x
,y
) ;
249 s
= s
+ sTmp
+ newline
;
252 //now do the text itself
253 s
.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x
,y
);
255 sTmp
= m_font
.GetFaceName () ;
256 if (sTmp
.Len () > 0) s
= s
+ wxT("style=\"font-family:") + sTmp
+ wxT("; ");
257 else s
= s
+ wxT("style=\" ") ;
259 wxString fontweights
[3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
260 s
= s
+ wxT("font-weight:") + fontweights
[m_font
.GetWeight() - wxNORMAL
] + semicolon
+ space
;
262 wxString fontstyles
[5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
263 s
= s
+ wxT("font-style:") + fontstyles
[m_font
.GetStyle() - wxNORMAL
] + semicolon
+ space
;
265 sTmp
.Printf (wxT("font-size:%dpt; fill:#"), m_font
.GetPointSize () );
267 s
= s
+ wxColStr (m_textForegroundColour
) + wxT("; stroke:#") + wxColStr (m_textForegroundColour
) + wxT("; ") ;
268 sTmp
.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle
, x
,y
) ;
269 s
= s
+ sTmp
+ sText
+ wxT("</text> ") + newline
;
274 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
279 void wxSVGFileDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
281 DoDrawRoundedRectangle(x
, y
, width
, height
, 0) ;
285 void wxSVGFileDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
288 if (m_graphics_changed
) NewGraphics ();
291 s
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "),
292 x
, y
, width
, height
, radius
);
294 s
= s
+ wxT(" /> ") + newline
;
297 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ;
298 CalcBoundingBox(x
, y
) ;
299 CalcBoundingBox(x
+ width
, y
+ height
) ;
304 void wxSVGFileDC::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
,int fillStyle
)
306 if (m_graphics_changed
) NewGraphics ();
308 s
= wxT("<polygon style=\"") ;
309 if ( fillStyle
== wxODDEVEN_RULE
)
310 s
= s
+ wxT("fill-rule:evenodd; ");
312 s
= s
+ wxT("fill-rule:nonzero; ");
314 s
= s
+ wxT("\" \npoints=\"") ;
316 for (int i
= 0; i
< n
; i
++)
318 sTmp
.Printf ( wxT("%d,%d"), points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
319 s
= s
+ sTmp
+ newline
;
320 CalcBoundingBox ( points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
322 s
= s
+ wxT("\" /> ") ;
326 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
330 void wxSVGFileDC::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
333 if (m_graphics_changed
) NewGraphics ();
339 s
.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x
+rw
,y
+rh
, rw
, rh
);
340 s
= s
+ wxT(" /> ") + newline
;
344 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
345 CalcBoundingBox(x
, y
) ;
346 CalcBoundingBox(x
+ width
, y
+ height
) ;
350 void wxSVGFileDC::DoDrawArc(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
352 /* Draws an arc of a circle, centred on (xc, yc), with starting point
353 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
354 and the current brush for filling the shape.
356 The arc is drawn in an anticlockwise direction from the start point to
359 Might be better described as Pie drawing */
361 if (m_graphics_changed
) NewGraphics ();
364 // we need the radius of the circle which has two estimates
365 double r1
= sqrt ( double( (x1
-xc
)*(x1
-xc
) ) + double( (y1
-yc
)*(y1
-yc
) ) );
366 double r2
= sqrt ( double( (x2
-xc
)*(x2
-xc
) ) + double( (y2
-yc
)*(y2
-yc
) ) );
368 wxASSERT_MSG( (fabs ( r2
-r1
) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ;
369 if ( fabs ( r2
-r1
) > 3 ) //pixels
371 s
= wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n") ;
375 double theta1
= atan2((double)(yc
-y1
),(double)(x1
-xc
));
376 if ( theta1
< 0 ) theta1
= theta1
+ M_PI
* 2;
377 double theta2
= atan2((double)(yc
-y2
), (double)(x2
-xc
));
378 if ( theta2
< 0 ) theta2
= theta2
+ M_PI
* 2;
379 if ( theta2
< theta1
) theta2
= theta2
+ M_PI
*2 ;
381 int fArc
; // flag for large or small arc 0 means less than 180 degrees
382 if ( fabs(theta2
- theta1
) > M_PI
) fArc
= 1; else fArc
= 0 ;
384 int fSweep
= 0 ; // flag for sweep always 0
386 s
.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
387 x1
,y1
, r1
, r2
, fArc
, fSweep
, x2
, y2
, xc
, yc
);
389 // the z means close the path and fill
390 s
= s
+ wxT(" \" /> ") + newline
;
398 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
402 void wxSVGFileDC::DoDrawEllipticArc(wxCoord x
,wxCoord y
,wxCoord w
,wxCoord h
,double sa
,double ea
)
405 Draws an arc of an ellipse. The current pen is used for drawing the arc
406 and the current brush is used for drawing the pie. This function is
407 currently only available for X window and PostScript device contexts.
409 x and y specify the x and y coordinates of the upper-left corner of the
410 rectangle that contains the ellipse.
412 width and height specify the width and height of the rectangle that
413 contains the ellipse.
415 start and end specify the start and end of the arc relative to the
416 three-o'clock position from the center of the rectangle. Angles are
417 specified in degrees (360 is a complete circle). Positive values mean
418 counter-clockwise motion. If start is equal to end, a complete ellipse
421 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
423 if (m_graphics_changed
) NewGraphics ();
433 double xs
, ys
, xe
, ye
;
434 xs
= xc
+ rx
* cos (DegToRad(sa
)) ;
435 xe
= xc
+ rx
* cos (DegToRad(ea
)) ;
436 ys
= yc
- ry
* sin (DegToRad(sa
)) ;
437 ye
= yc
- ry
* sin (DegToRad(ea
)) ;
439 ///now same as circle arc...
441 double theta1
= atan2(ys
-yc
, xs
-xc
);
442 double theta2
= atan2(ye
-yc
, xe
-xc
);
444 int fArc
; // flag for large or small arc 0 means less than 180 degrees
445 if ( (theta2
- theta1
) > 0 ) fArc
= 1; else fArc
= 0 ;
448 if ( fabs(theta2
- theta1
) > M_PI
) fSweep
= 1; else fSweep
= 0 ;
450 s
.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
451 int(xs
), int(ys
), int(rx
), int(ry
),
452 fArc
, fSweep
, int(xe
), int(ye
), int(xc
), int(yc
) );
455 s
= s
+ wxT(" \" /> ") + newline
;
462 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ;
466 void wxSVGFileDC::DoGetTextExtent(const wxString
& string
, wxCoord
*w
, wxCoord
*h
, wxCoord
*descent
, wxCoord
*externalLeading
, 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")) ;
478 wxCoord
wxSVGFileDC::GetCharHeight() const
482 sDC
.SetFont (m_font
);
484 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
485 return ( sDC
.GetCharHeight() );
490 wxCoord
wxSVGFileDC::GetCharWidth() const
493 sDC
.SetFont (m_font
);
495 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharWidth Call executing")) ;
496 return ( sDC
.GetCharWidth() ) ;
501 /// Set Functions /////////////////////////////////////////////////////////////////
502 void wxSVGFileDC::SetBackground( const wxBrush
&brush
)
505 m_backgroundBrush
= brush
;
510 void wxSVGFileDC::SetBackgroundMode( int mode
)
512 m_backgroundMode
= mode
;
517 void wxSVGFileDC::SetBrush(const wxBrush
& brush
)
522 m_graphics_changed
= TRUE
;
523 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetBrush Call executed")) ;
527 void wxSVGFileDC::SetPen(const wxPen
& pen
)
529 // width, color, ends, joins : currently implemented
530 // dashes, stipple : not implemented
533 m_graphics_changed
= TRUE
;
534 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetPen Call executed")) ;
537 void wxSVGFileDC::NewGraphics ()
540 int w
= m_pen
.GetWidth ();
541 wxColour c
= m_pen
.GetColour () ;
543 wxString s
, sBrush
, sPenCap
, sPenJoin
, sPenStyle
, sLast
, sWarn
;
545 sBrush
= wxT("</g>\n<g style=\"") + wxBrushString ( m_brush
.GetColour (), m_brush
.GetStyle () )
546 + wxT(" stroke:#") + wxColStr (c
) + wxT("; ") ;
548 switch ( m_pen
.GetCap () )
550 case wxCAP_PROJECTING
:
551 sPenCap
= wxT("stroke-linecap:square; ") ;
554 sPenCap
= wxT("stroke-linecap:butt; ") ;
558 sPenCap
= wxT("stroke-linecap:round; ") ;
560 switch ( m_pen
.GetJoin () )
563 sPenJoin
= wxT("stroke-linejoin:bevel; ") ;
566 sPenJoin
= wxT("stroke-linejoin:miter; ") ;
570 sPenJoin
= wxT("stroke-linejoin:round; ") ;
573 switch ( m_pen
.GetStyle () )
576 sPenStyle
= wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
579 sPenStyle
= wxT("stroke-opacity:0.0; stroke-opacity:0.0; ") ;
582 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available")) ;
583 sWarn
= sWarn
+ wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n") ;
586 sLast
.Printf ( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
587 w
, m_OriginX
, m_OriginY
, m_scaleX
, m_scaleY
);
589 s
= sBrush
+ sPenCap
+ sPenJoin
+ sPenStyle
+ sLast
+ newline
+ sWarn
;
591 m_graphics_changed
= FALSE
;
592 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::NewGraphics Call executed")) ;
596 void wxSVGFileDC::SetFont(const wxFont
& font
)
601 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetFont Call executed")) ;
605 void wxSVGFileDC::ComputeScaleAndOrigin()
607 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
608 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
609 m_OriginX
= m_logicalOriginX
* m_logicalScaleX
+ m_deviceOriginX
;
610 m_OriginY
= m_logicalOriginY
* m_logicalScaleY
+ m_deviceOriginY
;
611 m_graphics_changed
= TRUE
;
615 int wxSVGFileDC::GetMapMode()
617 return m_mappingMode
;
621 void wxSVGFileDC::SetMapMode( int mode
)
626 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
629 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
632 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
635 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
639 SetLogicalScale( 1.0, 1.0 );
642 m_mappingMode
= mode
;
644 /* we don't do this mega optimisation
645 if (mode != wxMM_TEXT)
647 m_needComputeScaleX = TRUE;
648 m_needComputeScaleY = TRUE;
654 void wxSVGFileDC::GetUserScale(double *x
, double *y
) const
661 void wxSVGFileDC::SetUserScale( double x
, double y
)
663 // allow negative ? -> no
666 ComputeScaleAndOrigin();
670 void wxSVGFileDC::SetLogicalScale( double x
, double y
)
675 ComputeScaleAndOrigin();
679 void wxSVGFileDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
681 // is this still correct ?
682 m_logicalOriginX
= x
* m_signX
;
683 m_logicalOriginY
= y
* m_signY
;
684 ComputeScaleAndOrigin();
688 void wxSVGFileDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
690 // only wxPostScripDC has m_signX = -1,
693 ComputeScaleAndOrigin();
697 void wxSVGFileDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
699 // only wxPostScripDC has m_signX = -1,
700 m_signX
= (xLeftRight
? 1 : -1);
701 m_signY
= (yBottomUp
? -1 : 1);
702 ComputeScaleAndOrigin();
706 // export a bitmap as a raster image in png
707 bool wxSVGFileDC::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
708 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
709 int logicalFunc
/*= wxCOPY*/, bool useMask
/*= FALSE*/,
710 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
712 if (logicalFunc
!= wxCOPY
)
714 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
717 if (useMask
!= FALSE
)
719 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
722 wxBitmap
myBitmap (width
, height
) ;
724 memDC
.SelectObject( myBitmap
);
725 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
726 memDC
.SelectObject( wxNullBitmap
);
727 DoDrawBitmap(myBitmap
, xdest
, ydest
);
728 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoBlit Call executed")) ;
733 void wxSVGFileDC::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
735 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() ) ;
737 memDC
.SelectObject( myBitmap
);
738 memDC
.DrawIcon(myIcon
,0,0);
739 memDC
.SelectObject( wxNullBitmap
);
740 DoDrawBitmap(myBitmap
, x
, y
);
741 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
747 void wxSVGFileDC::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
749 if (m_graphics_changed
) NewGraphics ();
751 wxString sTmp
, s
, sPNG
;
752 wxImage::AddHandler(new wxPNGHandler
);
754 // create suitable file name
755 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
756 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
757 while (wxFile::Exists(sPNG
) )
760 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
761 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
764 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
765 wxBitmap myBitmap
= bmp
;
767 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
769 // refrence the bitmap from the SVG doc
770 int w
= myBitmap
.GetWidth();
771 int h
= myBitmap
.GetHeight();
772 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
774 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
775 s
= s
+ sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + newline
;
781 m_OK
= m_outfile
->Ok () && bPNG_OK
;
782 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
788 // ---------------------------------------------------------------------------
789 // coordinates transformations
790 // ---------------------------------------------------------------------------
792 wxCoord
wxSVGFileDC::DeviceToLogicalX(wxCoord x
) const
798 wxCoord
wxSVGFileDC::DeviceToLogicalY(wxCoord y
) const
804 wxCoord
wxSVGFileDC::DeviceToLogicalXRel(wxCoord x
) const
806 return XDEV2LOGREL(x
);
810 wxCoord
wxSVGFileDC::DeviceToLogicalYRel(wxCoord y
) const
812 return YDEV2LOGREL(y
);
816 wxCoord
wxSVGFileDC::LogicalToDeviceX(wxCoord x
) const
822 wxCoord
wxSVGFileDC::LogicalToDeviceY(wxCoord y
) const
828 wxCoord
wxSVGFileDC::LogicalToDeviceXRel(wxCoord x
) const
830 return XLOG2DEVREL(x
);
834 wxCoord
wxSVGFileDC::LogicalToDeviceYRel(wxCoord y
) const
836 return YLOG2DEVREL(y
);
839 void wxSVGFileDC::write(const wxString
&s
)
841 const wxWX2MBbuf buf
= s
.mb_str(wxConvUTF8
);
842 m_outfile
->Write(buf
, strlen((const char *)buf
));
843 m_OK
= m_outfile
->Ok();