SVGSVGElement.h (9563B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef DOM_SVG_SVGSVGELEMENT_H_ 8 #define DOM_SVG_SVGSVGELEMENT_H_ 9 10 #include "SVGAnimatedEnumeration.h" 11 #include "SVGViewportElement.h" 12 #include "mozilla/SVGImageContext.h" 13 14 nsresult NS_NewSVGSVGElement( 15 nsIContent** aResult, already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 16 mozilla::dom::FromParser aFromParser); 17 18 // {4b83982c-e5e9-4ca1-abd4-14d27e8b3531} 19 #define MOZILLA_SVGSVGELEMENT_IID \ 20 {0x4b83982c, 0xe5e9, 0x4ca1, {0xab, 0xd4, 0x14, 0xd2, 0x7e, 0x8b, 0x35, 0x31}} 21 22 namespace mozilla { 23 class AutoSVGViewHandler; 24 class SMILTimeContainer; 25 class SVGFragmentIdentifier; 26 class EventChainPreVisitor; 27 28 namespace dom { 29 struct DOMMatrix2DInit; 30 class DOMSVGAngle; 31 class DOMSVGLength; 32 class DOMSVGNumber; 33 class DOMSVGPoint; 34 class SVGMatrix; 35 class SVGRect; 36 class SVGSVGElement; 37 38 // Stores svgView arguments of SVG fragment identifiers. 39 class SVGView { 40 public: 41 SVGView(); 42 43 SVGAnimatedEnumeration mZoomAndPan; 44 SVGAnimatedViewBox mViewBox; 45 SVGAnimatedPreserveAspectRatio mPreserveAspectRatio; 46 UniquePtr<SVGAnimatedTransformList> mTransforms; 47 }; 48 49 using SVGSVGElementBase = SVGViewportElement; 50 51 class SVGSVGElement final : public SVGSVGElementBase { 52 friend class mozilla::SVGFragmentIdentifier; 53 friend class mozilla::SVGOuterSVGFrame; 54 friend class mozilla::AutoSVGViewHandler; 55 friend class mozilla::AutoPreserveAspectRatioOverride; 56 friend class mozilla::dom::SVGView; 57 58 protected: 59 SVGSVGElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 60 FromParser aFromParser); 61 JSObject* WrapNode(JSContext* aCx, 62 JS::Handle<JSObject*> aGivenProto) override; 63 64 friend nsresult(::NS_NewSVGSVGElement( 65 nsIContent** aResult, 66 already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo, 67 mozilla::dom::FromParser aFromParser)); 68 69 ~SVGSVGElement() = default; 70 71 public: 72 NS_IMPL_FROMNODE_WITH_TAG(SVGSVGElement, kNameSpaceID_SVG, svg) 73 74 // interfaces: 75 NS_INLINE_DECL_STATIC_IID(MOZILLA_SVGSVGELEMENT_IID) 76 NS_DECL_ISUPPORTS_INHERITED 77 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SVGSVGElement, SVGSVGElementBase) 78 79 /* 80 * Send appropriate events and updates if our root translate 81 * has changed. 82 */ 83 MOZ_CAN_RUN_SCRIPT 84 void DidChangeTranslate(); 85 86 // nsIContent interface 87 void GetEventTargetParent(EventChainPreVisitor& aVisitor) override; 88 bool IsEventAttributeNameInternal(nsAtom* aName) override; 89 90 // nsINode methods: 91 nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override; 92 93 // WebIDL 94 already_AddRefed<DOMSVGAnimatedLength> X(); 95 already_AddRefed<DOMSVGAnimatedLength> Y(); 96 already_AddRefed<DOMSVGAnimatedLength> Width(); 97 already_AddRefed<DOMSVGAnimatedLength> Height(); 98 bool UseCurrentView() const; 99 float CurrentScale() const; 100 void SetCurrentScale(float aCurrentScale); 101 already_AddRefed<DOMSVGPoint> CurrentTranslate(); 102 uint32_t SuspendRedraw(uint32_t max_wait_milliseconds); 103 void UnsuspendRedraw(uint32_t suspend_handle_id); 104 void UnsuspendRedrawAll(); 105 void ForceRedraw(); 106 void PauseAnimations(); 107 void PauseAnimationsAt(float seconds); 108 void UnpauseAnimations(); 109 bool AnimationsPaused(); 110 float GetCurrentTimeAsFloat(); 111 void SetCurrentTime(float seconds); 112 MOZ_CAN_RUN_SCRIPT void DeselectAll(); 113 already_AddRefed<DOMSVGNumber> CreateSVGNumber(); 114 already_AddRefed<DOMSVGLength> CreateSVGLength(); 115 already_AddRefed<DOMSVGAngle> CreateSVGAngle(); 116 already_AddRefed<DOMSVGPoint> CreateSVGPoint(); 117 already_AddRefed<SVGMatrix> CreateSVGMatrix(); 118 already_AddRefed<SVGRect> CreateSVGRect(); 119 already_AddRefed<DOMSVGTransform> CreateSVGTransform(); 120 already_AddRefed<DOMSVGTransform> CreateSVGTransformFromMatrix( 121 const DOMMatrix2DInit& matrix, ErrorResult& rv); 122 using nsINode::GetElementById; // This does what we want 123 uint16_t ZoomAndPan() const; 124 void SetZoomAndPan(uint16_t aZoomAndPan, ErrorResult& rv); 125 126 // SVGElement overrides 127 128 nsresult BindToTree(BindContext&, nsINode& aParent) override; 129 void UnbindFromTree(UnbindContext&) override; 130 SVGAnimatedTransformList* GetAnimatedTransformList( 131 uint32_t aFlags = 0) override; 132 133 // SVGSVGElement methods: 134 135 // Returns true IFF our attributes are currently overridden by a <view> 136 // element and that element's ID matches the passed-in string. 137 bool IsOverriddenBy(const nsAString& aViewID) const { 138 return mCurrentViewID && mCurrentViewID->Equals(aViewID); 139 } 140 141 SMILTimeContainer* GetTimedDocumentRoot(); 142 143 // public helpers: 144 145 const SVGPoint& GetCurrentTranslate() const { return mCurrentTranslate; } 146 bool IsScaledOrTranslated() const { 147 return mCurrentTranslate != SVGPoint() || mCurrentScale != 1.0f; 148 } 149 150 LengthPercentage GetIntrinsicWidth(); 151 LengthPercentage GetIntrinsicHeight(); 152 153 // This services any pending notifications for the transform on on this root 154 // <svg> node needing to be recalculated. (Only applicable in 155 // SVG-as-an-image documents.) 156 virtual void FlushImageTransformInvalidation(); 157 158 private: 159 // SVGViewportElement methods: 160 161 virtual SVGViewElement* GetCurrentViewElement() const; 162 SVGPreserveAspectRatio GetPreserveAspectRatioWithOverride() const override; 163 164 // implementation helpers: 165 166 /* 167 * While binding to the tree we need to determine if we will be the outermost 168 * <svg> element _before_ the children are bound (as they want to know what 169 * timed document root to register with) and therefore _before_ our parent is 170 * set (both actions are performed by Element::BindToTree) so we 171 * can't use GetOwnerSVGElement() as it relies on GetParent(). This code is 172 * basically a simplified version of GetOwnerSVGElement that uses the parent 173 * parameters passed in instead. 174 * 175 * FIXME(bug 1596690): GetOwnerSVGElement() uses the flattened tree parent 176 * rather than the DOM tree parent nowadays. 177 */ 178 bool WillBeOutermostSVG(nsINode& aParent) const; 179 180 LengthPercentage GetIntrinsicWidthOrHeight(int aAttr); 181 182 // invalidate viewbox -> viewport xform & inform frames 183 void InvalidateTransformNotifyFrame(); 184 void DidChangeSVGView(); 185 186 // Methods for <image> elements to override my "PreserveAspectRatio" value. 187 // These are private so that only our friends 188 // (AutoPreserveAspectRatioOverride in particular) have access. 189 void SetImageOverridePreserveAspectRatio(const SVGPreserveAspectRatio& aPAR); 190 void ClearImageOverridePreserveAspectRatio(); 191 192 // Set/Clear properties to hold old version of preserveAspectRatio 193 // when it's being overridden by an <image> element that we are inside of. 194 bool SetPreserveAspectRatioProperty(const SVGPreserveAspectRatio& aPAR); 195 const SVGPreserveAspectRatio* GetPreserveAspectRatioProperty() const; 196 bool ClearPreserveAspectRatioProperty(); 197 198 const SVGAnimatedViewBox& GetViewBoxInternal() const override; 199 200 EnumAttributesInfo GetEnumInfo() override; 201 202 enum { ZOOMANDPAN }; 203 SVGAnimatedEnumeration mEnumAttributes[1]; 204 static SVGEnumMapping sZoomAndPanMap[]; 205 static EnumInfo sEnumInfo[1]; 206 207 // The time container for animations within this SVG document fragment. Set 208 // for all outermost <svg> elements (not nested <svg> elements). 209 UniquePtr<SMILTimeContainer> mTimedDocumentRoot; 210 211 SVGPoint mCurrentTranslate; 212 float mCurrentScale; 213 214 // For outermost <svg> elements created from parsing, animation is started by 215 // the onload event in accordance with the SVG spec, but for <svg> elements 216 // created by script or promoted from inner <svg> to outermost <svg> we need 217 // to manually kick off animation when they are bound to the tree. 218 bool mStartAnimationOnBindToTree; 219 220 bool mImageNeedsTransformInvalidation; 221 222 // mCurrentViewID and mSVGView are mutually exclusive; we can have 223 // at most one non-null. 224 UniquePtr<nsString> mCurrentViewID; 225 UniquePtr<SVGView> mSVGView; 226 }; 227 228 } // namespace dom 229 230 class MOZ_RAII AutoSVGTimeSetRestore { 231 public: 232 AutoSVGTimeSetRestore(dom::SVGSVGElement* aRootElem, float aFrameTime) 233 : mRootElem(aRootElem), 234 mOriginalTime(mRootElem->GetCurrentTimeAsFloat()) { 235 mRootElem->SetCurrentTime( 236 aFrameTime); // Does nothing if there's no change. 237 } 238 239 ~AutoSVGTimeSetRestore() { mRootElem->SetCurrentTime(mOriginalTime); } 240 241 private: 242 const RefPtr<dom::SVGSVGElement> mRootElem; 243 const float mOriginalTime; 244 }; 245 246 class MOZ_RAII AutoPreserveAspectRatioOverride { 247 public: 248 AutoPreserveAspectRatioOverride(const SVGImageContext& aSVGContext, 249 dom::SVGSVGElement* aRootElem) 250 : mRootElem(aRootElem), mDidOverride(false) { 251 MOZ_ASSERT(mRootElem, "No SVG/Symbol node to manage?"); 252 253 if (aSVGContext.GetPreserveAspectRatio().isSome()) { 254 // Override preserveAspectRatio in our helper document. 255 // XXXdholbert We should technically be overriding the helper doc's clip 256 // and overflow properties here, too. See bug 272288 comment 36. 257 mRootElem->SetImageOverridePreserveAspectRatio( 258 *aSVGContext.GetPreserveAspectRatio()); 259 mDidOverride = true; 260 } 261 } 262 263 ~AutoPreserveAspectRatioOverride() { 264 if (mDidOverride) { 265 mRootElem->ClearImageOverridePreserveAspectRatio(); 266 } 267 } 268 269 private: 270 const RefPtr<dom::SVGSVGElement> mRootElem; 271 bool mDidOverride; 272 }; 273 274 } // namespace mozilla 275 276 #endif // DOM_SVG_SVGSVGELEMENT_H_