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