]> git.saurik.com Git - wxWidgets.git/blob - contrib/src/svg/dcsvg.cpp
glibc's vswprintf doesn't nul terminate on truncation.
[wxWidgets.git] / contrib / src / svg / 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 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21
22 #include "wx/svg/dcsvg.h"
23
24 #include "wx/image.h"
25
26 #define wxSVG_DEBUG FALSE
27 // or TRUE to see the calls being executed
28 #define newline wxString(wxT("\n"))
29 #define space wxString(wxT(" "))
30 #define semicolon wxString(wxT(";"))
31 #define wx_round(a) (int)((a)+.5)
32
33 #ifdef __BORLANDC__
34 #pragma warn -rch
35 #pragma warn -ccc
36 #endif
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 void wxSVGFileDC::Init (wxString f, int Width, int Height, float dpi)
75
76 {
77 //set up things first wxDCBase does all this?
78 m_width = Width ;
79 m_height = Height ;
80
81 m_clipping = FALSE;
82 m_OK = TRUE;
83
84 m_mm_to_pix_x = dpi/25.4;
85 m_mm_to_pix_y = dpi/25.4;
86
87 m_signX = m_signY = 1;
88
89 m_userScaleX = m_userScaleY =
90 m_deviceOriginX = m_deviceOriginY = 0;
91
92 m_OriginX = m_OriginY = 0;
93 m_logicalOriginX = m_logicalOriginY = 0;
94 m_logicalScaleX = m_logicalScaleY = 0 ;
95 m_scaleX = m_scaleY = 1.0 ;
96
97 m_logicalFunction = wxCOPY;
98 m_backgroundMode = wxTRANSPARENT;
99 m_mappingMode = wxMM_TEXT;
100
101 m_backgroundBrush = *wxTRANSPARENT_BRUSH;
102 m_textForegroundColour = *wxBLACK;
103 m_textBackgroundColour = *wxWHITE;
104 m_colour = wxColourDisplay();
105
106 m_pen = *wxBLACK_PEN;
107 m_font = *wxNORMAL_FONT;
108 m_brush = *wxWHITE_BRUSH;
109
110 m_graphics_changed = TRUE ;
111
112 ////////////////////code here
113
114 m_outfile = new wxFileOutputStream(f) ;
115 m_OK = m_outfile->Ok ();
116 if (m_OK)
117 {
118 m_filename = f ;
119 m_sub_images = 0 ;
120 wxString s ;
121 s = wxT("<?xml version=\"1.0\" standalone=\"no\"?>") ; s = s + newline ;
122 write(s);
123 s = wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline ;
124 write(s);
125 s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline ;
126 write(s);
127 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 );
128 write(s);
129 s = wxT("<title>SVG Picture created as ") + wxFileNameFromPath(f) + 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 // constructors
141 wxSVGFileDC::wxSVGFileDC (wxString f)
142 {
143 // quarter 640x480 screen display at 72 dpi
144 Init (f,320,240,72.0);
145 };
146
147 wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height)
148 {
149 Init (f,Width,Height,72.0);
150 };
151
152 wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height, float dpi)
153 {
154 Init (f,Width,Height,dpi);
155 };
156
157 wxSVGFileDC::~wxSVGFileDC()
158 {
159 wxString s = wxT("</g> \n</svg> \n") ;
160 write(s);
161 delete m_outfile ;
162 }
163
164
165 //////////////////////////////////////////////////////////////////////////////////////////
166
167 void wxSVGFileDC::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
168 {
169 if (m_graphics_changed) NewGraphics ();
170 wxString s ;
171 s.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1,y1,x2,y2 );
172 if (m_OK)
173 {
174 write(s);
175 }
176 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")) ;
177 CalcBoundingBox(x1, y1) ;
178 CalcBoundingBox(x2, y2) ;
179 return;
180 };
181
182 void wxSVGFileDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset )
183 {
184 for ( int i = 1; i < n ; i++ )
185 {
186 DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset,
187 points [ i ].x + xoffset, points [ i ].y + yoffset ) ;
188 }
189 }
190
191
192 void wxSVGFileDC::DoDrawPoint (wxCoord x1, wxCoord y1)
193 {
194 wxString s;
195 if (m_graphics_changed) NewGraphics ();
196 s = wxT("<g style = \"stroke-linecap:round;\" > ") + newline ;
197 write(s);
198 DrawLine ( x1,y1,x1,y1 );
199 s = wxT("</g>");
200 write(s);
201 }
202
203
204 void wxSVGFileDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height)
205 {
206 wxDCBase::DoDrawCheckMark (x1,y1,width,height) ;
207 }
208
209
210 void wxSVGFileDC::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1)
211 {
212 DoDrawRotatedText(text, x1,y1,0.0);
213 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawText Call executed")) ;
214 }
215
216
217 void wxSVGFileDC::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle)
218 {
219 //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
220 if (m_graphics_changed) NewGraphics ();
221 wxString s, sTmp;
222
223 // calculate bounding box
224 wxCoord w, h, desc ;
225 DoGetTextExtent(sText, &w, &h, &desc);
226
227 double rad = DegToRad(angle);
228
229 // wxT("upper left") and wxT("upper right")
230 CalcBoundingBox(x, y);
231 CalcBoundingBox((wxCoord)(x + w*cos(rad)), (wxCoord)(y - h*sin(rad)));
232
233 // wxT("bottom left") and wxT("bottom right")
234 x += (wxCoord)(h*sin(rad));
235 y += (wxCoord)(h*cos(rad));
236 CalcBoundingBox(x, y);
237 CalcBoundingBox((wxCoord)(x + h*sin(rad)), (wxCoord)(y + h*cos(rad)));
238
239 if (m_backgroundMode == wxSOLID)
240 {
241 // draw background first
242 // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
243
244 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ;
245 sTmp.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x,y+desc-h, w, h );
246 s = sTmp + wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour) + wxT("; ") ;
247 s = s + wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour) + wxT("; ") ;
248 sTmp.Printf ( wxT("\" transform=\"rotate( %.2g %d %d ) \">"), -angle, x,y ) ;
249 s = s + sTmp + newline ;
250 write(s);
251 }
252 //now do the text itself
253 s.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x,y );
254
255 sTmp = m_font.GetFaceName () ;
256 if (sTmp.Len () > 0) s = s + wxT("style=\"font-family:") + sTmp + wxT("; ");
257 else s = s + wxT("style=\" ") ;
258
259 wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
260 s = s + wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space;
261
262 wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
263 s = s + wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + semicolon + space;
264
265 sTmp.Printf (wxT("font-size:%dpt; fill:#"), m_font.GetPointSize () );
266 s = s + sTmp ;
267 s = s + wxColStr (m_textForegroundColour) + wxT("; stroke:#") + wxColStr (m_textForegroundColour) + wxT("; ") ;
268 sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %.2g %d %d ) \" >"), -angle, x,y ) ;
269 s = s + sTmp + sText + wxT("</text> ") + newline ;
270 if (m_OK)
271 {
272 write(s);
273 }
274 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
275
276 }
277
278
279 void wxSVGFileDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
280 {
281 DoDrawRoundedRectangle(x, y, width, height, 0) ;
282 }
283
284
285 void wxSVGFileDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
286
287 {
288 if (m_graphics_changed) NewGraphics ();
289 wxString s ;
290
291 s.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "),
292 x, y, width, height, radius );
293
294 s = s + wxT(" /> ") + newline ;
295 write(s);
296
297 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ;
298 CalcBoundingBox(x, y) ;
299 CalcBoundingBox(x + width, y + height) ;
300
301 }
302
303
304 void wxSVGFileDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
305 {
306 if (m_graphics_changed) NewGraphics ();
307 wxString s, sTmp ;
308 s = wxT("<polygon style=\"") ;
309 if ( fillStyle == wxODDEVEN_RULE )
310 s = s + wxT("fill-rule:evenodd; ");
311 else
312 s = s + wxT("fill-rule:nonzero; ");
313
314 s = s + wxT("\" \npoints=\"") ;
315
316 for (int i = 0; i < n; i++)
317 {
318 sTmp.Printf ( wxT("%d,%d"), points [i].x+xoffset, points[i].y+yoffset );
319 s = s + sTmp + newline ;
320 CalcBoundingBox ( points [i].x+xoffset, points[i].y+yoffset);
321 }
322 s = s + wxT("\" /> ") ;
323 s = s + newline ;
324 write(s);
325
326 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
327 }
328
329
330 void wxSVGFileDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
331
332 {
333 if (m_graphics_changed) NewGraphics ();
334
335 int rh = height /2 ;
336 int rw = width /2 ;
337
338 wxString s;
339 s.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x+rw,y+rh, rw, rh );
340 s = s + wxT(" /> ") + newline ;
341
342 write(s);
343
344 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
345 CalcBoundingBox(x, y) ;
346 CalcBoundingBox(x + width, y + height) ;
347 }
348
349
350 void wxSVGFileDC::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
351 {
352 /* Draws an arc of a circle, centred on (xc, yc), with starting point
353 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
354 and the current brush for filling the shape.
355
356 The arc is drawn in an anticlockwise direction from the start point to
357 the end point.
358
359 Might be better described as Pie drawing */
360
361 if (m_graphics_changed) NewGraphics ();
362 wxString s ;
363
364 // we need the radius of the circle which has two estimates
365 double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) );
366 double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) );
367
368 wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ;
369 if ( fabs ( r2-r1 ) > 3 ) //pixels
370 {
371 s = wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n") ;
372 write(s);
373 }
374
375 double theta1 = atan2((double)(yc-y1),(double)(x1-xc));
376 if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2;
377 double theta2 = atan2((double)(yc-y2), (double)(x2-xc));
378 if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2;
379 if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2 ;
380
381 int fArc ; // flag for large or small arc 0 means less than 180 degrees
382 if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0 ;
383
384 int fSweep = 0 ; // flag for sweep always 0
385
386 s.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
387 x1,y1, r1, r2, fArc, fSweep, x2, y2, xc, yc );
388
389 // the z means close the path and fill
390 s = s + wxT(" \" /> ") + newline ;
391
392
393 if (m_OK)
394 {
395 write(s);
396 }
397
398 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
399 }
400
401
402 void wxSVGFileDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
403 {
404 /*
405 Draws an arc of an ellipse. The current pen is used for drawing the arc
406 and the current brush is used for drawing the pie. This function is
407 currently only available for X window and PostScript device contexts.
408
409 x and y specify the x and y coordinates of the upper-left corner of the
410 rectangle that contains the ellipse.
411
412 width and height specify the width and height of the rectangle that
413 contains the ellipse.
414
415 start and end specify the start and end of the arc relative to the
416 three-o'clock position from the center of the rectangle. Angles are
417 specified in degrees (360 is a complete circle). Positive values mean
418 counter-clockwise motion. If start is equal to end, a complete ellipse
419 will be drawn. */
420
421 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
422
423 if (m_graphics_changed) NewGraphics ();
424
425 wxString s ;
426 //radius
427 double rx = w / 2 ;
428 double ry = h / 2 ;
429 // center
430 double xc = x + rx ;
431 double yc = y + ry ;
432
433 double xs, ys, xe, ye ;
434 xs = xc + rx * cos (DegToRad(sa)) ;
435 xe = xc + rx * cos (DegToRad(ea)) ;
436 ys = yc - ry * sin (DegToRad(sa)) ;
437 ye = yc - ry * sin (DegToRad(ea)) ;
438
439 ///now same as circle arc...
440
441 double theta1 = atan2(ys-yc, xs-xc);
442 double theta2 = atan2(ye-yc, xe-xc);
443
444 int fArc ; // flag for large or small arc 0 means less than 180 degrees
445 if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0 ;
446
447 int fSweep ;
448 if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0 ;
449
450 s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
451 int(xs), int(ys), int(rx), int(ry),
452 fArc, fSweep, int(xe), int(ye), int(xc), int(yc) );
453
454
455 s = s + wxT(" \" /> ") + newline ;
456
457 if (m_OK)
458 {
459 write(s);
460 }
461
462 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ;
463 }
464
465
466 void wxSVGFileDC::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , wxFont *font) const
467
468 {
469 wxScreenDC sDC ;
470
471 sDC.SetFont (m_font);
472 if ( font != NULL ) sDC.SetFont ( *font );
473 sDC.GetTextExtent(string, w, h, descent, externalLeading );
474 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed")) ;
475 }
476
477
478 wxCoord wxSVGFileDC::GetCharHeight() const
479
480 {
481 wxScreenDC sDC ;
482 sDC.SetFont (m_font);
483
484 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
485 return ( sDC.GetCharHeight() );
486
487 }
488
489
490 wxCoord wxSVGFileDC::GetCharWidth() const
491 {
492 wxScreenDC sDC ;
493 sDC.SetFont (m_font);
494
495 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing")) ;
496 return ( sDC.GetCharWidth() ) ;
497
498 }
499
500
501 /// Set Functions /////////////////////////////////////////////////////////////////
502 void wxSVGFileDC::SetBackground( const wxBrush &brush )
503 {
504
505 m_backgroundBrush = brush;
506 return;
507 }
508
509
510 void wxSVGFileDC::SetBackgroundMode( int mode )
511 {
512 m_backgroundMode = mode;
513 return;
514 }
515
516
517 void wxSVGFileDC::SetBrush(const wxBrush& brush)
518
519 {
520 m_brush = brush ;
521
522 m_graphics_changed = TRUE ;
523 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed")) ;
524 }
525
526
527 void wxSVGFileDC::SetPen(const wxPen& pen)
528 {
529 // width, color, ends, joins : currently implemented
530 // dashes, stipple : not implemented
531 m_pen = pen ;
532
533 m_graphics_changed = TRUE ;
534 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")) ;
535 }
536
537 void wxSVGFileDC::NewGraphics ()
538 {
539
540 int w = m_pen.GetWidth ();
541 wxColour c = m_pen.GetColour () ;
542
543 wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
544
545 sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () )
546 + wxT(" stroke:#") + wxColStr (c) + wxT("; ") ;
547
548 switch ( m_pen.GetCap () )
549 {
550 case wxCAP_PROJECTING :
551 sPenCap = wxT("stroke-linecap:square; ") ;
552 break ;
553 case wxCAP_BUTT :
554 sPenCap = wxT("stroke-linecap:butt; ") ;
555 break ;
556 case wxCAP_ROUND :
557 default :
558 sPenCap = wxT("stroke-linecap:round; ") ;
559 };
560 switch ( m_pen.GetJoin () )
561 {
562 case wxJOIN_BEVEL :
563 sPenJoin = wxT("stroke-linejoin:bevel; ") ;
564 break ;
565 case wxJOIN_MITER :
566 sPenJoin = wxT("stroke-linejoin:miter; ") ;
567 break ;
568 case wxJOIN_ROUND :
569 default :
570 sPenJoin = wxT("stroke-linejoin:round; ") ;
571 };
572
573 switch ( m_pen.GetStyle () )
574 {
575 case wxSOLID :
576 sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
577 break ;
578 case wxTRANSPARENT :
579 sPenStyle = wxT("stroke-opacity:0.0; stroke-opacity:0.0; ") ;
580 break ;
581 default :
582 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available")) ;
583 sWarn = sWarn + wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n") ;
584 }
585
586 sLast.Printf ( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
587 w, m_OriginX, m_OriginY, m_scaleX, m_scaleY );
588
589 s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
590 write(s);
591 m_graphics_changed = FALSE ;
592 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")) ;
593 }
594
595
596 void wxSVGFileDC::SetFont(const wxFont& font)
597
598 {
599 m_font = font ;
600
601 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")) ;
602 }
603
604
605 void wxSVGFileDC::ComputeScaleAndOrigin()
606 {
607 m_scaleX = m_logicalScaleX * m_userScaleX;
608 m_scaleY = m_logicalScaleY * m_userScaleY;
609 m_OriginX = m_logicalOriginX * m_logicalScaleX + m_deviceOriginX ;
610 m_OriginY = m_logicalOriginY * m_logicalScaleY + m_deviceOriginY ;
611 m_graphics_changed = TRUE;
612 }
613
614
615 int wxSVGFileDC::GetMapMode()
616 {
617 return m_mappingMode ;
618 }
619
620
621 void wxSVGFileDC::SetMapMode( int mode )
622 {
623 switch (mode)
624 {
625 case wxMM_TWIPS:
626 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
627 break;
628 case wxMM_POINTS:
629 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
630 break;
631 case wxMM_METRIC:
632 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
633 break;
634 case wxMM_LOMETRIC:
635 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
636 break;
637 default:
638 case wxMM_TEXT:
639 SetLogicalScale( 1.0, 1.0 );
640 break;
641 }
642 m_mappingMode = mode;
643
644 /* we don't do this mega optimisation
645 if (mode != wxMM_TEXT)
646 {
647 m_needComputeScaleX = TRUE;
648 m_needComputeScaleY = TRUE;
649 }
650 */
651 }
652
653
654 void wxSVGFileDC::GetUserScale(double *x, double *y) const
655 {
656 *x = m_userScaleX ;
657 *y = m_userScaleY ;
658 }
659
660
661 void wxSVGFileDC::SetUserScale( double x, double y )
662 {
663 // allow negative ? -> no
664 m_userScaleX = x;
665 m_userScaleY = y;
666 ComputeScaleAndOrigin();
667 }
668
669
670 void wxSVGFileDC::SetLogicalScale( double x, double y )
671 {
672 // allow negative ?
673 m_logicalScaleX = x;
674 m_logicalScaleY = y;
675 ComputeScaleAndOrigin();
676 }
677
678
679 void wxSVGFileDC::SetLogicalOrigin( wxCoord x, wxCoord y )
680 {
681 // is this still correct ?
682 m_logicalOriginX = x * m_signX;
683 m_logicalOriginY = y * m_signY;
684 ComputeScaleAndOrigin();
685 }
686
687
688 void wxSVGFileDC::SetDeviceOrigin( wxCoord x, wxCoord y )
689 {
690 // only wxPostScripDC has m_signX = -1,
691 m_deviceOriginX = x;
692 m_deviceOriginY = y;
693 ComputeScaleAndOrigin();
694 }
695
696
697 void wxSVGFileDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
698 {
699 // only wxPostScripDC has m_signX = -1,
700 m_signX = (xLeftRight ? 1 : -1);
701 m_signY = (yBottomUp ? -1 : 1);
702 ComputeScaleAndOrigin();
703 }
704
705
706 // export a bitmap as a raster image in png
707 bool wxSVGFileDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
708 wxDC* source, wxCoord xsrc, wxCoord ysrc,
709 int logicalFunc /*= wxCOPY*/, bool useMask /*= FALSE*/,
710 wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/)
711 {
712 if (logicalFunc != wxCOPY)
713 {
714 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
715 return FALSE ;
716 }
717 if (useMask != FALSE)
718 {
719 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
720 return FALSE ;
721 }
722 wxBitmap myBitmap (width, height) ;
723 wxMemoryDC memDC;
724 memDC.SelectObject( myBitmap );
725 memDC.Blit(0, 0, width, height, source, xsrc, ysrc);
726 memDC.SelectObject( wxNullBitmap );
727 DoDrawBitmap(myBitmap, xdest, ydest);
728 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed")) ;
729 return FALSE ;
730 }
731
732
733 void wxSVGFileDC::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y)
734 {
735 wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() ) ;
736 wxMemoryDC memDC;
737 memDC.SelectObject( myBitmap );
738 memDC.DrawIcon(myIcon,0,0);
739 memDC.SelectObject( wxNullBitmap );
740 DoDrawBitmap(myBitmap, x, y);
741 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
742 return ;
743 }
744
745
746
747 void wxSVGFileDC::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ )
748 {
749 if (m_graphics_changed) NewGraphics ();
750
751 wxString sTmp, s, sPNG ;
752 wxImage::AddHandler(new wxPNGHandler);
753
754 // create suitable file name
755 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
756 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
757 while (wxFile::Exists(sPNG) )
758 {
759 m_sub_images ++ ;
760 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
761 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
762 }
763
764 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
765 wxBitmap myBitmap = bmp ;
766 //save it
767 bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG);
768
769 // refrence the bitmap from the SVG doc
770 int w = myBitmap.GetWidth();
771 int h = myBitmap.GetHeight();
772 sTmp.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x,y,w,h );
773 s = s + sTmp ;
774 sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
775 s = s + sTmp + wxT("<title>Image from wxSVG</title> </image>") + newline;
776
777 if (m_OK && bPNG_OK)
778 {
779 write(s);
780 }
781 m_OK = m_outfile->Ok () && bPNG_OK;
782 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
783
784 return ;
785 }
786
787
788 // ---------------------------------------------------------------------------
789 // coordinates transformations
790 // ---------------------------------------------------------------------------
791
792 wxCoord wxSVGFileDC::DeviceToLogicalX(wxCoord x) const
793 {
794 return XDEV2LOG(x);
795 }
796
797
798 wxCoord wxSVGFileDC::DeviceToLogicalY(wxCoord y) const
799 {
800 return YDEV2LOG(y);
801 }
802
803
804 wxCoord wxSVGFileDC::DeviceToLogicalXRel(wxCoord x) const
805 {
806 return XDEV2LOGREL(x);
807 }
808
809
810 wxCoord wxSVGFileDC::DeviceToLogicalYRel(wxCoord y) const
811 {
812 return YDEV2LOGREL(y);
813 }
814
815
816 wxCoord wxSVGFileDC::LogicalToDeviceX(wxCoord x) const
817 {
818 return XLOG2DEV(x);
819 }
820
821
822 wxCoord wxSVGFileDC::LogicalToDeviceY(wxCoord y) const
823 {
824 return YLOG2DEV(y);
825 }
826
827
828 wxCoord wxSVGFileDC::LogicalToDeviceXRel(wxCoord x) const
829 {
830 return XLOG2DEVREL(x);
831 }
832
833
834 wxCoord wxSVGFileDC::LogicalToDeviceYRel(wxCoord y) const
835 {
836 return YLOG2DEVREL(y);
837 }
838
839 void wxSVGFileDC::write(const wxString &s)
840 {
841 const wxWX2MBbuf buf = s.mb_str(wxConvUTF8);
842 m_outfile->Write(buf, strlen((const char *)buf));
843 m_OK = m_outfile->Ok();
844 }
845
846 #ifdef __BORLANDC__
847 #pragma warn .rch
848 #pragma warn .ccc
849 #endif