When linear gradients with scaling applied to them are loaded from an SVG, the drawing of them is not in line with other SVG renderers. The gradient points are transformed properly, however the actual coordinate system used when the gradient is drawn should also be transformed.
If you load an SVG in Inkscape or something with a transformed linear gradient, you’ll see that the gradient drawn won’t actually match with the points because of the coordinate system change.
What JUCE renders:
[attachment=2]juce gradient render.png[/attachment]
What Chrome renders:
[attachment=1]chrome gradient render.png[/attachment]
What the points look like in Inkscape:
[attachment=0]inkscape gradient render.png[/attachment]
I’ve figured out how to create a new gradient that will match what the transformed gradient is supposed to look like. There might be an easier way to do it, but this works:
Line 673 - juce_SVGParser.cpp
[code]FillType type (gradient);
if (gradient.isRadial == true)
{
type.transform = parseTransform (fillXml->getStringAttribute (“gradientTransform”))
.followedBy (transform);
}
else
{
// get the transformation for the gradient so we can use it
juce::AffineTransform gradientTransform = parseTransform (fillXml->getStringAttribute (“gradientTransform”))
.followedBy (transform);
// get the vector perpendicular to the vector of the gradient
juce::Point<float> perpendicular (gradient.point2.getY() - gradient.point1.getY(),
-(gradient.point2.getX() - gradient.point1.getX()));
// get the gradient transform without the translation so we can apply it to
// the perpendicular vector
juce::AffineTransform noTranslate = gradientTransform;
noTranslate.mat02 = 0.0f;
noTranslate.mat12 = 0.0f;
// transform the perpendicular vector into the new coordinate space for the gradient
// this vector is now the slope of the linear gradient as it should appear in the new
// coordinate space
perpendicular.applyTransform (noTranslate);
// get the gradient points in the new coordinate space
juce::Point<float> gradPoint1Trans = gradient.point1.transformedBy (gradientTransform);
juce::Point<float> gradPoint2Trans = gradient.point2.transformedBy (gradientTransform);
// get the gradient's vector in the new coordinate space
juce::Point<float> point2FromPoint1 (gradPoint2Trans.getX() - gradPoint1Trans.getX(),
gradPoint2Trans.getY() - gradPoint1Trans.getY());
// project the transformed gradient vector onto the transformed slope of the linear
// gradient as it should appear in the new coordinate space
float dotProduct = perpendicular.getX() * point2FromPoint1.getX() +
perpendicular.getY() * point2FromPoint1.getY();
dotProduct /= perpendicular.getX() * perpendicular.getX() +
perpendicular.getY() * perpendicular.getY();
juce::Point<float> pointProject (perpendicular.getX() * dotProduct,
perpendicular.getY() * dotProduct);
// set the new transformed gradient points
type.gradient->point1 = gradPoint1Trans;
type.gradient->point2 = gradPoint2Trans - pointProject;
}
return type;[/code]
As far as I can tell, radial gradients aren’t affected by this.
