mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1145195
part 2 - SVGFragmentIdentifier::ProcessSVGViewSpec() shouldn't actually let #svgView() affect attribute values r=dholbert
This commit is contained in:
parent
45631955a0
commit
ebdab47988
@ -40,109 +40,104 @@ GetViewElement(nsIDocument* aDocument, const nsAString& aId)
|
||||
static_cast<SVGViewElement*>(element) : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SVGFragmentIdentifier::SaveOldPreserveAspectRatio(SVGSVGElement* root)
|
||||
// Handles setting/clearing the root's mSVGView pointer.
|
||||
class MOZ_RAII AutoSVGViewHandler
|
||||
{
|
||||
if (root->mPreserveAspectRatio.IsExplicitlySet()) {
|
||||
root->SetPreserveAspectRatioProperty(root->mPreserveAspectRatio.GetBaseValue());
|
||||
public:
|
||||
explicit AutoSVGViewHandler(SVGSVGElement* aRoot
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: mRoot(aRoot), mValid(false) {
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
mWasOverridden = mRoot->UseCurrentView();
|
||||
mRoot->mSVGView = nullptr;
|
||||
mRoot->mCurrentViewID = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SVGFragmentIdentifier::RestoreOldPreserveAspectRatio(SVGSVGElement* root)
|
||||
{
|
||||
const SVGPreserveAspectRatio* oldPARPtr = root->GetPreserveAspectRatioProperty();
|
||||
if (oldPARPtr) {
|
||||
root->mPreserveAspectRatio.SetBaseValue(*oldPARPtr, root);
|
||||
} else if (root->mPreserveAspectRatio.IsExplicitlySet()) {
|
||||
ErrorResult error;
|
||||
root->RemoveAttribute(NS_LITERAL_STRING("preserveAspectRatio"), error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SVGFragmentIdentifier::SaveOldViewBox(SVGSVGElement* root)
|
||||
{
|
||||
if (root->mViewBox.IsExplicitlySet()) {
|
||||
root->SetViewBoxProperty(root->mViewBox.GetBaseValue());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SVGFragmentIdentifier::RestoreOldViewBox(SVGSVGElement* root)
|
||||
{
|
||||
const nsSVGViewBoxRect* oldViewBoxPtr = root->GetViewBoxProperty();
|
||||
if (oldViewBoxPtr) {
|
||||
root->mViewBox.SetBaseValue(*oldViewBoxPtr, root);
|
||||
} else if (root->mViewBox.IsExplicitlySet()) {
|
||||
ErrorResult error;
|
||||
root->RemoveAttribute(NS_LITERAL_STRING("viewBox"), error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SVGFragmentIdentifier::SaveOldZoomAndPan(SVGSVGElement* root)
|
||||
{
|
||||
if (root->mEnumAttributes[SVGSVGElement::ZOOMANDPAN].IsExplicitlySet()) {
|
||||
root->SetZoomAndPanProperty(root->mEnumAttributes[SVGSVGElement::ZOOMANDPAN].GetBaseValue());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SVGFragmentIdentifier::RestoreOldZoomAndPan(SVGSVGElement* root)
|
||||
{
|
||||
uint16_t oldZoomAndPan = root->GetZoomAndPanProperty();
|
||||
if (oldZoomAndPan != SVG_ZOOMANDPAN_UNKNOWN) {
|
||||
root->mEnumAttributes[SVGSVGElement::ZOOMANDPAN].SetBaseValue(oldZoomAndPan, root);
|
||||
} else if (root->mEnumAttributes[SVGSVGElement::ZOOMANDPAN].IsExplicitlySet()) {
|
||||
ErrorResult error;
|
||||
root->RemoveAttribute(NS_LITERAL_STRING("zoomAndPan"), error);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SVGFragmentIdentifier::SaveOldTransform(SVGSVGElement* root)
|
||||
{
|
||||
nsSVGAnimatedTransformList* transformList = root->GetAnimatedTransformList();
|
||||
|
||||
if (transformList && transformList->IsExplicitlySet()) {
|
||||
root->SetTransformProperty(transformList->GetBaseValue());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SVGFragmentIdentifier::RestoreOldTransform(SVGSVGElement* root)
|
||||
{
|
||||
const SVGTransformList* oldTransformPtr = root->GetTransformProperty();
|
||||
if (oldTransformPtr) {
|
||||
root->GetAnimatedTransformList(nsSVGElement::DO_ALLOCATE)->SetBaseValue(*oldTransformPtr);
|
||||
} else {
|
||||
nsSVGAnimatedTransformList* transformList = root->GetAnimatedTransformList();
|
||||
if (transformList && transformList->IsExplicitlySet()) {
|
||||
ErrorResult error;
|
||||
root->RemoveAttribute(NS_LITERAL_STRING("transform"), error);
|
||||
~AutoSVGViewHandler() {
|
||||
if (!mWasOverridden && !mValid) {
|
||||
// we weren't overridden before and we aren't
|
||||
// overridden now so nothing has changed.
|
||||
return;
|
||||
}
|
||||
if (mValid) {
|
||||
mRoot->mSVGView = mSVGView;
|
||||
}
|
||||
mRoot->InvalidateTransformNotifyFrame();
|
||||
}
|
||||
}
|
||||
|
||||
void CreateSVGView() {
|
||||
MOZ_ASSERT(!mSVGView, "CreateSVGView should not be called multiple times");
|
||||
mSVGView = new SVGView();
|
||||
}
|
||||
|
||||
bool ProcessAttr(const nsAString& aToken, const nsAString &aParams) {
|
||||
|
||||
MOZ_ASSERT(mSVGView, "CreateSVGView should have been called");
|
||||
|
||||
// SVGViewAttributes may occur in any order, but each type may only occur
|
||||
// at most one time in a correctly formed SVGViewSpec.
|
||||
// If we encounter any attribute more than once or get any syntax errors
|
||||
// we're going to return false and cancel any changes.
|
||||
|
||||
if (IsMatchingParameter(aToken, NS_LITERAL_STRING("viewBox"))) {
|
||||
if (mSVGView->mViewBox.IsExplicitlySet() ||
|
||||
NS_FAILED(mSVGView->mViewBox.SetBaseValueString(
|
||||
aParams, mRoot, false))) {
|
||||
return false;
|
||||
}
|
||||
} else if (IsMatchingParameter(aToken, NS_LITERAL_STRING("preserveAspectRatio"))) {
|
||||
if (mSVGView->mPreserveAspectRatio.IsExplicitlySet() ||
|
||||
NS_FAILED(mSVGView->mPreserveAspectRatio.SetBaseValueString(
|
||||
aParams, mRoot, false))) {
|
||||
return false;
|
||||
}
|
||||
} else if (IsMatchingParameter(aToken, NS_LITERAL_STRING("transform"))) {
|
||||
if (mSVGView->mTransforms) {
|
||||
return false;
|
||||
}
|
||||
mSVGView->mTransforms = new nsSVGAnimatedTransformList();
|
||||
if (NS_FAILED(mSVGView->mTransforms->SetBaseValueString(aParams))) {
|
||||
return false;
|
||||
}
|
||||
} else if (IsMatchingParameter(aToken, NS_LITERAL_STRING("zoomAndPan"))) {
|
||||
if (mSVGView->mZoomAndPan.IsExplicitlySet()) {
|
||||
return false;
|
||||
}
|
||||
nsIAtom* valAtom = NS_GetStaticAtom(aParams);
|
||||
if (!valAtom ||
|
||||
NS_FAILED(mSVGView->mZoomAndPan.SetBaseValueAtom(
|
||||
valAtom, mRoot))) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// We don't support viewTarget currently
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetValid() {
|
||||
mValid = true;
|
||||
}
|
||||
|
||||
private:
|
||||
SVGSVGElement* mRoot;
|
||||
nsAutoPtr<SVGView> mSVGView;
|
||||
bool mValid;
|
||||
bool mWasOverridden;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
bool
|
||||
SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString& aViewSpec,
|
||||
SVGSVGElement* root)
|
||||
SVGSVGElement* aRoot)
|
||||
{
|
||||
AutoSVGViewHandler viewHandler(aRoot);
|
||||
|
||||
if (!IsMatchingParameter(aViewSpec, NS_LITERAL_STRING("svgView"))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// SVGViewAttributes may occur in any order, but each type may only occur
|
||||
// at most one time in a correctly formed SVGViewSpec.
|
||||
// If we encounter any attribute more than once or get any syntax errors
|
||||
// we're going to return false and cancel any changes.
|
||||
|
||||
bool viewBoxFound = false;
|
||||
bool preserveAspectRatioFound = false;
|
||||
bool transformFound = false;
|
||||
bool zoomAndPanFound = false;
|
||||
|
||||
// Each token is a SVGViewAttribute
|
||||
int32_t bracketPos = aViewSpec.FindChar('(');
|
||||
uint32_t lengthOfViewSpec = aViewSpec.Length() - bracketPos - 2;
|
||||
@ -152,6 +147,8 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString& aViewSpec,
|
||||
if (!tokenizer.hasMoreTokens()) {
|
||||
return false;
|
||||
}
|
||||
viewHandler.CreateSVGView();
|
||||
|
||||
do {
|
||||
|
||||
nsAutoString token(tokenizer.nextToken());
|
||||
@ -165,75 +162,13 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString& aViewSpec,
|
||||
const nsAString ¶ms =
|
||||
Substring(token, bracketPos + 1, token.Length() - bracketPos - 2);
|
||||
|
||||
if (IsMatchingParameter(token, NS_LITERAL_STRING("viewBox"))) {
|
||||
if (viewBoxFound ||
|
||||
NS_FAILED(root->mViewBox.SetBaseValueString(
|
||||
params, root, true))) {
|
||||
return false;
|
||||
}
|
||||
viewBoxFound = true;
|
||||
} else if (IsMatchingParameter(token, NS_LITERAL_STRING("preserveAspectRatio"))) {
|
||||
if (preserveAspectRatioFound ||
|
||||
NS_FAILED(root->mPreserveAspectRatio.SetBaseValueString(
|
||||
params, root, true))) {
|
||||
return false;
|
||||
}
|
||||
preserveAspectRatioFound = true;
|
||||
} else if (IsMatchingParameter(token, NS_LITERAL_STRING("transform"))) {
|
||||
if (transformFound ||
|
||||
NS_FAILED(root->GetAnimatedTransformList(nsSVGElement::DO_ALLOCATE)->
|
||||
SetBaseValueString(params))) {
|
||||
return false;
|
||||
}
|
||||
transformFound = true;
|
||||
} else if (IsMatchingParameter(token, NS_LITERAL_STRING("zoomAndPan"))) {
|
||||
if (zoomAndPanFound) {
|
||||
return false;
|
||||
}
|
||||
nsIAtom* valAtom = NS_GetStaticAtom(params);
|
||||
if (!valAtom) {
|
||||
return false;
|
||||
}
|
||||
const nsSVGEnumMapping* mapping = SVGSVGElement::sZoomAndPanMap;
|
||||
while (mapping->mKey) {
|
||||
if (valAtom == *(mapping->mKey)) {
|
||||
// If we've got a valid zoomAndPan value, then set it on our root element.
|
||||
if (NS_FAILED(root->mEnumAttributes[SVGSVGElement::ZOOMANDPAN].SetBaseValue(
|
||||
mapping->mVal, root))) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
mapping++;
|
||||
}
|
||||
if (!mapping->mKey) {
|
||||
// Unrecognised zoomAndPan value
|
||||
return false;
|
||||
}
|
||||
zoomAndPanFound = true;
|
||||
} else {
|
||||
// We don't support viewTarget currently
|
||||
if (!viewHandler.ProcessAttr(token, params)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
} while (tokenizer.hasMoreTokens());
|
||||
|
||||
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) {
|
||||
RestoreOldTransform(root);
|
||||
}
|
||||
if (!viewBoxFound) {
|
||||
RestoreOldViewBox(root);
|
||||
}
|
||||
if (!preserveAspectRatioFound) {
|
||||
RestoreOldPreserveAspectRatio(root);
|
||||
}
|
||||
if (!zoomAndPanFound) {
|
||||
RestoreOldZoomAndPan(root);
|
||||
}
|
||||
}
|
||||
|
||||
viewHandler.SetValid();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -247,12 +182,6 @@ SVGFragmentIdentifier::ProcessFragmentIdentifier(nsIDocument* aDocument,
|
||||
SVGSVGElement* rootElement =
|
||||
static_cast<SVGSVGElement*>(aDocument->GetRootElement());
|
||||
|
||||
if (!rootElement->mUseCurrentView) {
|
||||
SaveOldViewBox(rootElement);
|
||||
SaveOldPreserveAspectRatio(rootElement);
|
||||
SaveOldZoomAndPan(rootElement);
|
||||
}
|
||||
|
||||
const SVGViewElement* viewElement = GetViewElement(aDocument, aAnchorName);
|
||||
|
||||
if (viewElement) {
|
||||
@ -260,32 +189,14 @@ SVGFragmentIdentifier::ProcessFragmentIdentifier(nsIDocument* aDocument,
|
||||
rootElement->mCurrentViewID = new nsString();
|
||||
}
|
||||
*rootElement->mCurrentViewID = aAnchorName;
|
||||
rootElement->mUseCurrentView = true;
|
||||
rootElement->mSVGView = nullptr;
|
||||
rootElement->InvalidateTransformNotifyFrame();
|
||||
// not an svgView()-style fragment identifier, return false so the caller
|
||||
// continues processing to match any :target pseudo elements
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wasOverridden = !!rootElement->mCurrentViewID;
|
||||
rootElement->mCurrentViewID = nullptr;
|
||||
|
||||
rootElement->mUseCurrentView = ProcessSVGViewSpec(aAnchorName, rootElement);
|
||||
if (rootElement->mUseCurrentView) {
|
||||
return true;
|
||||
}
|
||||
RestoreOldViewBox(rootElement);
|
||||
rootElement->ClearViewBoxProperty();
|
||||
RestoreOldPreserveAspectRatio(rootElement);
|
||||
rootElement->ClearPreserveAspectRatioProperty();
|
||||
RestoreOldZoomAndPan(rootElement);
|
||||
rootElement->ClearZoomAndPanProperty();
|
||||
RestoreOldTransform(rootElement);
|
||||
rootElement->ClearTransformProperty();
|
||||
if (wasOverridden) {
|
||||
rootElement->InvalidateTransformNotifyFrame();
|
||||
}
|
||||
return false;
|
||||
return ProcessSVGViewSpec(aAnchorName, rootElement);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -42,17 +42,6 @@ private:
|
||||
* @return true if there is a valid ViewSpec
|
||||
*/
|
||||
static bool ProcessSVGViewSpec(const nsAString &aViewSpec, dom::SVGSVGElement *root);
|
||||
|
||||
// Save and restore things we override in case we want to go back e.g. the
|
||||
// user presses the back button
|
||||
static void SaveOldPreserveAspectRatio(dom::SVGSVGElement *root);
|
||||
static void RestoreOldPreserveAspectRatio(dom::SVGSVGElement *root);
|
||||
static void SaveOldViewBox(dom::SVGSVGElement *root);
|
||||
static void RestoreOldViewBox(dom::SVGSVGElement *root);
|
||||
static void SaveOldZoomAndPan(dom::SVGSVGElement *root);
|
||||
static void RestoreOldZoomAndPan(dom::SVGSVGElement *root);
|
||||
static void SaveOldTransform(dom::SVGSVGElement *root);
|
||||
static void RestoreOldTransform(dom::SVGSVGElement *root);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -111,6 +111,14 @@ DOMSVGTranslatePoint::MatrixTransform(SVGMatrix& matrix)
|
||||
return point.forget();
|
||||
}
|
||||
|
||||
SVGView::SVGView()
|
||||
{
|
||||
mZoomAndPan.Init(SVGSVGElement::ZOOMANDPAN,
|
||||
SVG_ZOOMANDPAN_MAGNIFY);
|
||||
mViewBox.Init();
|
||||
mPreserveAspectRatio.Init();
|
||||
}
|
||||
|
||||
nsSVGElement::LengthInfo SVGSVGElement::sLengthInfo[4] =
|
||||
{
|
||||
{ &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
|
||||
@ -176,8 +184,7 @@ SVGSVGElement::SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo
|
||||
aFromParser == FROM_PARSER_XSLT),
|
||||
mImageNeedsTransformInvalidation(false),
|
||||
mIsPaintingSVGImageElement(false),
|
||||
mHasChildrenOnlyTransform(false),
|
||||
mUseCurrentView(false)
|
||||
mHasChildrenOnlyTransform(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -257,7 +264,7 @@ SVGSVGElement::ScreenPixelToMillimeterY()
|
||||
bool
|
||||
SVGSVGElement::UseCurrentView()
|
||||
{
|
||||
return mUseCurrentView;
|
||||
return mSVGView || mCurrentViewID;
|
||||
}
|
||||
|
||||
float
|
||||
@ -452,12 +459,6 @@ SVGSVGElement::PreserveAspectRatio()
|
||||
uint16_t
|
||||
SVGSVGElement::ZoomAndPan()
|
||||
{
|
||||
SVGViewElement* viewElement = GetCurrentViewElement();
|
||||
if (viewElement && viewElement->mEnumAttributes[
|
||||
SVGViewElement::ZOOMANDPAN].IsExplicitlySet()) {
|
||||
return viewElement->mEnumAttributes[
|
||||
SVGViewElement::ZOOMANDPAN].GetAnimValue();
|
||||
}
|
||||
return mEnumAttributes[ZOOMANDPAN].GetAnimValue();
|
||||
}
|
||||
|
||||
@ -841,6 +842,9 @@ SVGSVGElement::GetViewBoxWithSynthesis(
|
||||
if (viewElement && viewElement->mViewBox.HasRect()) {
|
||||
return viewElement->mViewBox.GetAnimValue();
|
||||
}
|
||||
if (mSVGView && mSVGView->mViewBox.HasRect()) {
|
||||
return mSVGView->mViewBox.GetAnimValue();
|
||||
}
|
||||
if (mViewBox.HasRect()) {
|
||||
return mViewBox.GetAnimValue();
|
||||
}
|
||||
@ -878,6 +882,7 @@ SVGSVGElement::GetPreserveAspectRatioWithOverride() const
|
||||
// We're just holding onto the viewElement that HasViewBoxRect() would look up,
|
||||
// so that we don't have to look it up again later.
|
||||
if (!((viewElement && viewElement->mViewBox.HasRect()) ||
|
||||
(mSVGView && mSVGView->mViewBox.HasRect()) ||
|
||||
mViewBox.HasRect()) &&
|
||||
ShouldSynthesizeViewBox()) {
|
||||
// If we're synthesizing a viewBox, use preserveAspectRatio="none";
|
||||
@ -887,6 +892,9 @@ SVGSVGElement::GetPreserveAspectRatioWithOverride() const
|
||||
if (viewElement && viewElement->mPreserveAspectRatio.IsExplicitlySet()) {
|
||||
return viewElement->mPreserveAspectRatio.GetAnimValue();
|
||||
}
|
||||
if (mSVGView && mSVGView->mPreserveAspectRatio.IsExplicitlySet()) {
|
||||
return mSVGView->mPreserveAspectRatio.GetAnimValue();
|
||||
}
|
||||
return mPreserveAspectRatio.GetAnimValue();
|
||||
}
|
||||
|
||||
@ -904,6 +912,8 @@ SVGSVGElement::GetLength(uint8_t aCtxType)
|
||||
// The logic here should match HasViewBoxRect().
|
||||
if (viewElement && viewElement->mViewBox.HasRect()) {
|
||||
viewbox = &viewElement->mViewBox.GetAnimValue();
|
||||
} else if (mSVGView && mSVGView->mViewBox.HasRect()) {
|
||||
viewbox = &mSVGView->mViewBox.GetAnimValue();
|
||||
} else if (mViewBox.HasRect()) {
|
||||
viewbox = &mViewBox.GetAnimValue();
|
||||
}
|
||||
@ -946,9 +956,12 @@ SVGSVGElement::GetLength(uint8_t aCtxType)
|
||||
SVGSVGElement::PrependLocalTransformsTo(
|
||||
const gfxMatrix &aMatrix, SVGTransformTypes aWhich) const
|
||||
{
|
||||
// 'transform' attribute:
|
||||
// 'transform' attribute (or an override from a fragment identifier):
|
||||
gfxMatrix fromUserSpace =
|
||||
SVGSVGElementBase::PrependLocalTransformsTo(aMatrix, aWhich);
|
||||
SVGContentUtils::PrependLocalTransformsTo(
|
||||
aMatrix, aWhich, mAnimateMotionTransform,
|
||||
mSVGView && mSVGView->mTransforms ? mSVGView->mTransforms : mTransforms);
|
||||
|
||||
if (aWhich == eUserSpaceToParent) {
|
||||
return fromUserSpace;
|
||||
}
|
||||
@ -975,6 +988,15 @@ SVGSVGElement::PrependLocalTransformsTo(
|
||||
return ThebesMatrix(GetViewBoxTransform()) * fromUserSpace;
|
||||
}
|
||||
|
||||
nsSVGAnimatedTransformList*
|
||||
SVGSVGElement::GetAnimatedTransformList(uint32_t aFlags)
|
||||
{
|
||||
if (!(aFlags & DO_ALLOCATE) && mSVGView && mSVGView->mTransforms) {
|
||||
return mSVGView->mTransforms;
|
||||
}
|
||||
return SVGSVGElementBase::GetAnimatedTransformList(aFlags);
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
SVGSVGElement::HasValidDimensions() const
|
||||
{
|
||||
@ -1015,7 +1037,8 @@ bool
|
||||
SVGSVGElement::HasViewBoxRect() const
|
||||
{
|
||||
SVGViewElement* viewElement = GetCurrentViewElement();
|
||||
if (viewElement && viewElement->mViewBox.HasRect()) {
|
||||
if ((viewElement && viewElement->mViewBox.HasRect()) ||
|
||||
(mSVGView && mSVGView->mViewBox.HasRect())) {
|
||||
return true;
|
||||
}
|
||||
return mViewBox.HasRect();
|
||||
@ -1136,106 +1159,6 @@ SVGSVGElement::FlushImageTransformInvalidation()
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
SVGSVGElement::SetViewBoxProperty(const nsSVGViewBoxRect& aViewBox)
|
||||
{
|
||||
nsSVGViewBoxRect* pViewBoxOverridePtr = new nsSVGViewBoxRect(aViewBox);
|
||||
nsresult rv = SetProperty(nsGkAtoms::viewBox,
|
||||
pViewBoxOverridePtr,
|
||||
nsINode::DeleteProperty<nsSVGViewBoxRect>,
|
||||
true);
|
||||
MOZ_ASSERT(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
|
||||
"Setting override value when it's already set...?");
|
||||
|
||||
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
|
||||
// property-insertion failed (e.g. OOM in property-table code)
|
||||
delete pViewBoxOverridePtr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const nsSVGViewBoxRect*
|
||||
SVGSVGElement::GetViewBoxProperty() const
|
||||
{
|
||||
void* valPtr = GetProperty(nsGkAtoms::viewBox);
|
||||
if (valPtr) {
|
||||
return static_cast<nsSVGViewBoxRect*>(valPtr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
SVGSVGElement::ClearViewBoxProperty()
|
||||
{
|
||||
void* valPtr = UnsetProperty(nsGkAtoms::viewBox);
|
||||
delete static_cast<nsSVGViewBoxRect*>(valPtr);
|
||||
return valPtr;
|
||||
}
|
||||
|
||||
bool
|
||||
SVGSVGElement::SetZoomAndPanProperty(uint16_t aValue)
|
||||
{
|
||||
nsresult rv = SetProperty(nsGkAtoms::zoomAndPan,
|
||||
reinterpret_cast<void*>(aValue),
|
||||
nullptr, true);
|
||||
MOZ_ASSERT(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
|
||||
"Setting override value when it's already set...?");
|
||||
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
SVGSVGElement::GetZoomAndPanProperty() const
|
||||
{
|
||||
void* valPtr = GetProperty(nsGkAtoms::zoomAndPan);
|
||||
if (valPtr) {
|
||||
return reinterpret_cast<uintptr_t>(valPtr);
|
||||
}
|
||||
return SVG_ZOOMANDPAN_UNKNOWN;
|
||||
}
|
||||
|
||||
bool
|
||||
SVGSVGElement::ClearZoomAndPanProperty()
|
||||
{
|
||||
return UnsetProperty(nsGkAtoms::zoomAndPan);
|
||||
}
|
||||
|
||||
bool
|
||||
SVGSVGElement::SetTransformProperty(const SVGTransformList& aTransform)
|
||||
{
|
||||
SVGTransformList* pTransformOverridePtr = new SVGTransformList(aTransform);
|
||||
nsresult rv = SetProperty(nsGkAtoms::transform,
|
||||
pTransformOverridePtr,
|
||||
nsINode::DeleteProperty<SVGTransformList>,
|
||||
true);
|
||||
MOZ_ASSERT(rv != NS_PROPTABLE_PROP_OVERWRITTEN,
|
||||
"Setting override value when it's already set...?");
|
||||
|
||||
if (MOZ_UNLIKELY(NS_FAILED(rv))) {
|
||||
// property-insertion failed (e.g. OOM in property-table code)
|
||||
delete pTransformOverridePtr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const SVGTransformList*
|
||||
SVGSVGElement::GetTransformProperty() const
|
||||
{
|
||||
void* valPtr = GetProperty(nsGkAtoms::transform);
|
||||
if (valPtr) {
|
||||
return static_cast<SVGTransformList*>(valPtr);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
SVGSVGElement::ClearTransformProperty()
|
||||
{
|
||||
return UnsetProperty(nsGkAtoms::transform);
|
||||
}
|
||||
|
||||
int32_t
|
||||
SVGSVGElement::GetIntrinsicWidth()
|
||||
{
|
||||
|
@ -33,6 +33,7 @@ class DOMSVGLength;
|
||||
class DOMSVGNumber;
|
||||
class EventChainPreVisitor;
|
||||
class SVGFragmentIdentifier;
|
||||
class AutoSVGViewHandler;
|
||||
|
||||
namespace dom {
|
||||
class SVGAngle;
|
||||
@ -85,13 +86,29 @@ public:
|
||||
float height;
|
||||
};
|
||||
|
||||
// Stores svgView arguments of SVG fragment identifiers.
|
||||
class SVGView {
|
||||
friend class mozilla::AutoSVGViewHandler;
|
||||
friend class mozilla::dom::SVGSVGElement;
|
||||
public:
|
||||
SVGView();
|
||||
|
||||
private:
|
||||
nsSVGEnum mZoomAndPan;
|
||||
nsSVGViewBox mViewBox;
|
||||
SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
|
||||
nsAutoPtr<nsSVGAnimatedTransformList> mTransforms;
|
||||
};
|
||||
|
||||
typedef SVGGraphicsElement SVGSVGElementBase;
|
||||
|
||||
class SVGSVGElement final : public SVGSVGElementBase
|
||||
{
|
||||
friend class ::nsSVGOuterSVGFrame;
|
||||
friend class ::nsSVGInnerSVGFrame;
|
||||
friend class mozilla::dom::SVGView;
|
||||
friend class mozilla::SVGFragmentIdentifier;
|
||||
friend class mozilla::AutoSVGViewHandler;
|
||||
friend class mozilla::AutoSVGRenderingState;
|
||||
|
||||
SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
|
||||
@ -141,6 +158,8 @@ public:
|
||||
virtual gfxMatrix PrependLocalTransformsTo(
|
||||
const gfxMatrix &aMatrix,
|
||||
SVGTransformTypes aWhich = eAllTransforms) const override;
|
||||
virtual nsSVGAnimatedTransformList*
|
||||
GetAnimatedTransformList(uint32_t aFlags = 0) override;
|
||||
virtual bool HasValidDimensions() const override;
|
||||
|
||||
// SVGSVGElement methods:
|
||||
@ -286,19 +305,11 @@ private:
|
||||
void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR);
|
||||
void ClearImageOverridePreserveAspectRatio();
|
||||
|
||||
// Set/Clear properties to hold old or override versions of attributes
|
||||
// Set/Clear properties to hold old version of preserveAspectRatio
|
||||
// when it's being overridden by an <image> element that we are inside of.
|
||||
bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR);
|
||||
const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const;
|
||||
bool ClearPreserveAspectRatioProperty();
|
||||
bool SetViewBoxProperty(const nsSVGViewBoxRect& aViewBox);
|
||||
const nsSVGViewBoxRect* GetViewBoxProperty() const;
|
||||
bool ClearViewBoxProperty();
|
||||
bool SetZoomAndPanProperty(uint16_t aValue);
|
||||
uint16_t GetZoomAndPanProperty() const;
|
||||
bool ClearZoomAndPanProperty();
|
||||
bool SetTransformProperty(const SVGTransformList& aValue);
|
||||
const SVGTransformList* GetTransformProperty() const;
|
||||
bool ClearTransformProperty();
|
||||
|
||||
bool IsRoot() const {
|
||||
NS_ASSERTION((IsInDoc() && !GetParent()) ==
|
||||
@ -369,7 +380,10 @@ private:
|
||||
nsSVGViewBox mViewBox;
|
||||
SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
|
||||
|
||||
// mCurrentViewID and mSVGView are mutually exclusive; we can have
|
||||
// at most one non-null.
|
||||
nsAutoPtr<nsString> mCurrentViewID;
|
||||
nsAutoPtr<SVGView> mSVGView;
|
||||
|
||||
// The size of the rectangular SVG viewport into which we render. This is
|
||||
// not (necessarily) the same as the content area. See:
|
||||
@ -401,7 +415,6 @@ private:
|
||||
bool mImageNeedsTransformInvalidation;
|
||||
bool mIsPaintingSVGImageElement;
|
||||
bool mHasChildrenOnlyTransform;
|
||||
bool mUseCurrentView;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -24,67 +24,92 @@ function Test(svgFragmentIdentifier, valid, viewBoxString,
|
||||
{
|
||||
this.svgFragmentIdentifier = svgFragmentIdentifier;
|
||||
this.valid = valid;
|
||||
this.viewBoxString = viewBoxString;
|
||||
this.preserveAspectRatioString = preserveAspectRatioString;
|
||||
this.zoomAndPanString = zoomAndPanString;
|
||||
}
|
||||
|
||||
function runTests()
|
||||
{
|
||||
var svg = $("svg");
|
||||
var doc = svg.contentWindow.document;
|
||||
|
||||
var rootElement = doc.rootElement;
|
||||
|
||||
var tests = [
|
||||
new Test("unknown", false, null, null, null),
|
||||
new Test("svgView(viewBox(0,0,200,200))", true, "0 0 200 200", null, null),
|
||||
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(viewBox(none))", true, "none", null, 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),
|
||||
new Test("unknown", false),
|
||||
new Test("svgView(viewBox(0,0,200,200))", true),
|
||||
new Test("svgView(preserveAspectRatio(xMaxYMin slice))", true),
|
||||
new Test("svgView(viewBox(1,2,3,4);preserveAspectRatio(xMinYMax))", true),
|
||||
new Test("svgView(viewBox(none))", true),
|
||||
new Test("svgView(zoomAndPan(disable))", true),
|
||||
new Test("svgView(transform(translate(-10,-20) scale(2) rotate(45) translate(5,10)))", true),
|
||||
// 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),
|
||||
new Test("svgView(zoomAndPan(disable);zoomAndPan(disable))", false),
|
||||
new Test("svgView(viewBox(0,0,200,200);viewBox(0,0,200,200))", false),
|
||||
new Test("svgView(preserveAspectRatio(xMaxYMin);preserveAspectRatio(xMaxYMin))", false),
|
||||
new Test("svgView(transform(translate(0,200));transform(translate(0,200)))", false),
|
||||
// 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),
|
||||
new Test("svgView(viewBox(bad)", false),
|
||||
new Test("svgView(preserveAspectRatio(bad))", false),
|
||||
new Test("svgView(zoomAndPan(bad))", false),
|
||||
new Test("svgView(transform(bad))", false),
|
||||
new Test("svgView", false),
|
||||
new Test("svgView(", false),
|
||||
new Test("svgView()", false),
|
||||
// Be sure we verify that there's a closing paren for svgView()
|
||||
// (and not too many closing parens)
|
||||
new Test("svgView(zoomAndPan(disable)", false, null, null, null),
|
||||
new Test("svgView(zoomAndPan(disable) ", false, null, null, null),
|
||||
new Test("svgView(zoomAndPan(disable)]", false, null, null, null),
|
||||
new Test("svgView(zoomAndPan(disable)))", false, null, null, null)
|
||||
new Test("svgView(zoomAndPan(disable)", false),
|
||||
new Test("svgView(zoomAndPan(disable) ", false),
|
||||
new Test("svgView(zoomAndPan(disable)]", false),
|
||||
new Test("svgView(zoomAndPan(disable)))", false)
|
||||
];
|
||||
|
||||
var src = svg.getAttribute("src");
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var test = tests[i];
|
||||
svg.setAttribute("src", src + "#" + test.svgFragmentIdentifier);
|
||||
is(doc.rootElement.useCurrentView, test.valid,
|
||||
"Expected " + test.svgFragmentIdentifier + " to be " +
|
||||
(test.valid ? "valid" : "invalid"));
|
||||
|
||||
is(doc.rootElement.getAttribute("viewBox"),
|
||||
test.viewBoxString, "unexpected viewBox");
|
||||
is(false, rootElement.hasAttribute("viewBox"),
|
||||
"expecting to start without a viewBox set");
|
||||
is(false, rootElement.hasAttribute("preserveAspectRatio"),
|
||||
"expecting to start without preserveAspectRatio set");
|
||||
is(false, rootElement.hasAttribute("zoomAndPan"),
|
||||
"expecting to start without zoomAndPan set");
|
||||
|
||||
is(doc.rootElement.getAttribute("preserveAspectRatio"),
|
||||
test.preserveAspectRatioString, "unexpected preserveAspectRatio");
|
||||
for (var j = 0; j < 2; j++) {
|
||||
var initialViewBox = rootElement.getAttribute("viewBox");
|
||||
var initialPreserveAspectRatio =
|
||||
rootElement.getAttribute("preserveAspectRatio");
|
||||
var initialZoomAndPan = rootElement.getAttribute("zoomAndPan");
|
||||
var initialTransform = rootElement.getAttribute("transform");
|
||||
|
||||
is(doc.rootElement.getAttribute("zoomAndPan"),
|
||||
test.zoomAndPanString, "unexpected zoomAndPan");
|
||||
for (var i = 0; i < tests.length; i++) {
|
||||
var test = tests[i];
|
||||
svg.setAttribute("src", src + "#" + test.svgFragmentIdentifier);
|
||||
is(rootElement.useCurrentView, test.valid,
|
||||
"Expected " + test.svgFragmentIdentifier + " to be " +
|
||||
(test.valid ? "valid" : "invalid"));
|
||||
|
||||
// check that assigning a viewSpec does not modify the underlying
|
||||
// attribute values.
|
||||
is(rootElement.getAttribute("viewBox"),
|
||||
initialViewBox, "unexpected viewBox");
|
||||
|
||||
is(rootElement.getAttribute("preserveAspectRatio"),
|
||||
initialPreserveAspectRatio, "unexpected preserveAspectRatio");
|
||||
|
||||
is(rootElement.getAttribute("zoomAndPan"),
|
||||
initialZoomAndPan, "unexpected zoomAndPan");
|
||||
|
||||
is(rootElement.getAttribute("transform"),
|
||||
initialTransform, "unexpected transform");
|
||||
}
|
||||
|
||||
// repeat tests with underlying attributes set to values
|
||||
rootElement.setAttribute("viewBox", "0 0 100 100");
|
||||
rootElement.setAttribute("preserveAspectRatio", "none");
|
||||
rootElement.setAttribute("zoomAndPan", "disable");
|
||||
rootElement.setAttribute("transform", "translate(10,10)");
|
||||
}
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
window.addEventListener("load", runTests, false);
|
||||
$(svg).addEventListener("load", runTests, false);
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
|
Loading…
Reference in New Issue
Block a user