]> git.saurik.com Git - wxWidgets.git/blame - src/common/dcsvg.cpp
use wxArrayString instead of wxStringList
[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
888dde65 292void wxSVGFileDCImpl::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
cdf3a589
CE
293{
294 if (m_graphics_changed) NewGraphics ();
13cfc51d
FM
295 wxString s, sTmp;
296 s = wxT("<polygon style=\"");
cdf3a589
CE
297 if ( fillStyle == wxODDEVEN_RULE )
298 s = s + wxT("fill-rule:evenodd; ");
299 else
300 s = s + wxT("fill-rule:nonzero; ");
301
13cfc51d 302 s = s + wxT("\" \npoints=\"");
cdf3a589
CE
303
304 for (int i = 0; i < n; i++)
305 {
306 sTmp.Printf ( wxT("%d,%d"), points [i].x+xoffset, points[i].y+yoffset );
13cfc51d 307 s = s + sTmp + newline;
cdf3a589
CE
308 CalcBoundingBox ( points [i].x+xoffset, points[i].y+yoffset);
309 }
13cfc51d
FM
310 s = s + wxT("\" /> ");
311 s = s + newline;
85b88942 312 write(s);
cdf3a589 313
13cfc51d 314 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed"));
cdf3a589
CE
315}
316
888dde65 317void wxSVGFileDCImpl::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
cdf3a589
CE
318
319{
320 if (m_graphics_changed) NewGraphics ();
321
13cfc51d
FM
322 int rh = height /2;
323 int rw = width /2;
cdf3a589
CE
324
325 wxString s;
326 s.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x+rw,y+rh, rw, rh );
13cfc51d 327 s = s + wxT(" /> ") + newline;
cdf3a589 328
85b88942 329 write(s);
cdf3a589 330
13cfc51d
FM
331 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed"));
332 CalcBoundingBox(x, y);
333 CalcBoundingBox(x + width, y + height);
cdf3a589
CE
334}
335
888dde65 336void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
cdf3a589
CE
337{
338 /* Draws an arc of a circle, centred on (xc, yc), with starting point
339 (x1, y1) and ending at (x2, y2). The current pen is used for the outline
340 and the current brush for filling the shape.
341
342 The arc is drawn in an anticlockwise direction from the start point to
343 the end point.
344
345 Might be better described as Pie drawing */
346
347 if (m_graphics_changed) NewGraphics ();
13cfc51d 348 wxString s;
cdf3a589
CE
349
350 // we need the radius of the circle which has two estimates
351 double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) );
352 double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) );
353
13cfc51d 354 wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle"));
cdf3a589
CE
355 if ( fabs ( r2-r1 ) > 3 ) //pixels
356 {
13cfc51d 357 s = wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n");
85b88942 358 write(s);
cdf3a589
CE
359 }
360
fb88ba48 361 double theta1 = atan2((double)(yc-y1),(double)(x1-xc));
3454ecd5 362 if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2;
fb88ba48 363 double theta2 = atan2((double)(yc-y2), (double)(x2-xc));
3454ecd5 364 if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2;
13cfc51d 365 if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2;
cdf3a589 366
13cfc51d
FM
367 int fArc; // flag for large or small arc 0 means less than 180 degrees
368 if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0;
cdf3a589 369
13cfc51d 370 int fSweep = 0; // flag for sweep always 0
cdf3a589
CE
371
372 s.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
373 x1,y1, r1, r2, fArc, fSweep, x2, y2, xc, yc );
374
375 // the z means close the path and fill
13cfc51d 376 s = s + wxT(" \" /> ") + newline;
cdf3a589
CE
377
378
379 if (m_OK)
380 {
85b88942 381 write(s);
cdf3a589 382 }
cdf3a589 383
13cfc51d 384 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed"));
cdf3a589
CE
385}
386
888dde65 387void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
cdf3a589
CE
388{
389 /*
390 Draws an arc of an ellipse. The current pen is used for drawing the arc
391 and the current brush is used for drawing the pie. This function is
392 currently only available for X window and PostScript device contexts.
393
394 x and y specify the x and y coordinates of the upper-left corner of the
395 rectangle that contains the ellipse.
396
397 width and height specify the width and height of the rectangle that
398 contains the ellipse.
399
400 start and end specify the start and end of the arc relative to the
401 three-o'clock position from the center of the rectangle. Angles are
402 specified in degrees (360 is a complete circle). Positive values mean
403 counter-clockwise motion. If start is equal to end, a complete ellipse
404 will be drawn. */
405
406 //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
407
408 if (m_graphics_changed) NewGraphics ();
409
13cfc51d 410 wxString s;
cdf3a589 411 //radius
13cfc51d
FM
412 double rx = w / 2;
413 double ry = h / 2;
cdf3a589 414 // center
13cfc51d
FM
415 double xc = x + rx;
416 double yc = y + ry;
cdf3a589 417
13cfc51d
FM
418 double xs, ys, xe, ye;
419 xs = xc + rx * cos (DegToRad(sa));
420 xe = xc + rx * cos (DegToRad(ea));
421 ys = yc - ry * sin (DegToRad(sa));
422 ye = yc - ry * sin (DegToRad(ea));
cdf3a589
CE
423
424 ///now same as circle arc...
425
426 double theta1 = atan2(ys-yc, xs-xc);
427 double theta2 = atan2(ye-yc, xe-xc);
428
13cfc51d
FM
429 int fArc; // flag for large or small arc 0 means less than 180 degrees
430 if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0;
cdf3a589 431
13cfc51d
FM
432 int fSweep;
433 if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0;
cdf3a589
CE
434
435 s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
436 int(xs), int(ys), int(rx), int(ry),
437 fArc, fSweep, int(xe), int(ye), int(xc), int(yc) );
438
439
13cfc51d 440 s = s + wxT(" \" /> ") + newline;
cdf3a589
CE
441
442 if (m_OK)
443 {
85b88942 444 write(s);
cdf3a589 445 }
cdf3a589 446
13cfc51d 447 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed"));
cdf3a589
CE
448}
449
888dde65 450void wxSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const
cdf3a589
CE
451
452{
13cfc51d 453 wxScreenDC sDC;
cdf3a589
CE
454
455 sDC.SetFont (m_font);
456 if ( font != NULL ) sDC.SetFont ( *font );
457 sDC.GetTextExtent(string, w, h, descent, externalLeading );
13cfc51d 458 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed"));
cdf3a589
CE
459}
460
888dde65 461wxCoord wxSVGFileDCImpl::GetCharHeight() const
cdf3a589
CE
462
463{
13cfc51d 464 wxScreenDC sDC;
cdf3a589
CE
465 sDC.SetFont (m_font);
466
13cfc51d 467 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing"));
cdf3a589
CE
468 return ( sDC.GetCharHeight() );
469
470}
471
888dde65 472wxCoord wxSVGFileDCImpl::GetCharWidth() const
cdf3a589 473{
13cfc51d 474 wxScreenDC sDC;
cdf3a589
CE
475 sDC.SetFont (m_font);
476
13cfc51d
FM
477 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing"));
478 return ( sDC.GetCharWidth() );
cdf3a589
CE
479
480}
481
482
13cfc51d
FM
483// ----------------------------------------------------------
484// wxSVGFileDCImpl - set functions
485// ----------------------------------------------------------
486
888dde65 487void wxSVGFileDCImpl::SetBackground( const wxBrush &brush )
cdf3a589
CE
488{
489
490 m_backgroundBrush = brush;
491 return;
492}
493
494
888dde65 495void wxSVGFileDCImpl::SetBackgroundMode( int mode )
cdf3a589
CE
496{
497 m_backgroundMode = mode;
498 return;
499}
500
501
888dde65 502void wxSVGFileDCImpl::SetBrush(const wxBrush& brush)
cdf3a589
CE
503
504{
13cfc51d 505 m_brush = brush;
cdf3a589 506
13cfc51d
FM
507 m_graphics_changed = true;
508 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed"));
cdf3a589
CE
509}
510
511
888dde65 512void wxSVGFileDCImpl::SetPen(const wxPen& pen)
cdf3a589
CE
513{
514 // width, color, ends, joins : currently implemented
515 // dashes, stipple : not implemented
13cfc51d 516 m_pen = pen;
3454ecd5 517
13cfc51d
FM
518 m_graphics_changed = true;
519 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed"));
cdf3a589
CE
520}
521
888dde65 522void wxSVGFileDCImpl::NewGraphics ()
cdf3a589
CE
523{
524
525 int w = m_pen.GetWidth ();
13cfc51d 526 wxColour c = m_pen.GetColour ();
cdf3a589
CE
527
528 wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
3454ecd5
WS
529
530 sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () )
13cfc51d 531 + wxT(" stroke:#") + wxColStr (c) + wxT("; ");
3454ecd5 532
cdf3a589
CE
533 switch ( m_pen.GetCap () )
534 {
535 case wxCAP_PROJECTING :
13cfc51d
FM
536 sPenCap = wxT("stroke-linecap:square; ");
537 break;
cdf3a589 538 case wxCAP_BUTT :
13cfc51d
FM
539 sPenCap = wxT("stroke-linecap:butt; ");
540 break;
cdf3a589
CE
541 case wxCAP_ROUND :
542 default :
13cfc51d 543 sPenCap = wxT("stroke-linecap:round; ");
cdf3a589
CE
544 };
545 switch ( m_pen.GetJoin () )
546 {
547 case wxJOIN_BEVEL :
13cfc51d
FM
548 sPenJoin = wxT("stroke-linejoin:bevel; ");
549 break;
cdf3a589 550 case wxJOIN_MITER :
13cfc51d
FM
551 sPenJoin = wxT("stroke-linejoin:miter; ");
552 break;
cdf3a589
CE
553 case wxJOIN_ROUND :
554 default :
13cfc51d 555 sPenJoin = wxT("stroke-linejoin:round; ");
cdf3a589
CE
556 };
557
558 switch ( m_pen.GetStyle () )
559 {
04ee05f9 560 case wxPENSTYLE_SOLID :
13cfc51d
FM
561 sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ");
562 break;
04ee05f9 563 case wxPENSTYLE_TRANSPARENT :
13cfc51d
FM
564 sPenStyle = wxT("stroke-opacity:0.0; stroke-opacity:0.0; ");
565 break;
cdf3a589 566 default :
13cfc51d
FM
567 wxASSERT_MSG(false, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available"));
568 sWarn = sWarn + wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n");
cdf3a589
CE
569 }
570
621b83d9 571 sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),
13cfc51d 572 w, double(m_logicalOriginX), double(m_logicalOriginY), m_scaleX, m_scaleY );
cdf3a589
CE
573
574 s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
85b88942 575 write(s);
13cfc51d
FM
576 m_graphics_changed = false;
577 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed"));
cdf3a589
CE
578}
579
580
888dde65 581void wxSVGFileDCImpl::SetFont(const wxFont& font)
cdf3a589
CE
582
583{
13cfc51d 584 m_font = font;
3454ecd5 585
13cfc51d 586 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed"));
cdf3a589
CE
587}
588
cdf3a589 589// export a bitmap as a raster image in png
888dde65 590bool wxSVGFileDCImpl::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
13cfc51d
FM
591 wxDC* source, wxCoord xsrc, wxCoord ysrc,
592 int logicalFunc /*= wxCOPY*/, bool useMask /*= false*/,
593 wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/)
cdf3a589 594{
cdf3a589
CE
595 if (logicalFunc != wxCOPY)
596 {
13cfc51d
FM
597 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible"));
598 return false;
cdf3a589 599 }
13cfc51d 600 if (useMask != false)
cdf3a589 601 {
13cfc51d
FM
602 wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested false mask; this is not possible"));
603 return false;
cdf3a589 604 }
13cfc51d 605 wxBitmap myBitmap (width, height);
cdf3a589
CE
606 wxMemoryDC memDC;
607 memDC.SelectObject( myBitmap );
608 memDC.Blit(0, 0, width, height, source, xsrc, ysrc);
609 memDC.SelectObject( wxNullBitmap );
610 DoDrawBitmap(myBitmap, xdest, ydest);
13cfc51d
FM
611 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed"));
612 return false;
cdf3a589
CE
613}
614
888dde65 615void wxSVGFileDCImpl::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y)
cdf3a589 616{
13cfc51d 617 wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() );
cdf3a589
CE
618 wxMemoryDC memDC;
619 memDC.SelectObject( myBitmap );
620 memDC.DrawIcon(myIcon,0,0);
621 memDC.SelectObject( wxNullBitmap );
622 DoDrawBitmap(myBitmap, x, y);
13cfc51d
FM
623 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed"));
624 return;
cdf3a589
CE
625}
626
888dde65 627void wxSVGFileDCImpl::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ )
cdf3a589
CE
628{
629 if (m_graphics_changed) NewGraphics ();
630
13cfc51d 631 wxString sTmp, s, sPNG;
79d8d561
VS
632 if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG) == NULL )
633 wxImage::AddHandler(new wxPNGHandler);
cdf3a589 634
3454ecd5 635// create suitable file name
cdf3a589
CE
636 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
637 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
638 while (wxFile::Exists(sPNG) )
639 {
13cfc51d 640 m_sub_images ++;
cdf3a589
CE
641 sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
642 sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
643 }
3454ecd5 644
cdf3a589 645//create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
13cfc51d 646 wxBitmap myBitmap = bmp;
cdf3a589
CE
647//save it
648 bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG);
649
ddabd45b
CE
650// reference the bitmap from the SVG doc
651// only use filename & ext
652 sPNG = sPNG.AfterLast(wxFileName::GetPathSeparator());
653
13cfc51d 654// reference the bitmap from the SVG doc
cdf3a589
CE
655 int w = myBitmap.GetWidth();
656 int h = myBitmap.GetHeight();
657 sTmp.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x,y,w,h );
13cfc51d 658 s = s + sTmp;
cdf3a589
CE
659 sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
660 s = s + sTmp + wxT("<title>Image from wxSVG</title> </image>") + newline;
3454ecd5 661
cdf3a589
CE
662 if (m_OK && bPNG_OK)
663 {
85b88942 664 write(s);
cdf3a589
CE
665 }
666 m_OK = m_outfile->Ok () && bPNG_OK;
13cfc51d 667 wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed"));
cdf3a589 668
13cfc51d 669 return;
cdf3a589
CE
670}
671
888dde65 672void wxSVGFileDCImpl::write(const wxString &s)
621b83d9 673{
6243633c 674 const wxCharBuffer buf = s.utf8_str();
621b83d9
RR
675 m_outfile->Write(buf, strlen((const char *)buf));
676 m_OK = m_outfile->Ok();
677}
cdf3a589 678
621b83d9 679
cdf3a589
CE
680#ifdef __BORLANDC__
681#pragma warn .rch
682#pragma warn .ccc
683#endif
8e10778e 684
b0fc907f
VZ
685#endif // wxUSE_SVG
686