tor-browser

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

SVGContextPaint.h (10232B)


      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 LAYOUT_SVG_SVGCONTEXTPAINT_H_
      8 #define LAYOUT_SVG_SVGCONTEXTPAINT_H_
      9 
     10 #include "DrawMode.h"
     11 #include "ImgDrawResult.h"
     12 #include "gfxMatrix.h"
     13 #include "gfxPattern.h"
     14 #include "gfxTypes.h"
     15 #include "gfxUtils.h"
     16 #include "mozilla/AlreadyAddRefed.h"
     17 #include "mozilla/Assertions.h"
     18 #include "mozilla/gfx/2D.h"
     19 #include "nsColor.h"
     20 #include "nsRefPtrHashtable.h"
     21 #include "nsStyleStruct.h"
     22 #include "nsTArray.h"
     23 
     24 class gfxContext;
     25 
     26 namespace mozilla {
     27 class SVGPaintServerFrame;
     28 
     29 namespace dom {
     30 class Document;
     31 }
     32 
     33 /**
     34 * This class is used to pass information about a context element through to
     35 * SVG painting code in order to resolve the 'context-fill' and related
     36 * keywords. See:
     37 *
     38 *   https://www.w3.org/TR/SVG2/painting.html#context-paint
     39 *
     40 * This feature allows the color in an SVG-in-OpenType glyph to come from the
     41 * computed style for the text that is being drawn, for example, or for color
     42 * in an SVG embedded by an <img> element to come from the embedding <img>
     43 * element.
     44 *
     45 * This class is reference counted so that it can be shared among many similar
     46 * SVGImageContext objects. (SVGImageContext objects are frequently
     47 * copy-constructed with small modifications, and we'd like for those copies to
     48 * be able to share their context-paint data cheaply.)  However, in most cases,
     49 * SVGContextPaint instances are stored in a local RefPtr and only last for the
     50 * duration of a function call.
     51 * XXX Note: SVGImageContext doesn't actually have a SVGContextPaint member yet,
     52 * but it will in a later patch in the patch series that added this comment.
     53 */
     54 class SVGContextPaint : public RefCounted<SVGContextPaint> {
     55 protected:
     56  using DrawTarget = mozilla::gfx::DrawTarget;
     57  using Float = mozilla::gfx::Float;
     58  using imgDrawingParams = mozilla::image::imgDrawingParams;
     59 
     60  SVGContextPaint() : mDashOffset(0.0f), mStrokeWidth(0.0f) {}
     61 
     62 public:
     63  MOZ_DECLARE_REFCOUNTED_TYPENAME(SVGContextPaint)
     64 
     65  virtual ~SVGContextPaint() = default;
     66 
     67  virtual already_AddRefed<gfxPattern> GetFillPattern(
     68      const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
     69      imgDrawingParams& aImgParams) = 0;
     70  virtual already_AddRefed<gfxPattern> GetStrokePattern(
     71      const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
     72      imgDrawingParams& aImgParams) = 0;
     73  virtual float GetFillOpacity() const = 0;
     74  virtual float GetStrokeOpacity() const = 0;
     75 
     76  already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
     77                                              const gfxMatrix& aCTM,
     78                                              imgDrawingParams& aImgParams) {
     79    return GetFillPattern(aDrawTarget, GetFillOpacity(), aCTM, aImgParams);
     80  }
     81 
     82  already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
     83                                                const gfxMatrix& aCTM,
     84                                                imgDrawingParams& aImgParams) {
     85    return GetStrokePattern(aDrawTarget, GetStrokeOpacity(), aCTM, aImgParams);
     86  }
     87 
     88  static SVGContextPaint* GetContextPaint(nsIContent* aContent);
     89 
     90  // XXX This gets the geometry params from the gfxContext.  We should get that
     91  // information from the actual paint context!
     92  void InitStrokeGeometry(gfxContext* aContext, float devUnitsPerSVGUnit);
     93 
     94  const FallibleTArray<Float>& GetStrokeDashArray() const { return mDashes; }
     95 
     96  Float GetStrokeDashOffset() const { return mDashOffset; }
     97 
     98  Float GetStrokeWidth() const { return mStrokeWidth; }
     99 
    100  virtual uint32_t Hash() const {
    101    MOZ_ASSERT_UNREACHABLE(
    102        "Only VectorImage needs to hash, and that should "
    103        "only be operating on our SVGEmbeddingContextPaint "
    104        "subclass");
    105    return 0;
    106  }
    107 
    108  /**
    109   * Returns true if image context paint is allowed to be used in an image that
    110   * has the given URI, else returns false.
    111   */
    112  static bool IsAllowedForImageFromURI(nsIURI* aURI);
    113 
    114 private:
    115  // Member-vars are initialized in InitStrokeGeometry.
    116  FallibleTArray<Float> mDashes;
    117  MOZ_INIT_OUTSIDE_CTOR Float mDashOffset;
    118  MOZ_INIT_OUTSIDE_CTOR Float mStrokeWidth;
    119 };
    120 
    121 /**
    122 * RAII class used to temporarily set and remove an SVGContextPaint while a
    123 * piece of SVG is being painted.  The context paint is set on the SVG's owner
    124 * document, as expected by SVGContextPaint::GetContextPaint.  Any pre-existing
    125 * context paint is restored after this class removes the context paint that it
    126 * set.
    127 */
    128 class MOZ_RAII AutoSetRestoreSVGContextPaint {
    129 public:
    130  AutoSetRestoreSVGContextPaint(const SVGContextPaint* aContextPaint,
    131                                dom::Document* aDocument);
    132  ~AutoSetRestoreSVGContextPaint();
    133 
    134 private:
    135  dom::Document* mDocument;
    136  // The context paint that needs to be restored by our dtor after it removes
    137  // aContextPaint:
    138  const SVGContextPaint* mOuterContextPaint;
    139 };
    140 
    141 /**
    142 * This class should be flattened into SVGContextPaint once we get rid of the
    143 * other sub-class (SimpleTextContextPaint).
    144 */
    145 struct SVGContextPaintImpl : public SVGContextPaint {
    146 protected:
    147  using DrawTarget = mozilla::gfx::DrawTarget;
    148 
    149 public:
    150  DrawMode Init(const DrawTarget* aDrawTarget, const gfxMatrix& aContextMatrix,
    151                nsIFrame* aFrame, SVGContextPaint* aOuterContextPaint,
    152                imgDrawingParams& aImgParams);
    153 
    154  already_AddRefed<gfxPattern> GetFillPattern(
    155      const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
    156      imgDrawingParams& aImgParams) override;
    157  already_AddRefed<gfxPattern> GetStrokePattern(
    158      const DrawTarget* aDrawTarget, float aOpacity, const gfxMatrix& aCTM,
    159      imgDrawingParams& aImgParams) override;
    160 
    161  void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
    162  float GetFillOpacity() const override { return mFillOpacity; }
    163 
    164  void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
    165  float GetStrokeOpacity() const override { return mStrokeOpacity; }
    166 
    167  struct Paint {
    168    enum class Tag : uint8_t {
    169      None,
    170      Color,
    171      PaintServer,
    172      ContextFill,
    173      ContextStroke,
    174    };
    175 
    176    Paint() : mPaintDefinition{}, mPaintType(Tag::None) {}
    177 
    178    void SetPaintServer(nsIFrame* aFrame, const gfxMatrix& aContextMatrix,
    179                        SVGPaintServerFrame* aPaintServerFrame) {
    180      mPaintType = Tag::PaintServer;
    181      mPaintDefinition.mPaintServerFrame = aPaintServerFrame;
    182      mFrame = aFrame;
    183      mContextMatrix = aContextMatrix;
    184    }
    185 
    186    void SetColor(const nscolor& aColor) {
    187      mPaintType = Tag::Color;
    188      mPaintDefinition.mColor = aColor;
    189    }
    190 
    191    void SetContextPaint(SVGContextPaint* aContextPaint, Tag aTag) {
    192      MOZ_ASSERT(aTag == Tag::ContextFill || aTag == Tag::ContextStroke);
    193      mPaintType = aTag;
    194      mPaintDefinition.mContextPaint = aContextPaint;
    195    }
    196 
    197    union {
    198      SVGPaintServerFrame* mPaintServerFrame;
    199      SVGContextPaint* mContextPaint;
    200      nscolor mColor;
    201    } mPaintDefinition;
    202 
    203    // Initialized (if needed) in SetPaintServer():
    204    MOZ_INIT_OUTSIDE_CTOR nsIFrame* mFrame;
    205    // CTM defining the user space for the pattern we will use.
    206    gfxMatrix mContextMatrix;
    207    Tag mPaintType;
    208 
    209    // Device-space-to-pattern-space
    210    gfxMatrix mPatternMatrix;
    211    nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
    212 
    213    already_AddRefed<gfxPattern> GetPattern(
    214        const DrawTarget* aDrawTarget, float aOpacity,
    215        StyleSVGPaint nsStyleSVG::* aFillOrStroke, const gfxMatrix& aCTM,
    216        imgDrawingParams& aImgParams);
    217  };
    218 
    219  Paint mFillPaint;
    220  Paint mStrokePaint;
    221 
    222  float mFillOpacity;
    223  float mStrokeOpacity;
    224 };
    225 
    226 /**
    227 * This class is used to pass context paint to an SVG image when an element
    228 * references that image (e.g. via HTML <img> or SVG <image>, or by referencing
    229 * it from a CSS property such as 'background-image').  In this case we only
    230 * support context colors and not paint servers.
    231 */
    232 class SVGEmbeddingContextPaint : public SVGContextPaint {
    233  using DeviceColor = gfx::DeviceColor;
    234 
    235 public:
    236  SVGEmbeddingContextPaint() : mFillOpacity(1.0f), mStrokeOpacity(1.0f) {}
    237 
    238  bool operator==(const SVGEmbeddingContextPaint& aOther) const {
    239    MOZ_ASSERT(GetStrokeWidth() == aOther.GetStrokeWidth() &&
    240                   GetStrokeDashOffset() == aOther.GetStrokeDashOffset() &&
    241                   GetStrokeDashArray() == aOther.GetStrokeDashArray(),
    242               "We don't currently include these in the context information "
    243               "from an embedding element");
    244    return mFill == aOther.mFill && mStroke == aOther.mStroke &&
    245           mFillOpacity == aOther.mFillOpacity &&
    246           mStrokeOpacity == aOther.mStrokeOpacity;
    247  }
    248 
    249  void SetFill(nscolor aFill) { mFill.emplace(gfx::ToDeviceColor(aFill)); }
    250  const Maybe<DeviceColor>& GetFill() const { return mFill; }
    251  void SetStroke(nscolor aStroke) {
    252    mStroke.emplace(gfx::ToDeviceColor(aStroke));
    253  }
    254  const Maybe<DeviceColor>& GetStroke() const { return mStroke; }
    255 
    256  /**
    257   * Returns a pattern of type PatternType::COLOR, or else nullptr.
    258   */
    259  already_AddRefed<gfxPattern> GetFillPattern(
    260      const DrawTarget* aDrawTarget, float aFillOpacity, const gfxMatrix& aCTM,
    261      imgDrawingParams& aImgParams) override;
    262 
    263  /**
    264   * Returns a pattern of type PatternType::COLOR, or else nullptr.
    265   */
    266  already_AddRefed<gfxPattern> GetStrokePattern(
    267      const DrawTarget* aDrawTarget, float aStrokeOpacity,
    268      const gfxMatrix& aCTM, imgDrawingParams& aImgParams) override;
    269 
    270  void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
    271  float GetFillOpacity() const override { return mFillOpacity; };
    272 
    273  void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
    274  float GetStrokeOpacity() const override { return mStrokeOpacity; };
    275 
    276  uint32_t Hash() const override;
    277 
    278 private:
    279  Maybe<DeviceColor> mFill;
    280  Maybe<DeviceColor> mStroke;
    281  float mFillOpacity;
    282  float mStrokeOpacity;
    283 };
    284 
    285 }  // namespace mozilla
    286 
    287 #endif  // LAYOUT_SVG_SVGCONTEXTPAINT_H_