]> git.saurik.com Git - wxWidgets.git/blob - src/common/dcsvg.cpp
wxDataViewChoiceRenderer's editor control should have the same size as the cell.
[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(" /> ") + 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("\" /> ");
308 s = s + wxT("\n");
309 write(s);
310
311 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed"));
312 }
313
314 void wxSVGFileDCImpl::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(" /> ") + wxT("\n");
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 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
334 {
335 /* Draws an arc of a circle, centred on (xc, yc), with starting point
336 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
337 and the current brush for filling the shape.
338
339 The arc is drawn in an anticlockwise direction from the start point to
340 the end point.
341
342 Might be better described as Pie drawing */
343
344 if (m_graphics_changed) NewGraphics ();
345 wxString s;
346
347 // we need the radius of the circle which has two estimates
348 double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) );
349 double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) );
350
351 wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle"));
352 if ( fabs ( r2-r1 ) > 3 ) //pixels
353 {
354 s = wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n");
355 write(s);
356 }
357
358 double theta1 = atan2((double)(yc-y1),(double)(x1-xc));
359 if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2;
360 double theta2 = atan2((double)(yc-y2), (double)(x2-xc));
361 if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2;
362 if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2;
363
364 int fArc; // flag for large or small arc 0 means less than 180 degrees
365 if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0;
366
367 int fSweep = 0; // flag for sweep always 0
368
369 s.Printf ( wxT("<path d=\"M%d %d A%s %s 0.0 %d %d %d %d L%d %d z "),
370 x1,y1, NumStr(r1), NumStr(r2), fArc, fSweep, x2, y2, xc, yc );
371
372 // the z means close the path and fill
373 s = s + wxT(" \" /> ") + wxT("\n");
374
375
376 if (m_OK)
377 {
378 write(s);
379 }
380
381 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed"));
382 }
383
384 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
385 {
386 /*
387 Draws an arc of an ellipse. The current pen is used for drawing the arc
388 and the current brush is used for drawing the pie. This function is
389 currently only available for X window and PostScript device contexts.
390
391 x and y specify the x and y coordinates of the upper-left corner of the
392 rectangle that contains the ellipse.
393
394 width and height specify the width and height of the rectangle that
395 contains the ellipse.
396
397 start and end specify the start and end of the arc relative to the
398 three-o'clock position from the center of the rectangle. Angles are
399 specified in degrees (360 is a complete circle). Positive values mean
400 counter-clockwise motion. If start is equal to end, a complete ellipse
401 will be drawn. */
402
403 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
404
405 if (m_graphics_changed) NewGraphics ();
406
407 wxString s;
408 //radius
409 double rx = w / 2;
410 double ry = h / 2;
411 // center
412 double xc = x + rx;
413 double yc = y + ry;
414
415 double xs, ys, xe, ye;
416 xs = xc + rx * cos (DegToRad(sa));
417 xe = xc + rx * cos (DegToRad(ea));
418 ys = yc - ry * sin (DegToRad(sa));
419 ye = yc - ry * sin (DegToRad(ea));
420
421 ///now same as circle arc...
422
423 double theta1 = atan2(ys-yc, xs-xc);
424 double theta2 = atan2(ye-yc, xe-xc);
425
426 int fArc; // flag for large or small arc 0 means less than 180 degrees
427 if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0;
428
429 int fSweep;
430 if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0;
431
432 s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
433 int(xs), int(ys), int(rx), int(ry),
434 fArc, fSweep, int(xe), int(ye), int(xc), int(yc) );
435
436
437 s = s + wxT(" \" /> ") + wxT("\n");
438
439 if (m_OK)
440 {
441 write(s);
442 }
443
444 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed"));
445 }
446
447 void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const
448
449 {
450 wxScreenDC sDC;
451
452 sDC.SetFont (m_font);
453 if ( font != NULL ) sDC.SetFont ( *font );
454 sDC.GetTextExtent(string, w, h, descent, externalLeading );
455 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed"));
456 }
457
458 wxCoord wxSVGFileDCImpl::GetCharHeight() const
459
460 {
461 wxScreenDC sDC;
462 sDC.SetFont (m_font);
463
464 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing"));
465 return ( sDC.GetCharHeight() );
466
467 }
468
469 wxCoord wxSVGFileDCImpl::GetCharWidth() const
470 {
471 wxScreenDC sDC;
472 sDC.SetFont (m_font);
473
474 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing"));
475 return ( sDC.GetCharWidth() );
476
477 }
478
479
480 // ----------------------------------------------------------
481 // wxSVGFileDCImpl - set functions
482 // ----------------------------------------------------------
483
484 void wxSVGFileDCImpl::SetBackground( const wxBrush &brush )
485 {
486
487 m_backgroundBrush = brush;
488 return;
489 }
490
491
492 void wxSVGFileDCImpl::SetBackgroundMode( int mode )
493 {
494 m_backgroundMode = mode;
495 return;
496 }
497
498
499 void wxSVGFileDCImpl::SetBrush(const wxBrush& brush)
500
501 {
502 m_brush = brush;
503
504 m_graphics_changed = true;
505 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed"));
506 }
507
508
509 void wxSVGFileDCImpl::SetPen(const wxPen& pen)
510 {
511 // width, color, ends, joins : currently implemented
512 // dashes, stipple : not implemented
513 m_pen = pen;
514
515 m_graphics_changed = true;
516 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed"));
517 }
518
519 void wxSVGFileDCImpl::NewGraphics ()
520 {
521
522 int w = m_pen.GetWidth ();
523 wxColour c = m_pen.GetColour ();
524
525 wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
526
527 sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () )
528 + wxT(" stroke:") + c.GetAsString(wxC2S_HTML_SYNTAX) + wxT("; ");
529
530 switch ( m_pen.GetCap () )
531 {
532 case wxCAP_PROJECTING :
533 sPenCap = wxT("stroke-linecap:square; ");
534 break;
535 case wxCAP_BUTT :
536 sPenCap = wxT("stroke-linecap:butt; ");
537 break;
538 case wxCAP_ROUND :
539 default :
540 sPenCap = wxT("stroke-linecap:round; ");
541 };
542 switch ( m_pen.GetJoin () )
543 {
544 case wxJOIN_BEVEL :
545 sPenJoin = wxT("stroke-linejoin:bevel; ");
546 break;
547 case wxJOIN_MITER :
548 sPenJoin = wxT("stroke-linejoin:miter; ");
549 break;
550 case wxJOIN_ROUND :
551 default :
552 sPenJoin = wxT("stroke-linejoin:round; ");
553 };
554
555 switch ( m_pen.GetStyle () )
556 {
557 case wxPENSTYLE_SOLID :
558 sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ");
559 break;
560 case wxPENSTYLE_TRANSPARENT :
561 sPenStyle = wxT("stroke-opacity:0.0; stroke-opacity:0.0; ");
562 break;
563 default :
564 wxASSERT_MSG(false, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available"));
565 sWarn = sWarn + wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n");
566 }
567
568 sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%s %s) scale(%s %s)\">"),
569 w, NumStr(m_logicalOriginX), NumStr(m_logicalOriginY), NumStr(m_scaleX), NumStr(m_scaleY) );
570
571 s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + wxT("\n") + sWarn;
572 write(s);
573 m_graphics_changed = false;
574 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed"));
575 }
576
577
578 void wxSVGFileDCImpl::SetFont(const wxFont& font)
579
580 {
581 m_font = font;
582
583 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed"));
584 }
585
586 // export a bitmap as a raster image in png
587 bool wxSVGFileDCImpl::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
588 wxDC* source, wxCoord xsrc, wxCoord ysrc,
589 wxRasterOperationMode logicalFunc /*= wxCOPY*/, bool useMask /*= false*/,
590 wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/)
591 {
592 if (logicalFunc != wxCOPY)
593 {
594 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible"));
595 return false;
596 }
597 if (useMask != false)
598 {
599 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested false mask; this is not possible"));
600 return false;
601 }
602 wxBitmap myBitmap (width, height);
603 wxMemoryDC memDC;
604 memDC.SelectObject( myBitmap );
605 memDC.Blit(0, 0, width, height, source, xsrc, ysrc);
606 memDC.SelectObject( wxNullBitmap );
607 DoDrawBitmap(myBitmap, xdest, ydest);
608 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed"));
609 return false;
610 }
611
612 void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y)
613 {
614 wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() );
615 wxMemoryDC memDC;
616 memDC.SelectObject( myBitmap );
617 memDC.DrawIcon(myIcon,0,0);
618 memDC.SelectObject( wxNullBitmap );
619 DoDrawBitmap(myBitmap, x, y);
620 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed"));
621 return;
622 }
623
624 void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ )
625 {
626 if (m_graphics_changed) NewGraphics ();
627
628 wxString sTmp, s, sPNG;
629 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG) == NULL )
630 wxImage::AddHandler(new wxPNGHandler);
631
632 // create suitable file name
633 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
634 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
635 while (wxFile::Exists(sPNG) )
636 {
637 m_sub_images ++;
638 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
639 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
640 }
641
642 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
643 wxBitmap myBitmap = bmp;
644 //save it
645 bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG);
646
647 // reference the bitmap from the SVG doc
648 // only use filename & ext
649 sPNG = sPNG.AfterLast(wxFileName::GetPathSeparator());
650
651 // reference the bitmap from the SVG doc
652 int w = myBitmap.GetWidth();
653 int h = myBitmap.GetHeight();
654 sTmp.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x,y,w,h );
655 s = s + sTmp;
656 sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
657 s = s + sTmp + wxT("<title>Image from wxSVG</title> </image>") + wxT("\n");
658
659 if (m_OK && bPNG_OK)
660 {
661 write(s);
662 }
663 m_OK = m_outfile->Ok () && bPNG_OK;
664 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed"));
665
666 return;
667 }
668
669 void wxSVGFileDCImpl::write(const wxString &s)
670 {
671 const wxCharBuffer buf = s.utf8_str();
672 m_outfile->Write(buf, strlen((const char *)buf));
673 m_OK = m_outfile->Ok();
674 }
675
676
677 #ifdef __BORLANDC__
678 #pragma warn .rch
679 #pragma warn .ccc
680 #endif
681
682 #endif // wxUSE_SVG
683