]> git.saurik.com Git - wxWidgets.git/blob - src/common/dcsvg.cpp
don't add new PNG handler instance every time wxSVGFileImplDC::DoDrawBitmap() is...
[wxWidgets.git] / src / common / dcsvg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: svg.cpp
3 // Purpose: SVG sample
4 // Author: Chris Elliott
5 // Modified by:
6 // RCS-ID: $Id$
7 // Licence: wxWindows license
8 /////////////////////////////////////////////////////////////////////////////
9
10
11 // For compilers that support precompilation, includes "wx/wx.h".
12 #include "wx/wxprec.h"
13
14 #ifdef __BORLANDC__
15 #pragma hdrstop
16 #endif
17
18 #if wxUSE_SVG
19
20 #ifndef WX_PRECOMP
21 #include "wx/dcmemory.h"
22 #include "wx/dcscreen.h"
23 #include "wx/icon.h"
24 #include "wx/image.h"
25 #endif
26
27 #include "wx/dcsvg.h"
28 #include "wx/wfstream.h"
29
30 #define wxSVG_DEBUG FALSE
31 // or TRUE to see the calls being executed
32
33 #define newline wxString(wxT("\n"))
34 #define space wxString(wxT(" "))
35 #define semicolon wxString(wxT(";"))
36 #define wx_round(a) (int)((a)+.5)
37
38 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
39
40 wxString wxColStr ( wxColour c )
41 {
42 unsigned char r, g, b ;
43 r = c.Red ();
44 g = c.Green ();
45 b = c. Blue ();
46
47 // possible Unicode bug here
48 wxString s = wxDecToHex(r) + wxDecToHex(g) + wxDecToHex(b) ;
49 return s ;
50 }
51
52
53 wxString wxBrushString ( wxColour c, int style )
54 {
55 wxString s = wxT("fill:#") + wxColStr (c) + semicolon + space ;
56 switch ( style )
57 {
58 case wxSOLID :
59 s = s + wxT("fill-opacity:1.0; ");
60 break ;
61 case wxTRANSPARENT:
62 s = s + wxT("fill-opacity:0.0; ");
63 break ;
64
65 default :
66 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::Requested Brush Style not available")) ;
67
68 }
69 s = s + newline ;
70 return s ;
71 }
72
73 // ----------------------------------------------------------
74 // wxSVGFileDC
75 // ----------------------------------------------------------
76
77 IMPLEMENT_ABSTRACT_CLASS(wxSVGFileImplDC, wxDC)
78
79 #if wxUSE_NEW_DC
80 wxSVGFileImplDC::wxSVGFileImplDC( wxSVGFileDC *owner, const wxString &filename,
81 int width, int height, double dpi ) :
82 wxImplDC( owner )
83 {
84 Init( filename, width, height, dpi );
85 }
86 #else
87 wxSVGFileDC::wxSVGFileDC( const wxString &filename,
88 int width, int height, double dpi )
89 {
90 Init( filename, width, height, dpi );
91 }
92 #endif
93
94 void wxSVGFileImplDC::Init (const wxString &filename, int Width, int Height, double dpi)
95 {
96 m_width = Width ;
97 m_height = Height ;
98
99 m_dpi = dpi;
100
101 m_OK = TRUE;
102
103 m_mm_to_pix_x = dpi/25.4;
104 m_mm_to_pix_y = dpi/25.4;
105
106 m_backgroundBrush = *wxTRANSPARENT_BRUSH;
107 m_textForegroundColour = *wxBLACK;
108 m_textBackgroundColour = *wxWHITE;
109 m_colour = wxColourDisplay();
110
111 m_pen = *wxBLACK_PEN;
112 m_font = *wxNORMAL_FONT;
113 m_brush = *wxWHITE_BRUSH;
114
115 m_graphics_changed = TRUE ;
116
117 ////////////////////code here
118
119 m_outfile = new wxFileOutputStream(filename) ;
120 m_OK = m_outfile->Ok ();
121 if (m_OK)
122 {
123 m_filename = filename ;
124 m_sub_images = 0 ;
125 wxString s ;
126 s = wxT("<?xml version=\"1.0\" standalone=\"no\"?>") ; s = s + newline ;
127 write(s);
128 s = wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline ;
129 write(s);
130 s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline ;
131 write(s);
132 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 );
133 write(s);
134 s = wxT("<title>SVG Picture created as ") + wxFileNameFromPath(filename) + wxT(" </title>") + newline ;
135 write(s);
136 s = wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion + wxT(" </desc>")+ newline ;
137 write(s);
138 s = wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline ;
139 write(s);
140
141 }
142 }
143
144
145
146 wxSVGFileImplDC::~wxSVGFileImplDC()
147 {
148 wxString s = wxT("</g> \n</svg> \n") ;
149 write(s);
150 delete m_outfile ;
151 }
152
153 void wxSVGFileImplDC::DoGetSizeMM( int *width, int *height ) const
154 {
155 if (width)
156 *width = wxRound( (double)m_width / m_mm_to_pix_x );
157
158 if (height)
159 *height = wxRound( (double)m_height / m_mm_to_pix_y );
160 }
161
162 wxSize wxSVGFileImplDC::GetPPI() const
163 {
164 return wxSize( wxRound(m_dpi), wxRound(m_dpi) );
165 }
166
167 void wxSVGFileImplDC::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
168 {
169 if (m_graphics_changed) NewGraphics ();
170 wxString s ;
171 s.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1,y1,x2,y2 );
172 if (m_OK)
173 {
174 write(s);
175 }
176 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")) ;
177 CalcBoundingBox(x1, y1) ;
178 CalcBoundingBox(x2, y2) ;
179 return;
180 }
181
182 void wxSVGFileImplDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset )
183 {
184 for ( int i = 1; i < n ; i++ )
185 {
186 DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset,
187 points [ i ].x + xoffset, points [ i ].y + yoffset ) ;
188 }
189 }
190
191
192 void wxSVGFileImplDC::DoDrawPoint (wxCoord x1, wxCoord y1)
193 {
194 wxString s;
195 if (m_graphics_changed) NewGraphics ();
196 s = wxT("<g style = \"stroke-linecap:round;\" > ") + newline ;
197 write(s);
198 DoDrawLine ( x1,y1,x1,y1 );
199 s = wxT("</g>");
200 write(s);
201 }
202
203
204 void wxSVGFileImplDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height)
205 {
206 #if wxUSE_NEW_DC
207 wxImplDC::DoDrawCheckMark (x1,y1,width,height) ;
208 #else
209 wxDCBase::DoDrawCheckMark (x1,y1,width,height) ;
210 #endif
211 }
212
213
214 void wxSVGFileImplDC::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1)
215 {
216 DoDrawRotatedText(text, x1,y1,0.0);
217 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawText Call executed")) ;
218 }
219
220
221 void wxSVGFileImplDC::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle)
222 {
223 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
224 if (m_graphics_changed) NewGraphics ();
225 wxString s, sTmp;
226
227 // calculate bounding box
228 wxCoord w, h, desc ;
229 DoGetTextExtent(sText, &w, &h, &desc);
230
231 double rad = DegToRad(angle);
232
233 // wxT("upper left") and wxT("upper right")
234 CalcBoundingBox(x, y);
235 CalcBoundingBox((wxCoord)(x + w*cos(rad)), (wxCoord)(y - h*sin(rad)));
236
237 // wxT("bottom left") and wxT("bottom right")
238 x += (wxCoord)(h*sin(rad));
239 y += (wxCoord)(h*cos(rad));
240 CalcBoundingBox(x, y);
241 CalcBoundingBox((wxCoord)(x + h*sin(rad)), (wxCoord)(y + h*cos(rad)));
242
243 if (m_backgroundMode == wxSOLID)
244 {
245 // draw background first
246 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
247
248 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ;
249 sTmp.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x,y+desc-h, w, h );
250 s = sTmp + wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour) + wxT("; ") ;
251 s = s + wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour) + wxT("; ") ;
252 sTmp.Printf ( wxT("\" transform=\"rotate( %.2g %d %d ) \">"), -angle, x,y ) ;
253 s = s + sTmp + newline ;
254 write(s);
255 }
256 //now do the text itself
257 s.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x,y );
258
259 sTmp = m_font.GetFaceName () ;
260 if (sTmp.Len () > 0) s = s + wxT("style=\"font-family:") + sTmp + wxT("; ");
261 else s = s + wxT("style=\" ") ;
262
263 wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
264 s = s + wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space;
265
266 wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
267 s = s + wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + semicolon + space;
268
269 sTmp.Printf (wxT("font-size:%dpt; fill:#"), m_font.GetPointSize () );
270 s = s + sTmp ;
271 s = s + wxColStr (m_textForegroundColour) + wxT("; stroke:#") + wxColStr (m_textForegroundColour) + wxT("; ") ;
272 sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle, x,y ) ;
273 s = s + sTmp + sText + wxT("</text> ") + newline ;
274 if (m_OK)
275 {
276 write(s);
277 }
278 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
279
280 }
281
282
283 void wxSVGFileImplDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
284 {
285 DoDrawRoundedRectangle(x, y, width, height, 0) ;
286 }
287
288
289 void wxSVGFileImplDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
290
291 {
292 if (m_graphics_changed) NewGraphics ();
293 wxString s ;
294
295 s.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "),
296 x, y, width, height, radius );
297
298 s = s + wxT(" /> ") + newline ;
299 write(s);
300
301 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ;
302 CalcBoundingBox(x, y) ;
303 CalcBoundingBox(x + width, y + height) ;
304
305 }
306
307
308 void wxSVGFileImplDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
309 {
310 if (m_graphics_changed) NewGraphics ();
311 wxString s, sTmp ;
312 s = wxT("<polygon style=\"") ;
313 if ( fillStyle == wxODDEVEN_RULE )
314 s = s + wxT("fill-rule:evenodd; ");
315 else
316 s = s + wxT("fill-rule:nonzero; ");
317
318 s = s + wxT("\" \npoints=\"") ;
319
320 for (int i = 0; i < n; i++)
321 {
322 sTmp.Printf ( wxT("%d,%d"), points [i].x+xoffset, points[i].y+yoffset );
323 s = s + sTmp + newline ;
324 CalcBoundingBox ( points [i].x+xoffset, points[i].y+yoffset);
325 }
326 s = s + wxT("\" /> ") ;
327 s = s + newline ;
328 write(s);
329
330 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
331 }
332
333
334 void wxSVGFileImplDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
335
336 {
337 if (m_graphics_changed) NewGraphics ();
338
339 int rh = height /2 ;
340 int rw = width /2 ;
341
342 wxString s;
343 s.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x+rw,y+rh, rw, rh );
344 s = s + wxT(" /> ") + newline ;
345
346 write(s);
347
348 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
349 CalcBoundingBox(x, y) ;
350 CalcBoundingBox(x + width, y + height) ;
351 }
352
353
354 void wxSVGFileImplDC::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
355 {
356 /* Draws an arc of a circle, centred on (xc, yc), with starting point
357 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
358 and the current brush for filling the shape.
359
360 The arc is drawn in an anticlockwise direction from the start point to
361 the end point.
362
363 Might be better described as Pie drawing */
364
365 if (m_graphics_changed) NewGraphics ();
366 wxString s ;
367
368 // we need the radius of the circle which has two estimates
369 double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) );
370 double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) );
371
372 wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ;
373 if ( fabs ( r2-r1 ) > 3 ) //pixels
374 {
375 s = wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n") ;
376 write(s);
377 }
378
379 double theta1 = atan2((double)(yc-y1),(double)(x1-xc));
380 if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2;
381 double theta2 = atan2((double)(yc-y2), (double)(x2-xc));
382 if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2;
383 if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2 ;
384
385 int fArc ; // flag for large or small arc 0 means less than 180 degrees
386 if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0 ;
387
388 int fSweep = 0 ; // flag for sweep always 0
389
390 s.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
391 x1,y1, r1, r2, fArc, fSweep, x2, y2, xc, yc );
392
393 // the z means close the path and fill
394 s = s + wxT(" \" /> ") + newline ;
395
396
397 if (m_OK)
398 {
399 write(s);
400 }
401
402 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
403 }
404
405
406 void wxSVGFileImplDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
407 {
408 /*
409 Draws an arc of an ellipse. The current pen is used for drawing the arc
410 and the current brush is used for drawing the pie. This function is
411 currently only available for X window and PostScript device contexts.
412
413 x and y specify the x and y coordinates of the upper-left corner of the
414 rectangle that contains the ellipse.
415
416 width and height specify the width and height of the rectangle that
417 contains the ellipse.
418
419 start and end specify the start and end of the arc relative to the
420 three-o'clock position from the center of the rectangle. Angles are
421 specified in degrees (360 is a complete circle). Positive values mean
422 counter-clockwise motion. If start is equal to end, a complete ellipse
423 will be drawn. */
424
425 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
426
427 if (m_graphics_changed) NewGraphics ();
428
429 wxString s ;
430 //radius
431 double rx = w / 2 ;
432 double ry = h / 2 ;
433 // center
434 double xc = x + rx ;
435 double yc = y + ry ;
436
437 double xs, ys, xe, ye ;
438 xs = xc + rx * cos (DegToRad(sa)) ;
439 xe = xc + rx * cos (DegToRad(ea)) ;
440 ys = yc - ry * sin (DegToRad(sa)) ;
441 ye = yc - ry * sin (DegToRad(ea)) ;
442
443 ///now same as circle arc...
444
445 double theta1 = atan2(ys-yc, xs-xc);
446 double theta2 = atan2(ye-yc, xe-xc);
447
448 int fArc ; // flag for large or small arc 0 means less than 180 degrees
449 if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0 ;
450
451 int fSweep ;
452 if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0 ;
453
454 s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
455 int(xs), int(ys), int(rx), int(ry),
456 fArc, fSweep, int(xe), int(ye), int(xc), int(yc) );
457
458
459 s = s + wxT(" \" /> ") + newline ;
460
461 if (m_OK)
462 {
463 write(s);
464 }
465
466 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ;
467 }
468
469
470 void wxSVGFileImplDC::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const
471
472 {
473 wxScreenDC sDC ;
474
475 sDC.SetFont (m_font);
476 if ( font != NULL ) sDC.SetFont ( *font );
477 sDC.GetTextExtent(string, w, h, descent, externalLeading );
478 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed")) ;
479 }
480
481
482 wxCoord wxSVGFileImplDC::GetCharHeight() const
483
484 {
485 wxScreenDC sDC ;
486 sDC.SetFont (m_font);
487
488 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
489 return ( sDC.GetCharHeight() );
490
491 }
492
493
494 wxCoord wxSVGFileImplDC::GetCharWidth() const
495 {
496 wxScreenDC sDC ;
497 sDC.SetFont (m_font);
498
499 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing")) ;
500 return ( sDC.GetCharWidth() ) ;
501
502 }
503
504
505 /// Set Functions /////////////////////////////////////////////////////////////////
506 void wxSVGFileImplDC::SetBackground( const wxBrush &brush )
507 {
508
509 m_backgroundBrush = brush;
510 return;
511 }
512
513
514 void wxSVGFileImplDC::SetBackgroundMode( int mode )
515 {
516 m_backgroundMode = mode;
517 return;
518 }
519
520
521 void wxSVGFileImplDC::SetBrush(const wxBrush& brush)
522
523 {
524 m_brush = brush ;
525
526 m_graphics_changed = TRUE ;
527 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed")) ;
528 }
529
530
531 void wxSVGFileImplDC::SetPen(const wxPen& pen)
532 {
533 // width, color, ends, joins : currently implemented
534 // dashes, stipple : not implemented
535 m_pen = pen ;
536
537 m_graphics_changed = TRUE ;
538 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")) ;
539 }
540
541 void wxSVGFileImplDC::NewGraphics ()
542 {
543
544 int w = m_pen.GetWidth ();
545 wxColour c = m_pen.GetColour () ;
546
547 wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
548
549 sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () )
550 + wxT(" stroke:#") + wxColStr (c) + wxT("; ") ;
551
552 switch ( m_pen.GetCap () )
553 {
554 case wxCAP_PROJECTING :
555 sPenCap = wxT("stroke-linecap:square; ") ;
556 break ;
557 case wxCAP_BUTT :
558 sPenCap = wxT("stroke-linecap:butt; ") ;
559 break ;
560 case wxCAP_ROUND :
561 default :
562 sPenCap = wxT("stroke-linecap:round; ") ;
563 };
564 switch ( m_pen.GetJoin () )
565 {
566 case wxJOIN_BEVEL :
567 sPenJoin = wxT("stroke-linejoin:bevel; ") ;
568 break ;
569 case wxJOIN_MITER :
570 sPenJoin = wxT("stroke-linejoin:miter; ") ;
571 break ;
572 case wxJOIN_ROUND :
573 default :
574 sPenJoin = wxT("stroke-linejoin:round; ") ;
575 };
576
577 switch ( m_pen.GetStyle () )
578 {
579 case wxSOLID :
580 sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
581 break ;
582 case wxTRANSPARENT :
583 sPenStyle = wxT("stroke-opacity:0.0; stroke-opacity:0.0; ") ;
584 break ;
585 default :
586 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available")) ;
587 sWarn = sWarn + wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n") ;
588 }
589
590 sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
591 w, (double)m_logicalOriginX, m_logicalOriginY, m_scaleX, m_scaleY );
592
593 s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
594 write(s);
595 m_graphics_changed = FALSE ;
596 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")) ;
597 }
598
599
600 void wxSVGFileImplDC::SetFont(const wxFont& font)
601
602 {
603 m_font = font ;
604
605 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")) ;
606 }
607
608
609 // export a bitmap as a raster image in png
610 bool wxSVGFileImplDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
611 wxDC* source, wxCoord xsrc, wxCoord ysrc,
612 int logicalFunc /*= wxCOPY*/, bool useMask /*= FALSE*/,
613 wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/)
614 {
615 if (logicalFunc != wxCOPY)
616 {
617 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
618 return FALSE ;
619 }
620 if (useMask != FALSE)
621 {
622 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
623 return FALSE ;
624 }
625 wxBitmap myBitmap (width, height) ;
626 wxMemoryDC memDC;
627 memDC.SelectObject( myBitmap );
628 memDC.Blit(0, 0, width, height, source, xsrc, ysrc);
629 memDC.SelectObject( wxNullBitmap );
630 DoDrawBitmap(myBitmap, xdest, ydest);
631 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed")) ;
632 return FALSE ;
633 }
634
635 void wxSVGFileImplDC::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y)
636 {
637 wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() ) ;
638 wxMemoryDC memDC;
639 memDC.SelectObject( myBitmap );
640 memDC.DrawIcon(myIcon,0,0);
641 memDC.SelectObject( wxNullBitmap );
642 DoDrawBitmap(myBitmap, x, y);
643 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
644 return ;
645 }
646
647 void wxSVGFileImplDC::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ )
648 {
649 if (m_graphics_changed) NewGraphics ();
650
651 wxString sTmp, s, sPNG ;
652 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG) == NULL )
653 wxImage::AddHandler(new wxPNGHandler);
654
655 // create suitable file name
656 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
657 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
658 while (wxFile::Exists(sPNG) )
659 {
660 m_sub_images ++ ;
661 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
662 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
663 }
664
665 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
666 wxBitmap myBitmap = bmp ;
667 //save it
668 bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG);
669
670 // refrence the bitmap from the SVG doc
671 int w = myBitmap.GetWidth();
672 int h = myBitmap.GetHeight();
673 sTmp.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x,y,w,h );
674 s = s + sTmp ;
675 sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
676 s = s + sTmp + wxT("<title>Image from wxSVG</title> </image>") + newline;
677
678 if (m_OK && bPNG_OK)
679 {
680 write(s);
681 }
682 m_OK = m_outfile->Ok () && bPNG_OK;
683 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
684
685 return ;
686 }
687
688 void wxSVGFileImplDC::write(const wxString &s)
689 {
690 const wxCharBuffer buf = s.utf8_str();
691 m_outfile->Write(buf, strlen((const char *)buf));
692 m_OK = m_outfile->Ok();
693 }
694
695 // ---------------------------------------------------------------------------
696 // coordinates transformations
697 // ---------------------------------------------------------------------------
698
699 #if wxUSE_NEW_DC
700 #else
701 void wxSVGFileImplDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
702 {
703 wxDCBase::SetAxisOrientation( xLeftRight, yBottomUp );
704 }
705
706 void wxSVGFileImplDC::SetMapMode(int mode)
707 {
708 wxDCBase::SetMapMode(mode);
709 }
710
711 void wxSVGFileImplDC::SetUserScale(double x, double y)
712 {
713 wxDCBase::SetUserScale(x,y);
714 }
715
716 void wxSVGFileImplDC::SetLogicalScale(double x, double y)
717 {
718 wxDCBase::SetLogicalScale(x,y);
719 }
720
721 void wxSVGFileImplDC::SetLogicalOrigin(wxCoord x, wxCoord y)
722 {
723 wxDCBase::SetLogicalOrigin(x,y);
724 }
725
726 void wxSVGFileImplDC::SetDeviceOrigin(wxCoord x, wxCoord y)
727 {
728 wxDCBase::SetDeviceOrigin(x,y);
729 }
730 #endif
731
732
733 #ifdef __BORLANDC__
734 #pragma warn .rch
735 #pragma warn .ccc
736 #endif
737
738 #endif // wxUSE_SVG
739