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