Improve whitespace formatting in generated SVG

Write coordinates first, then styles.
This commit is contained in:
Maarten Bent 2019-08-10 19:33:33 +02:00
parent 70f0900799
commit 215f844502

View File

@ -48,7 +48,10 @@ namespace
// in this code originally).
inline wxString NumStr(double f)
{
return wxString::FromCDouble(f, 2);
if ( f == 0 )
return wxS("0.00");
else
return wxString::FromCDouble(f, 2);
}
// Return the colour representation as HTML-like "#rrggbb" string and also
@ -74,7 +77,7 @@ wxString Col2SVG(wxColour c, float *opacity)
wxString wxPenString(wxColour c, int style = wxPENSTYLE_SOLID)
{
float opacity;
wxString s = wxS("stroke:") + Col2SVG(c, &opacity) + wxS("; ");
wxString s = wxS("stroke:") + Col2SVG(c, &opacity) + wxS(";");
switch ( style )
{
@ -84,10 +87,10 @@ wxString wxPenString(wxColour c, int style = wxPENSTYLE_SOLID)
case wxPENSTYLE_LONG_DASH:
case wxPENSTYLE_DOT_DASH:
case wxPENSTYLE_USER_DASH:
s += wxString::Format(wxS("stroke-opacity:%s; "), NumStr(opacity));
s += wxString::Format(wxS(" stroke-opacity:%s;"), NumStr(opacity));
break;
case wxPENSTYLE_TRANSPARENT:
s += wxS("stroke-opacity:0.0; ");
s += wxS(" stroke-opacity:0.0;");
break;
default:
wxASSERT_MSG(false, wxS("wxSVGFileDC::Requested Pen Style not available"));
@ -99,7 +102,7 @@ wxString wxPenString(wxColour c, int style = wxPENSTYLE_SOLID)
wxString wxBrushString(wxColour c, int style = wxBRUSHSTYLE_SOLID)
{
float opacity;
wxString s = wxS("fill:") + Col2SVG(c, &opacity) + wxS("; ");
wxString s = wxS("fill:") + Col2SVG(c, &opacity) + wxS(";");
switch ( style )
{
@ -109,10 +112,10 @@ wxString wxBrushString(wxColour c, int style = wxBRUSHSTYLE_SOLID)
case wxBRUSHSTYLE_CROSS_HATCH:
case wxBRUSHSTYLE_VERTICAL_HATCH:
case wxBRUSHSTYLE_HORIZONTAL_HATCH:
s += wxString::Format(wxS("fill-opacity:%s; "), NumStr(opacity));
s += wxString::Format(wxS(" fill-opacity:%s;"), NumStr(opacity));
break;
case wxBRUSHSTYLE_TRANSPARENT:
s += wxS("fill-opacity:0.0; ");
s += wxS(" fill-opacity:0.0;");
break;
default:
wxASSERT_MSG(false, wxS("wxSVGFileDC::Requested Brush Style not available"));
@ -139,16 +142,16 @@ wxString wxGetPenPattern(wxPen& pen)
switch (pen.GetStyle())
{
case wxPENSTYLE_DOT:
s = wxString::Format(wxS("stroke-dasharray=\"%f,%f\" "), w * 2, w * 5);
s = wxString::Format(wxS("stroke-dasharray=\"%f,%f\""), w * 2, w * 5);
break;
case wxPENSTYLE_SHORT_DASH:
s = wxString::Format(wxS("stroke-dasharray=\"%f,%f\" "), w * 10, w * 8);
s = wxString::Format(wxS("stroke-dasharray=\"%f,%f\""), w * 10, w * 8);
break;
case wxPENSTYLE_LONG_DASH:
s = wxString::Format(wxS("stroke-dasharray=\"%f,%f\" "), w * 15, w * 8);
s = wxString::Format(wxS("stroke-dasharray=\"%f,%f\""), w * 15, w * 8);
break;
case wxPENSTYLE_DOT_DASH:
s = wxString::Format(wxS("stroke-dasharray=\"%f,%f,%f,%f\" "), w * 8, w * 8, w * 2, w * 8);
s = wxString::Format(wxS("stroke-dasharray=\"%f,%f,%f,%f\""), w * 8, w * 8, w * 2, w * 8);
break;
case wxPENSTYLE_USER_DASH:
{
@ -164,7 +167,7 @@ wxString wxGetPenPattern(wxPen& pen)
s << ",";
}
}
s += wxS("\" ");
s += wxS("\"");
break;
}
case wxPENSTYLE_STIPPLE_MASK_OPAQUE:
@ -230,7 +233,7 @@ wxString wxGetBrushFill(wxBrush& brush)
wxString brushStyle = wxGetBrushStyleName(brush);
if (!brushStyle.IsEmpty())
s = wxS(" fill=\"url(#") + brushStyle + brush.GetColour().GetAsString(wxC2S_HTML_SYNTAX).substr(1) + wxS(")\"");
s = wxS("fill=\"url(#") + brushStyle + brush.GetColour().GetAsString(wxC2S_HTML_SYNTAX).substr(1) + wxS(")\"");
return s;
}
@ -242,32 +245,35 @@ wxString wxCreateBrushFill(wxBrush& brush)
if (!patternName.IsEmpty())
{
patternName += brush.GetColour().GetAsString(wxC2S_HTML_SYNTAX).substr(1);
s = wxS("<pattern id=\"") + patternName + wxS("\" patternUnits=\"userSpaceOnUse\" width=\"8\" height=\"8\">\n");
s += wxS(" <path style=\"stroke:") + brush.GetColour().GetAsString(wxC2S_HTML_SYNTAX) + wxS(";\" ");
wxString pattern;
switch (brush.GetStyle())
{
case wxBRUSHSTYLE_FDIAGONAL_HATCH:
s += wxS("d=\"M7,-1 l2,2 M0,0 l8,8 M-1,7 l2,2\"");
pattern = wxS("d=\"M7,-1 l2,2 M0,0 l8,8 M-1,7 l2,2\"");
break;
case wxBRUSHSTYLE_CROSSDIAG_HATCH:
s += wxS("d=\"M7,-1 l2,2 M0,0 l8,8 M-1,7 l2,2 M-1,1 l2,-2 M0,8 l8,-8 M7,9 l2,-2\"");
pattern = wxS("d=\"M7,-1 l2,2 M0,0 l8,8 M-1,7 l2,2 M-1,1 l2,-2 M0,8 l8,-8 M7,9 l2,-2\"");
break;
case wxBRUSHSTYLE_CROSS_HATCH:
s += wxS("d=\"M4,0 l0,8 M0,4 l8,0\"");
pattern = wxS("d=\"M4,0 l0,8 M0,4 l8,0\"");
break;
case wxBRUSHSTYLE_VERTICAL_HATCH:
s += wxS("d=\"M4,0 l0,8\"");
pattern = wxS("d=\"M4,0 l0,8\"");
break;
case wxBRUSHSTYLE_HORIZONTAL_HATCH:
s += wxS("d=\"M0,4 l8,0\"");
pattern = wxS("d=\"M0,4 l8,0\"");
break;
default:
break;
}
s += wxS("/>\n</pattern>\n");
wxString brushColourStr = brush.GetColour().GetAsString(wxC2S_HTML_SYNTAX);
s += wxString::Format(wxS(" <pattern id=\"%s%s\" patternUnits=\"userSpaceOnUse\" width=\"8\" height=\"8\">\n"),
patternName, brushColourStr.substr(1));
s += wxString::Format(wxS(" <path style=\"stroke:%s;\" %s/>\n"),
brushColourStr, pattern);
s += wxS(" </pattern>\n");
}
return s;
@ -490,7 +496,8 @@ void wxSVGFileDCImpl::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
NewGraphicsIfNeeded();
wxString s;
s = wxString::Format(wxS(" <path %sd=\"M%d %d L%d %d\"/>\n"), wxGetPenPattern(m_pen), x1, y1, x2, y2);
s = wxString::Format(wxS(" <path d=\"M%d %d L%d %d\" %s/>\n"),
x1, y1, x2, y2, wxGetPenPattern(m_pen));
write(s);
@ -505,8 +512,9 @@ void wxSVGFileDCImpl::DoDrawLines(int n, const wxPoint points[], wxCoord xoffset
NewGraphicsIfNeeded();
wxString s;
s = wxS(" <path ") + wxGetPenPattern(m_pen);
s += wxString::Format(wxS("d=\"M%d %d"), (points[0].x + xoffset), (points[0].y + yoffset));
s = wxString::Format(wxS(" <path d=\"M%d %d"),
(points[0].x + xoffset), (points[0].y + yoffset));
CalcBoundingBox(points[0].x + xoffset, points[0].y + yoffset);
for (int i = 1; i < n; ++i)
@ -515,7 +523,8 @@ void wxSVGFileDCImpl::DoDrawLines(int n, const wxPoint points[], wxCoord xoffset
CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
}
s += wxS("\" style=\"fill:none\"/>\n");
s += wxString::Format(wxS("\" style=\"fill:none\" %s/>\n"),
wxGetPenPattern(m_pen));
write(s);
}
@ -523,12 +532,16 @@ void wxSVGFileDCImpl::DoDrawLines(int n, const wxPoint points[], wxCoord xoffset
void wxSVGFileDCImpl::DoDrawPoint(wxCoord x1, wxCoord y1)
{
wxString s;
NewGraphicsIfNeeded();
s = wxS("<g style=\"stroke-linecap:round;\">\n");
wxString s;
s = wxS(" <g style=\"stroke-linecap:round;\">\n ");
write(s);
DoDrawLine(x1, y1, x1, y1);
s = wxS("</g>\n");
s = wxS(" </g>\n");
write(s);
}
@ -666,10 +679,10 @@ void wxSVGFileDCImpl::DoDrawRoundedRectangle(wxCoord x, wxCoord y, wxCoord width
NewGraphicsIfNeeded();
wxString s;
s = wxString::Format(wxS(" <rect %sx=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\"%s"),
wxGetPenPattern(m_pen), x, y, width, height, NumStr(radius), wxGetBrushFill(m_brush));
s = wxString::Format(wxS(" <rect x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" rx=\"%s\" %s %s/>\n"),
x, y, width, height, NumStr(radius),
wxGetPenPattern(m_pen), wxGetBrushFill(m_brush));
s += wxS("/>\n");
write(s);
CalcBoundingBox(x, y);
@ -681,22 +694,21 @@ void wxSVGFileDCImpl::DoDrawPolygon(int n, const wxPoint points[],
wxPolygonFillMode fillStyle)
{
NewGraphicsIfNeeded();
wxString s;
s = wxS(" <polygon style=\"");
if (fillStyle == wxODDEVEN_RULE)
s += wxS("fill-rule:evenodd;");
else
s += wxS("fill-rule:nonzero;");
s += wxS("\" ") + wxGetPenPattern(m_pen) + wxGetBrushFill(m_brush) + wxS(" points=\"");
s = wxS(" <polygon points=\"");
for (int i = 0; i < n; i++)
{
s += wxString::Format(wxS("%d %d "), points[i].x + xoffset, points[i].y + yoffset);
CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
}
s += wxS("\"/>\n");
s += wxString::Format(wxS("\" %s %s style=\"fill-rule:%s;\"/>\n"),
wxGetPenPattern(m_pen), wxGetBrushFill(m_brush),
(fillStyle == wxODDEVEN_RULE) ? wxS("evenodd") : wxS("nonzero"));
write(s);
}
@ -750,8 +762,8 @@ void wxSVGFileDCImpl::DoDrawEllipse(wxCoord x, wxCoord y, wxCoord width, wxCoord
int rw = width / 2;
wxString s;
s = wxString::Format(wxS(" <ellipse %scx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\""),
wxGetPenPattern(m_pen), x + rw, y + rh, rw, rh);
s = wxString::Format(wxS(" <ellipse cx=\"%d\" cy=\"%d\" rx=\"%d\" ry=\"%d\" %s"),
x + rw, y + rh, rw, rh, wxGetPenPattern(m_pen));
s += wxS("/>\n");
write(s);
@ -803,8 +815,8 @@ void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
if (x1 == x2 && y1 == y2)
{
// drawing full circle fails with default arc. Draw two half arcs instead.
s = wxString::Format(wxS(" <path %sd=\"M%d %d a%s %s 0 %d %d %s %s a%s %s 0 %d %d %s %s"),
wxGetPenPattern(m_pen), x1, y1,
s = wxString::Format(wxS(" <path d=\"M%d %d a%s %s 0 %d %d %s %s a%s %s 0 %d %d %s %s"),
x1, y1,
NumStr(r1), NumStr(r2), fArc, fSweep, NumStr( r1 * 2), NumStr(0),
NumStr(r1), NumStr(r2), fArc, fSweep, NumStr(-r1 * 2), NumStr(0));
}
@ -815,12 +827,11 @@ void wxSVGFileDCImpl::DoDrawArc(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2,
if (GetBrush().GetStyle() != wxBRUSHSTYLE_TRANSPARENT)
line = wxString::Format(wxS("L%d %d z"), xc, yc);
s = wxString::Format(wxS(" <path %sd=\"M%d %d A%s %s 0 %d %d %d %d %s"),
wxGetPenPattern(m_pen), x1, y1,
NumStr(r1), NumStr(r2), fArc, fSweep, x2, y2, line);
s = wxString::Format(wxS(" <path d=\"M%d %d A%s %s 0 %d %d %d %d %s"),
x1, y1, NumStr(r1), NumStr(r2), fArc, fSweep, x2, y2, line);
}
s += wxS("\"/>\n");
s += wxString::Format(wxS("\" %s/>\n"), wxGetPenPattern(m_pen));
write(s);
}
@ -883,15 +894,15 @@ void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord
{
// Drawing full circle fails with default arc. Draw two half arcs instead.
fArc = 1;
arcPath = wxString::Format(wxS(" <path %sd=\"M%s %s a%s %s 0 %d %d %s %s a%s %s 0 %d %d %s %s"),
wxGetPenPattern(m_pen), NumStr(x), NumStr(y + ry),
arcPath = wxString::Format(wxS(" <path d=\"M%s %s a%s %s 0 %d %d %s %s a%s %s 0 %d %d %s %s"),
NumStr(x), NumStr(y + ry),
NumStr(rx), NumStr(ry), fArc, fSweep, NumStr( rx * 2), NumStr(0),
NumStr(rx), NumStr(ry), fArc, fSweep, NumStr(-rx * 2), NumStr(0));
}
else
{
arcPath = wxString::Format(wxS(" <path %sd=\"M%s %s A%s %s 0 %d %d %s %s"),
wxGetPenPattern(m_pen), NumStr(xs), NumStr(ys),
arcPath = wxString::Format(wxS(" <path d=\"M%s %s A%s %s 0 %d %d %s %s"),
NumStr(xs), NumStr(ys),
NumStr(rx), NumStr(ry), fArc, fSweep, NumStr(xe), NumStr(ye));
}
@ -905,15 +916,16 @@ void wxSVGFileDCImpl::DoDrawEllipticArc(wxCoord x, wxCoord y, wxCoord w, wxCoord
NewGraphicsIfNeeded();
wxString arcFill = arcPath;
arcFill += wxString::Format(wxS(" L%s %s z"), NumStr(xc), NumStr(yc));
arcFill += wxS("\"/>\n");
arcFill += wxString::Format(wxS(" L%s %s z\" %s/>\n"),
NumStr(xc), NumStr(yc), wxGetPenPattern(m_pen));
write(arcFill);
}
wxDCBrushChanger setTransp(*GetOwner(), *wxTRANSPARENT_BRUSH);
NewGraphicsIfNeeded();
wxString arcLine = arcPath + wxS("\"/>\n");
wxString arcLine = wxString::Format(wxS("%s\" %s/>\n"),
arcPath, wxGetPenPattern(m_pen));
write(arcLine);
}
@ -1051,45 +1063,46 @@ void wxSVGFileDCImpl::NewGraphicsIfNeeded()
void wxSVGFileDCImpl::DoStartNewGraphics()
{
wxString s, sBrush, sPenCap, sPenJoin, sPenStyle, sLast;
sBrush = wxS("<g style=\"") + wxBrushString(m_brush.GetColour(), m_brush.GetStyle())
+ wxPenString(m_pen.GetColour(), m_pen.GetStyle());
wxString s, sPenCap, sPenJoin, sLast;
switch ( m_pen.GetCap() )
{
case wxCAP_PROJECTING:
sPenCap = wxS("stroke-linecap:square; ");
sPenCap = wxS("stroke-linecap:square;");
break;
case wxCAP_BUTT:
sPenCap = wxS("stroke-linecap:butt; ");
sPenCap = wxS("stroke-linecap:butt;");
break;
case wxCAP_ROUND:
default:
sPenCap = wxS("stroke-linecap:round; ");
sPenCap = wxS("stroke-linecap:round;");
}
switch (m_pen.GetJoin())
{
case wxJOIN_BEVEL:
sPenJoin = wxS("stroke-linejoin:bevel; ");
sPenJoin = wxS("stroke-linejoin:bevel;");
break;
case wxJOIN_MITER:
sPenJoin = wxS("stroke-linejoin:miter; ");
sPenJoin = wxS("stroke-linejoin:miter;");
break;
case wxJOIN_ROUND:
default:
sPenJoin = wxS("stroke-linejoin:round; ");
sPenJoin = wxS("stroke-linejoin:round;");
}
sLast = wxString::Format(wxS("stroke-width:%d\" transform=\"translate(%s %s) scale(%s %s)\">"),
sLast = wxString::Format(wxS("stroke-width:%d\" transform=\"translate(%s %s) scale(%s %s)\""),
m_pen.GetWidth(),
NumStr((m_deviceOriginX - m_logicalOriginX)* m_signX),
NumStr((m_deviceOriginY - m_logicalOriginY)* m_signY),
NumStr(m_scaleX * m_signX),
NumStr(m_scaleY * m_signY));
s = sBrush + sPenCap + sPenJoin + sPenStyle + sLast + wxS("\n");
s = wxString::Format(wxS("<g style=\"%s %s %s %s %s>\n"),
wxBrushString(m_brush.GetColour(), m_brush.GetStyle()),
wxPenString(m_pen.GetColour(), m_pen.GetStyle()),
sPenCap, sPenJoin, sLast);
write(s);
}