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