Bug 801317 - Support transforms in SVG fragment identifiers. r=dholbert

This commit is contained in:
Robert Longson 2012-10-22 10:13:24 +01:00
parent 9b5a2e0303
commit 814606cd60
6 changed files with 53 additions and 3 deletions

View File

@ -7,6 +7,7 @@
#include "nsIDOMSVGDocument.h"
#include "nsSVGSVGElement.h"
#include "nsSVGViewElement.h"
#include "SVGAnimatedTransformList.h"
using namespace mozilla;
@ -91,6 +92,13 @@ SVGFragmentIdentifier::RestoreOldZoomAndPan(nsSVGSVGElement *root)
}
}
void
SVGFragmentIdentifier::ClearTransform(nsSVGSVGElement *root)
{
root->mFragmentIdentifierTransform = nullptr;
root->InvalidateTransformNotifyFrame();
}
bool
SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
nsSVGSVGElement *root)
@ -106,6 +114,7 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
bool viewBoxFound = false;
bool preserveAspectRatioFound = false;
bool transformFound = false;
bool zoomAndPanFound = false;
// Each token is a SVGViewAttribute
@ -144,6 +153,19 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
return false;
}
preserveAspectRatioFound = true;
} else if (IsMatchingParameter(token, NS_LITERAL_STRING("transform"))) {
SVGAnimatedTransformList transforms;
if (transformFound ||
NS_FAILED(transforms.SetBaseValueString(params))) {
return false;
}
if (!root->mFragmentIdentifierTransform) {
root->mFragmentIdentifierTransform = new gfxMatrix();
}
*root->mFragmentIdentifierTransform =
transforms.GetBaseValue().GetConsolidationMatrix();
root->InvalidateTransformNotifyFrame();
transformFound = true;
} else if (IsMatchingParameter(token, NS_LITERAL_STRING("zoomAndPan"))) {
if (zoomAndPanFound) {
return false;
@ -170,7 +192,7 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
}
zoomAndPanFound = true;
} else {
// We don't support transform or viewTarget currently
// We don't support viewTarget currently
return false;
}
} while (tokenizer.hasMoreTokens());
@ -178,6 +200,9 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec,
if (root->mUseCurrentView) {
// A previous SVGViewSpec may have overridden some attributes.
// If they are no longer overridden we need to restore the old values.
if (!transformFound) {
ClearTransform(root);
}
if (!viewBoxFound) {
RestoreOldViewBox(root);
}
@ -233,6 +258,7 @@ SVGFragmentIdentifier::ProcessFragmentIdentifier(nsIDocument *aDocument,
rootElement->ClearPreserveAspectRatioProperty();
RestoreOldZoomAndPan(rootElement);
rootElement->ClearZoomAndPanProperty();
ClearTransform(rootElement);
if (wasOverridden) {
rootElement->InvalidateTransformNotifyFrame();
}

View File

@ -46,6 +46,7 @@ private:
static void RestoreOldViewBox(nsSVGSVGElement *root);
static void SaveOldZoomAndPan(nsSVGSVGElement *root);
static void RestoreOldZoomAndPan(nsSVGSVGElement *root);
static void ClearTransform(nsSVGSVGElement *root);
};
} // namespace mozilla

View File

@ -1234,7 +1234,9 @@ nsSVGSVGElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
gfxMatrix zoomPanTM;
zoomPanTM.Translate(gfxPoint(mCurrentTranslate.GetX(), mCurrentTranslate.GetY()));
zoomPanTM.Scale(mCurrentScale, mCurrentScale);
return GetViewBoxTransform() * zoomPanTM * aMatrix;
gfxMatrix matrix = mFragmentIdentifierTransform ?
*mFragmentIdentifierTransform * aMatrix : aMatrix;
return GetViewBoxTransform() * zoomPanTM * matrix;
}
// outer-<svg>, but inline in some other content:

View File

@ -351,6 +351,7 @@ private:
nsSVGViewBox mViewBox;
SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
nsAutoPtr<gfxMatrix> mFragmentIdentifierTransform;
nsAutoPtr<nsString> mCurrentViewID;
// The size of the rectangular SVG viewport into which we render. This is

View File

@ -40,9 +40,17 @@ function runTests()
new Test("svgView(preserveAspectRatio(xMaxYMin slice))", true, null, "xMaxYMin slice", null),
new Test("svgView(viewBox(1,2,3,4);preserveAspectRatio(xMinYMax))", true, "1 2 3 4", "xMinYMax meet", null),
new Test("svgView(zoomAndPan(disable))", true, null, null, "disable"),
new Test("svgView(transform(translate(-10,-20) scale(2) rotate(45) translate(5,10)))", true, null, null, null),
// No duplicates allowed
new Test("svgView(zoomAndPan(disable);zoomAndPan(disable))", false, null, null, null),
new Test("svgView(viewBox(0,0,200,200);viewBox(0,0,200,200))", false, null, null, null),
new Test("svgView(preserveAspectRatio(xMaxYMin);preserveAspectRatio(xMaxYMin))", false, null, null, null),
new Test("svgView(transform(translate(0,200));transform(translate(0,200)))", false, null, null, null),
// No invalid values allowed
new Test("svgView(viewBox(bad)", false, null, null, null),
new Test("svgView(preserveAspectRatio(bad))", false, null, null, null),
new Test("svgView(zoomAndPan(bad))", false, null, null, null),
new Test("svgView(transform(bad))", false, null, null, null),
new Test("svgView", false, null, null, null),
new Test("svgView(", false, null, null, null),
new Test("svgView()", false, null, null, null),

View File

@ -1,4 +1,4 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-wait">
<head>
<title>Testcases for SVG fragment identifiers</title>
</head>
@ -7,5 +7,17 @@
<object type="image/svg+xml" width="100" height="100" data="fragmentIdentifier-rect-01.svg#limeView" />
<object type="image/svg+xml" width="100" height="100" data="fragmentIdentifier-rect-01.svg#svgView(viewBox(0,200,100,100))" />
</div>
<div>
<object type="image/svg+xml" width="100" height="100" data="fragmentIdentifier-rect-01.svg#svgView(viewBox(0,0,100,100);transform(translate(0,200)))" />
<object id="replace" type="image/svg+xml" width="100" height="100" data="fragmentIdentifier-rect-01.svg#svgView(viewBox(0,0,100,100);transform(translate(0,0))" />
<object id="remove" type="image/svg+xml" width="100" height="100" data="fragmentIdentifier-rect-01.svg#svgView(viewBox(0,200,100,100);transform(translate(0,200)))" />
</div>
<script type="text/javascript">
window.onload = function() {
document.getElementById("replace").setAttribute("data","fragmentIdentifier-rect-01.svg#svgView(viewBox(0,0,100,100);transform(translate(0,200)))");
document.getElementById("remove").setAttribute("data","fragmentIdentifier-rect-01.svg#svgView(viewBox(0,200,100,100))");
document.documentElement.removeAttribute("class");
}
</script>
</body>
</html>