]>
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"
22 #include "wx/svg/dcsvg.h"
27 #define wxSVG_DEBUG FALSE
28 // or TRUE to see the calls being executed
29 #define newline wxString(wxT("\n"))
30 #define space wxString(wxT(" "))
31 #define semicolon wxString(wxT(";"))
32 #define wx_round(a) (int)((a)+.5)
39 static inline double DegToRad(double deg
) { return (deg
* 3.14) / 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
;
60 s
= s
+ wxT("fill-opacity:1.0; ");
63 s
= s
+ wxT("fill-opacity:0.0; ");
67 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::Requested Brush Style not available")) ;
75 void wxSVGFileDC::Init (wxString f
, int Width
, int Height
, float dpi
)
78 //set up things first wxDCBase does all this?
85 m_mm_to_pix_x
= dpi
/25.4;
86 m_mm_to_pix_y
= dpi
/25.4;
88 m_signX
= m_signY
= 1;
90 m_userScaleX
= m_userScaleY
=
91 m_deviceOriginX
= m_deviceOriginY
= 0;
93 m_OriginX
= m_OriginY
= 0;
94 m_logicalOriginX
= m_logicalOriginY
= 0;
95 m_logicalScaleX
= m_logicalScaleY
= 0 ;
96 m_scaleX
= m_scaleY
= 1.0 ;
98 m_logicalFunction
= wxCOPY
;
99 m_backgroundMode
= wxTRANSPARENT
;
100 m_mappingMode
= wxMM_TEXT
;
102 m_backgroundBrush
= *wxTRANSPARENT_BRUSH
;
103 m_textForegroundColour
= *wxBLACK
;
104 m_textBackgroundColour
= *wxWHITE
;
105 m_colour
= wxColourDisplay();
107 m_pen
= *wxBLACK_PEN
;
108 m_font
= *wxNORMAL_FONT
;
109 m_brush
= *wxWHITE_BRUSH
;
111 m_graphics_changed
= TRUE
;
113 ////////////////////code here
115 m_outfile
= new wxFileOutputStream(f
) ;
116 m_OK
= m_outfile
->Ok ();
122 s
= wxT("<?xml version=\"1.0\" standalone=\"no\"?>") ; s
= s
+ newline
;
124 s
= wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline
;
126 s
= wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline
;
128 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
);
130 s
= wxT("<title>SVG Picture created as ") + wxFileNameFromPath(f
) + wxT(" </title>") + newline
;
132 s
= wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion
+ wxT(" </desc>")+ newline
;
134 s
= wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline
;
142 wxSVGFileDC::wxSVGFileDC (wxString f
)
144 // quarter 640x480 screen display at 72 dpi
145 Init (f
,320,240,72.0);
148 wxSVGFileDC::wxSVGFileDC (wxString f
, int Width
, int Height
)
150 Init (f
,Width
,Height
,72.0);
153 wxSVGFileDC::wxSVGFileDC (wxString f
, int Width
, int Height
, float dpi
)
155 Init (f
,Width
,Height
,dpi
);
158 wxSVGFileDC::~wxSVGFileDC()
160 wxString s
= wxT("</g> \n</svg> \n") ;
166 //////////////////////////////////////////////////////////////////////////////////////////
168 void wxSVGFileDC::DoDrawLine (wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
)
170 if (m_graphics_changed
) NewGraphics ();
172 s
.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1
,y1
,x2
,y2
);
177 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawLine Call executed")) ;
178 CalcBoundingBox(x1
, y1
) ;
179 CalcBoundingBox(x2
, y2
) ;
183 void wxSVGFileDC::DoDrawLines(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
)
185 for ( int i
= 1; i
< n
; i
++ )
187 DoDrawLine ( points
[i
-1].x
+ xoffset
, points
[i
-1].y
+ yoffset
,
188 points
[ i
].x
+ xoffset
, points
[ i
].y
+ yoffset
) ;
193 void wxSVGFileDC::DoDrawPoint (wxCoord x1
, wxCoord y1
)
196 if (m_graphics_changed
) NewGraphics ();
197 s
= wxT("<g style = \"stroke-linecap:round;\" > ") + newline
;
199 DrawLine ( x1
,y1
,x1
,y1
);
205 void wxSVGFileDC::DoDrawCheckMark(wxCoord x1
, wxCoord y1
, wxCoord width
, wxCoord height
)
207 wxDCBase::DoDrawCheckMark (x1
,y1
,width
,height
) ;
211 void wxSVGFileDC::DoDrawText(const wxString
& text
, wxCoord x1
, wxCoord y1
)
213 DoDrawRotatedText(text
, x1
,y1
,0.0);
214 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawText Call executed")) ;
218 void wxSVGFileDC::DoDrawRotatedText(const wxString
& sText
, wxCoord x
, wxCoord y
, double angle
)
220 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
221 if (m_graphics_changed
) NewGraphics ();
224 // calculate bounding box
226 DoGetTextExtent(sText
, &w
, &h
, &desc
);
228 double rad
= DegToRad(angle
);
230 // wxT("upper left") and wxT("upper right")
231 CalcBoundingBox(x
, y
);
232 CalcBoundingBox((wxCoord
)(x
+ w
*cos(rad
)), (wxCoord
)(y
- h
*sin(rad
)));
234 // wxT("bottom left") and wxT("bottom right")
235 x
+= (wxCoord
)(h
*sin(rad
));
236 y
+= (wxCoord
)(h
*cos(rad
));
237 CalcBoundingBox(x
, y
);
238 CalcBoundingBox((wxCoord
)(x
+ h
*sin(rad
)), (wxCoord
)(y
+ h
*cos(rad
)));
240 if (m_backgroundMode
== wxSOLID
)
242 // draw background first
243 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
245 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ;
246 sTmp
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x
,y
+desc
-h
, w
, h
);
247 s
= sTmp
+ wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour
) + wxT("; ") ;
248 s
= s
+ wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour
) + wxT("; ") ;
249 sTmp
.Printf ( wxT("\" transform=\"rotate( %.2g %d %d ) \">"), -angle
, x
,y
) ;
250 s
= s
+ sTmp
+ newline
;
253 //now do the text itself
254 s
.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x
,y
);
256 sTmp
= m_font
.GetFaceName () ;
257 if (sTmp
.Len () > 0) s
= s
+ wxT("style=\"font-family:") + sTmp
+ wxT("; ");
258 else s
= s
+ wxT("style=\" ") ;
260 wxString fontweights
[3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
261 s
= s
+ wxT("font-weight:") + fontweights
[m_font
.GetWeight() - wxNORMAL
] + semicolon
+ space
;
263 wxString fontstyles
[5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
264 s
= s
+ wxT("font-style:") + fontstyles
[m_font
.GetStyle() - wxNORMAL
] + semicolon
+ space
;
266 sTmp
.Printf (wxT("font-size:%dpt; fill:#"), m_font
.GetPointSize () );
268 s
= s
+ wxColStr (m_textForegroundColour
) + wxT("; stroke:#") + wxColStr (m_textForegroundColour
) + wxT("; ") ;
269 sTmp
.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle
, x
,y
) ;
270 s
= s
+ sTmp
+ sText
+ wxT("</text> ") + newline
;
275 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
280 void wxSVGFileDC::DoDrawRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
282 DoDrawRoundedRectangle(x
, y
, width
, height
, 0) ;
286 void wxSVGFileDC::DoDrawRoundedRectangle(wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
, double radius
)
289 if (m_graphics_changed
) NewGraphics ();
292 s
.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "),
293 x
, y
, width
, height
, radius
);
295 s
= s
+ wxT(" /> ") + newline
;
298 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ;
299 CalcBoundingBox(x
, y
) ;
300 CalcBoundingBox(x
+ width
, y
+ height
) ;
305 void wxSVGFileDC::DoDrawPolygon(int n
, wxPoint points
[], wxCoord xoffset
, wxCoord yoffset
,int fillStyle
)
307 if (m_graphics_changed
) NewGraphics ();
309 s
= wxT("<polygon style=\"") ;
310 if ( fillStyle
== wxODDEVEN_RULE
)
311 s
= s
+ wxT("fill-rule:evenodd; ");
313 s
= s
+ wxT("fill-rule:nonzero; ");
315 s
= s
+ wxT("\" \npoints=\"") ;
317 for (int i
= 0; i
< n
; i
++)
319 sTmp
.Printf ( wxT("%d,%d"), points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
320 s
= s
+ sTmp
+ newline
;
321 CalcBoundingBox ( points
[i
].x
+xoffset
, points
[i
].y
+yoffset
);
323 s
= s
+ wxT("\" /> ") ;
327 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
331 void wxSVGFileDC::DoDrawEllipse (wxCoord x
, wxCoord y
, wxCoord width
, wxCoord height
)
334 if (m_graphics_changed
) NewGraphics ();
340 s
.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x
+rw
,y
+rh
, rw
, rh
);
341 s
= s
+ wxT(" /> ") + newline
;
345 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
346 CalcBoundingBox(x
, y
) ;
347 CalcBoundingBox(x
+ width
, y
+ height
) ;
351 void wxSVGFileDC::DoDrawArc(wxCoord x1
, wxCoord y1
, wxCoord x2
, wxCoord y2
, wxCoord xc
, wxCoord yc
)
353 /* Draws an arc of a circle, centred on (xc, yc), with starting point
354 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
355 and the current brush for filling the shape.
357 The arc is drawn in an anticlockwise direction from the start point to
360 Might be better described as Pie drawing */
362 if (m_graphics_changed
) NewGraphics ();
365 // we need the radius of the circle which has two estimates
366 double r1
= sqrt ( double( (x1
-xc
)*(x1
-xc
) ) + double( (y1
-yc
)*(y1
-yc
) ) );
367 double r2
= sqrt ( double( (x2
-xc
)*(x2
-xc
) ) + double( (y2
-yc
)*(y2
-yc
) ) );
369 wxASSERT_MSG( (fabs ( r2
-r1
) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ;
370 if ( fabs ( r2
-r1
) > 3 ) //pixels
372 s
= wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n") ;
376 double theta1
= atan2((double)(yc
-y1
),(double)(x1
-xc
));
377 if ( theta1
< 0 ) theta1
= theta1
+ 3.14 * 2;
378 double theta2
= atan2((double)(yc
-y2
), (double)(x2
-xc
));
379 if ( theta2
< 0 ) theta2
= theta2
+ 3.14 * 2;
380 if ( theta2
< theta1
) theta2
= theta2
+ 3.14 *2 ;
382 int fArc
; // flag for large or small arc 0 means less than 180 degrees
383 if ( fabs(theta2
- theta1
) > 3.14 ) fArc
= 1; else fArc
= 0 ;
385 int fSweep
= 0 ; // flag for sweep always 0
387 s
.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
388 x1
,y1
, r1
, r2
, fArc
, fSweep
, x2
, y2
, xc
, yc
);
390 // the z means close the path and fill
391 s
= s
+ wxT(" \" /> ") + newline
;
399 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
403 void wxSVGFileDC::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
) > 3.14) 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")) ;
467 void wxSVGFileDC::DoGetTextExtent(const wxString
& string
, wxCoord
*w
, wxCoord
*h
, wxCoord
*descent
, wxCoord
*externalLeading
, wxFont
*font
) const
472 sDC
.SetFont (m_font
);
473 if ( font
!= NULL
) sDC
.SetFont ( *font
);
474 sDC
.GetTextExtent(string
, w
, h
, descent
, externalLeading
);
475 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetTextExtent Call executed")) ;
479 wxCoord
wxSVGFileDC::GetCharHeight() const
483 sDC
.SetFont (m_font
);
485 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
486 return ( sDC
.GetCharHeight() );
491 wxCoord
wxSVGFileDC::GetCharWidth() const
494 sDC
.SetFont (m_font
);
496 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::GetCharWidth Call executing")) ;
497 return ( sDC
.GetCharWidth() ) ;
502 /// Set Functions /////////////////////////////////////////////////////////////////
503 void wxSVGFileDC::SetBackground( const wxBrush
&brush
)
506 m_backgroundBrush
= brush
;
511 void wxSVGFileDC::SetBackgroundMode( int mode
)
513 m_backgroundMode
= mode
;
518 void wxSVGFileDC::SetBrush(const wxBrush
& brush
)
523 m_graphics_changed
= TRUE
;
524 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetBrush Call executed")) ;
528 void wxSVGFileDC::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 wxSVGFileDC::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 () )
577 sPenStyle
= wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
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(%.2g %.2g) scale(%.2g %.2g)\">"),
588 w
, m_OriginX
, m_OriginY
, m_scaleX
, 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 wxSVGFileDC::SetFont(const wxFont
& font
)
602 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::SetFont Call executed")) ;
606 void wxSVGFileDC::ComputeScaleAndOrigin()
608 m_scaleX
= m_logicalScaleX
* m_userScaleX
;
609 m_scaleY
= m_logicalScaleY
* m_userScaleY
;
610 m_OriginX
= m_logicalOriginX
* m_logicalScaleX
+ m_deviceOriginX
;
611 m_OriginY
= m_logicalOriginY
* m_logicalScaleY
+ m_deviceOriginY
;
612 m_graphics_changed
= TRUE
;
616 int wxSVGFileDC::GetMapMode()
618 return m_mappingMode
;
622 void wxSVGFileDC::SetMapMode( int mode
)
627 SetLogicalScale( twips2mm
*m_mm_to_pix_x
, twips2mm
*m_mm_to_pix_y
);
630 SetLogicalScale( pt2mm
*m_mm_to_pix_x
, pt2mm
*m_mm_to_pix_y
);
633 SetLogicalScale( m_mm_to_pix_x
, m_mm_to_pix_y
);
636 SetLogicalScale( m_mm_to_pix_x
/10.0, m_mm_to_pix_y
/10.0 );
640 SetLogicalScale( 1.0, 1.0 );
643 m_mappingMode
= mode
;
645 /* we don't do this mega optimisation
646 if (mode != wxMM_TEXT)
648 m_needComputeScaleX = TRUE;
649 m_needComputeScaleY = TRUE;
655 void wxSVGFileDC::GetUserScale(double *x
, double *y
) const
662 void wxSVGFileDC::SetUserScale( double x
, double y
)
664 // allow negative ? -> no
667 ComputeScaleAndOrigin();
671 void wxSVGFileDC::SetLogicalScale( double x
, double y
)
676 ComputeScaleAndOrigin();
680 void wxSVGFileDC::SetLogicalOrigin( wxCoord x
, wxCoord y
)
682 // is this still correct ?
683 m_logicalOriginX
= x
* m_signX
;
684 m_logicalOriginY
= y
* m_signY
;
685 ComputeScaleAndOrigin();
689 void wxSVGFileDC::SetDeviceOrigin( wxCoord x
, wxCoord y
)
691 // only wxPostScripDC has m_signX = -1,
694 ComputeScaleAndOrigin();
698 void wxSVGFileDC::SetAxisOrientation( bool xLeftRight
, bool yBottomUp
)
700 // only wxPostScripDC has m_signX = -1,
701 m_signX
= (xLeftRight
? 1 : -1);
702 m_signY
= (yBottomUp
? -1 : 1);
703 ComputeScaleAndOrigin();
707 // export a bitmap as a raster image in png
708 bool wxSVGFileDC::DoBlit(wxCoord xdest
, wxCoord ydest
, wxCoord width
, wxCoord height
,
709 wxDC
* source
, wxCoord xsrc
, wxCoord ysrc
,
710 int logicalFunc
/*= wxCOPY*/, bool useMask
/*= FALSE*/,
711 wxCoord
/*xsrcMask = -1*/, wxCoord
/*ysrcMask = -1*/)
714 if (logicalFunc
!= wxCOPY
)
716 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
719 if (useMask
!= FALSE
)
721 wxASSERT_MSG(FALSE
, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
724 wxBitmap
myBitmap (width
, height
) ;
726 memDC
.SelectObject( myBitmap
);
727 memDC
.Blit(0, 0, width
, height
, source
, xsrc
, ysrc
);
728 memDC
.SelectObject( wxNullBitmap
);
729 DoDrawBitmap(myBitmap
, xdest
, ydest
);
730 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoBlit Call executed")) ;
735 void wxSVGFileDC::DoDrawIcon(const class wxIcon
& myIcon
, wxCoord x
, wxCoord y
)
737 wxBitmap
myBitmap (myIcon
.GetWidth(), myIcon
.GetHeight() ) ;
739 memDC
.SelectObject( myBitmap
);
740 memDC
.DrawIcon(myIcon
,0,0);
741 memDC
.SelectObject( wxNullBitmap
);
742 DoDrawBitmap(myBitmap
, x
, y
);
743 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
749 void wxSVGFileDC::DoDrawBitmap(const class wxBitmap
& bmp
, wxCoord x
, wxCoord y
, bool WXUNUSED(bTransparent
) /*=0*/ )
751 if (m_graphics_changed
) NewGraphics ();
753 wxString sTmp
, s
, sPNG
;
754 wxImage::AddHandler(new wxPNGHandler
);
756 // create suitable file name
757 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
758 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
759 while (wxFile::Exists(sPNG
) )
762 sTmp
.Printf ( wxT("_image%d.png"), m_sub_images
);
763 sPNG
= m_filename
.BeforeLast(wxT('.')) + sTmp
;
766 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
767 wxBitmap myBitmap
= bmp
;
769 bool bPNG_OK
= myBitmap
.SaveFile(sPNG
,wxBITMAP_TYPE_PNG
);
771 // refrence the bitmap from the SVG doc
772 int w
= myBitmap
.GetWidth();
773 int h
= myBitmap
.GetHeight();
774 sTmp
.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x
,y
,w
,h
);
776 sTmp
.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG
.c_str() );
777 s
= s
+ sTmp
+ wxT("<title>Image from wxSVG</title> </image>") + newline
;
783 m_OK
= m_outfile
->Ok () && bPNG_OK
;
784 wxASSERT_MSG(!wxSVG_DEBUG
, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
790 // ---------------------------------------------------------------------------
791 // coordinates transformations
792 // ---------------------------------------------------------------------------
794 wxCoord
wxSVGFileDC::DeviceToLogicalX(wxCoord x
) const
800 wxCoord
wxSVGFileDC::DeviceToLogicalY(wxCoord y
) const
806 wxCoord
wxSVGFileDC::DeviceToLogicalXRel(wxCoord x
) const
808 return XDEV2LOGREL(x
);
812 wxCoord
wxSVGFileDC::DeviceToLogicalYRel(wxCoord y
) const
814 return YDEV2LOGREL(y
);
818 wxCoord
wxSVGFileDC::LogicalToDeviceX(wxCoord x
) const
824 wxCoord
wxSVGFileDC::LogicalToDeviceY(wxCoord y
) const
830 wxCoord
wxSVGFileDC::LogicalToDeviceXRel(wxCoord x
) const
832 return XLOG2DEVREL(x
);
836 wxCoord
wxSVGFileDC::LogicalToDeviceYRel(wxCoord y
) const
838 return YLOG2DEVREL(y
);
841 void wxSVGFileDC::write(const wxString
&s
)
843 const wxWX2MBbuf buf
= s
.mb_str(wxConvUTF8
);
844 m_outfile
->Write(buf
, strlen((const char *)buf
));
845 m_OK
= m_outfile
->Ok();