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