]> git.saurik.com Git - wxWidgets.git/blob - src/common/dcsvg.cpp
removed extra semicolons (patch #1700459; fixes compilation with gcc's -pedantic...
[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 #ifndef WX_PRECOMP
19 #include "wx/wx.h"
20 #endif
21
22 #include "wx/dcsvg.h"
23 #include "wx/image.h"
24
25 #define wxSVG_DEBUG FALSE
26 // or TRUE to see the calls being executed
27
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 static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
34
35 wxString wxColStr ( wxColour c )
36 {
37 unsigned char r, g, b ;
38 r = c.Red ();
39 g = c.Green ();
40 b = c. Blue ();
41
42 // possible Unicode bug here
43 wxString s = wxDecToHex(r) + wxDecToHex(g) + wxDecToHex(b) ;
44 return s ;
45 }
46
47
48 wxString wxBrushString ( wxColour c, int style )
49 {
50 wxString s = wxT("fill:#") + wxColStr (c) + semicolon + space ;
51 switch ( style )
52 {
53 case wxSOLID :
54 s = s + wxT("fill-opacity:1.0; ");
55 break ;
56 case wxTRANSPARENT:
57 s = s + wxT("fill-opacity:0.0; ");
58 break ;
59
60 default :
61 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::Requested Brush Style not available")) ;
62
63 }
64 s = s + newline ;
65 return s ;
66 }
67
68
69 void wxSVGFileDC::Init (wxString f, int Width, int Height, float dpi)
70
71 {
72 //set up things first wxDCBase does all this?
73 m_width = Width ;
74 m_height = Height ;
75
76 m_clipping = FALSE;
77 m_OK = TRUE;
78
79 m_mm_to_pix_x = dpi/25.4;
80 m_mm_to_pix_y = dpi/25.4;
81
82 m_signX = m_signY = 1;
83
84 m_userScaleX = m_userScaleY =
85 m_deviceOriginX = m_deviceOriginY = 0;
86
87 m_OriginX = m_OriginY = 0;
88 m_logicalOriginX = m_logicalOriginY = 0;
89 m_logicalScaleX = m_logicalScaleY = 0 ;
90 m_scaleX = m_scaleY = 1.0 ;
91
92 m_logicalFunction = wxCOPY;
93 m_backgroundMode = wxTRANSPARENT;
94 m_mappingMode = wxMM_TEXT;
95
96 m_backgroundBrush = *wxTRANSPARENT_BRUSH;
97 m_textForegroundColour = *wxBLACK;
98 m_textBackgroundColour = *wxWHITE;
99 m_colour = wxColourDisplay();
100
101 m_pen = *wxBLACK_PEN;
102 m_font = *wxNORMAL_FONT;
103 m_brush = *wxWHITE_BRUSH;
104
105 m_graphics_changed = TRUE ;
106
107 ////////////////////code here
108
109 m_outfile = new wxFileOutputStream(f) ;
110 m_OK = m_outfile->Ok ();
111 if (m_OK)
112 {
113 m_filename = f ;
114 m_sub_images = 0 ;
115 wxString s ;
116 s = wxT("<?xml version=\"1.0\" standalone=\"no\"?>") ; s = s + newline ;
117 write(s);
118 s = wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline ;
119 write(s);
120 s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline ;
121 write(s);
122 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 );
123 write(s);
124 s = wxT("<title>SVG Picture created as ") + wxFileNameFromPath(f) + wxT(" </title>") + newline ;
125 write(s);
126 s = wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion + wxT(" </desc>")+ newline ;
127 write(s);
128 s = wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline ;
129 write(s);
130
131 }
132 }
133
134
135 // constructors
136 wxSVGFileDC::wxSVGFileDC (wxString f)
137 {
138 // quarter 640x480 screen display at 72 dpi
139 Init (f,320,240,72.0);
140 }
141
142 wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height)
143 {
144 Init (f,Width,Height,72.0);
145 }
146
147 wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height, float dpi)
148 {
149 Init (f,Width,Height,dpi);
150 }
151
152 wxSVGFileDC::~wxSVGFileDC()
153 {
154 wxString s = wxT("</g> \n</svg> \n") ;
155 write(s);
156 delete m_outfile ;
157 }
158
159
160 //////////////////////////////////////////////////////////////////////////////////////////
161
162 void wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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 DrawLine ( x1,y1,x1,y1 );
194 s = wxT("</g>");
195 write(s);
196 }
197
198
199 void wxSVGFileDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height)
200 {
201 wxDCBase::DoDrawCheckMark (x1,y1,width,height) ;
202 }
203
204
205 void wxSVGFileDC::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 wxSVGFileDC::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 == wxSOLID)
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 wxSVGFileDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
275 {
276 DoDrawRoundedRectangle(x, y, width, height, 0) ;
277 }
278
279
280 void wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , 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 wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::SetBackground( const wxBrush &brush )
498 {
499
500 m_backgroundBrush = brush;
501 return;
502 }
503
504
505 void wxSVGFileDC::SetBackgroundMode( int mode )
506 {
507 m_backgroundMode = mode;
508 return;
509 }
510
511
512 void wxSVGFileDC::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 wxSVGFileDC::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 wxSVGFileDC::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 wxSOLID :
571 sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
572 break ;
573 case wxTRANSPARENT :
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, m_OriginX, m_OriginY, 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 wxSVGFileDC::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 void wxSVGFileDC::ComputeScaleAndOrigin()
601 {
602 m_scaleX = m_logicalScaleX * m_userScaleX;
603 m_scaleY = m_logicalScaleY * m_userScaleY;
604 m_OriginX = m_logicalOriginX * m_logicalScaleX + m_deviceOriginX ;
605 m_OriginY = m_logicalOriginY * m_logicalScaleY + m_deviceOriginY ;
606 m_graphics_changed = TRUE;
607 }
608
609
610 int wxSVGFileDC::GetMapMode()
611 {
612 return m_mappingMode ;
613 }
614
615
616 void wxSVGFileDC::SetMapMode( int mode )
617 {
618 switch (mode)
619 {
620 case wxMM_TWIPS:
621 SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
622 break;
623 case wxMM_POINTS:
624 SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
625 break;
626 case wxMM_METRIC:
627 SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
628 break;
629 case wxMM_LOMETRIC:
630 SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
631 break;
632 default:
633 case wxMM_TEXT:
634 SetLogicalScale( 1.0, 1.0 );
635 break;
636 }
637 m_mappingMode = mode;
638
639 /* we don't do this mega optimisation
640 if (mode != wxMM_TEXT)
641 {
642 m_needComputeScaleX = TRUE;
643 m_needComputeScaleY = TRUE;
644 }
645 */
646 }
647
648
649 void wxSVGFileDC::GetUserScale(double *x, double *y) const
650 {
651 *x = m_userScaleX ;
652 *y = m_userScaleY ;
653 }
654
655
656 void wxSVGFileDC::SetUserScale( double x, double y )
657 {
658 // allow negative ? -> no
659 m_userScaleX = x;
660 m_userScaleY = y;
661 ComputeScaleAndOrigin();
662 }
663
664
665 void wxSVGFileDC::SetLogicalScale( double x, double y )
666 {
667 // allow negative ?
668 m_logicalScaleX = x;
669 m_logicalScaleY = y;
670 ComputeScaleAndOrigin();
671 }
672
673
674 void wxSVGFileDC::SetLogicalOrigin( wxCoord x, wxCoord y )
675 {
676 // is this still correct ?
677 m_logicalOriginX = x * m_signX;
678 m_logicalOriginY = y * m_signY;
679 ComputeScaleAndOrigin();
680 }
681
682
683 void wxSVGFileDC::SetDeviceOrigin( wxCoord x, wxCoord y )
684 {
685 // only wxPostScripDC has m_signX = -1,
686 m_deviceOriginX = x;
687 m_deviceOriginY = y;
688 ComputeScaleAndOrigin();
689 }
690
691
692 void wxSVGFileDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
693 {
694 // only wxPostScripDC has m_signX = -1,
695 m_signX = (xLeftRight ? 1 : -1);
696 m_signY = (yBottomUp ? -1 : 1);
697 ComputeScaleAndOrigin();
698 }
699
700
701 // export a bitmap as a raster image in png
702 bool wxSVGFileDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
703 wxDC* source, wxCoord xsrc, wxCoord ysrc,
704 int logicalFunc /*= wxCOPY*/, bool useMask /*= FALSE*/,
705 wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/)
706 {
707 if (logicalFunc != wxCOPY)
708 {
709 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
710 return FALSE ;
711 }
712 if (useMask != FALSE)
713 {
714 wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
715 return FALSE ;
716 }
717 wxBitmap myBitmap (width, height) ;
718 wxMemoryDC memDC;
719 memDC.SelectObject( myBitmap );
720 memDC.Blit(0, 0, width, height, source, xsrc, ysrc);
721 memDC.SelectObject( wxNullBitmap );
722 DoDrawBitmap(myBitmap, xdest, ydest);
723 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed")) ;
724 return FALSE ;
725 }
726
727
728 void wxSVGFileDC::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y)
729 {
730 wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() ) ;
731 wxMemoryDC memDC;
732 memDC.SelectObject( myBitmap );
733 memDC.DrawIcon(myIcon,0,0);
734 memDC.SelectObject( wxNullBitmap );
735 DoDrawBitmap(myBitmap, x, y);
736 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
737 return ;
738 }
739
740
741
742 void wxSVGFileDC::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ )
743 {
744 if (m_graphics_changed) NewGraphics ();
745
746 wxString sTmp, s, sPNG ;
747 wxImage::AddHandler(new wxPNGHandler);
748
749 // create suitable file name
750 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
751 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
752 while (wxFile::Exists(sPNG) )
753 {
754 m_sub_images ++ ;
755 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
756 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
757 }
758
759 //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
760 wxBitmap myBitmap = bmp ;
761 //save it
762 bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG);
763
764 // refrence the bitmap from the SVG doc
765 int w = myBitmap.GetWidth();
766 int h = myBitmap.GetHeight();
767 sTmp.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x,y,w,h );
768 s = s + sTmp ;
769 sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
770 s = s + sTmp + wxT("<title>Image from wxSVG</title> </image>") + newline;
771
772 if (m_OK && bPNG_OK)
773 {
774 write(s);
775 }
776 m_OK = m_outfile->Ok () && bPNG_OK;
777 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
778
779 return ;
780 }
781
782
783 // ---------------------------------------------------------------------------
784 // coordinates transformations
785 // ---------------------------------------------------------------------------
786
787 wxCoord wxSVGFileDC::DeviceToLogicalX(wxCoord x) const
788 {
789 return XDEV2LOG(x);
790 }
791
792
793 wxCoord wxSVGFileDC::DeviceToLogicalY(wxCoord y) const
794 {
795 return YDEV2LOG(y);
796 }
797
798
799 wxCoord wxSVGFileDC::DeviceToLogicalXRel(wxCoord x) const
800 {
801 return XDEV2LOGREL(x);
802 }
803
804
805 wxCoord wxSVGFileDC::DeviceToLogicalYRel(wxCoord y) const
806 {
807 return YDEV2LOGREL(y);
808 }
809
810
811 wxCoord wxSVGFileDC::LogicalToDeviceX(wxCoord x) const
812 {
813 return XLOG2DEV(x);
814 }
815
816
817 wxCoord wxSVGFileDC::LogicalToDeviceY(wxCoord y) const
818 {
819 return YLOG2DEV(y);
820 }
821
822
823 wxCoord wxSVGFileDC::LogicalToDeviceXRel(wxCoord x) const
824 {
825 return XLOG2DEVREL(x);
826 }
827
828
829 wxCoord wxSVGFileDC::LogicalToDeviceYRel(wxCoord y) const
830 {
831 return YLOG2DEVREL(y);
832 }
833
834 void wxSVGFileDC::write(const wxString &s)
835 {
836 const wxWX2MBbuf buf = s.mb_str(wxConvUTF8);
837 m_outfile->Write(buf, strlen((const char *)buf));
838 m_OK = m_outfile->Ok();
839 }
840
841 #ifdef __BORLANDC__
842 #pragma warn .rch
843 #pragma warn .ccc
844 #endif