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