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

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
Loading
Loading
Loading
Loading
+651 −38
Original line number Diff line number Diff line
@@ -19,20 +19,663 @@
#include <wx/wx.h>
#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 <wx/filename.h>
#include <wx/image.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 space      wxString( wxT( " " ) )
#define semicolon  wxString( wxT( ";" ) )
@@ -212,7 +855,6 @@ void wxSVGFileDC::DoDrawLine( wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2 )
    {
        write( s );
    }
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DrawLine Call executed" ) );
    CalcBoundingBox( x1, y1 );
    CalcBoundingBox( x2, y2 );
    return;
@@ -251,7 +893,6 @@ void wxSVGFileDC::DoDrawCheckMark( wxCoord x1, wxCoord y1, wxCoord width, wxCoor
void wxSVGFileDC::DoDrawText( const wxString& text, wxCoord x1, wxCoord y1 )
{
    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
        // 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

        wxASSERT_MSG( !wxSVG_DEBUG,
                     wxT( "wxSVGFileDC::Draw Rotated Text Call plotting text background" ) );
        sTmp.Printf( wxT(
                         " <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\"  " ), x, y + desc -
                     h, w, h );
@@ -323,7 +962,6 @@ void wxSVGFileDC::DoDrawRotatedText( const wxString& sText, wxCoord x, wxCoord y
    {
        write( s );
    }
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DrawRotatedText Call executed" ) );
}


@@ -350,7 +988,6 @@ void wxSVGFileDC::DoDrawRoundedRectangle( wxCoord x,
    s = s + wxT( " /> " ) + newline;
    write( s );

    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawRoundedRectangle Call executed" ) );
    CalcBoundingBox( x, y );
    CalcBoundingBox( x + width, y + height );
}
@@ -383,8 +1020,6 @@ void wxSVGFileDC::DoDrawPolygon( int n,
    s = s + wxT( "\" /> " );
    s = s + newline;
    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

    write( s );

    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawEllipse Call executed" ) );
    CalcBoundingBox( x, y );
    CalcBoundingBox( x + width, y + height );
}
@@ -477,8 +1111,6 @@ void wxSVGFileDC::DoDrawArc( wxCoord x1,
    {
        write( s );
    }

    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawArc Call executed" ) );
}


@@ -560,8 +1192,6 @@ void wxSVGFileDC::DoDrawEllipticArc( wxCoord x,
    {
        write( s );
    }

    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawEllipticArc Call executed" ) );
}


@@ -579,7 +1209,6 @@ void wxSVGFileDC::DoGetTextExtent( const wxString& string,
    if( font != NULL )
        sDC.SetFont( *font );
    sDC.GetTextExtent( string, w, h, descent, externalLeading );
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::GetTextExtent Call executed" ) );
}


@@ -590,7 +1219,6 @@ wxCoord wxSVGFileDC::GetCharHeight() const

    sDC.SetFont( m_font );

    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::GetCharHeight Call executing" ) );
    return sDC.GetCharHeight();
}

@@ -601,7 +1229,6 @@ wxCoord wxSVGFileDC::GetCharWidth() const

    sDC.SetFont( m_font );

    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::GetCharWidth Call executing" ) );
    return sDC.GetCharWidth();
}

@@ -627,7 +1254,6 @@ void wxSVGFileDC::SetBrush( const wxBrush& brush )
    m_brush = brush;

    m_graphics_changed = true;
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::SetBrush Call executed" ) );
}


@@ -638,7 +1264,6 @@ void wxSVGFileDC::SetPen( const wxPen& pen )
    m_pen = pen;

    m_graphics_changed = true;
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::SetPen Call executed" ) );
}


@@ -711,7 +1336,6 @@ void wxSVGFileDC::NewGraphics()
    s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + newline + sWarn;
    write( s );
    m_graphics_changed = false;
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::NewGraphics Call executed" ) );
}


@@ -719,8 +1343,6 @@ void wxSVGFileDC::SetFont( const wxFont& 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
    memDC.Blit( 0, 0, width, height, source, xsrc, ysrc );
    memDC.SelectObject( wxNullBitmap );
    DoDrawBitmap( myBitmap, xdest, ydest );
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoBlit Call executed" ) );
    return false;
}

@@ -870,7 +1491,6 @@ void wxSVGFileDC::DoDrawIcon( const class wxIcon& myIcon, wxCoord x, wxCoord y )
    memDC.DrawIcon( myIcon, 0, 0 );
    memDC.SelectObject( wxNullBitmap );
    DoDrawBitmap( myBitmap, x, y );
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawIcon Call executed" ) );
    return;
}

@@ -915,7 +1535,6 @@ void wxSVGFileDC::DoDrawBitmap( const class wxBitmap& bmp,
        write( s );
    }
    m_OK = m_outfile->Ok() && bPNG_OK;
    wxASSERT_MSG( !wxSVG_DEBUG, wxT( "wxSVGFileDC::DoDrawBitmap Call executed" ) );

    return;
}
@@ -981,10 +1600,4 @@ void wxSVGFileDC::write( const wxString& s )
    m_OK = m_outfile->Ok();
}


#ifdef __BORLANDC__
#pragma warn .rch
#pragma warn .ccc
#endif

#endif // wxCHECK_VERSION
+1 −1
Original line number Diff line number Diff line
@@ -217,7 +217,7 @@ bool DIALOG_SVG_PRINT::DrawSVGPage( EDA_DRAW_FRAME* frame,
    LOCALE_IO   toggle;

    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();
    GRResetPenAndBrush( &dc );
+211 −18

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1

File changed.

Preview size limit exceeded, changes collapsed.