diff --git a/modules/juce_gui_basics/drawables/juce_SVGParser.cpp b/modules/juce_gui_basics/drawables/juce_SVGParser.cpp index 4445749224..6ebfdcffc2 100644 --- a/modules/juce_gui_basics/drawables/juce_SVGParser.cpp +++ b/modules/juce_gui_basics/drawables/juce_SVGParser.cpp @@ -62,15 +62,15 @@ public: { const String viewBoxAtt (xml.getStringAttribute ("viewBox")); String::CharPointerType viewParams (viewBoxAtt.getCharPointer()); - float vx, vy, vw, vh; + Point vxy, vwh; - if (parseCoords (viewParams, vx, vy, true) - && parseCoords (viewParams, vw, vh, true) - && vw > 0 - && vh > 0) + if (parseCoords (viewParams, vxy, true) + && parseCoords (viewParams, vwh, true) + && vwh.x > 0 + && vwh.y > 0) { - newState.viewBoxW = vw; - newState.viewBoxH = vh; + newState.viewBoxW = vwh.x; + newState.viewBoxH = vwh.y; int placementFlags = 0; @@ -103,8 +103,8 @@ public: const RectanglePlacement placement (placementFlags); newState.transform - = placement.getTransformToFit (Rectangle (vx, vy, vw, vh), - Rectangle (0.0f, 0.0f, newState.width, newState.height)) + = placement.getTransformToFit (Rectangle (vxy.x, vxy.y, vwh.x, vwh.y), + Rectangle (newState.width, newState.height)) .followedBy (newState.transform); } } @@ -196,8 +196,7 @@ private: if (getStyleAttribute (&xml, "fill-rule").trim().equalsIgnoreCase ("evenodd")) path.setUsingNonZeroWinding (false); - float lastX = 0, lastY = 0; - float lastX2 = 0, lastY2 = 0; + Point subpathStart, last, last2, p1, p2, p3; juce_wchar lastCommandChar = 0; bool isRelative = true; bool carryOn = true; @@ -206,8 +205,6 @@ private: while (! d.isEmpty()) { - float x, y, x2, y2, x3, y3; - if (validCommandChars.indexOf (*d) >= 0) { lastCommandChar = d.getAndAdvance(); @@ -220,45 +217,36 @@ private: case 'm': case 'L': case 'l': - if (parseCoords (d, x, y, false)) + if (parseCoordsOrSkip (d, p1, false)) { if (isRelative) - { - x += lastX; - y += lastY; - } + p1 += last; if (lastCommandChar == 'M' || lastCommandChar == 'm') { - path.startNewSubPath (x, y); + subpathStart = p1; + path.startNewSubPath (p1); lastCommandChar = 'l'; } else - path.lineTo (x, y); + path.lineTo (p1); - lastX2 = lastX; - lastY2 = lastY; - lastX = x; - lastY = y; - } - else - { - ++d; + last2 = last; + last = p1; } - break; case 'H': case 'h': - if (parseCoord (d, x, false, true)) + if (parseCoord (d, p1.x, false, true)) { if (isRelative) - x += lastX; + p1.x += last.x; - path.lineTo (x, lastY); + path.lineTo (p1.x, last.y); - lastX2 = lastX; - lastX = x; + last2.x = last.x; + last.x = p1.x; } else { @@ -268,15 +256,15 @@ private: case 'V': case 'v': - if (parseCoord (d, y, false, false)) + if (parseCoord (d, p1.y, false, false)) { if (isRelative) - y += lastY; + p1.y += last.y; - path.lineTo (lastX, y); + path.lineTo (last.x, p1.y); - lastY2 = lastY; - lastY = y; + last2.y = last.y; + last.y = p1.y; } else { @@ -286,115 +274,79 @@ private: case 'C': case 'c': - if (parseCoords (d, x, y, false) - && parseCoords (d, x2, y2, false) - && parseCoords (d, x3, y3, false)) + if (parseCoordsOrSkip (d, p1, false) + && parseCoordsOrSkip (d, p2, false) + && parseCoordsOrSkip (d, p3, false)) { if (isRelative) { - x += lastX; - y += lastY; - x2 += lastX; - y2 += lastY; - x3 += lastX; - y3 += lastY; + p1 += last; + p2 += last; + p3 += last; } - path.cubicTo (x, y, x2, y2, x3, y3); + path.cubicTo (p1, p2, p3); - lastX2 = x2; - lastY2 = y2; - lastX = x3; - lastY = y3; - } - else - { - ++d; + last2 = p2; + last = p3; } break; case 'S': case 's': - if (parseCoords (d, x, y, false) - && parseCoords (d, x3, y3, false)) + if (parseCoordsOrSkip (d, p1, false) + && parseCoordsOrSkip (d, p3, false)) { if (isRelative) { - x += lastX; - y += lastY; - x3 += lastX; - y3 += lastY; + p1 += last; + p3 += last; } - x2 = lastX + (lastX - lastX2); - y2 = lastY + (lastY - lastY2); - path.cubicTo (x2, y2, x, y, x3, y3); + p2 = last + (last - last2); + path.cubicTo (p2, p1, p3); - lastX2 = x; - lastY2 = y; - lastX = x3; - lastY = y3; - } - else - { - ++d; + last2 = p1; + last = p3; } break; case 'Q': case 'q': - if (parseCoords (d, x, y, false) - && parseCoords (d, x2, y2, false)) + if (parseCoordsOrSkip (d, p1, false) + && parseCoordsOrSkip (d, p2, false)) { if (isRelative) { - x += lastX; - y += lastY; - x2 += lastX; - y2 += lastY; + p1 += last; + p2 += last; } - path.quadraticTo (x, y, x2, y2); + path.quadraticTo (p1, p2); - lastX2 = x; - lastY2 = y; - lastX = x2; - lastY = y2; - } - else - { - ++d; + last2 = p1; + last = p2; } break; case 'T': case 't': - if (parseCoords (d, x, y, false)) + if (parseCoordsOrSkip (d, p1, false)) { if (isRelative) - { - x += lastX; - y += lastY; - } + p1 += last; - x2 = lastX + (lastX - lastX2); - y2 = lastY + (lastY - lastY2); - path.quadraticTo (x2, y2, x, y); + p2 = last + (last - last2); + path.quadraticTo (p2, p1); - lastX2 = x2; - lastY2 = y2; - lastX = x; - lastY = y; - } - else - { - ++d; + last2 = p2; + last = p1; } break; case 'A': case 'a': - if (parseCoords (d, x, y, false)) + if (parseCoordsOrSkip (d, p1, false)) { String num; @@ -410,20 +362,17 @@ private: { const bool sweep = num.getIntValue() != 0; - if (parseCoords (d, x2, y2, false)) + if (parseCoordsOrSkip (d, p2, false)) { if (isRelative) - { - x2 += lastX; - y2 += lastY; - } + p2 += last; - if (lastX != x2 || lastY != y2) + if (last != p2) { double centreX, centreY, startAngle, deltaAngle; - double rx = x, ry = y; + double rx = p1.x, ry = p1.y; - endpointToCentreParameters (lastX, lastY, x2, y2, + endpointToCentreParameters (last.x, last.y, p2.x, p2.y, angle, largeArc, sweep, rx, ry, centreX, centreY, startAngle, deltaAngle); @@ -433,28 +382,23 @@ private: angle, (float) startAngle, (float) (startAngle + deltaAngle), false); - path.lineTo (x2, y2); + path.lineTo (p2); } - lastX2 = lastX; - lastY2 = lastY; - lastX = x2; - lastY = y2; + last2 = last; + last = p2; } } } } } - else - { - ++d; - } break; case 'Z': case 'z': path.closeSubPath(); + last = last2 = subpathStart; d = d.findEndOfWhitespace(); break; @@ -551,24 +495,21 @@ private: const String pointsAtt (xml.getStringAttribute ("points")); String::CharPointerType points (pointsAtt.getCharPointer()); Path path; - float x, y; + Point p; - if (parseCoords (points, x, y, true)) + if (parseCoords (points, p, true)) { - float firstX = x; - float firstY = y; - float lastX = 0, lastY = 0; + Point first (p), last; - path.startNewSubPath (x, y); + path.startNewSubPath (first); - while (parseCoords (points, x, y, true)) + while (parseCoords (points, p, true)) { - lastX = x; - lastY = y; - path.lineTo (x, y); + last = p; + path.lineTo (p); } - if ((! isPolyline) || (firstX == lastX && firstY == lastY)) + if ((! isPolyline) || first == last) path.closeSubPath(); } @@ -865,10 +806,19 @@ private: return true; } - bool parseCoords (String::CharPointerType& s, float& x, float& y, const bool allowUnits) const + bool parseCoords (String::CharPointerType& s, Point& p, const bool allowUnits) const { - return parseCoord (s, x, allowUnits, true) - && parseCoord (s, y, allowUnits, false); + return parseCoord (s, p.x, allowUnits, true) + && parseCoord (s, p.y, allowUnits, false); + } + + bool parseCoordsOrSkip (String::CharPointerType& s, Point& p, const bool allowUnits) const + { + const bool b = parseCoords (s, p, allowUnits); + if (! b) + ++s; + + return b; } float getCoordLength (const String& s, const float sizeForProportions) const