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