зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1383650 - Notify style system when SMIL animation changes length r=birtles,longsonr
When animating geometry attribute, we need to notify style system about the change of SMIL override style. Differential Revision: https://phabricator.services.mozilla.com/D30361 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
e3fcbc33d6
Коммит
a5f610a05c
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "SMILCompositor.h"
|
||||
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
#include "nsComputedDOMStyle.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
@ -147,19 +148,21 @@ nsCSSPropertyID SMILCompositor::GetCSSPropertyToAnimate() const {
|
|||
|
||||
// If we are animating the 'width' or 'height' of an outer SVG
|
||||
// element we should animate it as a CSS property, but for other elements
|
||||
// (e.g. <rect>) we should animate it as a length attribute.
|
||||
// The easiest way to test for an outer SVG element, is to see if it is an
|
||||
// SVG-namespace element mapping its width/height attribute to style.
|
||||
//
|
||||
// If we have animation of 'width' or 'height' on an SVG element that is
|
||||
// NOT mapping that attributes to style then it must not be an outermost SVG
|
||||
// element so we should return eCSSProperty_UNKNOWN to indicate that we
|
||||
// should animate as an attribute instead.
|
||||
// in SVG namespace (e.g. <rect>) we should animate it as a length attribute.
|
||||
if ((mKey.mAttributeName == nsGkAtoms::width ||
|
||||
mKey.mAttributeName == nsGkAtoms::height) &&
|
||||
mKey.mElement->GetNameSpaceID() == kNameSpaceID_SVG &&
|
||||
!mKey.mElement->IsAttributeMapped(mKey.mAttributeName)) {
|
||||
return eCSSProperty_UNKNOWN;
|
||||
mKey.mElement->GetNameSpaceID() == kNameSpaceID_SVG) {
|
||||
// Not an <svg> element.
|
||||
if (!mKey.mElement->IsSVGElement(nsGkAtoms::svg)) {
|
||||
return eCSSProperty_UNKNOWN;
|
||||
}
|
||||
|
||||
// An inner <svg> element
|
||||
if (static_cast<dom::SVGSVGElement const&>(*mKey.mElement).IsInner()) {
|
||||
return eCSSProperty_UNKNOWN;
|
||||
}
|
||||
|
||||
// Indeed an outer <svg> element, fall through.
|
||||
}
|
||||
|
||||
return propID;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "nsAttrValueOrString.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsDOMCSSAttrDeclaration.h"
|
||||
#include "nsICSSDeclaration.h"
|
||||
#include "nsIContentInlines.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
|
@ -53,6 +54,7 @@
|
|||
#include "SVGAnimatedOrient.h"
|
||||
#include "SVGAnimatedString.h"
|
||||
#include "SVGAnimatedViewBox.h"
|
||||
#include "SVGGeometryProperty.h"
|
||||
#include "SVGMotionSMILAttr.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
|
@ -1020,6 +1022,41 @@ already_AddRefed<DOMSVGAnimatedString> SVGElement::ClassName() {
|
|||
return mClassAttribute.ToDOMAnimatedString(this);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool SVGElement::UpdateDeclarationBlockFromLength(
|
||||
DeclarationBlock& aBlock, nsCSSPropertyID aPropId,
|
||||
const SVGAnimatedLength& aLength, ValToUse aValToUse) {
|
||||
aBlock.AssertMutable();
|
||||
|
||||
float value;
|
||||
if (aValToUse == ValToUse::Anim) {
|
||||
value = aLength.GetAnimValInSpecifiedUnits();
|
||||
} else {
|
||||
MOZ_ASSERT(aValToUse == ValToUse::Base);
|
||||
value = aLength.GetBaseValInSpecifiedUnits();
|
||||
}
|
||||
|
||||
// SVG parser doesn't check non-negativity of some parsed value,
|
||||
// we should not pass those to CSS side.
|
||||
if (value < 0 &&
|
||||
SVGGeometryProperty::IsNonNegativeGeometryProperty(aPropId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCSSUnit cssUnit = SVGGeometryProperty::SpecifiedUnitTypeToCSSUnit(
|
||||
aLength.GetSpecifiedUnitType());
|
||||
|
||||
if (cssUnit == eCSSUnit_Percent) {
|
||||
Servo_DeclarationBlock_SetPercentValue(aBlock.Raw(), aPropId,
|
||||
value / 100.f);
|
||||
} else {
|
||||
Servo_DeclarationBlock_SetLengthValue(aBlock.Raw(), aPropId, value,
|
||||
cssUnit);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Helper class: MappedAttrParser, for parsing values of mapped attributes
|
||||
|
||||
|
@ -1391,6 +1428,15 @@ void SVGElement::DidChangeLength(uint8_t aAttrEnum,
|
|||
}
|
||||
|
||||
void SVGElement::DidAnimateLength(uint8_t aAttrEnum) {
|
||||
if (SVGGeometryProperty::ElementMapsLengthsToStyle(this)) {
|
||||
nsCSSPropertyID propId =
|
||||
SVGGeometryProperty::AttrEnumToCSSPropId(this, aAttrEnum);
|
||||
|
||||
SMILOverrideStyle()->SetSMILValue(propId,
|
||||
GetLengthInfo().mLengths[aAttrEnum]);
|
||||
return;
|
||||
}
|
||||
|
||||
ClearAnyCachedPath();
|
||||
|
||||
nsIFrame* frame = GetPrimaryFrame();
|
||||
|
|
|
@ -165,6 +165,12 @@ class SVGElement : public SVGElementBase // nsIContent
|
|||
virtual bool HasValidDimensions() const { return true; }
|
||||
void SetLength(nsAtom* aName, const SVGAnimatedLength& aLength);
|
||||
|
||||
enum class ValToUse { Base, Anim };
|
||||
static bool UpdateDeclarationBlockFromLength(DeclarationBlock& aBlock,
|
||||
nsCSSPropertyID aPropId,
|
||||
const SVGAnimatedLength& aLength,
|
||||
ValToUse aValToUse);
|
||||
|
||||
nsAttrValue WillChangeLength(uint8_t aAttrEnum);
|
||||
nsAttrValue WillChangeNumberPair(uint8_t aAttrEnum);
|
||||
nsAttrValue WillChangeIntegerPair(uint8_t aAttrEnum);
|
||||
|
|
|
@ -69,6 +69,19 @@ nsCSSPropertyID AttrEnumToCSSPropId(const SVGElement* aElement,
|
|||
return eCSSProperty_UNKNOWN;
|
||||
}
|
||||
|
||||
bool IsNonNegativeGeometryProperty(nsCSSPropertyID aProp) {
|
||||
return aProp == eCSSProperty_r || aProp == eCSSProperty_rx ||
|
||||
aProp == eCSSProperty_ry || aProp == eCSSProperty_width ||
|
||||
aProp == eCSSProperty_height;
|
||||
}
|
||||
|
||||
bool ElementMapsLengthsToStyle(SVGElement const* aElement) {
|
||||
return aElement->IsSVGElement(nsGkAtoms::rect) ||
|
||||
aElement->IsSVGElement(nsGkAtoms::circle) ||
|
||||
aElement->IsSVGElement(nsGkAtoms::ellipse) ||
|
||||
aElement->IsSVGElement(nsGkAtoms::foreignObject);
|
||||
}
|
||||
|
||||
} // namespace SVGGeometryProperty
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -152,6 +152,9 @@ nsCSSUnit SpecifiedUnitTypeToCSSUnit(uint8_t aSpecifiedUnit);
|
|||
nsCSSPropertyID AttrEnumToCSSPropId(const SVGElement* aElement,
|
||||
uint8_t aAttrEnum);
|
||||
|
||||
bool IsNonNegativeGeometryProperty(nsCSSPropertyID aProp);
|
||||
bool ElementMapsLengthsToStyle(SVGElement const* aElement);
|
||||
|
||||
} // namespace SVGGeometryProperty
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -124,6 +124,17 @@ class SVGViewportElement : public SVGGraphicsElement {
|
|||
mViewportHeight = aSize.height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if either this is an SVG <svg> element that is the child of
|
||||
* another non-foreignObject SVG element, or this is a SVG <symbol> element
|
||||
* this is the root of a use-element shadow tree.
|
||||
*/
|
||||
bool IsInner() const {
|
||||
const nsIContent* parent = GetFlattenedTreeParent();
|
||||
return parent && parent->IsSVGElement() &&
|
||||
!parent->IsSVGElement(nsGkAtoms::foreignObject);
|
||||
}
|
||||
|
||||
// WebIDL
|
||||
already_AddRefed<SVGAnimatedRect> ViewBox();
|
||||
already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
|
||||
|
@ -139,17 +150,6 @@ class SVGViewportElement : public SVGGraphicsElement {
|
|||
return IsInUncomposedDoc() && !GetParent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if either this is an SVG <svg> element that is the child of
|
||||
* another non-foreignObject SVG element, or this is a SVG <symbol> element
|
||||
* this is the root of a use-element shadow tree.
|
||||
*/
|
||||
bool IsInner() const {
|
||||
const nsIContent* parent = GetFlattenedTreeParent();
|
||||
return parent && parent->IsSVGElement() &&
|
||||
!parent->IsSVGElement(nsGkAtoms::foreignObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the explicit or default preserveAspectRatio, unless we're
|
||||
* synthesizing a viewBox, in which case it returns the "none" value.
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/SVGElement.h"
|
||||
#include "mozilla/dom/MutationEventBinding.h"
|
||||
#include "mozilla/DeclarationBlock.h"
|
||||
#include "mozilla/InternalMutationEvent.h"
|
||||
#include "mozilla/SMILCSSValueType.h"
|
||||
#include "mozilla/SMILValue.h"
|
||||
#include "mozAutoDocUpdate.h"
|
||||
#include "nsIURI.h"
|
||||
#include "nsNodeUtils.h"
|
||||
|
@ -133,9 +135,10 @@ nsDOMCSSAttributeDeclaration::GetParsingEnvironment(
|
|||
};
|
||||
}
|
||||
|
||||
nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
|
||||
const nsCSSPropertyID aPropID, const SMILValue& aValue) {
|
||||
template <typename SetterFunc>
|
||||
nsresult nsDOMCSSAttributeDeclaration::SetSMILValueHelper(SetterFunc aFunc) {
|
||||
MOZ_ASSERT(mIsSMILOverride);
|
||||
|
||||
// No need to do the ActiveLayerTracker / ScrollLinkedEffectDetector bits,
|
||||
// since we're in a SMIL animation anyway, no need to try to detect we're a
|
||||
// scripted animation.
|
||||
|
@ -147,7 +150,9 @@ nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
|
|||
}
|
||||
mozAutoDocUpdate autoUpdate(DocToUpdate(), true);
|
||||
RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
|
||||
bool changed = SMILCSSValueType::SetPropertyValues(aValue, *decl);
|
||||
|
||||
bool changed = aFunc(*decl);
|
||||
|
||||
if (changed) {
|
||||
// We can pass nullptr as the latter param, since this is
|
||||
// mIsSMILOverride == true case.
|
||||
|
@ -156,6 +161,23 @@ nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
|
||||
const nsCSSPropertyID /*aPropID*/, const SMILValue& aValue) {
|
||||
MOZ_ASSERT(aValue.mType == &SMILCSSValueType::sSingleton,
|
||||
"We should only try setting a CSS value type");
|
||||
return SetSMILValueHelper([&aValue](DeclarationBlock& aDecl) {
|
||||
return SMILCSSValueType::SetPropertyValues(aValue, aDecl);
|
||||
});
|
||||
}
|
||||
|
||||
nsresult nsDOMCSSAttributeDeclaration::SetSMILValue(
|
||||
const nsCSSPropertyID aPropID, const SVGAnimatedLength& aLength) {
|
||||
return SetSMILValueHelper([aPropID, &aLength](DeclarationBlock& aDecl) {
|
||||
return SVGElement::UpdateDeclarationBlockFromLength(
|
||||
aDecl, aPropID, aLength, SVGElement::ValToUse::Anim);
|
||||
});
|
||||
}
|
||||
|
||||
nsresult nsDOMCSSAttributeDeclaration::SetPropertyValue(
|
||||
const nsCSSPropertyID aPropID, const nsAString& aValue,
|
||||
nsIPrincipal* aSubjectPrincipal) {
|
||||
|
|
|
@ -18,6 +18,7 @@ struct RawServoUnlockedDeclarationBlock;
|
|||
namespace mozilla {
|
||||
|
||||
class SMILValue;
|
||||
class SVGAnimatedLength;
|
||||
|
||||
namespace dom {
|
||||
class DomGroup;
|
||||
|
@ -29,6 +30,7 @@ class nsDOMCSSAttributeDeclaration final : public nsDOMCSSDeclaration {
|
|||
public:
|
||||
typedef mozilla::dom::Element Element;
|
||||
typedef mozilla::SMILValue SMILValue;
|
||||
typedef mozilla::SVGAnimatedLength SVGAnimatedLength;
|
||||
nsDOMCSSAttributeDeclaration(Element* aContent, bool aIsSMILOverride);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
@ -45,7 +47,9 @@ class nsDOMCSSAttributeDeclaration final : public nsDOMCSSDeclaration {
|
|||
|
||||
nsINode* GetParentObject() override { return mElement; }
|
||||
|
||||
nsresult SetSMILValue(const nsCSSPropertyID aPropID, const SMILValue&);
|
||||
nsresult SetSMILValue(const nsCSSPropertyID aPropID, const SMILValue& aValue);
|
||||
nsresult SetSMILValue(const nsCSSPropertyID aPropID,
|
||||
const SVGAnimatedLength& aLength);
|
||||
|
||||
nsresult SetPropertyValue(const nsCSSPropertyID aPropID,
|
||||
const nsAString& aValue,
|
||||
|
@ -79,6 +83,10 @@ class nsDOMCSSAttributeDeclaration final : public nsDOMCSSDeclaration {
|
|||
* than the inline style rule).
|
||||
*/
|
||||
const bool mIsSMILOverride;
|
||||
|
||||
private:
|
||||
template <typename SetterFunc>
|
||||
nsresult SetSMILValueHelper(SetterFunc aFunc);
|
||||
};
|
||||
|
||||
#endif /* nsDOMCSSAttributeDeclaration_h */
|
||||
|
|
Загрузка…
Ссылка в новой задаче