]> git.saurik.com Git - wxWidgets.git/blame - src/common/dcsvg.cpp
Silence warning about truncation since the comment says it ok
[wxWidgets.git] / src / common / dcsvg.cpp
CommitLineData
cdf3a589
CE
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
3454ecd5 21
cdf3a589
CE
22#include "wx/svg/dcsvg.h"
23
cdf3a589
CE
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
3454ecd5 38static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; } ;
cdf3a589
CE
39
40wxString 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
53wxString 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
74void 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 ;
85b88942 122 write(s);
cdf3a589 123 s = wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline ;
85b88942 124 write(s);
cdf3a589 125 s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline ;
85b88942 126 write(s);
cdf3a589 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 );
85b88942 128 write(s);
cdf3a589 129 s = wxT("<title>SVG Picture created as ") + wxFileNameFromPath(f) + wxT(" </title>") + newline ;
85b88942 130 write(s);
cdf3a589 131 s = wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion + wxT(" </desc>")+ newline ;
85b88942 132 write(s);
cdf3a589 133 s = wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline ;
85b88942 134 write(s);
cdf3a589
CE
135
136 }
cdf3a589
CE
137}
138
139
140// constructors
141wxSVGFileDC::wxSVGFileDC (wxString f)
3454ecd5 142{
cdf3a589
CE
143 // quarter 640x480 screen display at 72 dpi
144 Init (f,320,240,72.0);
145};
146
147wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height)
148{
149 Init (f,Width,Height,72.0);
150};
151
152wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height, float dpi)
153{
154 Init (f,Width,Height,dpi);
155};
156
157wxSVGFileDC::~wxSVGFileDC()
158{
159 wxString s = wxT("</g> \n</svg> \n") ;
85b88942 160 write(s);
cdf3a589
CE
161 delete m_outfile ;
162}
163
164
165//////////////////////////////////////////////////////////////////////////////////////////
166
167void 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 {
85b88942 174 write(s);
cdf3a589 175 }
cdf3a589
CE
176 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")) ;
177 CalcBoundingBox(x1, y1) ;
178 CalcBoundingBox(x2, y2) ;
179 return;
180};
181
182void 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
192void 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 ;
85b88942 197 write(s);
cdf3a589
CE
198 DrawLine ( x1,y1,x1,y1 );
199 s = wxT("</g>");
85b88942 200 write(s);
cdf3a589
CE
201}
202
203
204void wxSVGFileDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height)
205{
206 wxDCBase::DoDrawCheckMark (x1,y1,width,height) ;
207}
208
209
210void 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
217void 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);
216db41f 231 CalcBoundingBox((wxCoord)(x + w*cos(rad)), (wxCoord)(y - h*sin(rad)));
cdf3a589
CE
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);
216db41f 237 CalcBoundingBox((wxCoord)(x + h*sin(rad)), (wxCoord)(y + h*cos(rad)));
cdf3a589
CE
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 ;
85b88942 250 write(s);
cdf3a589
CE
251 }
252 //now do the text itself
253 s.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x,y );
3454ecd5 254
cdf3a589
CE
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;
3454ecd5 261
cdf3a589
CE
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;
3454ecd5 264
cdf3a589
CE
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 {
85b88942 272 write(s);
cdf3a589 273 }
cdf3a589
CE
274 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
275
276}
277
278
279void wxSVGFileDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
280{
281 DoDrawRoundedRectangle(x, y, width, height, 0) ;
282}
283
284
285void wxSVGFileDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
286
287{
288 if (m_graphics_changed) NewGraphics ();
289 wxString s ;
290
3454ecd5 291 s.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "),
cdf3a589
CE
292 x, y, width, height, radius );
293
294 s = s + wxT(" /> ") + newline ;
85b88942 295 write(s);
cdf3a589
CE
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
304void 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 ;
85b88942 324 write(s);
cdf3a589
CE
325
326 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
327}
328
329
330void 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
85b88942 342 write(s);
cdf3a589
CE
343
344 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
345 CalcBoundingBox(x, y) ;
346 CalcBoundingBox(x + width, y + height) ;
347}
348
349
350void 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") ;
85b88942 372 write(s);
cdf3a589
CE
373 }
374
fb88ba48 375 double theta1 = atan2((double)(yc-y1),(double)(x1-xc));
3454ecd5 376 if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2;
fb88ba48 377 double theta2 = atan2((double)(yc-y2), (double)(x2-xc));
3454ecd5
WS
378 if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2;
379 if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2 ;
cdf3a589
CE
380
381 int fArc ; // flag for large or small arc 0 means less than 180 degrees
3454ecd5 382 if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0 ;
cdf3a589
CE
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 {
85b88942 395 write(s);
cdf3a589 396 }
cdf3a589
CE
397
398 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
399}
400
401
402void 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 ;
3454ecd5 448 if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0 ;
cdf3a589
CE
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 {
85b88942 459 write(s);
cdf3a589 460 }
cdf3a589
CE
461
462 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ;
463}
464
465
466void 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
478wxCoord 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
490wxCoord 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 /////////////////////////////////////////////////////////////////
502void wxSVGFileDC::SetBackground( const wxBrush &brush )
503{
504
505 m_backgroundBrush = brush;
506 return;
507}
508
509
510void wxSVGFileDC::SetBackgroundMode( int mode )
511{
512 m_backgroundMode = mode;
513 return;
514}
515
516
517void 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
527void wxSVGFileDC::SetPen(const wxPen& pen)
528{
529 // width, color, ends, joins : currently implemented
530 // dashes, stipple : not implemented
531 m_pen = pen ;
3454ecd5 532
cdf3a589
CE
533 m_graphics_changed = TRUE ;
534 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")) ;
535}
536
537void 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;
3454ecd5
WS
544
545 sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () )
546 + wxT(" stroke:#") + wxColStr (c) + wxT("; ") ;
547
cdf3a589
CE
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
3454ecd5 586 sLast.Printf ( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
cdf3a589
CE
587 w, m_OriginX, m_OriginY, m_scaleX, m_scaleY );
588
589 s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
85b88942 590 write(s);
cdf3a589
CE
591 m_graphics_changed = FALSE ;
592 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")) ;
593}
594
595
596void wxSVGFileDC::SetFont(const wxFont& font)
597
598{
599 m_font = font ;
3454ecd5 600
cdf3a589
CE
601 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")) ;
602}
603
604
605void 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
615int wxSVGFileDC::GetMapMode()
616{
617 return m_mappingMode ;
618}
619
620
621void 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
654void wxSVGFileDC::GetUserScale(double *x, double *y) const
655{
656 *x = m_userScaleX ;
657 *y = m_userScaleY ;
658}
659
660
661void wxSVGFileDC::SetUserScale( double x, double y )
662{
663 // allow negative ? -> no
664 m_userScaleX = x;
665 m_userScaleY = y;
666 ComputeScaleAndOrigin();
667}
668
669
670void wxSVGFileDC::SetLogicalScale( double x, double y )
671{
672 // allow negative ?
673 m_logicalScaleX = x;
674 m_logicalScaleY = y;
675 ComputeScaleAndOrigin();
676}
677
678
679void 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
688void wxSVGFileDC::SetDeviceOrigin( wxCoord x, wxCoord y )
689{
3454ecd5 690 // only wxPostScripDC has m_signX = -1,
cdf3a589
CE
691 m_deviceOriginX = x;
692 m_deviceOriginY = y;
693 ComputeScaleAndOrigin();
694}
695
696
697void wxSVGFileDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
698{
3454ecd5 699 // only wxPostScripDC has m_signX = -1,
cdf3a589
CE
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
707bool wxSVGFileDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
3454ecd5
WS
708 wxDC* source, wxCoord xsrc, wxCoord ysrc,
709 int logicalFunc /*= wxCOPY*/, bool useMask /*= FALSE*/,
710 wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/)
cdf3a589 711{
cdf3a589
CE
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
733void 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
3454ecd5 746
1a55595e 747void wxSVGFileDC::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ )
cdf3a589
CE
748{
749 if (m_graphics_changed) NewGraphics ();
750
3454ecd5 751 wxString sTmp, s, sPNG ;
cdf3a589
CE
752 wxImage::AddHandler(new wxPNGHandler);
753
3454ecd5 754// create suitable file name
cdf3a589
CE
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 }
3454ecd5 763
cdf3a589
CE
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;
3454ecd5 776
cdf3a589
CE
777 if (m_OK && bPNG_OK)
778 {
85b88942 779 write(s);
cdf3a589
CE
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
792wxCoord wxSVGFileDC::DeviceToLogicalX(wxCoord x) const
793{
794 return XDEV2LOG(x);
795}
796
797
798wxCoord wxSVGFileDC::DeviceToLogicalY(wxCoord y) const
799{
800 return YDEV2LOG(y);
801}
802
803
804wxCoord wxSVGFileDC::DeviceToLogicalXRel(wxCoord x) const
805{
806 return XDEV2LOGREL(x);
807}
808
809
810wxCoord wxSVGFileDC::DeviceToLogicalYRel(wxCoord y) const
811{
812 return YDEV2LOGREL(y);
813}
814
815
816wxCoord wxSVGFileDC::LogicalToDeviceX(wxCoord x) const
817{
818 return XLOG2DEV(x);
819}
820
821
822wxCoord wxSVGFileDC::LogicalToDeviceY(wxCoord y) const
823{
824 return YLOG2DEV(y);
825}
826
827
828wxCoord wxSVGFileDC::LogicalToDeviceXRel(wxCoord x) const
829{
830 return XLOG2DEVREL(x);
831}
832
833
834wxCoord wxSVGFileDC::LogicalToDeviceYRel(wxCoord y) const
835{
836 return YLOG2DEVREL(y);
837}
838
85b88942
JS
839void wxSVGFileDC::write(const wxString &s)
840{
3454ecd5
WS
841 const wxWX2MBbuf buf = s.mb_str(wxConvUTF8);
842 m_outfile->Write(buf, strlen((const char *)buf));
843 m_OK = m_outfile->Ok();
85b88942 844}
cdf3a589
CE
845
846#ifdef __BORLANDC__
847#pragma warn .rch
848#pragma warn .ccc
849#endif