]> git.saurik.com Git - wxWidgets.git/blob - src/common/dcsvg.cpp
replaced unweildy GAddress functions with wxSockAddressImpl class, similarly to GSock...
[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 #include "wx/filename.h"
30
31 #define wxSVG_DEBUG FALSE
32 // or TRUE to see the calls being executed
33
34 #define newline wxString(wxT("\n"))
35 #define space wxString(wxT(" "))
36 #define semicolon wxString(wxT(";"))
37 #define wx_round(a) (int)((a)+.5)
38
39 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
40
41 wxString wxColStr ( wxColour c )
42 {
43 unsigned char r, g, b ;
44 r = c.Red ();
45 g = c.Green ();
46 b = c. Blue ();
47
48 // possible Unicode bug here
49 wxString s = wxDecToHex(r) + wxDecToHex(g) + wxDecToHex(b) ;
50 return s ;
51 }
52
53
54 wxString wxBrushString ( wxColour c, int style )
55 {
56 wxString s = wxT("fill:#") + wxColStr (c) + semicolon + space ;
57 switch ( style )
58 {
59 case wxBRUSHSTYLE_SOLID :
60 s = s + wxT("fill-opacity:1.0; ");
61 break ;
62 case wxBRUSHSTYLE_TRANSPARENT:
63 s = s + wxT("fill-opacity:0.0; ");
64 break ;
65
66 default :
67 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::Requested Brush Style not available")) ;
68
69 }
70 s = s + newline ;
71 return s ;
72 }
73
74 // ----------------------------------------------------------
75 // wxSVGFileDC
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\"?>") ; s = s + newline ;
120 write(s);
121 s = wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline ;
122 write(s);
123 s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ") + newline ;
124 write(s);
125 s = wxT("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ") + newline;
126 write(s);
127 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 );
128 write(s);
129 s = wxT("<title>SVG Picture created as ") + wxFileNameFromPath(filename) + wxT(" </title>") + newline ;
130 write(s);
131 s = wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion + wxT(" </desc>")+ newline ;
132 write(s);
133 s = wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline ;
134 write(s);
135
136 }
137 }
138
139
140
141 wxSVGFileDCImpl::~wxSVGFileDCImpl()
142 {
143 wxString s = wxT("</g> \n</svg> \n") ;
144 write(s);
145 delete m_outfile ;
146 }
147
148 void wxSVGFileDCImpl::DoGetSizeMM( int *width, int *height ) const
149 {
150 if (width)
151 *width = wxRound( (double)m_width / m_mm_to_pix_x );
152
153 if (height)
154 *height = wxRound( (double)m_height / m_mm_to_pix_y );
155 }
156
157 wxSize wxSVGFileDCImpl::GetPPI() const
158 {
159 return wxSize( wxRound(m_dpi), wxRound(m_dpi) );
160 }
161
162 void wxSVGFileDCImpl::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
163 {
164 if (m_graphics_changed) NewGraphics ();
165 wxString s ;
166 s.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1,y1,x2,y2 );
167 if (m_OK)
168 {
169 write(s);
170 }
171 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")) ;
172 CalcBoundingBox(x1, y1) ;
173 CalcBoundingBox(x2, y2) ;
174 return;
175 }
176
177 void wxSVGFileDCImpl::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset )
178 {
179 for ( int i = 1; i < n ; i++ )
180 {
181 DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset,
182 points [ i ].x + xoffset, points [ i ].y + yoffset ) ;
183 }
184 }
185
186
187 void wxSVGFileDCImpl::DoDrawPoint (wxCoord x1, wxCoord y1)
188 {
189 wxString s;
190 if (m_graphics_changed) NewGraphics ();
191 s = wxT("<g style = \"stroke-linecap:round;\" > ") + newline ;
192 write(s);
193 DoDrawLine ( x1,y1,x1,y1 );
194 s = wxT("</g>");
195 write(s);
196 }
197
198
199 void wxSVGFileDCImpl::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height)
200 {
201 wxDCImpl::DoDrawCheckMark (x1,y1,width,height) ;
202 }
203
204
205 void wxSVGFileDCImpl::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1)
206 {
207 DoDrawRotatedText(text, x1,y1,0.0);
208 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawText Call executed")) ;
209 }
210
211
212 void wxSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle)
213 {
214 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
215 if (m_graphics_changed) NewGraphics ();
216 wxString s, sTmp;
217
218 // calculate bounding box
219 wxCoord w, h, desc ;
220 DoGetTextExtent(sText, &w, &h, &desc);
221
222 double rad = DegToRad(angle);
223
224 // wxT("upper left") and wxT("upper right")
225 CalcBoundingBox(x, y);
226 CalcBoundingBox((wxCoord)(x + w*cos(rad)), (wxCoord)(y - h*sin(rad)));
227
228 // wxT("bottom left") and wxT("bottom right")
229 x += (wxCoord)(h*sin(rad));
230 y += (wxCoord)(h*cos(rad));
231 CalcBoundingBox(x, y);
232 CalcBoundingBox((wxCoord)(x + h*sin(rad)), (wxCoord)(y + h*cos(rad)));
233
234 if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
235 {
236 // draw background first
237 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
238
239 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ;
240 sTmp.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x,y+desc-h, w, h );
241 s = sTmp + wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour) + wxT("; ") ;
242 s = s + wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour) + wxT("; ") ;
243 sTmp.Printf ( wxT("\" transform=\"rotate( %.2g %d %d ) \">"), -angle, x,y ) ;
244 s = s + sTmp + newline ;
245 write(s);
246 }
247 //now do the text itself
248 s.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x,y );
249
250 sTmp = m_font.GetFaceName () ;
251 if (sTmp.Len () > 0) s = s + wxT("style=\"font-family:") + sTmp + wxT("; ");
252 else s = s + wxT("style=\" ") ;
253
254 wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
255 s = s + wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space;
256
257 wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
258 s = s + wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + semicolon + space;
259
260 sTmp.Printf (wxT("font-size:%dpt; fill:#"), m_font.GetPointSize () );
261 s = s + sTmp ;
262 s = s + wxColStr (m_textForegroundColour) + wxT("; stroke:#") + wxColStr (m_textForegroundColour) + wxT("; ") ;
263 sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle, x,y ) ;
264 s = s + sTmp + sText + wxT("</text> ") + newline ;
265 if (m_OK)
266 {
267 write(s);
268 }
269 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
270
271 }
272
273
274 void wxSVGFileDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
275 {
276 DoDrawRoundedRectangle(x, y, width, height, 0) ;
277 }
278
279
280 void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
281
282 {
283 if (m_graphics_changed) NewGraphics ();
284 wxString s ;
285
286 s.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "),
287 x, y, width, height, radius );
288
289 s = s + wxT(" /> ") + newline ;
290 write(s);
291
292 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ;
293 CalcBoundingBox(x, y) ;
294 CalcBoundingBox(x + width, y + height) ;
295
296 }
297
298
299 void wxSVGFileDCImpl::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
300 {
301 if (m_graphics_changed) NewGraphics ();
302 wxString s, sTmp ;
303 s = wxT("<polygon style=\"") ;
304 if ( fillStyle == wxODDEVEN_RULE )
305 s = s + wxT("fill-rule:evenodd; ");
306 else
307 s = s + wxT("fill-rule:nonzero; ");
308
309 s = s + wxT("\" \npoints=\"") ;
310
311 for (int i = 0; i < n; i++)
312 {
313 sTmp.Printf ( wxT("%d,%d"), points [i].x+xoffset, points[i].y+yoffset );
314 s = s + sTmp + newline ;
315 CalcBoundingBox ( points [i].x+xoffset, points[i].y+yoffset);
316 }
317 s = s + wxT("\" /> ") ;
318 s = s + newline ;
319 write(s);
320
321 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
322 }
323
324
325 void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
326
327 {
328 if (m_graphics_changed) NewGraphics ();
329
330 int rh = height /2 ;
331 int rw = width /2 ;
332
333 wxString s;
334 s.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x+rw,y+rh, rw, rh );
335 s = s + wxT(" /> ") + newline ;
336
337 write(s);
338
339 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
340 CalcBoundingBox(x, y) ;
341 CalcBoundingBox(x + width, y + height) ;
342 }
343
344
345 void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
346 {
347 /* Draws an arc of a circle, centred on (xc, yc), with starting point
348 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
349 and the current brush for filling the shape.
350
351 The arc is drawn in an anticlockwise direction from the start point to
352 the end point.
353
354 Might be better described as Pie drawing */
355
356 if (m_graphics_changed) NewGraphics ();
357 wxString s ;
358
359 // we need the radius of the circle which has two estimates
360 double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) );
361 double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) );
362
363 wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ;
364 if ( fabs ( r2-r1 ) > 3 ) //pixels
365 {
366 s = wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n") ;
367 write(s);
368 }
369
370 double theta1 = atan2((double)(yc-y1),(double)(x1-xc));
371 if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2;
372 double theta2 = atan2((double)(yc-y2), (double)(x2-xc));
373 if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2;
374 if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2 ;
375
376 int fArc ; // flag for large or small arc 0 means less than 180 degrees
377 if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0 ;
378
379 int fSweep = 0 ; // flag for sweep always 0
380
381 s.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
382 x1,y1, r1, r2, fArc, fSweep, x2, y2, xc, yc );
383
384 // the z means close the path and fill
385 s = s + wxT(" \" /> ") + newline ;
386
387
388 if (m_OK)
389 {
390 write(s);
391 }
392
393 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
394 }
395
396
397 void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
398 {
399 /*
400 Draws an arc of an ellipse. The current pen is used for drawing the arc
401 and the current brush is used for drawing the pie. This function is
402 currently only available for X window and PostScript device contexts.
403
404 x and y specify the x and y coordinates of the upper-left corner of the
405 rectangle that contains the ellipse.
406
407 width and height specify the width and height of the rectangle that
408 contains the ellipse.
409
410 start and end specify the start and end of the arc relative to the
411 three-o'clock position from the center of the rectangle. Angles are
412 specified in degrees (360 is a complete circle). Positive values mean
413 counter-clockwise motion. If start is equal to end, a complete ellipse
414 will be drawn. */
415
416 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
417
418 if (m_graphics_changed) NewGraphics ();
419
420 wxString s ;
421 //radius
422 double rx = w / 2 ;
423 double ry = h / 2 ;
424 // center
425 double xc = x + rx ;
426 double yc = y + ry ;
427
428 double xs, ys, xe, ye ;
429 xs = xc + rx * cos (DegToRad(sa)) ;
430 xe = xc + rx * cos (DegToRad(ea)) ;
431 ys = yc - ry * sin (DegToRad(sa)) ;
432 ye = yc - ry * sin (DegToRad(ea)) ;
433
434 ///now same as circle arc...
435
436 double theta1 = atan2(ys-yc, xs-xc);
437 double theta2 = atan2(ye-yc, xe-xc);
438
439 int fArc ; // flag for large or small arc 0 means less than 180 degrees
440 if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0 ;
441
442 int fSweep ;
443 if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0 ;
444
445 s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
446 int(xs), int(ys), int(rx), int(ry),
447 fArc, fSweep, int(xe), int(ye), int(xc), int(yc) );
448
449
450 s = s + wxT(" \" /> ") + newline ;
451
452 if (m_OK)
453 {
454 write(s);
455 }
456
457 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ;
458 }
459
460
461 void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const
462
463 {
464 wxScreenDC sDC ;
465
466 sDC.SetFont (m_font);
467 if ( font != NULL ) sDC.SetFont ( *font );
468 sDC.GetTextExtent(string, w, h, descent, externalLeading );
469 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed")) ;
470 }
471
472
473 wxCoord wxSVGFileDCImpl::GetCharHeight() const
474
475 {
476 wxScreenDC sDC ;
477 sDC.SetFont (m_font);
478
479 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
480 return ( sDC.GetCharHeight() );
481
482 }
483
484
485 wxCoord wxSVGFileDCImpl::GetCharWidth() const
486 {
487 wxScreenDC sDC ;
488 sDC.SetFont (m_font);
489
490 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing")) ;
491 return ( sDC.GetCharWidth() ) ;
492
493 }
494
495
496 /// Set Functions /////////////////////////////////////////////////////////////////
497 void wxSVGFileDCImpl::SetBackground( const wxBrush &brush )
498 {
499
500 m_backgroundBrush = brush;
501 return;
502 }
503
504
505 void wxSVGFileDCImpl::SetBackgroundMode( int mode )
506 {
507 m_backgroundMode = mode;
508 return;
509 }
510
511
512 void wxSVGFileDCImpl::SetBrush(const wxBrush& brush)
513
514 {
515 m_brush = brush ;
516
517 m_graphics_changed = TRUE ;
518 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed")) ;
519 }
520
521
522 void wxSVGFileDCImpl::SetPen(const wxPen& pen)
523 {
524 // width, color, ends, joins : currently implemented
525 // dashes, stipple : not implemented
526 m_pen = pen ;
527
528 m_graphics_changed = TRUE ;
529 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")) ;
530 }
531
532 void wxSVGFileDCImpl::NewGraphics ()
533 {
534
535 int w = m_pen.GetWidth ();
536 wxColour c = m_pen.GetColour () ;
537
538 wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
539
540 sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () )
541 + wxT(" stroke:#") + wxColStr (c) + wxT("; ") ;
542
543 switch ( m_pen.GetCap () )
544 {
545 case wxCAP_PROJECTING :
546 sPenCap = wxT("stroke-linecap:square; ") ;
547 break ;
548 case wxCAP_BUTT :
549 sPenCap = wxT("stroke-linecap:butt; ") ;
550 break ;
551 case wxCAP_ROUND :
552 default :
553 sPenCap = wxT("stroke-linecap:round; ") ;
554 };
555 switch ( m_pen.GetJoin () )
556 {
557 case wxJOIN_BEVEL :
558 sPenJoin = wxT("stroke-linejoin:bevel; ") ;
559 break ;
560 case wxJOIN_MITER :
561 sPenJoin = wxT("stroke-linejoin:miter; ") ;
562 break ;
563 case wxJOIN_ROUND :
564 default :
565 sPenJoin = wxT("stroke-linejoin:round; ") ;
566 };
567
568 switch ( m_pen.GetStyle () )
569 {
570 case wxPENSTYLE_SOLID :
571 sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
572 break ;
573 case wxPENSTYLE_TRANSPARENT :
574 sPenStyle = wxT("stroke-opacity:0.0; stroke-opacity:0.0; ") ;
575 break ;
576 default :
577 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available")) ;
578 sWarn = sWarn + wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n") ;
579 }
580
581 sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
582 w, double(m_logicalOriginX), double(m_logicalOriginY), m_scaleX, m_scaleY );
583
584 s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
585 write(s);
586 m_graphics_changed = FALSE ;
587 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")) ;
588 }
589
590
591 void wxSVGFileDCImpl::SetFont(const wxFont& font)
592
593 {
594 m_font = font ;
595
596 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")) ;
597 }
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 int 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 // refrence 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 = s + sTmp ;
670 sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
671 s = s + sTmp + wxT("<title>Image from wxSVG</title> </image>") + newline;
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