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