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