Bug 1800263 - Part 1: Tidup, make MarkingState a private enum inside GCMarker r=sfink
[gecko.git] / layout / svg / SVGContextPaint.h
blobd42066d682ef5033e350c564cf70ac55188c605e
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/. */
7 #ifndef LAYOUT_SVG_SVGCONTEXTPAINT_H_
8 #define LAYOUT_SVG_SVGCONTEXTPAINT_H_
10 #include "DrawMode.h"
11 #include "gfxMatrix.h"
12 #include "gfxPattern.h"
13 #include "gfxTypes.h"
14 #include "gfxUtils.h"
15 #include "mozilla/AlreadyAddRefed.h"
16 #include "mozilla/Assertions.h"
17 #include "mozilla/gfx/2D.h"
18 #include "nsColor.h"
19 #include "nsStyleStruct.h"
20 #include "nsTArray.h"
21 #include "ImgDrawResult.h"
22 #include "nsRefPtrHashtable.h"
24 class gfxContext;
26 namespace mozilla {
27 class SVGPaintServerFrame;
29 namespace dom {
30 class SVGDocument;
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:
38 * https://www.w3.org/TR/SVG2/painting.html#context-paint
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.
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.
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;
60 SVGContextPaint() : mDashOffset(0.0f), mStrokeWidth(0.0f) {}
62 public:
63 MOZ_DECLARE_REFCOUNTED_TYPENAME(SVGContextPaint)
65 virtual ~SVGContextPaint() = default;
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;
76 already_AddRefed<gfxPattern> GetFillPattern(const DrawTarget* aDrawTarget,
77 const gfxMatrix& aCTM,
78 imgDrawingParams& aImgParams) {
79 return GetFillPattern(aDrawTarget, GetFillOpacity(), aCTM, aImgParams);
82 already_AddRefed<gfxPattern> GetStrokePattern(const DrawTarget* aDrawTarget,
83 const gfxMatrix& aCTM,
84 imgDrawingParams& aImgParams) {
85 return GetStrokePattern(aDrawTarget, GetStrokeOpacity(), aCTM, aImgParams);
88 static SVGContextPaint* GetContextPaint(nsIContent* aContent);
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);
94 const FallibleTArray<Float>& GetStrokeDashArray() const { return mDashes; }
96 Float GetStrokeDashOffset() const { return mDashOffset; }
98 Float GetStrokeWidth() const { return mStrokeWidth; }
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;
109 * Returns true if image context paint is allowed to be used in an image that
110 * has the given URI, else returns false.
112 static bool IsAllowedForImageFromURI(nsIURI* aURI);
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;
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.
128 class MOZ_RAII AutoSetRestoreSVGContextPaint {
129 public:
130 AutoSetRestoreSVGContextPaint(const SVGContextPaint& aContextPaint,
131 dom::SVGDocument& aSVGDocument);
132 ~AutoSetRestoreSVGContextPaint();
134 private:
135 dom::SVGDocument& mSVGDocument;
136 // The context paint that needs to be restored by our dtor after it removes
137 // aContextPaint:
138 const SVGContextPaint* mOuterContextPaint;
142 * This class should be flattened into SVGContextPaint once we get rid of the
143 * other sub-class (SimpleTextContextPaint).
145 struct SVGContextPaintImpl : public SVGContextPaint {
146 protected:
147 using DrawTarget = mozilla::gfx::DrawTarget;
149 public:
150 DrawMode Init(const DrawTarget* aDrawTarget, const gfxMatrix& aContextMatrix,
151 nsIFrame* aFrame, SVGContextPaint* aOuterContextPaint,
152 imgDrawingParams& aImgParams);
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;
161 void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
162 float GetFillOpacity() const override { return mFillOpacity; }
164 void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
165 float GetStrokeOpacity() const override { return mStrokeOpacity; }
167 struct Paint {
168 enum class Tag : uint8_t {
169 None,
170 Color,
171 PaintServer,
172 ContextFill,
173 ContextStroke,
176 Paint() : mPaintDefinition{}, mPaintType(Tag::None) {}
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;
186 void SetColor(const nscolor& aColor) {
187 mPaintType = Tag::Color;
188 mPaintDefinition.mColor = aColor;
191 void SetContextPaint(SVGContextPaint* aContextPaint, Tag aTag) {
192 MOZ_ASSERT(aTag == Tag::ContextFill || aTag == Tag::ContextStroke);
193 mPaintType = aTag;
194 mPaintDefinition.mContextPaint = aContextPaint;
197 union {
198 SVGPaintServerFrame* mPaintServerFrame;
199 SVGContextPaint* mContextPaint;
200 nscolor mColor;
201 } mPaintDefinition;
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;
209 // Device-space-to-pattern-space
210 gfxMatrix mPatternMatrix;
211 nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache;
213 already_AddRefed<gfxPattern> GetPattern(
214 const DrawTarget* aDrawTarget, float aOpacity,
215 StyleSVGPaint nsStyleSVG::*aFillOrStroke, const gfxMatrix& aCTM,
216 imgDrawingParams& aImgParams);
219 Paint mFillPaint;
220 Paint mStrokePaint;
222 float mFillOpacity;
223 float mStrokeOpacity;
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.
232 class SVGEmbeddingContextPaint : public SVGContextPaint {
233 using DeviceColor = gfx::DeviceColor;
235 public:
236 SVGEmbeddingContextPaint() : mFillOpacity(1.0f), mStrokeOpacity(1.0f) {}
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;
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));
254 const Maybe<DeviceColor>& GetStroke() const { return mStroke; }
257 * Returns a pattern of type PatternType::COLOR, or else nullptr.
259 already_AddRefed<gfxPattern> GetFillPattern(
260 const DrawTarget* aDrawTarget, float aFillOpacity, const gfxMatrix& aCTM,
261 imgDrawingParams& aImgParams) override;
264 * Returns a pattern of type PatternType::COLOR, or else nullptr.
266 already_AddRefed<gfxPattern> GetStrokePattern(
267 const DrawTarget* aDrawTarget, float aStrokeOpacity,
268 const gfxMatrix& aCTM, imgDrawingParams& aImgParams) override;
270 void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; }
271 float GetFillOpacity() const override { return mFillOpacity; };
273 void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; }
274 float GetStrokeOpacity() const override { return mStrokeOpacity; };
276 uint32_t Hash() const override;
278 private:
279 Maybe<DeviceColor> mFill;
280 Maybe<DeviceColor> mStroke;
281 float mFillOpacity;
282 float mStrokeOpacity;
285 } // namespace mozilla
287 #endif // LAYOUT_SVG_SVGCONTEXTPAINT_H_