deprecate wxDos2UnixFilename, wxUnix2DosFilename, wxStripExtension, wxGetTempFileName...
[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[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
293 {
294 if (m_graphics_changed) NewGraphics ();
295 wxString s, sTmp;
296 s = wxT("<polygon style=\"");
297 if ( fillStyle == wxODDEVEN_RULE )
298 s = s + wxT("fill-rule:evenodd; ");
299 else
300 s = s + wxT("fill-rule:nonzero; ");
301
302 s = s + wxT("\" \npoints=\"");
303
304 for (int i = 0; i < n; i++)
305 {
306 sTmp.Printf ( wxT("%d,%d"), points [i].x+xoffset, points[i].y+yoffset );
307 s = s + sTmp + newline;
308 CalcBoundingBox ( points [i].x+xoffset, points[i].y+yoffset);
309 }
310 s = s + wxT("\" /> ");
311 s = s + newline;
312 write(s);
313
314 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed"));
315 }
316
317 void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
318
319 {
320 if (m_graphics_changed) NewGraphics ();
321
322 int rh = height /2;
323 int rw = width /2;
324
325 wxString s;
326 s.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x+rw,y+rh, rw, rh );
327 s = s + wxT(" /> ") + newline;
328
329 write(s);
330
331 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed"));
332 CalcBoundingBox(x, y);
333 CalcBoundingBox(x + width, y + height);
334 }
335
336 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
337 {
338 /* Draws an arc of a circle, centred on (xc, yc), with starting point
339 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
340 and the current brush for filling the shape.
341
342 The arc is drawn in an anticlockwise direction from the start point to
343 the end point.
344
345 Might be better described as Pie drawing */
346
347 if (m_graphics_changed) NewGraphics ();
348 wxString s;
349
350 // we need the radius of the circle which has two estimates
351 double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) );
352 double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) );
353
354 wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle"));
355 if ( fabs ( r2-r1 ) > 3 ) //pixels
356 {
357 s = wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n");
358 write(s);
359 }
360
361 double theta1 = atan2((double)(yc-y1),(double)(x1-xc));
362 if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2;
363 double theta2 = atan2((double)(yc-y2), (double)(x2-xc));
364 if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2;
365 if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2;
366
367 int fArc; // flag for large or small arc 0 means less than 180 degrees
368 if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0;
369
370 int fSweep = 0; // flag for sweep always 0
371
372 s.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
373 x1,y1, r1, r2, fArc, fSweep, x2, y2, xc, yc );
374
375 // the z means close the path and fill
376 s = s + wxT(" \" /> ") + newline;
377
378
379 if (m_OK)
380 {
381 write(s);
382 }
383
384 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed"));
385 }
386
387 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
388 {
389 /*
390 Draws an arc of an ellipse. The current pen is used for drawing the arc
391 and the current brush is used for drawing the pie. This function is
392 currently only available for X window and PostScript device contexts.
393
394 x and y specify the x and y coordinates of the upper-left corner of the
395 rectangle that contains the ellipse.
396
397 width and height specify the width and height of the rectangle that
398 contains the ellipse.
399
400 start and end specify the start and end of the arc relative to the
401 three-o'clock position from the center of the rectangle. Angles are
402 specified in degrees (360 is a complete circle). Positive values mean
403 counter-clockwise motion. If start is equal to end, a complete ellipse
404 will be drawn. */
405
406 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
407
408 if (m_graphics_changed) NewGraphics ();
409
410 wxString s;
411 //radius
412 double rx = w / 2;
413 double ry = h / 2;
414 // center
415 double xc = x + rx;
416 double yc = y + ry;
417
418 double xs, ys, xe, ye;
419 xs = xc + rx * cos (DegToRad(sa));
420 xe = xc + rx * cos (DegToRad(ea));
421 ys = yc - ry * sin (DegToRad(sa));
422 ye = yc - ry * sin (DegToRad(ea));
423
424 ///now same as circle arc...
425
426 double theta1 = atan2(ys-yc, xs-xc);
427 double theta2 = atan2(ye-yc, xe-xc);
428
429 int fArc; // flag for large or small arc 0 means less than 180 degrees
430 if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0;
431
432 int fSweep;
433 if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0;
434
435 s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
436 int(xs), int(ys), int(rx), int(ry),
437 fArc, fSweep, int(xe), int(ye), int(xc), int(yc) );
438
439
440 s = s + wxT(" \" /> ") + newline;
441
442 if (m_OK)
443 {
444 write(s);
445 }
446
447 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed"));
448 }
449
450 void wxSVGFileDCImpl::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 wxCoord wxSVGFileDCImpl::GetCharHeight() const
462
463 {
464 wxScreenDC sDC;
465 sDC.SetFont (m_font);
466
467 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing"));
468 return ( sDC.GetCharHeight() );
469
470 }
471
472 wxCoord wxSVGFileDCImpl::GetCharWidth() const
473 {
474 wxScreenDC sDC;
475 sDC.SetFont (m_font);
476
477 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing"));
478 return ( sDC.GetCharWidth() );
479
480 }
481
482
483 // ----------------------------------------------------------
484 // wxSVGFileDCImpl - set functions
485 // ----------------------------------------------------------
486
487 void wxSVGFileDCImpl::SetBackground( const wxBrush &brush )
488 {
489
490 m_backgroundBrush = brush;
491 return;
492 }
493
494
495 void wxSVGFileDCImpl::SetBackgroundMode( int mode )
496 {
497 m_backgroundMode = mode;
498 return;
499 }
500
501
502 void wxSVGFileDCImpl::SetBrush(const wxBrush& brush)
503
504 {
505 m_brush = brush;
506
507 m_graphics_changed = true;
508 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed"));
509 }
510
511
512 void wxSVGFileDCImpl::SetPen(const wxPen& pen)
513 {
514 // width, color, ends, joins : currently implemented
515 // dashes, stipple : not implemented
516 m_pen = pen;
517
518 m_graphics_changed = true;
519 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed"));
520 }
521
522 void wxSVGFileDCImpl::NewGraphics ()
523 {
524
525 int w = m_pen.GetWidth ();
526 wxColour c = m_pen.GetColour ();
527
528 wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
529
530 sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () )
531 + wxT(" stroke:#") + wxColStr (c) + wxT("; ");
532
533 switch ( m_pen.GetCap () )
534 {
535 case wxCAP_PROJECTING :
536 sPenCap = wxT("stroke-linecap:square; ");
537 break;
538 case wxCAP_BUTT :
539 sPenCap = wxT("stroke-linecap:butt; ");
540 break;
541 case wxCAP_ROUND :
542 default :
543 sPenCap = wxT("stroke-linecap:round; ");
544 };
545 switch ( m_pen.GetJoin () )
546 {
547 case wxJOIN_BEVEL :
548 sPenJoin = wxT("stroke-linejoin:bevel; ");
549 break;
550 case wxJOIN_MITER :
551 sPenJoin = wxT("stroke-linejoin:miter; ");
552 break;
553 case wxJOIN_ROUND :
554 default :
555 sPenJoin = wxT("stroke-linejoin:round; ");
556 };
557
558 switch ( m_pen.GetStyle () )
559 {
560 case wxPENSTYLE_SOLID :
561 sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ");
562 break;
563 case wxPENSTYLE_TRANSPARENT :
564 sPenStyle = wxT("stroke-opacity:0.0; stroke-opacity:0.0; ");
565 break;
566 default :
567 wxASSERT_MSG(false, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available"));
568 sWarn = sWarn + wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n");
569 }
570
571 sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
572 w, double(m_logicalOriginX), double(m_logicalOriginY), m_scaleX, m_scaleY );
573
574 s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
575 write(s);
576 m_graphics_changed = false;
577 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed"));
578 }
579
580
581 void wxSVGFileDCImpl::SetFont(const wxFont& font)
582
583 {
584 m_font = font;
585
586 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed"));
587 }
588
589 // export a bitmap as a raster image in png
590 bool wxSVGFileDCImpl::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 wxSVGFileDCImpl::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 wxSVGFileDCImpl::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 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG) == NULL )
633 wxImage::AddHandler(new wxPNGHandler);
634
635 // create suitable file name
636 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
637 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
638 while (wxFile::Exists(sPNG) )
639 {
640 m_sub_images ++;
641 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
642 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
643 }
644
645 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
646 wxBitmap myBitmap = bmp;
647 //save it
648 bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG);
649
650 // reference the bitmap from the SVG doc
651 // only use filename & ext
652 sPNG = sPNG.AfterLast(wxFileName::GetPathSeparator());
653
654 // reference the bitmap from the SVG doc
655 int w = myBitmap.GetWidth();
656 int h = myBitmap.GetHeight();
657 sTmp.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x,y,w,h );
658 s = s + sTmp;
659 sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
660 s = s + sTmp + wxT("<title>Image from wxSVG</title> </image>") + newline;
661
662 if (m_OK && bPNG_OK)
663 {
664 write(s);
665 }
666 m_OK = m_outfile->Ok () && bPNG_OK;
667 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed"));
668
669 return;
670 }
671
672 void wxSVGFileDCImpl::write(const wxString &s)
673 {
674 const wxCharBuffer buf = s.utf8_str();
675 m_outfile->Write(buf, strlen((const char *)buf));
676 m_OK = m_outfile->Ok();
677 }
678
679
680 #ifdef __BORLANDC__
681 #pragma warn .rch
682 #pragma warn .ccc
683 #endif
684
685 #endif // wxUSE_SVG
686