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