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