|
|
@@ -146,9 +146,7 @@ private: |
|
|
|
|
|
|
|
DrawableComposite* parseSwitch (const XmlElement& xml)
|
|
|
|
{
|
|
|
|
const XmlElement* const group = xml.getChildByName ("g");
|
|
|
|
|
|
|
|
if (group != nullptr)
|
|
|
|
if (const XmlElement* const group = xml.getChildByName ("g"))
|
|
|
|
return parseGroupElement (*group);
|
|
|
|
|
|
|
|
return nullptr;
|
|
|
@@ -572,142 +570,141 @@ private: |
|
|
|
|
|
|
|
void addGradientStopsIn (ColourGradient& cg, const XmlElement* const fillXml) const
|
|
|
|
{
|
|
|
|
if (fillXml == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
forEachXmlChildElementWithTagName (*fillXml, e, "stop")
|
|
|
|
if (fillXml != nullptr)
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
Colour col (parseColour (getStyleAttribute (e, "stop-color"), index, Colours::black));
|
|
|
|
forEachXmlChildElementWithTagName (*fillXml, e, "stop")
|
|
|
|
{
|
|
|
|
int index = 0;
|
|
|
|
Colour col (parseColour (getStyleAttribute (e, "stop-color"), index, Colours::black));
|
|
|
|
|
|
|
|
const String opacity (getStyleAttribute (e, "stop-opacity", "1"));
|
|
|
|
col = col.withMultipliedAlpha (jlimit (0.0f, 1.0f, opacity.getFloatValue()));
|
|
|
|
const String opacity (getStyleAttribute (e, "stop-opacity", "1"));
|
|
|
|
col = col.withMultipliedAlpha (jlimit (0.0f, 1.0f, opacity.getFloatValue()));
|
|
|
|
|
|
|
|
double offset = e->getDoubleAttribute ("offset");
|
|
|
|
double offset = e->getDoubleAttribute ("offset");
|
|
|
|
|
|
|
|
if (e->getStringAttribute ("offset").containsChar ('%'))
|
|
|
|
offset *= 0.01;
|
|
|
|
if (e->getStringAttribute ("offset").containsChar ('%'))
|
|
|
|
offset *= 0.01;
|
|
|
|
|
|
|
|
cg.addColour (jlimit (0.0, 1.0, offset), col);
|
|
|
|
cg.addColour (jlimit (0.0, 1.0, offset), col);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FillType getPathFillType (const Path& path,
|
|
|
|
const String& fill,
|
|
|
|
const String& fillOpacity,
|
|
|
|
const String& overallOpacity,
|
|
|
|
const Colour& defaultColour) const
|
|
|
|
FillType getGradientFillType (const XmlElement* fillXml,
|
|
|
|
const Path& path,
|
|
|
|
const float opacity) const
|
|
|
|
{
|
|
|
|
float opacity = 1.0f;
|
|
|
|
ColourGradient gradient;
|
|
|
|
|
|
|
|
if (overallOpacity.isNotEmpty())
|
|
|
|
opacity = jlimit (0.0f, 1.0f, overallOpacity.getFloatValue());
|
|
|
|
addGradientStopsIn (gradient, findLinkedElement (fillXml));
|
|
|
|
addGradientStopsIn (gradient, fillXml);
|
|
|
|
|
|
|
|
if (fillOpacity.isNotEmpty())
|
|
|
|
opacity *= (jlimit (0.0f, 1.0f, fillOpacity.getFloatValue()));
|
|
|
|
|
|
|
|
if (fill.startsWithIgnoreCase ("url"))
|
|
|
|
if (gradient.getNumColours() > 0)
|
|
|
|
{
|
|
|
|
const String id (fill.fromFirstOccurrenceOf ("#", false, false)
|
|
|
|
.upToLastOccurrenceOf (")", false, false).trim());
|
|
|
|
gradient.addColour (0.0, gradient.getColour (0));
|
|
|
|
gradient.addColour (1.0, gradient.getColour (gradient.getNumColours() - 1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gradient.addColour (0.0, Colours::black);
|
|
|
|
gradient.addColour (1.0, Colours::black);
|
|
|
|
}
|
|
|
|
|
|
|
|
const XmlElement* const fillXml = findElementForId (topLevelXml, id);
|
|
|
|
if (opacity < 1.0f)
|
|
|
|
gradient.multiplyOpacity (opacity);
|
|
|
|
|
|
|
|
if (fillXml != nullptr
|
|
|
|
&& (fillXml->hasTagName ("linearGradient")
|
|
|
|
|| fillXml->hasTagName ("radialGradient")))
|
|
|
|
{
|
|
|
|
const XmlElement* inheritedFrom = findLinkedElement (fillXml);
|
|
|
|
jassert (gradient.getNumColours() > 0);
|
|
|
|
|
|
|
|
ColourGradient gradient;
|
|
|
|
gradient.isRadial = fillXml->hasTagName ("radialGradient");
|
|
|
|
|
|
|
|
addGradientStopsIn (gradient, inheritedFrom);
|
|
|
|
addGradientStopsIn (gradient, fillXml);
|
|
|
|
float gradientWidth = viewBoxW;
|
|
|
|
float gradientHeight = viewBoxH;
|
|
|
|
float dx = 0.0f;
|
|
|
|
float dy = 0.0f;
|
|
|
|
|
|
|
|
if (gradient.getNumColours() > 0)
|
|
|
|
{
|
|
|
|
gradient.addColour (0.0, gradient.getColour (0));
|
|
|
|
gradient.addColour (1.0, gradient.getColour (gradient.getNumColours() - 1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gradient.addColour (0.0, Colours::black);
|
|
|
|
gradient.addColour (1.0, Colours::black);
|
|
|
|
}
|
|
|
|
const bool userSpace = fillXml->getStringAttribute ("gradientUnits").equalsIgnoreCase ("userSpaceOnUse");
|
|
|
|
|
|
|
|
if (overallOpacity.isNotEmpty())
|
|
|
|
gradient.multiplyOpacity (overallOpacity.getFloatValue());
|
|
|
|
if (! userSpace)
|
|
|
|
{
|
|
|
|
const Rectangle<float> bounds (path.getBounds());
|
|
|
|
dx = bounds.getX();
|
|
|
|
dy = bounds.getY();
|
|
|
|
gradientWidth = bounds.getWidth();
|
|
|
|
gradientHeight = bounds.getHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
jassert (gradient.getNumColours() > 0);
|
|
|
|
if (gradient.isRadial)
|
|
|
|
{
|
|
|
|
if (userSpace)
|
|
|
|
gradient.point1.setXY (dx + getCoordLength (fillXml->getStringAttribute ("cx", "50%"), gradientWidth),
|
|
|
|
dy + getCoordLength (fillXml->getStringAttribute ("cy", "50%"), gradientHeight));
|
|
|
|
else
|
|
|
|
gradient.point1.setXY (dx + gradientWidth * getCoordLength (fillXml->getStringAttribute ("cx", "50%"), 1.0f),
|
|
|
|
dy + gradientHeight * getCoordLength (fillXml->getStringAttribute ("cy", "50%"), 1.0f));
|
|
|
|
|
|
|
|
gradient.isRadial = fillXml->hasTagName ("radialGradient");
|
|
|
|
const float radius = getCoordLength (fillXml->getStringAttribute ("r", "50%"), gradientWidth);
|
|
|
|
gradient.point2 = gradient.point1 + Point<float> (radius, 0.0f);
|
|
|
|
|
|
|
|
float gradientWidth = viewBoxW;
|
|
|
|
float gradientHeight = viewBoxH;
|
|
|
|
float dx = 0.0f;
|
|
|
|
float dy = 0.0f;
|
|
|
|
//xxx (the fx, fy focal point isn't handled properly here..)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (userSpace)
|
|
|
|
{
|
|
|
|
gradient.point1.setXY (dx + getCoordLength (fillXml->getStringAttribute ("x1", "0%"), gradientWidth),
|
|
|
|
dy + getCoordLength (fillXml->getStringAttribute ("y1", "0%"), gradientHeight));
|
|
|
|
|
|
|
|
const bool userSpace = fillXml->getStringAttribute ("gradientUnits").equalsIgnoreCase ("userSpaceOnUse");
|
|
|
|
gradient.point2.setXY (dx + getCoordLength (fillXml->getStringAttribute ("x2", "100%"), gradientWidth),
|
|
|
|
dy + getCoordLength (fillXml->getStringAttribute ("y2", "0%"), gradientHeight));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gradient.point1.setXY (dx + gradientWidth * getCoordLength (fillXml->getStringAttribute ("x1", "0%"), 1.0f),
|
|
|
|
dy + gradientHeight * getCoordLength (fillXml->getStringAttribute ("y1", "0%"), 1.0f));
|
|
|
|
|
|
|
|
if (! userSpace)
|
|
|
|
{
|
|
|
|
const Rectangle<float> bounds (path.getBounds());
|
|
|
|
dx = bounds.getX();
|
|
|
|
dy = bounds.getY();
|
|
|
|
gradientWidth = bounds.getWidth();
|
|
|
|
gradientHeight = bounds.getHeight();
|
|
|
|
}
|
|
|
|
gradient.point2.setXY (dx + gradientWidth * getCoordLength (fillXml->getStringAttribute ("x2", "100%"), 1.0f),
|
|
|
|
dy + gradientHeight * getCoordLength (fillXml->getStringAttribute ("y2", "0%"), 1.0f));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gradient.isRadial)
|
|
|
|
{
|
|
|
|
if (userSpace)
|
|
|
|
gradient.point1.setXY (dx + getCoordLength (fillXml->getStringAttribute ("cx", "50%"), gradientWidth),
|
|
|
|
dy + getCoordLength (fillXml->getStringAttribute ("cy", "50%"), gradientHeight));
|
|
|
|
else
|
|
|
|
gradient.point1.setXY (dx + gradientWidth * getCoordLength (fillXml->getStringAttribute ("cx", "50%"), 1.0f),
|
|
|
|
dy + gradientHeight * getCoordLength (fillXml->getStringAttribute ("cy", "50%"), 1.0f));
|
|
|
|
if (gradient.point1 == gradient.point2)
|
|
|
|
return Colour (gradient.getColour (gradient.getNumColours() - 1));
|
|
|
|
}
|
|
|
|
|
|
|
|
const float radius = getCoordLength (fillXml->getStringAttribute ("r", "50%"), gradientWidth);
|
|
|
|
gradient.point2 = gradient.point1 + Point<float> (radius, 0.0f);
|
|
|
|
FillType type (gradient);
|
|
|
|
type.transform = parseTransform (fillXml->getStringAttribute ("gradientTransform"))
|
|
|
|
.followedBy (transform);
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
//xxx (the fx, fy focal point isn't handled properly here..)
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (userSpace)
|
|
|
|
{
|
|
|
|
gradient.point1.setXY (dx + getCoordLength (fillXml->getStringAttribute ("x1", "0%"), gradientWidth),
|
|
|
|
dy + getCoordLength (fillXml->getStringAttribute ("y1", "0%"), gradientHeight));
|
|
|
|
FillType getPathFillType (const Path& path,
|
|
|
|
const String& fill,
|
|
|
|
const String& fillOpacity,
|
|
|
|
const String& overallOpacity,
|
|
|
|
const Colour& defaultColour) const
|
|
|
|
{
|
|
|
|
float opacity = 1.0f;
|
|
|
|
|
|
|
|
gradient.point2.setXY (dx + getCoordLength (fillXml->getStringAttribute ("x2", "100%"), gradientWidth),
|
|
|
|
dy + getCoordLength (fillXml->getStringAttribute ("y2", "0%"), gradientHeight));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gradient.point1.setXY (dx + gradientWidth * getCoordLength (fillXml->getStringAttribute ("x1", "0%"), 1.0f),
|
|
|
|
dy + gradientHeight * getCoordLength (fillXml->getStringAttribute ("y1", "0%"), 1.0f));
|
|
|
|
if (overallOpacity.isNotEmpty())
|
|
|
|
opacity = jlimit (0.0f, 1.0f, overallOpacity.getFloatValue());
|
|
|
|
|
|
|
|
gradient.point2.setXY (dx + gradientWidth * getCoordLength (fillXml->getStringAttribute ("x2", "100%"), 1.0f),
|
|
|
|
dy + gradientHeight * getCoordLength (fillXml->getStringAttribute ("y2", "0%"), 1.0f));
|
|
|
|
}
|
|
|
|
if (fillOpacity.isNotEmpty())
|
|
|
|
opacity *= (jlimit (0.0f, 1.0f, fillOpacity.getFloatValue()));
|
|
|
|
|
|
|
|
if (gradient.point1 == gradient.point2)
|
|
|
|
return Colour (gradient.getColour (gradient.getNumColours() - 1));
|
|
|
|
}
|
|
|
|
if (fill.startsWithIgnoreCase ("url"))
|
|
|
|
{
|
|
|
|
const String id (fill.fromFirstOccurrenceOf ("#", false, false)
|
|
|
|
.upToLastOccurrenceOf (")", false, false).trim());
|
|
|
|
|
|
|
|
FillType type (gradient);
|
|
|
|
type.transform = parseTransform (fillXml->getStringAttribute ("gradientTransform"))
|
|
|
|
.followedBy (transform);
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
if (const XmlElement* const fillXml = findElementForId (topLevelXml, id))
|
|
|
|
if (fillXml->hasTagName ("linearGradient") || fillXml->hasTagName ("radialGradient"))
|
|
|
|
return getGradientFillType (fillXml, path, opacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fill.equalsIgnoreCase ("none"))
|
|
|
|
return Colours::transparentBlack;
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
const Colour colour (parseColour (fill, i, defaultColour));
|
|
|
|
return colour.withMultipliedAlpha (opacity);
|
|
|
|
return parseColour (fill, i, defaultColour).withMultipliedAlpha (opacity);
|
|
|
|
}
|
|
|
|
|
|
|
|
PathStrokeType getStrokeFor (const XmlElement* const xml) const
|
|
|
@@ -1216,9 +1213,7 @@ private: |
|
|
|
if (e->compareAttribute ("id", id))
|
|
|
|
return e;
|
|
|
|
|
|
|
|
const XmlElement* const found = findElementForId (e, id);
|
|
|
|
|
|
|
|
if (found != nullptr)
|
|
|
|
if (const XmlElement* const found = findElementForId (e, id))
|
|
|
|
return found;
|
|
|
|
}
|
|
|
|
|
|
|
|