tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SVGAnimatedLength.h (12130B)


      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_SVGANIMATEDLENGTH_H_
      8 #define DOM_SVG_SVGANIMATEDLENGTH_H_
      9 
     10 #include "mozilla/SMILAttr.h"
     11 #include "mozilla/SVGContentUtils.h"
     12 #include "mozilla/UniquePtr.h"
     13 #include "mozilla/dom/SVGElement.h"
     14 #include "mozilla/dom/SVGLengthBinding.h"
     15 #include "nsError.h"
     16 
     17 struct GeckoFontMetrics;
     18 class nsPresContext;
     19 class nsFontMetrics;
     20 class mozAutoDocUpdate;
     21 class nsIFrame;
     22 
     23 namespace mozilla {
     24 
     25 class AutoChangeLengthNotifier;
     26 class SMILValue;
     27 
     28 namespace dom {
     29 class DOMSVGAnimatedLength;
     30 class DOMSVGLength;
     31 class SVGAnimationElement;
     32 class SVGViewportElement;
     33 
     34 class UserSpaceMetrics {
     35 public:
     36  enum class Type : uint32_t { This, Root };
     37  static GeckoFontMetrics DefaultFontMetrics();
     38  static GeckoFontMetrics GetFontMetrics(const Element* aElement);
     39  static WritingMode GetWritingMode(const Element* aElement);
     40  static float GetZoom(const Element* aElement);
     41  static CSSSize GetCSSViewportSizeFromContext(const nsPresContext* aContext);
     42 
     43  virtual ~UserSpaceMetrics() = default;
     44 
     45  virtual float GetEmLength(Type aType) const = 0;
     46  virtual float GetZoom() const = 0;
     47  virtual float GetRootZoom() const = 0;
     48  float GetExLength(Type aType) const;
     49  float GetChSize(Type aType) const;
     50  float GetIcWidth(Type aType) const;
     51  float GetCapHeight(Type aType) const;
     52  virtual float GetAxisLength(uint8_t aCtxType) const = 0;
     53  virtual CSSSize GetCSSViewportSize() const = 0;
     54  virtual float GetLineHeight(Type aType) const = 0;
     55 
     56 protected:
     57  virtual GeckoFontMetrics GetFontMetricsForType(Type aType) const = 0;
     58  virtual WritingMode GetWritingModeForType(Type aType) const = 0;
     59 };
     60 
     61 class UserSpaceMetricsWithSize : public UserSpaceMetrics {
     62 public:
     63  virtual gfx::Size GetSize() const = 0;
     64  float GetAxisLength(uint8_t aCtxType) const override;
     65 };
     66 
     67 class SVGElementMetrics final : public UserSpaceMetrics {
     68 public:
     69  explicit SVGElementMetrics(const SVGElement* aSVGElement,
     70                             const SVGViewportElement* aCtx = nullptr);
     71 
     72  float GetEmLength(Type aType) const override {
     73    return SVGContentUtils::GetFontSize(GetElementForType(aType));
     74  }
     75  float GetAxisLength(uint8_t aCtxType) const override;
     76  CSSSize GetCSSViewportSize() const override;
     77  float GetLineHeight(Type aType) const override;
     78  float GetZoom() const override;
     79  float GetRootZoom() const override;
     80 
     81 private:
     82  bool EnsureCtx() const;
     83  const Element* GetElementForType(Type aType) const;
     84  GeckoFontMetrics GetFontMetricsForType(Type aType) const override;
     85  WritingMode GetWritingModeForType(Type aType) const override;
     86 
     87  const SVGElement* mSVGElement;
     88  mutable const SVGViewportElement* mCtx;
     89 };
     90 
     91 class NonSVGFrameUserSpaceMetrics final : public UserSpaceMetricsWithSize {
     92 public:
     93  explicit NonSVGFrameUserSpaceMetrics(nsIFrame* aFrame);
     94 
     95  float GetEmLength(Type aType) const override;
     96  gfx::Size GetSize() const override;
     97  CSSSize GetCSSViewportSize() const override;
     98  float GetLineHeight(Type aType) const override;
     99  float GetZoom() const override;
    100  float GetRootZoom() const override;
    101 
    102 private:
    103  GeckoFontMetrics GetFontMetricsForType(Type aType) const override;
    104  WritingMode GetWritingModeForType(Type aType) const override;
    105  nsIFrame* mFrame;
    106 };
    107 
    108 }  // namespace dom
    109 
    110 class SVGAnimatedLength {
    111  friend class AutoChangeLengthNotifier;
    112  friend class dom::DOMSVGAnimatedLength;
    113  friend class dom::DOMSVGLength;
    114  using DOMSVGLength = dom::DOMSVGLength;
    115  using SVGElement = dom::SVGElement;
    116  using SVGViewportElement = dom::SVGViewportElement;
    117  using UserSpaceMetrics = dom::UserSpaceMetrics;
    118 
    119 public:
    120  void Init(uint8_t aCtxType = SVGContentUtils::XY, uint8_t aAttrEnum = 0xff,
    121            float aValue = 0,
    122            uint8_t aUnitType = dom::SVGLength_Binding::SVG_LENGTHTYPE_NUMBER) {
    123    mAnimVal = mBaseVal = aValue;
    124    mBaseUnitType = mAnimUnitType = aUnitType;
    125    mAttrEnum = aAttrEnum;
    126    mCtxType = aCtxType;
    127    mIsAnimated = false;
    128    mIsBaseSet = false;
    129  }
    130 
    131  SVGAnimatedLength& operator=(const SVGAnimatedLength& aLength) {
    132    mBaseVal = aLength.mBaseVal;
    133    mAnimVal = aLength.mAnimVal;
    134    mBaseUnitType = aLength.mBaseUnitType;
    135    mAnimUnitType = aLength.mAnimUnitType;
    136    mIsAnimated = aLength.mIsAnimated;
    137    mIsBaseSet = aLength.mIsBaseSet;
    138    return *this;
    139  }
    140 
    141  nsresult SetBaseValueString(const nsAString& aValue, SVGElement* aSVGElement,
    142                              bool aDoSetAttr);
    143  void GetBaseValueString(nsAString& aValue) const;
    144  void GetAnimValueString(nsAString& aValue) const;
    145 
    146  float GetBaseValue(const SVGElement* aSVGElement) const {
    147    return mBaseVal * GetPixelsPerUnit(aSVGElement, mBaseUnitType);
    148  }
    149 
    150  float GetAnimValue(const SVGElement* aSVGElement) const {
    151    return mAnimVal * GetPixelsPerUnit(aSVGElement, mAnimUnitType);
    152  }
    153  float GetAnimValueWithZoom(const SVGElement* aSVGElement) const {
    154    return mAnimVal * GetPixelsPerUnitWithZoom(aSVGElement, mAnimUnitType);
    155  }
    156  float GetAnimValueWithZoom(nsIFrame* aFrame) const {
    157    return mAnimVal * GetPixelsPerUnitWithZoom(aFrame, mAnimUnitType);
    158  }
    159  float GetAnimValueWithZoom(const SVGViewportElement* aCtx) const {
    160    return mAnimVal * GetPixelsPerUnitWithZoom(aCtx, mAnimUnitType);
    161  }
    162  float GetAnimValueWithZoom(const UserSpaceMetrics& aMetrics) const {
    163    return mAnimVal * GetPixelsPerUnitWithZoom(aMetrics, mAnimUnitType);
    164  }
    165 
    166  uint8_t GetCtxType() const { return mCtxType; }
    167  uint8_t GetBaseUnitType() const { return mBaseUnitType; }
    168  uint8_t GetAnimUnitType() const { return mAnimUnitType; }
    169  bool IsPercentage() const {
    170    return mAnimUnitType == dom::SVGLength_Binding::SVG_LENGTHTYPE_PERCENTAGE;
    171  }
    172  float GetAnimValInSpecifiedUnits() const { return mAnimVal; }
    173  float GetBaseValInSpecifiedUnits() const { return mBaseVal; }
    174 
    175  bool HasBaseVal() const { return mIsBaseSet; }
    176  // Returns true if the animated value of this length has been explicitly
    177  // set (either by animation, or by taking on the base value which has been
    178  // explicitly set by markup or a DOM call), false otherwise.
    179  // If this returns false, the animated value is still valid, that is,
    180  // usable, and represents the default base value of the attribute.
    181  bool IsExplicitlySet() const { return mIsAnimated || mIsBaseSet; }
    182 
    183  bool IsAnimated() const { return mIsAnimated; }
    184 
    185  already_AddRefed<dom::DOMSVGAnimatedLength> ToDOMAnimatedLength(
    186      SVGElement* aSVGElement);
    187 
    188  UniquePtr<SMILAttr> ToSMILAttr(SVGElement* aSVGElement);
    189 
    190 private:
    191  float mAnimVal;
    192  float mBaseVal;
    193  uint8_t mBaseUnitType;
    194  uint8_t mAnimUnitType;
    195  uint8_t mAttrEnum : 6;  // element specified tracking for attribute
    196  uint8_t mCtxType : 2;   // X, Y or Unspecified
    197  bool mIsAnimated : 1;
    198  bool mIsBaseSet : 1;
    199 
    200  // These APIs returns the number of user-unit pixels per unit of the
    201  // given type, in a given context (frame/element/etc).
    202  float GetPixelsPerUnit(const SVGElement* aSVGElement,
    203                         uint8_t aUnitType) const;
    204  float GetPixelsPerUnitWithZoom(nsIFrame* aFrame, uint8_t aUnitType) const;
    205  float GetPixelsPerUnitWithZoom(const UserSpaceMetrics& aMetrics,
    206                                 uint8_t aUnitType) const;
    207  float GetPixelsPerUnitWithZoom(const SVGElement* aSVGElement,
    208                                 uint8_t aUnitType) const;
    209  float GetPixelsPerUnitWithZoom(const SVGViewportElement* aCtx,
    210                                 uint8_t aUnitType) const;
    211 
    212  // SetBaseValue and SetAnimValue set the value in user units. This may fail
    213  // if unit conversion fails e.g. conversion to ex or em units where the
    214  // font-size is 0.
    215  // SetBaseValueInSpecifiedUnits and SetAnimValueInSpecifiedUnits do not
    216  // perform unit conversion and are therefore infallible.
    217  nsresult SetBaseValue(float aValue, SVGElement* aSVGElement, bool aDoSetAttr);
    218  void SetBaseValueInSpecifiedUnits(float aValue, SVGElement* aSVGElement,
    219                                    bool aDoSetAttr);
    220  void SetAnimValue(float aValue, uint16_t aUnitType, SVGElement* aSVGElement);
    221  void SetAnimValueInSpecifiedUnits(float aValue, SVGElement* aSVGElement);
    222  void NewValueSpecifiedUnits(uint16_t aUnitType, float aValueInSpecifiedUnits,
    223                              SVGElement* aSVGElement);
    224  void ConvertToSpecifiedUnits(uint16_t aUnitType, SVGElement* aSVGElement,
    225                               ErrorResult& aRv);
    226  already_AddRefed<DOMSVGLength> ToDOMBaseVal(SVGElement* aSVGElement);
    227  already_AddRefed<DOMSVGLength> ToDOMAnimVal(SVGElement* aSVGElement);
    228 
    229 public:
    230  struct SMILLength : public SMILAttr {
    231   public:
    232    SMILLength(SVGAnimatedLength* aVal, SVGElement* aSVGElement)
    233        : mVal(aVal), mSVGElement(aSVGElement) {}
    234 
    235    // These will stay alive because a SMILAttr only lives as long
    236    // as the Compositing step, and DOM elements don't get a chance to
    237    // die during that.
    238    SVGAnimatedLength* mVal;
    239    SVGElement* mSVGElement;
    240 
    241    // SMILAttr methods
    242    nsresult ValueFromString(const nsAString& aStr,
    243                             const dom::SVGAnimationElement* aSrcElement,
    244                             SMILValue& aValue,
    245                             bool& aPreventCachingOfSandwich) const override;
    246    SMILValue GetBaseValue() const override;
    247    void ClearAnimValue() override;
    248    nsresult SetAnimValue(const SMILValue& aValue) override;
    249  };
    250 };
    251 
    252 /**
    253 * This class is used by the SMIL code when a length is to be stored in a
    254 * SMILValue instance. Since SMILValue objects may be cached, it is necessary
    255 * for us to hold a strong reference to our element so that it doesn't
    256 * disappear out from under us if, say, the element is removed from the DOM
    257 * tree.
    258 */
    259 class SVGLengthAndInfo {
    260 public:
    261  SVGLengthAndInfo() = default;
    262 
    263  explicit SVGLengthAndInfo(dom::SVGElement* aElement)
    264      : mElement(do_GetWeakReference(aElement->AsNode())) {}
    265 
    266  void SetInfo(dom::SVGElement* aElement) {
    267    mElement = do_GetWeakReference(aElement->AsNode());
    268  }
    269 
    270  dom::SVGElement* Element() const {
    271    nsCOMPtr<nsIContent> e = do_QueryReferent(mElement);
    272    return static_cast<dom::SVGElement*>(e.get());
    273  }
    274 
    275  bool operator==(const SVGLengthAndInfo& rhs) const {
    276    return mValue == rhs.mValue && mUnitType == rhs.mUnitType &&
    277           mCtxType == rhs.mCtxType;
    278  }
    279 
    280  float Value() const { return mValue; }
    281 
    282  uint8_t UnitType() const { return mUnitType; }
    283 
    284  void CopyFrom(const SVGLengthAndInfo& rhs) {
    285    mElement = rhs.mElement;
    286    mValue = rhs.mValue;
    287    mUnitType = rhs.mUnitType;
    288    mCtxType = rhs.mCtxType;
    289  }
    290 
    291  float ConvertUnits(const SVGLengthAndInfo& aTo) const;
    292 
    293  float ValueInPixels(const dom::UserSpaceMetrics& aMetrics) const;
    294 
    295  void Add(const SVGLengthAndInfo& aValueToAdd, uint32_t aCount);
    296 
    297  static void Interpolate(const SVGLengthAndInfo& aStart,
    298                          const SVGLengthAndInfo& aEnd, double aUnitDistance,
    299                          SVGLengthAndInfo& aResult);
    300 
    301  /**
    302   * Enables SVGAnimatedLength values to be copied into SVGLengthAndInfo
    303   * objects. Note that callers should also call SetInfo() when using this
    304   * method!
    305   */
    306  void CopyBaseFrom(const SVGAnimatedLength& rhs) {
    307    mValue = rhs.GetBaseValInSpecifiedUnits();
    308    mUnitType = rhs.GetBaseUnitType();
    309    mCtxType = rhs.GetCtxType();
    310  }
    311 
    312  void Set(float aValue, uint8_t aUnitType, uint8_t aCtxType) {
    313    mValue = aValue;
    314    mUnitType = aUnitType;
    315    mCtxType = aCtxType;
    316  }
    317 
    318 private:
    319  // We must keep a weak reference to our element because we may belong to a
    320  // cached baseVal SMILValue. See the comments starting at:
    321  // https://bugzilla.mozilla.org/show_bug.cgi?id=515116#c15
    322  // See also https://bugzilla.mozilla.org/show_bug.cgi?id=653497
    323  nsWeakPtr mElement;
    324  float mValue = 0.0f;
    325  uint8_t mUnitType = dom::SVGLength_Binding::SVG_LENGTHTYPE_NUMBER;
    326  uint8_t mCtxType = SVGContentUtils::XY;
    327 };
    328 
    329 }  // namespace mozilla
    330 
    331 #endif  // DOM_SVG_SVGANIMATEDLENGTH_H_