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