nsresult nsSVGAnimatedTransformList::SetBaseValue(const SVGTransformList& aValue) { SVGAnimatedTransformList *domWrapper = SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // We must send this notification *before* changing mBaseVal! If the length // of our baseVal is being reduced, our baseVal's DOM wrapper list may have // to remove DOM items from itself, and any removed DOM items need to copy // their internal counterpart values *before* we change them. // domWrapper->InternalBaseValListWillChangeLengthTo(aValue.Length()); } // We don't need to call DidChange* here - we're only called by // nsSVGElement::ParseAttribute under Element::SetAttr, // which takes care of notifying. nsresult rv = mBaseVal.CopyFrom(aValue); if (NS_FAILED(rv) && domWrapper) { // Attempting to increase mBaseVal's length failed - reduce domWrapper // back to the same length: domWrapper->InternalBaseValListWillChangeLengthTo(mBaseVal.Length()); } else { mIsAttrSet = true; } return rv; }
bool DOMSVGTransform::IndexIsValid() { SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList(); return (mIsAnimValItem && mListIndex < alist->GetAnimValue().Length()) || (!mIsAnimValItem && mListIndex < alist->GetBaseValue().Length()); }
gfxMatrix nsSVGPatternFrame::GetPatternTransform() { SVGAnimatedTransformList* animTransformList = GetPatternTransformList(mContent); if (!animTransformList) return gfxMatrix(); return animTransformList->GetAnimValue().GetConsolidationMatrix(); }
void nsSVGAnimatedTransformList::ClearBaseValue() { SVGAnimatedTransformList *domWrapper = SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // We must send this notification *before* changing mBaseVal! (See above.) domWrapper->InternalBaseValListWillChangeLengthTo(0); } mBaseVal.Clear(); mIsAttrSet = false; // Caller notifies }
JSValue* JSSVGAnimatedTransformList::getValueProperty(ExecState* exec, int token) const { switch (token) { case BaseValAttrNum: { SVGAnimatedTransformList* imp = static_cast<SVGAnimatedTransformList*>(impl()); return toJS(exec, WTF::getPtr(imp->baseVal()), context()); } case AnimValAttrNum: { SVGAnimatedTransformList* imp = static_cast<SVGAnimatedTransformList*>(impl()); return toJS(exec, WTF::getPtr(imp->animVal()), context()); } } return 0; }
SVGAnimatedTransformList* nsSVGPatternFrame::GetPatternTransformList(nsIContent* aDefault) { SVGAnimatedTransformList *thisTransformList = static_cast<nsSVGPatternElement *>(mContent)->GetAnimatedTransformList(); if (thisTransformList && thisTransformList->IsExplicitlySet()) return thisTransformList; AutoPatternReferencer patternRef(this); nsSVGPatternFrame *next = GetReferencedPatternIfNotInUse(); return next ? next->GetPatternTransformList(aDefault) : static_cast<nsSVGPatternElement *>(aDefault)->mPatternTransform.get(); }
void nsSVGAnimatedTransformList::ClearAnimValue(nsSVGElement *aElement) { SVGAnimatedTransformList *domWrapper = SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // When all animation ends, animVal simply mirrors baseVal, which may have // a different number of items to the last active animated value. We must // keep the length of our animVal's DOM wrapper list in sync, and again we // must do that before touching mAnimVal. See comments above. // domWrapper->InternalAnimValListWillChangeLengthTo(mBaseVal.Length()); } mAnimVal = nullptr; aElement->DidAnimateTransformList(); }
const SVGAnimatedTransformList* nsSVGGradientFrame::GetGradientTransformList(nsIContent* aDefault) { SVGAnimatedTransformList *thisTransformList = static_cast<dom::SVGGradientElement*>(mContent)->GetAnimatedTransformList(); if (thisTransformList && thisTransformList->IsExplicitlySet()) return thisTransformList; AutoGradientReferencer gradientRef(this); nsSVGGradientFrame *next = GetReferencedGradientIfNotInUse(); return next ? next->GetGradientTransformList(aDefault) : static_cast<const dom::SVGGradientElement*>(aDefault) ->mGradientTransform.get(); }
nsresult nsSVGAnimatedTransformList::SetAnimValue(const SVGTransformList& aValue, nsSVGElement *aElement) { bool prevSet = HasTransform() || aElement->GetAnimateMotionTransform(); SVGAnimatedTransformList *domWrapper = SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // A new animation may totally change the number of items in the animVal // list, replacing what was essentially a mirror of the baseVal list, or // else replacing and overriding an existing animation. When this happens // we must try and keep our animVal's DOM wrapper in sync (see the comment // in SVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo). // // It's not possible for us to reliably distinguish between calls to this // method that are setting a new sample for an existing animation, and // calls that are setting the first sample of an animation that will // override an existing animation. Happily it's cheap to just blindly // notify our animVal's DOM wrapper of its internal counterpart's new value // each time this method is called, so that's what we do. // // Note that we must send this notification *before* setting or changing // mAnimVal! (See the comment in SetBaseValueString above.) // domWrapper->InternalAnimValListWillChangeLengthTo(aValue.Length()); } if (!mAnimVal) { mAnimVal = new SVGTransformList(); } nsresult rv = mAnimVal->CopyFrom(aValue); if (NS_FAILED(rv)) { // OOM. We clear the animation, and, importantly, ClearAnimValue() ensures // that mAnimVal and its DOM wrapper (if any) will have the same length! ClearAnimValue(aElement); return rv; } int32_t modType; if(prevSet) { modType = nsIDOMMutationEvent::MODIFICATION; } else { modType = nsIDOMMutationEvent::ADDITION; } aElement->DidAnimateTransformList(modType); return NS_OK; }
void nsSVGAnimatedTransformList::ClearAnimValue(nsSVGElement *aElement) { SVGAnimatedTransformList *domWrapper = SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // When all animation ends, animVal simply mirrors baseVal, which may have // a different number of items to the last active animated value. We must // keep the length of our animVal's DOM wrapper list in sync, and again we // must do that before touching mAnimVal. See comments above. // domWrapper->InternalAnimValListWillChangeLengthTo(mBaseVal.Length()); } mAnimVal = nullptr; int32_t modType; if (HasTransform() || aElement->GetAnimateMotionTransform()) { modType = nsIDOMMutationEvent::MODIFICATION; } else { modType = nsIDOMMutationEvent::REMOVAL; } aElement->DidAnimateTransformList(modType); }
gfxMatrix nsSVGGradientFrame::GetGradientTransform(nsIFrame *aSource, const gfxRect *aOverrideBounds) { gfxMatrix bboxMatrix; PRUint16 gradientUnits = GetGradientUnits(); if (gradientUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_USERSPACEONUSE) { // If this gradient is applied to text, our caller // will be the glyph, which is not a container, so we // need to get the parent if (aSource->GetContent()->IsNodeOfType(nsINode::eTEXT)) mSource = aSource->GetParent(); else mSource = aSource; } else { NS_ASSERTION(gradientUnits == nsIDOMSVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX, "Unknown gradientUnits type"); // objectBoundingBox is the default anyway gfxRect bbox = aOverrideBounds ? *aOverrideBounds : nsSVGUtils::GetBBox(aSource); bboxMatrix = gfxMatrix(bbox.Width(), 0, 0, bbox.Height(), bbox.X(), bbox.Y()); } nsSVGGradientElement *element = GetGradientWithAttr(nsGkAtoms::gradientTransform, mContent); SVGAnimatedTransformList* animTransformList = element->GetAnimatedTransformList(); if (!animTransformList) return bboxMatrix; gfxMatrix gradientTransform = animTransformList->GetAnimValue().GetConsolidationMatrix(); return bboxMatrix.PreMultiply(gradientTransform); }
bool SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec, nsSVGSVGElement *root) { 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; nsCharSeparatedTokenizerTemplate<IgnoreWhitespace> tokenizer( Substring(aViewSpec, bracketPos + 1, lengthOfViewSpec), ';'); if (!tokenizer.hasMoreTokens()) { return false; } do { nsAutoString token(tokenizer.nextToken()); bracketPos = token.FindChar('('); if (bracketPos < 1 || token.Last() != ')') { // invalid SVGViewAttribute syntax return false; } 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"))) { 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; } nsIAtom *valAtom = NS_GetStaticAtom(params); if (!valAtom) { return false; } const nsSVGEnumMapping *mapping = nsSVGSVGElement::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[nsSVGSVGElement::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 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) { ClearTransform(root); } if (!viewBoxFound) { RestoreOldViewBox(root); } if (!preserveAspectRatioFound) { RestoreOldPreserveAspectRatio(root); } if (!zoomAndPanFound) { RestoreOldZoomAndPan(root); } } return true; }