home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / contrib / src / svg / dcsvg.cpp next >
Text File  |  2002-06-19  |  25KB  |  857 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        svg.cpp
  3. // Purpose:     SVG sample
  4. // Author:      Chris Elliott
  5. // Modified by:
  6. // RCS-ID:      $Id: dcsvg.cpp,v 1.1 2002/06/19 09:16:19 CE Exp $
  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.  
  18. #ifndef WX_PRECOMP
  19. #include "wx/wx.h"
  20. #endif
  21.  
  22. #include "wx/svg/dcsvg.h"
  23.  
  24. #include <math.h>
  25. #include "wx/image.h"
  26.  
  27. #define wxSVG_DEBUG FALSE
  28. // or TRUE to see the calls being executed
  29. #define newline    wxString(wxT("\n"))
  30. #define space      wxString(wxT(" "))
  31. #define semicolon  wxString(wxT(";"))
  32. #define     wx_round(a)    (int)((a)+.5)
  33.  
  34. #ifdef __BORLANDC__
  35. #pragma warn -rch
  36. #pragma warn -ccc
  37. #endif
  38.  
  39. static inline double DegToRad(double deg) { return (deg * 3.14) / 180.0; } ;
  40.  
  41. wxString 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.  
  54. wxString wxBrushString ( wxColour c, int style )
  55. {
  56.     wxString s = wxT("fill:#") + wxColStr (c)  + semicolon + space ;
  57.     switch ( style )
  58.     {
  59.         case wxSOLID :
  60.             s = s + wxT("fill-opacity:1.0; ");
  61.             break ;
  62.         case wxTRANSPARENT:
  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.  
  74.  
  75. void wxSVGFileDC::Init (wxString f, int Width, int Height, float dpi)
  76.  
  77. {
  78.     //set up things first  wxDCBase does all this?
  79.     m_width = Width ;
  80.     m_height = Height ;
  81.  
  82.     m_clipping = FALSE;
  83.     m_OK = TRUE;
  84.  
  85.     m_mm_to_pix_x = dpi/25.4;
  86.     m_mm_to_pix_y = dpi/25.4;
  87.  
  88.     m_signX = m_signY = 1;
  89.  
  90.     m_userScaleX = m_userScaleY =
  91.         m_deviceOriginX = m_deviceOriginY = 0;
  92.  
  93.     m_OriginX = m_OriginY = 0;
  94.     m_logicalOriginX = m_logicalOriginY = 0;
  95.     m_logicalScaleX = m_logicalScaleY = 0 ;
  96.     m_scaleX = m_scaleY = 1.0 ;
  97.  
  98.     m_logicalFunction = wxCOPY;
  99.     m_backgroundMode = wxTRANSPARENT;
  100.     m_mappingMode = wxMM_TEXT;
  101.  
  102.     m_backgroundBrush = *wxTRANSPARENT_BRUSH;
  103.     m_textForegroundColour = *wxBLACK;
  104.     m_textBackgroundColour = *wxWHITE;
  105.     m_colour = wxColourDisplay();
  106.  
  107.     m_pen   = *wxBLACK_PEN;
  108.     m_font  = *wxNORMAL_FONT;
  109.     m_brush = *wxWHITE_BRUSH;
  110.  
  111.     m_graphics_changed = TRUE ;
  112.  
  113.     ////////////////////code here
  114.  
  115.     m_outfile = new wxFileOutputStream(f) ;
  116.     m_OK = m_outfile->Ok ();
  117.     if (m_OK)
  118.     {
  119.         m_filename = f ;
  120.         m_sub_images = 0 ;
  121.         wxString s ;
  122.         s = wxT("<?xml version=\"1.0\" standalone=\"no\"?>") ; s = s + newline ;
  123.         m_outfile->Write (s.c_str(), s.Len() ) ;
  124.         s = wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + newline ;
  125.         m_outfile->Write (s.c_str(), s.Len() ) ;
  126.         s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ")+ newline ;
  127.         m_outfile->Write (s.c_str(), s.Len() ) ;
  128.         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 );
  129.         m_outfile->Write (s.c_str(), s.Len() ) ;
  130.         s = wxT("<title>SVG Picture created as ") + wxFileNameFromPath(f) + wxT(" </title>") + newline ;
  131.         m_outfile->Write (s.c_str(), s.Len() ) ;
  132.         s = wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion + wxT(" </desc>")+ newline ;
  133.         m_outfile->Write (s.c_str(), s.Len() ) ;
  134.         s =  wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + newline ;
  135.         m_outfile->Write (s.c_str(), s.Len() ) ;
  136.  
  137.     }
  138.     m_OK = m_outfile->Ok ();
  139. }
  140.  
  141.  
  142. // constructors
  143. wxSVGFileDC::wxSVGFileDC (wxString f)
  144. {                                
  145.     // quarter 640x480 screen display at 72 dpi
  146.     Init (f,320,240,72.0);
  147. };
  148.  
  149. wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height)
  150. {
  151.     Init (f,Width,Height,72.0);
  152. };
  153.  
  154. wxSVGFileDC::wxSVGFileDC (wxString f, int Width, int Height, float dpi)
  155. {
  156.     Init (f,Width,Height,dpi);
  157. };
  158.  
  159. wxSVGFileDC::~wxSVGFileDC()
  160. {
  161.     wxString s = wxT("</g> \n</svg> \n") ;
  162.     m_outfile->Write (s.c_str(), s.Len() ) ;
  163.     m_OK = m_outfile->Ok ();
  164.     delete m_outfile ;
  165. }
  166.  
  167.  
  168. //////////////////////////////////////////////////////////////////////////////////////////
  169.  
  170. void wxSVGFileDC::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
  171. {
  172.     if (m_graphics_changed) NewGraphics ();
  173.     wxString s ;
  174.     s.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1,y1,x2,y2 );
  175.     if (m_OK)
  176.     {
  177.         m_outfile->Write (s.c_str(), s.Len() ) ;
  178.     }
  179.     m_OK = m_outfile->Ok ();
  180.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawLine Call executed")) ;
  181.     CalcBoundingBox(x1, y1) ;
  182.     CalcBoundingBox(x2, y2) ;
  183.     return;
  184. };
  185.  
  186. void wxSVGFileDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset )
  187. {
  188.     for ( int i = 1; i < n ; i++ )
  189.     {
  190.         DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset,
  191.             points [ i ].x + xoffset, points [ i ].y + yoffset ) ;
  192.     }
  193. }
  194.  
  195.  
  196. void wxSVGFileDC::DoDrawPoint (wxCoord x1, wxCoord y1)
  197. {
  198.     wxString s;
  199.     if (m_graphics_changed) NewGraphics ();
  200.     s = wxT("<g style = \"stroke-linecap:round;\" > ") + newline ;
  201.     m_outfile->Write (s.c_str(), s.Len() ) ;
  202.     DrawLine ( x1,y1,x1,y1 );
  203.     s = wxT("</g>");
  204.     m_outfile->Write (s.c_str(), s.Len() ) ;
  205.     m_OK = m_outfile->Ok ();
  206. }
  207.  
  208.  
  209. void wxSVGFileDC::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height)
  210. {
  211.     wxDCBase::DoDrawCheckMark (x1,y1,width,height) ;
  212. }
  213.  
  214.  
  215. void wxSVGFileDC::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1)
  216. {
  217.     DoDrawRotatedText(text, x1,y1,0.0);
  218.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawText Call executed")) ;
  219. }
  220.  
  221.  
  222. void wxSVGFileDC::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle)
  223. {
  224.     //known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
  225.     if (m_graphics_changed) NewGraphics ();
  226.     wxString s, sTmp;
  227.  
  228.     // calculate bounding box
  229.     wxCoord w, h, desc ;
  230.     DoGetTextExtent(sText, &w, &h, &desc);
  231.  
  232.     double rad = DegToRad(angle);
  233.  
  234.     // wxT("upper left") and wxT("upper right")
  235.     CalcBoundingBox(x, y);
  236.     CalcBoundingBox(x + w*cos(rad), y - h*sin(rad));
  237.  
  238.     // wxT("bottom left") and wxT("bottom right")
  239.     x += (wxCoord)(h*sin(rad));
  240.     y += (wxCoord)(h*cos(rad));
  241.     CalcBoundingBox(x, y);
  242.     CalcBoundingBox(x + h*sin(rad), y + h*cos(rad));
  243.  
  244.     if (m_backgroundMode == wxSOLID)
  245.     {
  246.         // draw background first
  247.         // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
  248.  
  249.         wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::Draw Rotated Text Call plotting text background")) ;
  250.         sTmp.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"  "), x,y+desc-h, w, h );
  251.         s = sTmp + wxT("style=\"fill:#") + wxColStr (m_textBackgroundColour) + wxT("; ") ;
  252.         s = s + wxT("stroke-width:1; stroke:#") + wxColStr (m_textBackgroundColour) + wxT("; ") ;
  253.         sTmp.Printf ( wxT("\" transform=\"rotate( %.2g %d %d )  \">"), -angle, x,y ) ;
  254.         s = s + sTmp + newline ;
  255.         m_outfile->Write (s.c_str(), s.Len() ) ;
  256.     }
  257.     //now do the text itself
  258.     s.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x,y );
  259.    
  260.     sTmp = m_font.GetFaceName () ;
  261.     if (sTmp.Len () > 0)  s = s + wxT("style=\"font-family:") + sTmp + wxT("; ");
  262.     else s = s + wxT("style=\" ") ;
  263.  
  264.     wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
  265.     s = s + wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + semicolon + space;
  266.     
  267.     wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
  268.     s = s + wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + semicolon  + space;
  269.     
  270.     sTmp.Printf (wxT("font-size:%dpt; fill:#"), m_font.GetPointSize () );
  271.     s = s + sTmp ;
  272.     s = s + wxColStr (m_textForegroundColour) + wxT("; stroke:#") + wxColStr (m_textForegroundColour) + wxT("; ") ;
  273.     sTmp.Printf ( wxT("stroke-width:0;\"  transform=\"rotate( %.2g %d %d )  \" >"),  -angle, x,y ) ;
  274.     s = s + sTmp + sText + wxT("</text> ") + newline ;
  275.     if (m_OK)
  276.     {
  277.         m_outfile->Write (s.c_str(), s.Len() ) ;
  278.     }
  279.     m_OK = m_outfile->Ok ();
  280.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DrawRotatedText Call executed")) ;
  281.  
  282. }
  283.  
  284.  
  285. void wxSVGFileDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
  286. {
  287.     DoDrawRoundedRectangle(x, y, width, height, 0)  ;
  288. }
  289.  
  290.  
  291. void wxSVGFileDC::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
  292.  
  293. {
  294.     if (m_graphics_changed) NewGraphics ();
  295.     wxString s ;
  296.  
  297.     s.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%.2g\" "), 
  298.                x, y, width, height, radius );
  299.  
  300.     s = s + wxT(" /> ") + newline ;
  301.     m_outfile->Write (s.c_str(), s.Len() ) ;
  302.     m_OK = m_outfile->Ok ();
  303.  
  304.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawRoundedRectangle Call executed")) ;
  305.     CalcBoundingBox(x, y) ;
  306.     CalcBoundingBox(x + width, y + height) ;
  307.  
  308. }
  309.  
  310.  
  311. void wxSVGFileDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
  312. {
  313.     if (m_graphics_changed) NewGraphics ();
  314.     wxString s, sTmp ;
  315.     s = wxT("<polygon style=\"") ;
  316.     if ( fillStyle == wxODDEVEN_RULE )
  317.         s = s + wxT("fill-rule:evenodd; ");
  318.     else
  319.         s = s + wxT("fill-rule:nonzero; ");
  320.  
  321.     s = s  + wxT("\" \npoints=\"") ;
  322.  
  323.     for (int i = 0; i < n;  i++)
  324.     {
  325.         sTmp.Printf ( wxT("%d,%d"), points [i].x+xoffset, points[i].y+yoffset );
  326.         s = s + sTmp + newline ;
  327.         CalcBoundingBox ( points [i].x+xoffset, points[i].y+yoffset);
  328.     }
  329.     s = s + wxT("\" /> ") ;
  330.     s = s + newline ;
  331.     m_outfile->Write (s.c_str(), s.Len() ) ;
  332.     m_OK = m_outfile->Ok ();
  333.  
  334.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawPolygon Call executed")) ;
  335. }
  336.  
  337.  
  338. void wxSVGFileDC::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
  339.  
  340. {
  341.     if (m_graphics_changed) NewGraphics ();
  342.  
  343.     int rh = height /2 ;
  344.     int rw = width  /2 ;
  345.  
  346.     wxString s;
  347.     s.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x+rw,y+rh, rw, rh );
  348.     s = s + wxT(" /> ") + newline ;
  349.  
  350.     m_outfile->Write (s.c_str(), s.Len() ) ;
  351.     m_OK = m_outfile->Ok ();
  352.  
  353.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipse Call executed")) ;
  354.     CalcBoundingBox(x, y) ;
  355.     CalcBoundingBox(x + width, y + height) ;
  356. }
  357.  
  358.  
  359. void wxSVGFileDC::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
  360. {
  361.     /* Draws an arc of a circle, centred on (xc, yc), with starting point
  362.     (x1, y1) and ending at (x2, y2). The current pen is used for the outline
  363.     and the current brush for filling the shape.
  364.  
  365.     The arc is drawn in an anticlockwise direction from the start point to
  366.     the end point.
  367.  
  368.     Might be better described as Pie drawing */
  369.  
  370.     if (m_graphics_changed) NewGraphics ();
  371.     wxString s ;
  372.  
  373.     // we need the radius of the circle which has two estimates
  374.     double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) );
  375.     double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) );
  376.  
  377.     wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle")) ;
  378.     if ( fabs ( r2-r1 ) > 3 )    //pixels
  379.     {
  380.         s = wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n") ;
  381.         m_outfile->Write (s.c_str(), s.Len() ) ;
  382.     }
  383.  
  384.     double theta1 = atan2(yc-y1,x1-xc);
  385.     if ( theta1 < 0 ) theta1 = theta1 + 3.14 * 2;
  386.     double theta2 = atan2(yc-y2, x2-xc);
  387.     if ( theta2 < 0 ) theta2 = theta2 + 3.14 * 2;
  388.     if ( theta2 < theta1 ) theta2 = theta2 + 3.14 *2 ;
  389.  
  390.     int fArc  ;                  // flag for large or small arc 0 means less than 180 degrees
  391.     if (  fabs((theta2 - theta1) > 3.14 )) fArc = 1; else fArc = 0 ;
  392.  
  393.     int fSweep = 0 ;             // flag for sweep always 0
  394.  
  395.     s.Printf ( wxT("<path d=\"M%d %d A%.2g %.2g 0.0 %d %d %d %d L%d %d z "),
  396.         x1,y1, r1, r2, fArc, fSweep, x2, y2, xc, yc );
  397.  
  398.     // the z means close the path and fill
  399.     s = s + wxT(" \" /> ") + newline ;
  400.  
  401.  
  402.     if (m_OK)
  403.     {
  404.         m_outfile->Write (s.c_str(), s.Len() ) ;
  405.     }
  406.     m_OK = m_outfile->Ok ();
  407.  
  408.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawArc Call executed")) ;
  409. }
  410.  
  411.  
  412. void wxSVGFileDC::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
  413. {
  414.     /*
  415.     Draws an arc of an ellipse. The current pen is used for drawing the arc
  416.     and the current brush is used for drawing the pie. This function is
  417.     currently only available for X window and PostScript device contexts.
  418.  
  419.     x and y specify the x and y coordinates of the upper-left corner of the
  420.     rectangle that contains the ellipse.
  421.  
  422.     width and height specify the width and height of the rectangle that
  423.     contains the ellipse.
  424.  
  425.     start and end specify the start and end of the arc relative to the
  426.     three-o'clock position from the center of the rectangle. Angles are
  427.     specified in degrees (360 is a complete circle). Positive values mean
  428.     counter-clockwise motion. If start is equal to end, a complete ellipse
  429.     will be drawn. */
  430.  
  431.     //known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
  432.  
  433.     if (m_graphics_changed) NewGraphics ();
  434.  
  435.     wxString s ;
  436.     //radius
  437.     double rx = w / 2 ;
  438.     double ry = h / 2 ;
  439.     // center
  440.     double xc = x + rx ;
  441.     double yc = y + ry ;
  442.  
  443.     double xs, ys, xe, ye ;
  444.     xs = xc + rx * cos (DegToRad(sa)) ;
  445.     xe = xc + rx * cos (DegToRad(ea)) ;
  446.     ys = yc - ry * sin (DegToRad(sa)) ;
  447.     ye = yc - ry * sin (DegToRad(ea)) ;
  448.  
  449.     ///now same as circle arc...
  450.  
  451.     double theta1 = atan2(ys-yc, xs-xc);
  452.     double theta2 = atan2(ye-yc, xe-xc);
  453.  
  454.     int fArc  ;                  // flag for large or small arc 0 means less than 180 degrees
  455.     if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0 ;
  456.  
  457.     int fSweep ;
  458.     if ( fabs( (theta2 - theta1) > 3.14)) fSweep = 1; else fSweep = 0 ;
  459.  
  460.     s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d  %d %d L %d %d z "),
  461.         int(xs), int(ys), int(rx), int(ry),
  462.         fArc, fSweep, int(xe), int(ye), int(xc), int(yc)  );
  463.  
  464.  
  465.     s = s + wxT(" \" /> ") + newline ;
  466.  
  467.     if (m_OK)
  468.     {
  469.         m_outfile->Write (s.c_str(), s.Len() ) ;
  470.     }
  471.     m_OK = m_outfile->Ok ();
  472.  
  473.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawEllipticArc Call executed")) ;
  474. }
  475.  
  476.  
  477. void wxSVGFileDC::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , wxFont *font) const
  478.  
  479. {
  480.     wxScreenDC sDC ;
  481.  
  482.     sDC.SetFont (m_font);
  483.     if ( font != NULL ) sDC.SetFont ( *font );
  484.     sDC.GetTextExtent(string, w,  h, descent, externalLeading );
  485.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetTextExtent Call executed")) ;
  486. }
  487.  
  488.  
  489. wxCoord wxSVGFileDC::GetCharHeight() const
  490.  
  491. {
  492.     wxScreenDC sDC ;
  493.     sDC.SetFont (m_font);
  494.  
  495.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharHeight Call executing")) ;
  496.     return ( sDC.GetCharHeight() );
  497.  
  498. }
  499.  
  500.  
  501. wxCoord wxSVGFileDC::GetCharWidth() const
  502. {
  503.     wxScreenDC sDC ;
  504.     sDC.SetFont (m_font);
  505.  
  506.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::GetCharWidth Call executing")) ;
  507.     return ( sDC.GetCharWidth() ) ;
  508.  
  509. }
  510.  
  511.  
  512. /// Set Functions /////////////////////////////////////////////////////////////////
  513. void wxSVGFileDC::SetBackground( const wxBrush &brush )
  514. {
  515.  
  516.     m_backgroundBrush = brush;
  517.     return;
  518. }
  519.  
  520.  
  521. void wxSVGFileDC::SetBackgroundMode( int mode )
  522. {
  523.     m_backgroundMode = mode;
  524.     return;
  525. }
  526.  
  527.  
  528. void wxSVGFileDC::SetBrush(const wxBrush& brush)
  529.  
  530. {
  531.     m_brush = brush ;
  532.  
  533.     m_graphics_changed = TRUE ;
  534.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetBrush Call executed")) ;
  535. }
  536.  
  537.  
  538. void wxSVGFileDC::SetPen(const wxPen& pen)
  539. {
  540.     // width, color, ends, joins : currently implemented
  541.     // dashes, stipple :  not implemented
  542.     m_pen = pen ;
  543.   
  544.     m_graphics_changed = TRUE ;
  545.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetPen Call executed")) ;
  546. }
  547.  
  548. void wxSVGFileDC::NewGraphics ()
  549. {
  550.  
  551.     int w = m_pen.GetWidth ();
  552.     wxColour c = m_pen.GetColour () ;
  553.  
  554.     wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
  555.     
  556.     sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour (), m_brush.GetStyle () ) 
  557.     + wxT("  stroke:#") + wxColStr (c) + wxT("; ") ;
  558.     
  559.     switch ( m_pen.GetCap () )
  560.     {
  561.         case  wxCAP_PROJECTING :
  562.             sPenCap = wxT("stroke-linecap:square; ") ;
  563.             break ;
  564.         case  wxCAP_BUTT :
  565.             sPenCap = wxT("stroke-linecap:butt; ") ;
  566.             break ;
  567.         case    wxCAP_ROUND :
  568.         default :
  569.             sPenCap = wxT("stroke-linecap:round; ") ;
  570.     };
  571.     switch ( m_pen.GetJoin () )
  572.     {
  573.         case  wxJOIN_BEVEL :
  574.             sPenJoin = wxT("stroke-linejoin:bevel; ") ;
  575.             break ;
  576.         case  wxJOIN_MITER :
  577.             sPenJoin = wxT("stroke-linejoin:miter; ") ;
  578.             break ;
  579.         case    wxJOIN_ROUND :
  580.         default :
  581.             sPenJoin = wxT("stroke-linejoin:round; ") ;
  582.     };
  583.  
  584.     switch ( m_pen.GetStyle () )
  585.     {
  586.         case  wxSOLID :
  587.             sPenStyle = wxT("stroke-opacity:1.0; stroke-opacity:1.0; ") ;
  588.             break ;
  589.         case  wxTRANSPARENT :
  590.             sPenStyle = wxT("stroke-opacity:0.0; stroke-opacity:0.0; ") ;
  591.             break ;
  592.         default :
  593.             wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::SetPen Call called to set a Style which is not available")) ;
  594.             sWarn = sWarn + wxT("<!--- wxSVGFileDC::SetPen Call called to set a Style which is not available --> \n") ;
  595.     }
  596.  
  597.     sLast.Printf (   wxT("stroke-width:%d\" \n   transform=\"translate(%.2g %.2g) scale(%.2g %.2g)\">"),  
  598.                   w, m_OriginX, m_OriginY, m_scaleX, m_scaleY  );
  599.  
  600.     s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
  601.     m_outfile->Write (s.c_str(), s.Len() ) ;
  602.     m_OK = m_outfile->Ok ();
  603.     m_graphics_changed = FALSE ;
  604.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::NewGraphics Call executed")) ;
  605. }
  606.  
  607.  
  608. void wxSVGFileDC::SetFont(const wxFont& font)
  609.  
  610. {
  611.     m_font = font ;
  612.     
  613.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::SetFont Call executed")) ;
  614. }
  615.  
  616.  
  617. void wxSVGFileDC::ComputeScaleAndOrigin()
  618. {
  619.     m_scaleX = m_logicalScaleX * m_userScaleX;
  620.     m_scaleY = m_logicalScaleY * m_userScaleY;
  621.     m_OriginX = m_logicalOriginX * m_logicalScaleX + m_deviceOriginX ;
  622.     m_OriginY = m_logicalOriginY * m_logicalScaleY + m_deviceOriginY ;
  623.     m_graphics_changed = TRUE;
  624. }
  625.  
  626.  
  627. int wxSVGFileDC::GetMapMode()
  628. {
  629.     return m_mappingMode ;
  630. }
  631.  
  632.  
  633. void wxSVGFileDC::SetMapMode( int mode )
  634. {
  635.     switch (mode)
  636.     {
  637.         case wxMM_TWIPS:
  638.             SetLogicalScale( twips2mm*m_mm_to_pix_x, twips2mm*m_mm_to_pix_y );
  639.             break;
  640.         case wxMM_POINTS:
  641.             SetLogicalScale( pt2mm*m_mm_to_pix_x, pt2mm*m_mm_to_pix_y );
  642.             break;
  643.         case wxMM_METRIC:
  644.             SetLogicalScale( m_mm_to_pix_x, m_mm_to_pix_y );
  645.             break;
  646.         case wxMM_LOMETRIC:
  647.             SetLogicalScale( m_mm_to_pix_x/10.0, m_mm_to_pix_y/10.0 );
  648.             break;
  649.         default:
  650.         case wxMM_TEXT:
  651.             SetLogicalScale( 1.0, 1.0 );
  652.             break;
  653.     }
  654.     m_mappingMode = mode;
  655.  
  656.     /*  we don't do this mega optimisation
  657.         if (mode != wxMM_TEXT)
  658.         {
  659.             m_needComputeScaleX = TRUE;
  660.             m_needComputeScaleY = TRUE;
  661.         }
  662.     */
  663. }
  664.  
  665.  
  666. void wxSVGFileDC::GetUserScale(double *x, double *y) const
  667. {
  668.     *x = m_userScaleX ;
  669.     *y = m_userScaleY ;
  670. }
  671.  
  672.  
  673. void wxSVGFileDC::SetUserScale( double x, double y )
  674. {
  675.     // allow negative ? -> no
  676.     m_userScaleX = x;
  677.     m_userScaleY = y;
  678.     ComputeScaleAndOrigin();
  679. }
  680.  
  681.  
  682. void wxSVGFileDC::SetLogicalScale( double x, double y )
  683. {
  684.     // allow negative ?
  685.     m_logicalScaleX = x;
  686.     m_logicalScaleY = y;
  687.     ComputeScaleAndOrigin();
  688. }
  689.  
  690.  
  691. void wxSVGFileDC::SetLogicalOrigin( wxCoord x, wxCoord y )
  692. {
  693.     // is this still correct ?
  694.     m_logicalOriginX = x * m_signX;
  695.     m_logicalOriginY = y * m_signY;
  696.     ComputeScaleAndOrigin();
  697. }
  698.  
  699.  
  700. void wxSVGFileDC::SetDeviceOrigin( wxCoord x, wxCoord y )
  701. {
  702.     // only wxPostScripDC has m_signX = -1, 
  703.     m_deviceOriginX = x;
  704.     m_deviceOriginY = y;
  705.     ComputeScaleAndOrigin();
  706. }
  707.  
  708.  
  709. void wxSVGFileDC::SetAxisOrientation( bool xLeftRight, bool yBottomUp )
  710. {
  711.     // only wxPostScripDC has m_signX = -1, 
  712.     m_signX = (xLeftRight ?  1 : -1);
  713.     m_signY = (yBottomUp  ? -1 :  1);
  714.     ComputeScaleAndOrigin();
  715. }
  716.  
  717.  
  718. // export a bitmap as a raster image in png
  719. bool wxSVGFileDC::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
  720.                          wxDC* source, wxCoord xsrc, wxCoord ysrc, 
  721.              int logicalFunc /*= wxCOPY*/, bool useMask /*= FALSE*/,
  722.              wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/)
  723. {
  724.     
  725.     if (logicalFunc != wxCOPY)
  726.     {
  727.         wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible")) ;
  728.         return FALSE ;
  729.     }
  730.     if (useMask != FALSE)
  731.     {
  732.         wxASSERT_MSG(FALSE, wxT("wxSVGFileDC::DoBlit Call requested False mask ; this is not possible")) ;
  733.         return FALSE ;
  734.     }
  735.     wxBitmap myBitmap (width, height) ;
  736.     wxMemoryDC memDC;
  737.     memDC.SelectObject( myBitmap );
  738.     memDC.Blit(0, 0, width, height, source, xsrc, ysrc);
  739.     memDC.SelectObject( wxNullBitmap );
  740.     DoDrawBitmap(myBitmap, xdest, ydest);
  741.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoBlit Call executed")) ;
  742.     return FALSE ;
  743. }
  744.  
  745.  
  746. void wxSVGFileDC::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y)
  747. {
  748.     wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() ) ;
  749.     wxMemoryDC memDC;
  750.     memDC.SelectObject( myBitmap );
  751.     memDC.DrawIcon(myIcon,0,0);
  752.     memDC.SelectObject( wxNullBitmap );
  753.     DoDrawBitmap(myBitmap, x, y);
  754.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawIcon Call executed")) ;
  755.     return ;
  756. }
  757.  
  758.  
  759.                                  
  760. void wxSVGFileDC::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool bTransparent /*=0*/ )
  761. {
  762.     if (m_graphics_changed) NewGraphics ();
  763.  
  764.     wxString sTmp, s, sPNG ; 
  765.     wxImage::AddHandler(new wxPNGHandler);
  766.  
  767. // create suitable file name   
  768.     sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
  769.     sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
  770.     while (wxFile::Exists(sPNG) )
  771.     {
  772.         m_sub_images ++ ;
  773.         sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
  774.         sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
  775.     }
  776.     
  777. //create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
  778.     wxBitmap myBitmap = bmp ;
  779. //save it
  780.     bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG);
  781.  
  782. // refrence the bitmap from the SVG doc
  783.     int w = myBitmap.GetWidth();
  784.     int h = myBitmap.GetHeight();
  785.     sTmp.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x,y,w,h );
  786.     s = s + sTmp ;
  787.     sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
  788.     s = s + sTmp + wxT("<title>Image from wxSVG</title>  </image>") + newline;
  789.     
  790.     if (m_OK && bPNG_OK)
  791.     {
  792.         m_outfile->Write (s.c_str(), s.Len() ) ;
  793.     }
  794.     m_OK = m_outfile->Ok () && bPNG_OK;
  795.     wxASSERT_MSG(!wxSVG_DEBUG, wxT("wxSVGFileDC::DoDrawBitmap Call executed")) ;
  796.  
  797.     return  ;
  798. }
  799.  
  800.  
  801. // ---------------------------------------------------------------------------
  802. // coordinates transformations
  803. // ---------------------------------------------------------------------------
  804.  
  805. wxCoord wxSVGFileDC::DeviceToLogicalX(wxCoord x) const
  806. {
  807.     return XDEV2LOG(x);
  808. }
  809.  
  810.  
  811. wxCoord wxSVGFileDC::DeviceToLogicalY(wxCoord y) const
  812. {
  813.     return YDEV2LOG(y);
  814. }
  815.  
  816.  
  817. wxCoord wxSVGFileDC::DeviceToLogicalXRel(wxCoord x) const
  818. {
  819.     return XDEV2LOGREL(x);
  820. }
  821.  
  822.  
  823. wxCoord wxSVGFileDC::DeviceToLogicalYRel(wxCoord y) const
  824. {
  825.     return YDEV2LOGREL(y);
  826. }
  827.  
  828.  
  829. wxCoord wxSVGFileDC::LogicalToDeviceX(wxCoord x) const
  830. {
  831.     return XLOG2DEV(x);
  832. }
  833.  
  834.  
  835. wxCoord wxSVGFileDC::LogicalToDeviceY(wxCoord y) const
  836. {
  837.     return YLOG2DEV(y);
  838. }
  839.  
  840.  
  841. wxCoord wxSVGFileDC::LogicalToDeviceXRel(wxCoord x) const
  842. {
  843.     return XLOG2DEVREL(x);
  844. }
  845.  
  846.  
  847. wxCoord wxSVGFileDC::LogicalToDeviceYRel(wxCoord y) const
  848. {
  849.     return YLOG2DEVREL(y);
  850. }
  851.  
  852.  
  853. #ifdef __BORLANDC__
  854. #pragma warn .rch
  855. #pragma warn .ccc
  856. #endif
  857.