Commit 5e5ec6f1 authored by jean-pierre charras's avatar jean-pierre charras

All: try to fix incorrect acs in plot SVG under wxWidgets 2.9:

wxWidgets 2.9 knows wxSVGFILEDC device context.
Unfortunately, arcs are drawn as pies (this is a feature, not a bug).
This is not correct for Kicad.
So Kicad has its own wxSVGFILEDC (named KicadSVGFileDC) that is basically the same as wxSVGFILEDC,
but with arcs drawn as arcs, not pies.
Note also under wxWidgets 2.8 does not know wxSVGFILEDC , so kicad had already its own SVG device context.
parent db7c8cfd
...@@ -19,20 +19,663 @@ ...@@ -19,20 +19,663 @@
#include <wx/wx.h> #include <wx/wx.h>
#endif #endif
#if wxCHECK_VERSION( 2, 9, 0 )
// Do nothing, because wxWidgets 3 supports the SVG format
// previously, was a contribution library, not included in wxWidgets base
#else
#include <dcsvg.h> #include <dcsvg.h>
#include <wx/filename.h>
#include <wx/image.h> #include <wx/image.h>
#include <macros.h> #include <macros.h>
#define wxSVG_DEBUG false #if wxCHECK_VERSION( 2, 9, 0 )
// We could do nothing, because wxWidgets 3 supports the SVG format
// (previously, it was a contribution library, not included in wxWidgets)
// However arcs are drawn as pies, and we must change it.
// Unfortunately most of functions are private, and we cannot derive
// our KicadSVGFileDCImpl from wxSVGFileDCImpl
// and just override the 2 incorrect functions
// Just wxWidget dcsvg is copied here and 2 functions are modified:
// KicadSVGFileDCImpl::DoDrawArc() and KicadSVGFileDCImpl::DoDrawEllipticArc()
namespace
{
inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
// This function returns a string representation of a floating point number in
// C locale (i.e. always using "." for the decimal separator) and with the
// fixed precision (which is 2 for some unknown reason but this is what it was
// in this code originally).
inline wxString NumStr(double f)
{
return wxString::FromCDouble(f, 2);
}
// Return the colour representation as HTML-like "#rrggbb" string and also
// returns its alpha as opacity number in 0..1 range.
wxString Col2SVG(wxColour c, float *opacity)
{
if ( c.Alpha() != wxALPHA_OPAQUE )
{
*opacity = c.Alpha()/255.;
// Remove the alpha before using GetAsString(wxC2S_HTML_SYNTAX) as it
// doesn't support colours with alpha channel.
c = wxColour(c.GetRGB());
}
else // No alpha.
{
*opacity = 1.;
}
return c.GetAsString(wxC2S_HTML_SYNTAX);
}
wxString wxPenString(wxColour c, int style = wxPENSTYLE_SOLID)
{
float opacity;
wxString s = wxT("stroke:") + Col2SVG(c, &opacity) + wxT("; ");
switch ( style )
{
case wxPENSTYLE_SOLID:
s += wxString::Format(wxT("stroke-opacity:%s; "), NumStr(opacity));
break;
case wxPENSTYLE_TRANSPARENT:
s += wxT("stroke-opacity:0.0; ");
break;
default :
wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Pen Style not available"));
}
return s;
}
wxString wxBrushString(wxColour c, int style = wxBRUSHSTYLE_SOLID)
{
float opacity;
wxString s = wxT("fill:") + Col2SVG(c, &opacity) + wxT("; ");
switch ( style )
{
case wxBRUSHSTYLE_SOLID:
s += wxString::Format(wxT("fill-opacity:%s; "), NumStr(opacity));
break;
case wxBRUSHSTYLE_TRANSPARENT:
s += wxT("fill-opacity:0.0; ");
break;
default :
wxASSERT_MSG(false, wxT("wxSVGFileDC::Requested Brush Style not available"));
}
return s;
}
} // anonymous namespace
// ----------------------------------------------------------
// KicadSVGFileDCImpl
// ----------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(KicadSVGFileDCImpl, wxDC)
KicadSVGFileDCImpl::KicadSVGFileDCImpl( KicadSVGFileDC *owner, const wxString &filename,
int width, int height, double dpi ) :
wxDCImpl( owner )
{
Init( filename, width, height, dpi );
}
void KicadSVGFileDCImpl::Init (const wxString &filename, int Width, int Height, double dpi)
{
m_width = Width;
m_height = Height;
m_dpi = dpi;
m_OK = true;
m_mm_to_pix_x = dpi/25.4;
m_mm_to_pix_y = dpi/25.4;
m_backgroundBrush = *wxTRANSPARENT_BRUSH;
m_textForegroundColour = *wxBLACK;
m_textBackgroundColour = *wxWHITE;
m_colour = wxColourDisplay();
m_pen = *wxBLACK_PEN;
m_font = *wxNORMAL_FONT;
m_brush = *wxWHITE_BRUSH;
m_graphics_changed = true;
////////////////////code here
m_outfile = new wxFileOutputStream(filename);
m_OK = m_outfile->IsOk();
if (m_OK)
{
m_filename = filename;
m_sub_images = 0;
wxString s;
s = wxT("<?xml version=\"1.0\" standalone=\"no\"?>") + wxString(wxT("\n"));
write(s);
s = wxT("<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20010904//EN\" ") + wxString(wxT("\n"));
write(s);
s = wxT("\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\"> ") + wxString(wxT("\n"));
write(s);
s = wxT("<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" ") + wxString(wxT("\n"));
write(s);
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 );
write(s);
s = wxT("<title>SVG Picture created as ") + wxFileName(filename).GetFullName() + wxT(" </title>") + wxT("\n");
write(s);
s = wxString (wxT("<desc>Picture generated by wxSVG ")) + wxSVGVersion + wxT(" </desc>")+ wxT("\n");
write(s);
s = wxT("<g style=\"fill:black; stroke:black; stroke-width:1\">") + wxString(wxT("\n"));
write(s);
}
}
KicadSVGFileDCImpl::~KicadSVGFileDCImpl()
{
wxString s = wxT("</g> \n</svg> \n");
write(s);
delete m_outfile;
}
void KicadSVGFileDCImpl::DoGetSizeMM( int *width, int *height ) const
{
if (width)
*width = wxRound( (double)m_width / m_mm_to_pix_x );
if (height)
*height = wxRound( (double)m_height / m_mm_to_pix_y );
}
wxSize KicadSVGFileDCImpl::GetPPI() const
{
return wxSize( wxRound(m_dpi), wxRound(m_dpi) );
}
void KicadSVGFileDCImpl::DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
{
if (m_graphics_changed) NewGraphics();
wxString s;
s.Printf ( wxT("<path d=\"M%d %d L%d %d\" /> \n"), x1,y1,x2,y2 );
if (m_OK)
{
write(s);
}
CalcBoundingBox(x1, y1);
CalcBoundingBox(x2, y2);
}
void KicadSVGFileDCImpl::DoDrawLines(int n, wxPoint points[], wxCoord xoffset , wxCoord yoffset )
{
for ( int i = 1; i < n; i++ )
{
DoDrawLine ( points [i-1].x + xoffset, points [i-1].y + yoffset,
points [ i ].x + xoffset, points [ i ].y + yoffset );
}
}
void KicadSVGFileDCImpl::DoDrawPoint (wxCoord x1, wxCoord y1)
{
wxString s;
if (m_graphics_changed) NewGraphics();
s = wxT("<g style = \"stroke-linecap:round;\" > ") + wxString(wxT("\n"));
write(s);
DoDrawLine ( x1,y1,x1,y1 );
s = wxT("</g>");
write(s);
}
void KicadSVGFileDCImpl::DoDrawCheckMark(wxCoord x1, wxCoord y1, wxCoord width, wxCoord height)
{
wxDCImpl::DoDrawCheckMark (x1,y1,width,height);
}
void KicadSVGFileDCImpl::DoDrawText(const wxString& text, wxCoord x1, wxCoord y1)
{
DoDrawRotatedText(text, x1,y1,0.0);
}
void KicadSVGFileDCImpl::DoDrawRotatedText(const wxString& sText, wxCoord x, wxCoord y, double angle)
{
//known bug; if the font is drawn in a scaled DC, it will not behave exactly as wxMSW
if (m_graphics_changed) NewGraphics();
wxString s, sTmp;
// calculate bounding box
wxCoord w, h, desc;
DoGetTextExtent(sText, &w, &h, &desc);
double rad = DegToRad(angle);
// wxT("upper left") and wxT("upper right")
CalcBoundingBox(x, y);
CalcBoundingBox((wxCoord)(x + w*cos(rad)), (wxCoord)(y - h*sin(rad)));
// wxT("bottom left") and wxT("bottom right")
x += (wxCoord)(h*sin(rad));
y += (wxCoord)(h*cos(rad));
CalcBoundingBox(x, y);
CalcBoundingBox((wxCoord)(x + h*sin(rad)), (wxCoord)(y + h*cos(rad)));
if (m_backgroundMode == wxBRUSHSTYLE_SOLID)
{
// draw background first
// just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
sTmp.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "), x,y+desc-h, w, h );
s = sTmp + wxT("style=\"") + wxBrushString(m_textBackgroundColour);
s += wxT("stroke-width:1; ") + wxPenString(m_textBackgroundColour);
sTmp.Printf ( wxT("\" transform=\"rotate( %s %d %d ) \" />"), NumStr(-angle), x,y );
s += sTmp + wxT("\n");
write(s);
}
//now do the text itself
s.Printf (wxT(" <text x=\"%d\" y=\"%d\" "),x,y );
sTmp = m_font.GetFaceName();
if (sTmp.Len() > 0) s += wxT("style=\"font-family:") + sTmp + wxT("; ");
else s += wxT("style=\" ");
wxString fontweights [3] = { wxT("normal"), wxT("lighter"), wxT("bold") };
s += wxT("font-weight:") + fontweights[m_font.GetWeight() - wxNORMAL] + wxT("; ");
wxString fontstyles [5] = { wxT("normal"), wxT("style error"), wxT("style error"), wxT("italic"), wxT("oblique") };
s += wxT("font-style:") + fontstyles[m_font.GetStyle() - wxNORMAL] + wxT("; ");
sTmp.Printf (wxT("font-size:%dpt; "), m_font.GetPointSize() );
s += sTmp;
//text will be solid, unless alpha value isn't opaque in the foreground colour
s += wxBrushString(m_textForegroundColour) + wxPenString(m_textForegroundColour);
sTmp.Printf ( wxT("stroke-width:0;\" transform=\"rotate( %s %d %d ) \" >"), NumStr(-angle), x,y );
s += sTmp + sText + wxT("</text> ") + wxT("\n");
if (m_OK)
{
write(s);
}
}
void KicadSVGFileDCImpl::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{
DoDrawRoundedRectangle(x, y, width, height, 0);
}
void KicadSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height, double radius )
{
if (m_graphics_changed) NewGraphics();
wxString s;
s.Printf ( wxT(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" "),
x, y, width, height, NumStr(radius) );
s += wxT(" /> \n");
write(s);
CalcBoundingBox(x, y);
CalcBoundingBox(x + width, y + height);
}
void KicadSVGFileDCImpl::DoDrawPolygon(int n, wxPoint points[],
wxCoord xoffset, wxCoord yoffset,
wxPolygonFillMode fillStyle)
{
if (m_graphics_changed) NewGraphics();
wxString s, sTmp;
s = wxT("<polygon style=\"");
if ( fillStyle == wxODDEVEN_RULE )
s += wxT("fill-rule:evenodd; ");
else
s += wxT("fill-rule:nonzero; ");
s += wxT("\" \npoints=\"");
for (int i = 0; i < n; i++)
{
sTmp.Printf ( wxT("%d,%d"), points [i].x+xoffset, points[i].y+yoffset );
s += sTmp + wxT("\n");
CalcBoundingBox ( points [i].x+xoffset, points[i].y+yoffset);
}
s += wxT("\" /> \n");
write(s);
}
void KicadSVGFileDCImpl::DoDrawEllipse (wxCoord x, wxCoord y, wxCoord width, wxCoord height)
{
if (m_graphics_changed) NewGraphics();
int rh = height /2;
int rw = width /2;
wxString s;
s.Printf ( wxT("<ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" "), x+rw,y+rh, rw, rh );
s += wxT(" /> \n");
write(s);
CalcBoundingBox(x, y);
CalcBoundingBox(x + width, y + height);
}
void KicadSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2, wxCoord xc, wxCoord yc)
{
/* Draws an arc of a circle, centred on (xc, yc), with starting point
(x1, y1) and ending at (x2, y2). The current pen is used for the outline
and the current brush for filling the shape.
The arc is drawn in an anticlockwise direction from the start point to
the end point
*/
if (m_graphics_changed) NewGraphics();
wxString s;
// we need the radius of the circle which has two estimates
double r1 = sqrt ( double( (x1-xc)*(x1-xc) ) + double( (y1-yc)*(y1-yc) ) );
double r2 = sqrt ( double( (x2-xc)*(x2-xc) ) + double( (y2-yc)*(y2-yc) ) );
wxASSERT_MSG( (fabs ( r2-r1 ) <= 3), wxT("wxSVGFileDC::DoDrawArc Error in getting radii of circle"));
if ( fabs ( r2-r1 ) > 3 ) //pixels
{
s = wxT("<!--- wxSVGFileDC::DoDrawArc Error in getting radii of circle --> \n");
write(s);
}
double theta1 = atan2((double)(yc-y1),(double)(x1-xc));
if ( theta1 < 0 ) theta1 = theta1 + M_PI * 2;
double theta2 = atan2((double)(yc-y2), (double)(x2-xc));
if ( theta2 < 0 ) theta2 = theta2 + M_PI * 2;
if ( theta2 < theta1 ) theta2 = theta2 + M_PI *2;
int fArc; // flag for large or small arc 0 means less than 180 degrees
if ( fabs(theta2 - theta1) > M_PI ) fArc = 1; else fArc = 0;
int fSweep = 0; // flag for sweep always 0
// Draw a pie:
// the z means close the path and fill
// s.Printf ( wxT("<path d=\"M%d %d A%s %s 0.0 %d %d %d %d L%d %d z "),
// x1,y1, NumStr(r1), NumStr(r2), fArc, fSweep, x2, y2, xc, yc );
// Draw a single arc:
s.Printf( wxT("<path d=\"M%d %d A%s %s 0.0 %d %d %d %d" ),
x1,y1, NumStr(r1), NumStr(r2), fArc, fSweep, x2, y2 );
s += wxT(" \" /> \n");
if (m_OK)
{
write(s);
}
}
void KicadSVGFileDCImpl::DoDrawEllipticArc(wxCoord x,wxCoord y,wxCoord w,wxCoord h,double sa,double ea)
{
/*
Draws an arc of an ellipse. The current pen is used for drawing the arc
and the current brush is used for drawing the pie. This function is
currently only available for X window and PostScript device contexts.
x and y specify the x and y coordinates of the upper-left corner of the
rectangle that contains the ellipse.
width and height specify the width and height of the rectangle that
contains the ellipse.
start and end specify the start and end of the arc relative to the
three-o'clock position from the center of the rectangle. Angles are
specified in degrees (360 is a complete circle). Positive values mean
counter-clockwise motion. If start is equal to end, a complete ellipse
will be drawn. */
//known bug: SVG draws with the current pen along the radii, but this does not happen in wxMSW
if (m_graphics_changed) NewGraphics();
wxString s;
//radius
double rx = w / 2;
double ry = h / 2;
// center
double xc = x + rx;
double yc = y + ry;
double xs, ys, xe, ye;
xs = xc + rx * cos (DegToRad(sa));
xe = xc + rx * cos (DegToRad(ea));
ys = yc - ry * sin (DegToRad(sa));
ye = yc - ry * sin (DegToRad(ea));
///now same as circle arc...
double theta1 = atan2(ys-yc, xs-xc);
double theta2 = atan2(ye-yc, xe-xc);
int fArc; // flag for large or small arc 0 means less than 180 degrees
if ( (theta2 - theta1) > 0 ) fArc = 1; else fArc = 0;
int fSweep;
if ( fabs(theta2 - theta1) > M_PI) fSweep = 1; else fSweep = 0;
// Draw a pie:
// s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d L %d %d z "),
// int(xs), int(ys), int(rx), int(ry),
// fArc, fSweep, int(xe), int(ye), int(xc), int(yc) );
// Draw an arc:
s.Printf ( wxT("<path d=\"M%d %d A%d %d 0.0 %d %d %d %d"),
int(xs), int(ys), int(rx), int(ry),
fArc, fSweep, int(xe), int(ye) );
s += wxT(" \" /> \n");
if (m_OK)
{
write(s);
}
}
void KicadSVGFileDCImpl::DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h, wxCoord *descent , wxCoord *externalLeading , const wxFont *font) const
{
wxScreenDC sDC;
sDC.SetFont (m_font);
if ( font != NULL ) sDC.SetFont ( *font );
sDC.GetTextExtent(string, w, h, descent, externalLeading );
}
wxCoord KicadSVGFileDCImpl::GetCharHeight() const
{
wxScreenDC sDC;
sDC.SetFont (m_font);
return sDC.GetCharHeight();
}
wxCoord KicadSVGFileDCImpl::GetCharWidth() const
{
wxScreenDC sDC;
sDC.SetFont (m_font);
return sDC.GetCharWidth();
}
// ----------------------------------------------------------
// wxSVGFileDCImpl - set functions
// ----------------------------------------------------------
void KicadSVGFileDCImpl::SetBackground( const wxBrush &brush )
{
m_backgroundBrush = brush;
}
void KicadSVGFileDCImpl::SetBackgroundMode( int mode )
{
m_backgroundMode = mode;
}
void KicadSVGFileDCImpl::SetBrush(const wxBrush& brush)
{
m_brush = brush;
m_graphics_changed = true;
}
void KicadSVGFileDCImpl::SetPen(const wxPen& pen)
{
// width, color, ends, joins : currently implemented
// dashes, stipple : not implemented
m_pen = pen;
m_graphics_changed = true;
}
void KicadSVGFileDCImpl::NewGraphics()
{
wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast, sWarn;
sBrush = wxT("</g>\n<g style=\"") + wxBrushString ( m_brush.GetColour(), m_brush.GetStyle() )
+ wxPenString(m_pen.GetColour(), m_pen.GetStyle());
switch ( m_pen.GetCap() )
{
case wxCAP_PROJECTING :
sPenCap = wxT("stroke-linecap:square; ");
break;
case wxCAP_BUTT :
sPenCap = wxT("stroke-linecap:butt; ");
break;
case wxCAP_ROUND :
default :
sPenCap = wxT("stroke-linecap:round; ");
}
switch ( m_pen.GetJoin() )
{
case wxJOIN_BEVEL :
sPenJoin = wxT("stroke-linejoin:bevel; ");
break;
case wxJOIN_MITER :
sPenJoin = wxT("stroke-linejoin:miter; ");
break;
case wxJOIN_ROUND :
default :
sPenJoin = wxT("stroke-linejoin:round; ");
}
sLast.Printf( wxT("stroke-width:%d\" \n transform=\"translate(%s %s) scale(%s %s)\">"),
m_pen.GetWidth(), NumStr(m_logicalOriginX), NumStr(m_logicalOriginY), NumStr(m_scaleX), NumStr(m_scaleY) );
s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + wxT("\n") + sWarn;
write(s);
m_graphics_changed = false;
}
void KicadSVGFileDCImpl::SetFont(const wxFont& font)
{
m_font = font;
}
// export a bitmap as a raster image in png
bool KicadSVGFileDCImpl::DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
wxDC* source, wxCoord xsrc, wxCoord ysrc,
wxRasterOperationMode logicalFunc /*= wxCOPY*/, bool useMask /*= false*/,
wxCoord /*xsrcMask = -1*/, wxCoord /*ysrcMask = -1*/)
{
if (logicalFunc != wxCOPY)
{
wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested nonCopy mode; this is not possible"));
return false;
}
if (useMask != false)
{
wxASSERT_MSG(false, wxT("wxSVGFileDC::DoBlit Call requested false mask; this is not possible"));
return false;
}
wxBitmap myBitmap (width, height);
wxMemoryDC memDC;
memDC.SelectObject( myBitmap );
memDC.Blit(0, 0, width, height, source, xsrc, ysrc);
memDC.SelectObject( wxNullBitmap );
DoDrawBitmap(myBitmap, xdest, ydest);
return false;
}
void KicadSVGFileDCImpl::DoDrawIcon(const class wxIcon & myIcon, wxCoord x, wxCoord y)
{
wxBitmap myBitmap (myIcon.GetWidth(), myIcon.GetHeight() );
wxMemoryDC memDC;
memDC.SelectObject( myBitmap );
memDC.DrawIcon(myIcon,0,0);
memDC.SelectObject( wxNullBitmap );
DoDrawBitmap(myBitmap, x, y);
}
void KicadSVGFileDCImpl::DoDrawBitmap(const class wxBitmap & bmp, wxCoord x, wxCoord y , bool WXUNUSED(bTransparent) /*=0*/ )
{
if (m_graphics_changed) NewGraphics();
wxString sTmp, s, sPNG;
if ( wxImage::FindHandler(wxBITMAP_TYPE_PNG) == NULL )
wxImage::AddHandler(new wxPNGHandler);
// create suitable file name
sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
while (wxFile::Exists(sPNG) )
{
m_sub_images ++;
sTmp.Printf ( wxT("_image%d.png"), m_sub_images);
sPNG = m_filename.BeforeLast(wxT('.')) + sTmp;
}
//create copy of bitmap (wxGTK doesn't like saving a constant bitmap)
wxBitmap myBitmap = bmp;
//save it
bool bPNG_OK = myBitmap.SaveFile(sPNG,wxBITMAP_TYPE_PNG);
// reference the bitmap from the SVG doc
// only use filename & ext
sPNG = sPNG.AfterLast(wxFileName::GetPathSeparator());
// reference the bitmap from the SVG doc
int w = myBitmap.GetWidth();
int h = myBitmap.GetHeight();
sTmp.Printf ( wxT(" <image x=\"%d\" y=\"%d\" width=\"%dpx\" height=\"%dpx\" "), x,y,w,h );
s += sTmp;
sTmp.Printf ( wxT(" xlink:href=\"%s\"> \n"), sPNG.c_str() );
s += sTmp + wxT("<title>Image from wxSVG</title> </image>") + wxT("\n");
if (m_OK && bPNG_OK)
{
write(s);
}
m_OK = m_outfile->IsOk() && bPNG_OK;
}
void KicadSVGFileDCImpl::write(const wxString &s)
{
const wxCharBuffer buf = s.utf8_str();
m_outfile->Write(buf, strlen((const char *)buf));
m_OK = m_outfile->IsOk();
}
#else
// or true to see the calls being executed
#define newline wxString( wxT( "\n" ) ) #define newline wxString( wxT( "\n" ) )
#define space wxString( wxT( " " ) ) #define space wxString( wxT( " " ) )
#define semicolon wxString( wxT( ";" ) ) #define semicolon wxString( wxT( ";" ) )
...@@ -212,7 +855,6 @@ void wxSVGFileDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 ) ...@@ -212,7 +855,6 @@ void wxSVGFileDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
{ {
write( s ); write( s );
} }
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DrawLine Call executed" ) );
CalcBoundingBox( x1, y1 ); CalcBoundingBox( x1, y1 );
CalcBoundingBox( x2, y2 ); CalcBoundingBox( x2, y2 );
return; return;
...@@ -251,7 +893,6 @@ void wxSVGFileDC::DoDrawCheckMark( wxCoord x1, wxCoord y1, wxCoord width, wxCoor ...@@ -251,7 +893,6 @@ void wxSVGFileDC::DoDrawCheckMark( wxCoord x1, wxCoord y1, wxCoord width, wxCoor
void wxSVGFileDC::DoDrawText( const wxString& text, wxCoord x1, wxCoord y1 ) void wxSVGFileDC::DoDrawText( const wxString& text, wxCoord x1, wxCoord y1 )
{ {
DoDrawRotatedText( text, x1, y1, 0.0 ); DoDrawRotatedText( text, x1, y1, 0.0 );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DrawText Call executed" ) );
} }
...@@ -283,8 +924,6 @@ void wxSVGFileDC::DoDrawRotatedText( const wxString& sText, wxCoord x, wxCoord y ...@@ -283,8 +924,6 @@ void wxSVGFileDC::DoDrawRotatedText( const wxString& sText, wxCoord x, wxCoord y
// draw background first // draw background first
// just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background // just like DoDrawRectangle except we pass the text color to it and set the border to a 1 pixel wide text background
wxASSERT_MSG( !wxSVG_DEBUG,
wxT( "wxSVGFileDC::Draw Rotated Text Call plotting text background" ) );
sTmp.Printf( wxT( sTmp.Printf( wxT(
" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" " ), x, y + desc - " <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" " ), x, y + desc -
h, w, h ); h, w, h );
...@@ -323,7 +962,6 @@ void wxSVGFileDC::DoDrawRotatedText( const wxString& sText, wxCoord x, wxCoord y ...@@ -323,7 +962,6 @@ void wxSVGFileDC::DoDrawRotatedText( const wxString& sText, wxCoord x, wxCoord y
{ {
write( s ); write( s );
} }
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DrawRotatedText Call executed" ) );
} }
...@@ -350,7 +988,6 @@ void wxSVGFileDC::DoDrawRoundedRectangle( wxCoord x, ...@@ -350,7 +988,6 @@ void wxSVGFileDC::DoDrawRoundedRectangle( wxCoord x,
s = s + wxT( " /> " ) + newline; s = s + wxT( " /> " ) + newline;
write( s ); write( s );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawRoundedRectangle Call executed" ) );
CalcBoundingBox( x, y ); CalcBoundingBox( x, y );
CalcBoundingBox( x + width, y + height ); CalcBoundingBox( x + width, y + height );
} }
...@@ -383,8 +1020,6 @@ void wxSVGFileDC::DoDrawPolygon( int n, ...@@ -383,8 +1020,6 @@ void wxSVGFileDC::DoDrawPolygon( int n,
s = s + wxT( "\" /> " ); s = s + wxT( "\" /> " );
s = s + newline; s = s + newline;
write( s ); write( s );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawPolygon Call executed" ) );
} }
...@@ -403,7 +1038,6 @@ void wxSVGFileDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord he ...@@ -403,7 +1038,6 @@ void wxSVGFileDC::DoDrawEllipse( wxCoord x, wxCoord y, wxCoord width, wxCoord he
write( s ); write( s );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawEllipse Call executed" ) );
CalcBoundingBox( x, y ); CalcBoundingBox( x, y );
CalcBoundingBox( x + width, y + height ); CalcBoundingBox( x + width, y + height );
} }
...@@ -477,8 +1111,6 @@ void wxSVGFileDC::DoDrawArc( wxCoord x1, ...@@ -477,8 +1111,6 @@ void wxSVGFileDC::DoDrawArc( wxCoord x1,
{ {
write( s ); write( s );
} }
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawArc Call executed" ) );
} }
...@@ -560,8 +1192,6 @@ void wxSVGFileDC::DoDrawEllipticArc( wxCoord x, ...@@ -560,8 +1192,6 @@ void wxSVGFileDC::DoDrawEllipticArc( wxCoord x,
{ {
write( s ); write( s );
} }
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawEllipticArc Call executed" ) );
} }
...@@ -579,7 +1209,6 @@ void wxSVGFileDC::DoGetTextExtent( const wxString& string, ...@@ -579,7 +1209,6 @@ void wxSVGFileDC::DoGetTextExtent( const wxString& string,
if( font != NULL ) if( font != NULL )
sDC.SetFont( *font ); sDC.SetFont( *font );
sDC.GetTextExtent( string, w, h, descent, externalLeading ); sDC.GetTextExtent( string, w, h, descent, externalLeading );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::GetTextExtent Call executed" ) );
} }
...@@ -590,7 +1219,6 @@ wxCoord wxSVGFileDC::GetCharHeight() const ...@@ -590,7 +1219,6 @@ wxCoord wxSVGFileDC::GetCharHeight() const
sDC.SetFont( m_font ); sDC.SetFont( m_font );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::GetCharHeight Call executing" ) );
return sDC.GetCharHeight(); return sDC.GetCharHeight();
} }
...@@ -601,7 +1229,6 @@ wxCoord wxSVGFileDC::GetCharWidth() const ...@@ -601,7 +1229,6 @@ wxCoord wxSVGFileDC::GetCharWidth() const
sDC.SetFont( m_font ); sDC.SetFont( m_font );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::GetCharWidth Call executing" ) );
return sDC.GetCharWidth(); return sDC.GetCharWidth();
} }
...@@ -627,7 +1254,6 @@ void wxSVGFileDC::SetBrush( const wxBrush& brush ) ...@@ -627,7 +1254,6 @@ void wxSVGFileDC::SetBrush( const wxBrush& brush )
m_brush = brush; m_brush = brush;
m_graphics_changed = true; m_graphics_changed = true;
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::SetBrush Call executed" ) );
} }
...@@ -638,7 +1264,6 @@ void wxSVGFileDC::SetPen( const wxPen& pen ) ...@@ -638,7 +1264,6 @@ void wxSVGFileDC::SetPen( const wxPen& pen )
m_pen = pen; m_pen = pen;
m_graphics_changed = true; m_graphics_changed = true;
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::SetPen Call executed" ) );
} }
...@@ -711,7 +1336,6 @@ void wxSVGFileDC::NewGraphics() ...@@ -711,7 +1336,6 @@ void wxSVGFileDC::NewGraphics()
s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn; s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
write( s ); write( s );
m_graphics_changed = false; m_graphics_changed = false;
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::NewGraphics Call executed" ) );
} }
...@@ -719,8 +1343,6 @@ void wxSVGFileDC::SetFont( const wxFont& font ) ...@@ -719,8 +1343,6 @@ void wxSVGFileDC::SetFont( const wxFont& font )
{ {
m_font = font; m_font = font;
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::SetFont Call executed" ) );
} }
...@@ -856,7 +1478,6 @@ bool wxSVGFileDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord h ...@@ -856,7 +1478,6 @@ bool wxSVGFileDC::DoBlit( wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord h
memDC.Blit( 0, 0, width, height, source, xsrc, ysrc ); memDC.Blit( 0, 0, width, height, source, xsrc, ysrc );
memDC.SelectObject( wxNullBitmap ); memDC.SelectObject( wxNullBitmap );
DoDrawBitmap( myBitmap, xdest, ydest ); DoDrawBitmap( myBitmap, xdest, ydest );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoBlit Call executed" ) );
return false; return false;
} }
...@@ -870,7 +1491,6 @@ void wxSVGFileDC::DoDrawIcon( const class wxIcon& myIcon, wxCoord x, wxCoord y ) ...@@ -870,7 +1491,6 @@ void wxSVGFileDC::DoDrawIcon( const class wxIcon& myIcon, wxCoord x, wxCoord y )
memDC.DrawIcon( myIcon, 0, 0 ); memDC.DrawIcon( myIcon, 0, 0 );
memDC.SelectObject( wxNullBitmap ); memDC.SelectObject( wxNullBitmap );
DoDrawBitmap( myBitmap, x, y ); DoDrawBitmap( myBitmap, x, y );
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawIcon Call executed" ) );
return; return;
} }
...@@ -915,7 +1535,6 @@ void wxSVGFileDC::DoDrawBitmap( const class wxBitmap& bmp, ...@@ -915,7 +1535,6 @@ void wxSVGFileDC::DoDrawBitmap( const class wxBitmap& bmp,
write( s ); write( s );
} }
m_OK = m_outfile->Ok() && bPNG_OK; m_OK = m_outfile->Ok() && bPNG_OK;
wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawBitmap Call executed" ) );
return; return;
} }
...@@ -981,10 +1600,4 @@ void wxSVGFileDC::write( const wxString& s ) ...@@ -981,10 +1600,4 @@ void wxSVGFileDC::write( const wxString& s )
m_OK = m_outfile->Ok(); m_OK = m_outfile->Ok();
} }
#ifdef __BORLANDC__
#pragma warn .rch
#pragma warn .ccc
#endif
#endif // wxCHECK_VERSION #endif // wxCHECK_VERSION
...@@ -217,7 +217,7 @@ bool DIALOG_SVG_PRINT::DrawSVGPage( EDA_DRAW_FRAME* frame, ...@@ -217,7 +217,7 @@ bool DIALOG_SVG_PRINT::DrawSVGPage( EDA_DRAW_FRAME* frame,
LOCALE_IO toggle; LOCALE_IO toggle;
float dpi = (float) frame->GetInternalUnits(); float dpi = (float) frame->GetInternalUnits();
wxSVGFileDC dc( FullFileName, sheetSize.x, sheetSize.y, dpi ); KicadSVGFileDC dc( FullFileName, sheetSize.x, sheetSize.y, dpi );
EDA_RECT tmp = *panel->GetClipBox(); EDA_RECT tmp = *panel->GetClipBox();
GRResetPenAndBrush( &dc ); GRResetPenAndBrush( &dc );
......
#if wxCHECK_VERSION( 2, 9, 0 )
// Do nothing, because wxWidgets 3 supports the SVG format
// previously, was a contribution library, not included in wxWidgets base
#include <wx/dcsvg.h>
#else
#ifndef __DCSVG_H #ifndef __KICAD_DCSVG_H
#define __DCSVG_H #define __KICAD_DCSVG_H
#include <wx/dc.h>
#include <wx/wfstream.h> #include <wx/wfstream.h>
#include <wx/string.h> #include <wx/string.h>
#define wxSVGVersion wxT( "v0101" ) #define wxSVGVersion wxT( "v0101" )
#ifdef __BORLANDC__
#pragma warn -rch #if wxCHECK_VERSION( 2, 9, 0 )
#pragma warn -ccc
#endif // We could do nothing, because wxWidgets 3 supports the SVG format
// (previously, it was a contribution library, not included in wxWidgets)
// However arcs are drawn as pies, and we must change it.
// Unfortunately most of functions are private, and we cannot derive
// our KicadSVGFileDCImpl from wxSVGFileDCImpl
// and just override the 2 incorrect functions
// Just wxWidget dcsvg is copied here and 2 functions are modified:
// KicadSVGFileDCImpl::DoDrawArc() and KicadSVGFileDCImpl::DoDrawEllipticArc()
// Also note: SetLogicalFunction() does not set an error in debug mode
class WXDLLIMPEXP_FWD_BASE wxFileOutputStream;
class WXDLLIMPEXP_FWD_CORE KicadSVGFileDC;
class WXDLLIMPEXP_CORE KicadSVGFileDCImpl : public wxDCImpl
{
public:
KicadSVGFileDCImpl( KicadSVGFileDC *owner, const wxString &filename,
int width=320, int height=240, double dpi=72.0 );
virtual ~KicadSVGFileDCImpl();
bool IsOk() const { return m_OK; }
virtual bool CanDrawBitmap() const { return true; }
virtual bool CanGetTextExtent() const { return true; }
virtual int GetDepth() const
{
wxFAIL_MSG(wxT("wxSVGFILEDC::GetDepth Call not implemented"));
return -1;
}
virtual void Clear()
{
wxFAIL_MSG(wxT("wxSVGFILEDC::Clear() Call not implemented \nNot sensible for an output file?"));
}
virtual void DestroyClippingRegion()
{
wxFAIL_MSG(wxT("wxSVGFILEDC::void Call not yet implemented"));
}
virtual wxCoord GetCharHeight() const;
virtual wxCoord GetCharWidth() const;
virtual void SetClippingRegion(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
wxCoord WXUNUSED(w), wxCoord WXUNUSED(h))
{
wxFAIL_MSG(wxT("wxSVGFILEDC::SetClippingRegion not implemented"));
}
virtual void SetPalette(const wxPalette& WXUNUSED(palette))
{
wxFAIL_MSG(wxT("wxSVGFILEDC::SetPalette not implemented"));
}
virtual void GetClippingBox(wxCoord *WXUNUSED(x), wxCoord *WXUNUSED(y),
wxCoord *WXUNUSED(w), wxCoord *WXUNUSED(h))
{
wxFAIL_MSG(wxT("wxSVGFILEDC::GetClippingBox not implemented"));
}
virtual void SetLogicalFunction(wxRasterOperationMode WXUNUSED(function))
{
// wxFAIL_MSG(wxT("KicadSVGFILEDC::SetLogicalFunction not implemented"));
}
virtual wxRasterOperationMode GetLogicalFunction() const
{
wxFAIL_MSG(wxT("wxSVGFILEDC::GetLogicalFunction() not implemented"));
return wxCOPY;
}
virtual void SetBackground( const wxBrush &brush );
virtual void SetBackgroundMode( int mode );
virtual void SetBrush(const wxBrush& brush);
virtual void SetFont(const wxFont& font);
virtual void SetPen(const wxPen& pen);
private:
virtual bool DoGetPixel(wxCoord, wxCoord, wxColour *) const
{
wxFAIL_MSG(wxT("wxSVGFILEDC::DoGetPixel Call not implemented"));
return true;
}
virtual bool DoBlit(wxCoord, wxCoord, wxCoord, wxCoord, wxDC *,
wxCoord, wxCoord, wxRasterOperationMode = wxCOPY,
bool = 0, int = -1, int = -1);
virtual void DoCrossHair(wxCoord, wxCoord)
{
wxFAIL_MSG(wxT("wxSVGFILEDC::CrossHair Call not implemented"));
}
virtual void DoDrawArc(wxCoord, wxCoord, wxCoord, wxCoord, wxCoord, wxCoord);
virtual void DoDrawBitmap(const wxBitmap &, wxCoord, wxCoord, bool = false);
virtual void DoDrawCheckMark(wxCoord x, wxCoord y, wxCoord w, wxCoord h);
virtual void DoDrawEllipse(wxCoord x, wxCoord y, wxCoord w, wxCoord h);
virtual void DoDrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord h,
double sa, double ea);
virtual void DoDrawIcon(const wxIcon &, wxCoord, wxCoord);
virtual void DoDrawLine (wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2);
virtual void DoDrawLines(int n, wxPoint points[],
wxCoord xoffset = 0, wxCoord yoffset = 0);
virtual void DoDrawPoint(wxCoord, wxCoord);
virtual void DoDrawPolygon(int n, wxPoint points[],
wxCoord xoffset, wxCoord yoffset,
wxPolygonFillMode fillStyle);
virtual void DoDrawRectangle(wxCoord x, wxCoord y, wxCoord w, wxCoord h);
virtual void DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y,
double angle);
virtual void DoDrawRoundedRectangle(wxCoord x, wxCoord y,
wxCoord w, wxCoord h,
double radius = 20) ;
virtual void DoDrawText(const wxString& text, wxCoord x, wxCoord y);
virtual bool DoFloodFill(wxCoord WXUNUSED(x), wxCoord WXUNUSED(y),
const wxColour& WXUNUSED(col),
wxFloodFillStyle WXUNUSED(style) = wxFLOOD_SURFACE)
{
wxFAIL_MSG(wxT("wxSVGFILEDC::DoFloodFill Call not implemented"));
return false;
}
virtual void DoGetSize(int * x, int *y) const
{
if ( x )
*x = m_width;
if ( y )
*y = m_height;
}
virtual void DoGetTextExtent(const wxString& string, wxCoord *w, wxCoord *h,
wxCoord *descent = NULL,
wxCoord *externalLeading = NULL,
const wxFont *font = NULL) const;
virtual void DoSetDeviceClippingRegion(const wxRegion& WXUNUSED(region))
{
wxFAIL_MSG(wxT("wxSVGFILEDC::DoSetDeviceClippingRegion not yet implemented"));
}
virtual void DoSetClippingRegion( int WXUNUSED(x), int WXUNUSED(y), int WXUNUSED(width), int WXUNUSED(height) )
{
wxFAIL_MSG(wxT("wxSVGFILEDC::DoSetClippingRegion not yet implemented"));
}
virtual void DoGetSizeMM( int *width, int *height ) const;
virtual wxSize GetPPI() const;
void Init (const wxString &filename, int width, int height, double dpi);
void NewGraphics();
void write( const wxString &s );
private:
wxFileOutputStream *m_outfile;
wxString m_filename;
int m_sub_images; // number of png format images we have
bool m_OK;
bool m_graphics_changed;
int m_width, m_height;
double m_dpi;
private:
DECLARE_ABSTRACT_CLASS(KicadSVGFileDCImpl)
};
class WXDLLIMPEXP_CORE KicadSVGFileDC : public wxDC
{
public:
KicadSVGFileDC(const wxString& filename,
int width = 320,
int height = 240,
double dpi = 72.0)
: wxDC(new KicadSVGFileDCImpl(this, filename, width, height, dpi))
{
}
};
#else
class wxSVGFileDC : public wxDC class wxSVGFileDC : public wxDC
{ {
...@@ -387,7 +581,8 @@ public: ...@@ -387,7 +581,8 @@ public:
void SetFont( const wxFont& font ); void SetFont( const wxFont& font );
void SetLogicalFunction( int WXUNUSED (function) ) void SetLogicalFunction( int WXUNUSED (function) )
{ /*wxASSERT_MSG (false, wxT("wxSVGFILEDC::SetLogicalFunction Call implemented")); */ {
//wxASSERT_MSG (false, wxT("wxSVGFILEDC::SetLogicalFunction not implemented"));
return; return;
}; };
...@@ -414,10 +609,8 @@ public: ...@@ -414,10 +609,8 @@ public:
}; };
}; };
#ifdef __BORLANDC__ typedef KicadSVGFileDC wxSVGFileDC;
#pragma warn .rch
#pragma warn .ccc #endif // wxCHECK_VERSION
#endif
#endif
#endif // wxCHECK_VERSION #endif // __KICAD_DCSVG_H
...@@ -250,7 +250,7 @@ bool DIALOG_SVG_PRINT::DrawPage( const wxString& FullFileName, ...@@ -250,7 +250,7 @@ bool DIALOG_SVG_PRINT::DrawPage( const wxString& FullFileName,
// paper pageSize is in internal units, either nanometers or deci-mils // paper pageSize is in internal units, either nanometers or deci-mils
wxSize pageSize = m_Parent->GetPageSizeIU(); wxSize pageSize = m_Parent->GetPageSizeIU();
wxSVGFileDC dc( FullFileName, pageSize.x, pageSize.y, dpi ); KicadSVGFileDC dc( FullFileName, pageSize.x, pageSize.y, dpi );
EDA_RECT tmp = *panel->GetClipBox(); EDA_RECT tmp = *panel->GetClipBox();
GRResetPenAndBrush( &dc ); GRResetPenAndBrush( &dc );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment