]>
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"
25 #define wxSVG_DEBUG FALSE
26 // 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)
33 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
35 wxString
wxColStr ( wxColour c
)
37 unsigned char r
, g
, b
;
42 // possible Unicode bug here
43 wxString s
= wxDecToHex(r
) + wxDecToHex(g
) + wxDecToHex(b
) ;
48 wxString
wxBrushString ( wxColour c
, int style
)
50 wxString s
= wxT("fill:#") + wxColStr (c
) + semicolon
+ space
;
54 s
= s
+ wxT("fill-opacity:1.0; ");
57 s
= s
+ wxT("fill-opacity:0.0; ");
61 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::Requested Brush Style not available")) ;
69 void wxSVGFileDC::Init (wxString f
, int Width
, int Height
, float dpi
)
72 //set up things first wxDCBase does all this?
79 m_mm_to_pix_x
= dpi
/25.4;
80 m_mm_to_pix_y
= dpi
/25.4;
82 m_signX
= m_signY
= 1;
84 m_userScaleX
= m_userScaleY
=
85 m_deviceOriginX
= m_deviceOriginY
= 0;
87 m_OriginX
= m_OriginY
= 0;
88 m_logicalOriginX
= m_logicalOriginY
= 0;
89 m_logicalScaleX
= m_logicalScaleY
= 0 ;
90 m_scaleX
= m_scaleY
= 1.0 ;
92 m_logicalFunction
= wxCOPY
;
93 m_backgroundMode
= wxTRANSPARENT
;
94 m_mappingMode
= wxMM_TEXT
;
96 m_backgroundBrush
= *wxTRANSPARENT_BRUSH
;
97 m_textForegroundColour
= *wxBLACK
;
98 m_textBackgroundColour
= *wxWHITE
;
99 m_colour
= wxColourDisplay();
101 m_pen
= *wxBLACK_PEN
;
102 m_font
= *wxNORMAL_FONT
;
103 m_brush
= *wxWHITE_BRUSH
;
105 m_graphics_changed
= TRUE
;
107 ////////////////////code here
109 m_outfile
= new wxFileOutputStream(f
) ;
110 m_OK
= m_outfile
->Ok ();
116 s
= wxT("<?xml version=\"1.0\" standalone=\"no\"?>") ; s
= s
+ newline
;
118 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline
;
120 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline
;
122 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
);
124 s
= wxT("<title>SVG Picture created as ") + wxFileNameFromPath(f
) + wxT(" </title>") + newline
;
126 s
= wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion
+ wxT(" </desc>")+ newline
;
128 s
= wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline
;
136 wxSVGFileDC::wxSVGFileDC (wxString f
)
138 // quarter 640x480 screen display at 72 dpi
139 Init (f
,320,240,72.0);
142 wxSVGFileDC::wxSVGFileDC (wxString f
, int Width
, int Height
)
144 Init (f
,Width
,Height
,72.0);
147 wxSVGFileDC::wxSVGFileDC (wxString f
, int Width
, int Height
, float dpi
)
149 Init (f
,Width
,Height
,dpi
);
152 wxSVGFileDC::~wxSVGFileDC()
154 wxString s
= wxT("</g> \n</svg> \n") ;
160 //////////////////////////////////////////////////////////////////////////////////////////
162 void wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::DoDrawPoint (wxCoord x1
, wxCoord y1
)
190 if (m_graphics_changed
) NewGraphics ();
191 s
= wxT("<g style = \"stroke-linecap:round;\" > ") + newline
;
193 DrawLine ( x1
,y1
,x1
,y1
);
199 void wxSVGFileDC::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
201 wxDCBase::DoDrawCheckMark (x1
,y1
,width
,height
) ;
205 void wxSVGFileDC::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 wxSVGFileDC::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
== wxSOLID
)
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 wxSVGFileDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
276 DoDrawRoundedRectangle(x
, y
, width
, height
, 0) ;
280 void wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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
wxSVGFileDC::GetCharHeight() const
477 sDC
.SetFont (m_font
);
479 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
480 return ( sDC
.GetCharHeight() );
485 wxCoord
wxSVGFileDC::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 wxSVGFileDC::SetBackground( const wxBrush
&brush
)
500 m_backgroundBrush
= brush
;
505 void wxSVGFileDC::SetBackgroundMode( int mode
)
507 m_backgroundMode
= mode
;
512 void wxSVGFileDC::SetBrush(const wxBrush
& brush
)
517 m_graphics_changed
= TRUE
;
518 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetBrush Call executed")) ;
522 void wxSVGFileDC::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 wxSVGFileDC::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 () )
571 sPenStyle
= wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
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
, m_OriginX
, m_OriginY
, 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 wxSVGFileDC::SetFont(const wxFont
& font
)
596 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetFont Call executed")) ;
600 void wxSVGFileDC::ComputeScaleAndOrigin()
602 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
603 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
604 m_OriginX
= m_logicalOriginX
* m_logicalScaleX
+ m_deviceOriginX
;
605 m_OriginY
= m_logicalOriginY
* m_logicalScaleY
+ m_deviceOriginY
;
606 m_graphics_changed
= TRUE
;
610 int wxSVGFileDC::GetMapMode() const
612 return m_mappingMode
;
616 void wxSVGFileDC::SetMapMode( int mode
)
621 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
624 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
627 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
630 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
634 SetLogicalScale( 1.0, 1.0 );
637 m_mappingMode
= mode
;
639 /* we don't do this mega optimisation
640 if (mode != wxMM_TEXT)
642 m_needComputeScaleX = TRUE;
643 m_needComputeScaleY = TRUE;
649 void wxSVGFileDC::GetUserScale(double *x
, double *y
) const
656 void wxSVGFileDC::SetUserScale( double x
, double y
)
658 // allow negative ? -> no
661 ComputeScaleAndOrigin();
665 void wxSVGFileDC::SetLogicalScale( double x
, double y
)
670 ComputeScaleAndOrigin();
674 void wxSVGFileDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
676 // is this still correct ?
677 m_logicalOriginX
= x
* m_signX
;
678 m_logicalOriginY
= y
* m_signY
;
679 ComputeScaleAndOrigin();
683 void wxSVGFileDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
685 // only wxPostScripDC has m_signX = -1,
688 ComputeScaleAndOrigin();
692 void wxSVGFileDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
694 // only wxPostScripDC has m_signX = -1,
695 m_signX
= (xLeftRight
? 1 : -1);
696 m_signY
= (yBottomUp
? -1 : 1);
697 ComputeScaleAndOrigin();
701 // export a bitmap as a raster image in png
702 bool wxSVGFileDC::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
703 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
704 int logicalFunc
/*= wxCOPY*/, bool useMask
/*= FALSE*/,
705 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
707 if (logicalFunc
!= wxCOPY
)
709 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
712 if (useMask
!= FALSE
)
714 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
717 wxBitmap
myBitmap (width
, height
) ;
719 memDC
.SelectObject( myBitmap
);
720 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
721 memDC
.SelectObject( wxNullBitmap
);
722 DoDrawBitmap(myBitmap
, xdest
, ydest
);
723 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoBlit Call executed")) ;
728 void wxSVGFileDC::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
730 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() ) ;
732 memDC
.SelectObject( myBitmap
);
733 memDC
.DrawIcon(myIcon
,0,0);
734 memDC
.SelectObject( wxNullBitmap
);
735 DoDrawBitmap(myBitmap
, x
, y
);
736 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
742 void wxSVGFileDC::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
744 if (m_graphics_changed
) NewGraphics ();
746 wxString sTmp
, s
, sPNG
;
747 wxImage::AddHandler(new wxPNGHandler
);
749 // create suitable file name
750 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
751 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
752 while (wxFile::Exists(sPNG
) )
755 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
756 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
759 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
760 wxBitmap myBitmap
= bmp
;
762 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
764 // refrence the bitmap from the SVG doc
765 int w
= myBitmap
.GetWidth();
766 int h
= myBitmap
.GetHeight();
767 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
769 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
770 s
= s
+ sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + newline
;
776 m_OK
= m_outfile
->Ok () && bPNG_OK
;
777 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
783 // ---------------------------------------------------------------------------
784 // coordinates transformations
785 // ---------------------------------------------------------------------------
787 wxCoord
wxSVGFileDC::DeviceToLogicalX(wxCoord x
) const
793 wxCoord
wxSVGFileDC::DeviceToLogicalY(wxCoord y
) const
799 wxCoord
wxSVGFileDC::DeviceToLogicalXRel(wxCoord x
) const
801 return XDEV2LOGREL(x
);
805 wxCoord
wxSVGFileDC::DeviceToLogicalYRel(wxCoord y
) const
807 return YDEV2LOGREL(y
);
811 wxCoord
wxSVGFileDC::LogicalToDeviceX(wxCoord x
) const
817 wxCoord
wxSVGFileDC::LogicalToDeviceY(wxCoord y
) const
823 wxCoord
wxSVGFileDC::LogicalToDeviceXRel(wxCoord x
) const
825 return XLOG2DEVREL(x
);
829 wxCoord
wxSVGFileDC::LogicalToDeviceYRel(wxCoord y
) const
831 return YLOG2DEVREL(y
);
834 void wxSVGFileDC::write(const wxString
&s
)
836 const wxWX2MBbuf buf
= s
.mb_str(wxConvUTF8
);
837 m_outfile
->Write(buf
, strlen((const char *)buf
));
838 m_OK
= m_outfile
->Ok();