Browse Source

Added method Drawable::parseSVGPath()

tags/2021-05-28
jules 12 years ago
parent
commit
0e978e13b1
2 changed files with 88 additions and 76 deletions
  1. +3
    -0
      modules/juce_gui_basics/drawables/juce_Drawable.h
  2. +85
    -76
      modules/juce_gui_basics/drawables/juce_SVGParser.cpp

+ 3
- 0
modules/juce_gui_basics/drawables/juce_Drawable.h View File

@@ -156,6 +156,9 @@ public:
*/
static Drawable* createFromSVG (const XmlElement& svgDocument);
/** Parses an SVG path string and returns it. */
static Path parseSVGPath (const String& svgPath);
//==============================================================================
/** Tries to create a Drawable from a previously-saved ValueTree.
The ValueTree must have been created by the createValueTree() method.


+ 85
- 76
modules/juce_gui_basics/drawables/juce_SVGParser.cpp View File

@@ -27,7 +27,7 @@ class SVGState
{
public:
//==============================================================================
SVGState (const XmlElement* const topLevel)
explicit SVGState (const XmlElement* const topLevel)
: topLevelXml (topLevel),
elementX (0), elementY (0),
width (512), height (512),
@@ -113,82 +113,7 @@ public:
return drawable;
}
private:
//==============================================================================
const XmlElement* const topLevelXml;
float elementX, elementY, width, height, viewBoxW, viewBoxH;
AffineTransform transform;
String cssStyleText;
//==============================================================================
void parseSubElements (const XmlElement& xml, DrawableComposite& parentDrawable)
{
forEachXmlChildElement (xml, e)
parentDrawable.addAndMakeVisible (parseSubElement (*e));
}
Drawable* parseSubElement (const XmlElement& xml)
{
const String tag (xml.getTagNameWithoutNamespace());
if (tag == "g") return parseGroupElement (xml);
if (tag == "svg") return parseSVGElement (xml);
if (tag == "path") return parsePath (xml);
if (tag == "rect") return parseRect (xml);
if (tag == "circle") return parseCircle (xml);
if (tag == "ellipse") return parseEllipse (xml);
if (tag == "line") return parseLine (xml);
if (tag == "polyline") return parsePolygon (xml, true);
if (tag == "polygon") return parsePolygon (xml, false);
if (tag == "text") return parseText (xml);
if (tag == "switch") return parseSwitch (xml);
if (tag == "style") parseCSSStyle (xml);
return nullptr;
}
DrawableComposite* parseSwitch (const XmlElement& xml)
{
if (const XmlElement* const group = xml.getChildByName ("g"))
return parseGroupElement (*group);
return nullptr;
}
DrawableComposite* parseGroupElement (const XmlElement& xml)
{
DrawableComposite* const drawable = new DrawableComposite();
drawable->setName (xml.getStringAttribute ("id"));
if (xml.hasAttribute ("transform"))
{
SVGState newState (*this);
newState.addTransform (xml);
newState.parseSubElements (xml, *drawable);
}
else
{
parseSubElements (xml, *drawable);
}
drawable->resetContentAreaAndBoundingBoxToFitChildren();
return drawable;
}
//==============================================================================
Drawable* parsePath (const XmlElement& xml) const
{
Path path;
parsePathString (path, xml.getStringAttribute ("d"));
if (getStyleAttribute (&xml, "fill-rule").trim().equalsIgnoreCase ("evenodd"))
path.setUsingNonZeroWinding (false);
return parseShape (xml, path);
}
void parsePathString (Path& path, const String& pathString) const
{
String::CharPointerType d (pathString.getCharPointer().findEndOfWhitespace());
@@ -410,6 +335,82 @@ private:
}
}
private:
//==============================================================================
const XmlElement* const topLevelXml;
float elementX, elementY, width, height, viewBoxW, viewBoxH;
AffineTransform transform;
String cssStyleText;
//==============================================================================
void parseSubElements (const XmlElement& xml, DrawableComposite& parentDrawable)
{
forEachXmlChildElement (xml, e)
parentDrawable.addAndMakeVisible (parseSubElement (*e));
}
Drawable* parseSubElement (const XmlElement& xml)
{
const String tag (xml.getTagNameWithoutNamespace());
if (tag == "g") return parseGroupElement (xml);
if (tag == "svg") return parseSVGElement (xml);
if (tag == "path") return parsePath (xml);
if (tag == "rect") return parseRect (xml);
if (tag == "circle") return parseCircle (xml);
if (tag == "ellipse") return parseEllipse (xml);
if (tag == "line") return parseLine (xml);
if (tag == "polyline") return parsePolygon (xml, true);
if (tag == "polygon") return parsePolygon (xml, false);
if (tag == "text") return parseText (xml);
if (tag == "switch") return parseSwitch (xml);
if (tag == "style") parseCSSStyle (xml);
return nullptr;
}
DrawableComposite* parseSwitch (const XmlElement& xml)
{
if (const XmlElement* const group = xml.getChildByName ("g"))
return parseGroupElement (*group);
return nullptr;
}
DrawableComposite* parseGroupElement (const XmlElement& xml)
{
DrawableComposite* const drawable = new DrawableComposite();
drawable->setName (xml.getStringAttribute ("id"));
if (xml.hasAttribute ("transform"))
{
SVGState newState (*this);
newState.addTransform (xml);
newState.parseSubElements (xml, *drawable);
}
else
{
parseSubElements (xml, *drawable);
}
drawable->resetContentAreaAndBoundingBoxToFitChildren();
return drawable;
}
//==============================================================================
Drawable* parsePath (const XmlElement& xml) const
{
Path path;
parsePathString (path, xml.getStringAttribute ("d"));
if (getStyleAttribute (&xml, "fill-rule").trim().equalsIgnoreCase ("evenodd"))
path.setUsingNonZeroWinding (false);
return parseShape (xml, path);
}
Drawable* parseRect (const XmlElement& xml) const
{
Path rect;
@@ -1267,3 +1268,11 @@ Drawable* Drawable::createFromSVG (const XmlElement& svgDocument)
SVGState state (&svgDocument);
return state.parseSVGElement (svgDocument);
}
Path Drawable::parseSVGPath (const String& svgPath)
{
SVGState state (nullptr);
Path p;
state.parsePathString (p, svgPath);
return p;
}

Loading…
Cancel
Save