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