/work/obj-fuzz/dist/include/mozilla/SVGContextPaint.h
Line | Count | Source (jump to first uncovered line) |
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 MOZILLA_SVGCONTEXTPAINT_H_ |
8 | | #define MOZILLA_SVGCONTEXTPAINT_H_ |
9 | | |
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 | | |
23 | | class gfxContext; |
24 | | class nsIDocument; |
25 | | class nsSVGPaintServerFrame; |
26 | | |
27 | | namespace mozilla { |
28 | | |
29 | | namespace dom { |
30 | | class SVGDocument; |
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 | | { |
56 | | protected: |
57 | | typedef mozilla::gfx::DrawTarget DrawTarget; |
58 | | typedef mozilla::gfx::Float Float; |
59 | | typedef mozilla::image::imgDrawingParams imgDrawingParams; |
60 | | |
61 | | SVGContextPaint() |
62 | | : mDashOffset(0.0f) |
63 | | , mStrokeWidth(0.0f) |
64 | 0 | {} |
65 | | |
66 | | public: |
67 | | |
68 | | MOZ_DECLARE_REFCOUNTED_TYPENAME(SVGContextPaint) |
69 | | |
70 | 0 | virtual ~SVGContextPaint() {} |
71 | | |
72 | | virtual already_AddRefed<gfxPattern> |
73 | | GetFillPattern(const DrawTarget* aDrawTarget, |
74 | | float aOpacity, |
75 | | const gfxMatrix& aCTM, |
76 | | imgDrawingParams& aImgParams) = 0; |
77 | | virtual already_AddRefed<gfxPattern> |
78 | | GetStrokePattern(const DrawTarget* aDrawTarget, |
79 | | float aOpacity, |
80 | | const gfxMatrix& aCTM, |
81 | | imgDrawingParams& aImgParams) = 0; |
82 | | virtual float GetFillOpacity() const = 0; |
83 | | virtual float GetStrokeOpacity() const = 0; |
84 | | |
85 | | already_AddRefed<gfxPattern> |
86 | | GetFillPattern(const DrawTarget* aDrawTarget, const gfxMatrix& aCTM, |
87 | 0 | imgDrawingParams& aImgParams) { |
88 | 0 | return GetFillPattern(aDrawTarget, GetFillOpacity(), aCTM, aImgParams); |
89 | 0 | } |
90 | | |
91 | | already_AddRefed<gfxPattern> |
92 | | GetStrokePattern(const DrawTarget* aDrawTarget, const gfxMatrix& aCTM, |
93 | 0 | imgDrawingParams& aImgParams) { |
94 | 0 | return GetStrokePattern(aDrawTarget, GetStrokeOpacity(), aCTM, aImgParams); |
95 | 0 | } |
96 | | |
97 | | static SVGContextPaint* GetContextPaint(nsIContent* aContent); |
98 | | |
99 | | // XXX This gets the geometry params from the gfxContext. We should get that |
100 | | // information from the actual paint context! |
101 | | void InitStrokeGeometry(gfxContext *aContext, |
102 | | float devUnitsPerSVGUnit); |
103 | | |
104 | 0 | const FallibleTArray<Float>& GetStrokeDashArray() const { |
105 | 0 | return mDashes; |
106 | 0 | } |
107 | | |
108 | 0 | Float GetStrokeDashOffset() const { |
109 | 0 | return mDashOffset; |
110 | 0 | } |
111 | | |
112 | 0 | Float GetStrokeWidth() const { |
113 | 0 | return mStrokeWidth; |
114 | 0 | } |
115 | | |
116 | 0 | virtual uint32_t Hash() const { |
117 | 0 | MOZ_ASSERT_UNREACHABLE("Only VectorImage needs to hash, and that should " |
118 | 0 | "only be operating on our SVGEmbeddingContextPaint " |
119 | 0 | "subclass"); |
120 | 0 | return 0; |
121 | 0 | } |
122 | | |
123 | | /** |
124 | | * Returns true if image context paint is allowed to be used in an image that |
125 | | * has the given URI, else returns false. |
126 | | */ |
127 | | static bool IsAllowedForImageFromURI(nsIURI* aURI); |
128 | | |
129 | | private: |
130 | | // Member-vars are initialized in InitStrokeGeometry. |
131 | | FallibleTArray<Float> mDashes; |
132 | | MOZ_INIT_OUTSIDE_CTOR Float mDashOffset; |
133 | | MOZ_INIT_OUTSIDE_CTOR Float mStrokeWidth; |
134 | | }; |
135 | | |
136 | | /** |
137 | | * RAII class used to temporarily set and remove an SVGContextPaint while a |
138 | | * piece of SVG is being painted. The context paint is set on the SVG's owner |
139 | | * document, as expected by SVGContextPaint::GetContextPaint. Any pre-existing |
140 | | * context paint is restored after this class removes the context paint that it |
141 | | * set. |
142 | | */ |
143 | | class MOZ_RAII AutoSetRestoreSVGContextPaint |
144 | | { |
145 | | public: |
146 | | AutoSetRestoreSVGContextPaint(const SVGContextPaint& aContextPaint, |
147 | | dom::SVGDocument& aSVGDocument); |
148 | | ~AutoSetRestoreSVGContextPaint(); |
149 | | private: |
150 | | dom::SVGDocument& mSVGDocument; |
151 | | // The context paint that needs to be restored by our dtor after it removes |
152 | | // aContextPaint: |
153 | | const SVGContextPaint* mOuterContextPaint; |
154 | | }; |
155 | | |
156 | | |
157 | | /** |
158 | | * This class should be flattened into SVGContextPaint once we get rid of the |
159 | | * other sub-class (SimpleTextContextPaint). |
160 | | */ |
161 | | struct SVGContextPaintImpl : public SVGContextPaint |
162 | | { |
163 | | protected: |
164 | | typedef mozilla::gfx::DrawTarget DrawTarget; |
165 | | |
166 | | public: |
167 | | |
168 | | DrawMode |
169 | | Init(const DrawTarget* aDrawTarget, |
170 | | const gfxMatrix& aContextMatrix, |
171 | | nsIFrame* aFrame, |
172 | | SVGContextPaint* aOuterContextPaint, |
173 | | imgDrawingParams& aImgParams); |
174 | | |
175 | | already_AddRefed<gfxPattern> |
176 | | GetFillPattern(const DrawTarget* aDrawTarget, |
177 | | float aOpacity, |
178 | | const gfxMatrix& aCTM, |
179 | | imgDrawingParams& aImgParams) override; |
180 | | already_AddRefed<gfxPattern> |
181 | | GetStrokePattern(const DrawTarget* aDrawTarget, |
182 | | float aOpacity, |
183 | | const gfxMatrix& aCTM, |
184 | | imgDrawingParams& aImgParams) override; |
185 | | |
186 | 0 | void SetFillOpacity(float aOpacity) { mFillOpacity = aOpacity; } |
187 | 0 | float GetFillOpacity() const override { return mFillOpacity; } |
188 | | |
189 | 0 | void SetStrokeOpacity(float aOpacity) { mStrokeOpacity = aOpacity; } |
190 | 0 | float GetStrokeOpacity() const override { return mStrokeOpacity; } |
191 | | |
192 | | struct Paint { |
193 | | Paint() |
194 | | : mPaintDefinition{} |
195 | | , mPaintType(eStyleSVGPaintType_None) |
196 | 0 | {} |
197 | | |
198 | | void SetPaintServer(nsIFrame* aFrame, |
199 | | const gfxMatrix& aContextMatrix, |
200 | 0 | nsSVGPaintServerFrame* aPaintServerFrame) { |
201 | 0 | mPaintType = eStyleSVGPaintType_Server; |
202 | 0 | mPaintDefinition.mPaintServerFrame = aPaintServerFrame; |
203 | 0 | mFrame = aFrame; |
204 | 0 | mContextMatrix = aContextMatrix; |
205 | 0 | } |
206 | | |
207 | 0 | void SetColor(const nscolor &aColor) { |
208 | 0 | mPaintType = eStyleSVGPaintType_Color; |
209 | 0 | mPaintDefinition.mColor = aColor; |
210 | 0 | } |
211 | | |
212 | | void SetContextPaint(SVGContextPaint* aContextPaint, |
213 | 0 | nsStyleSVGPaintType aPaintType) { |
214 | 0 | NS_ASSERTION(aPaintType == eStyleSVGPaintType_ContextFill || |
215 | 0 | aPaintType == eStyleSVGPaintType_ContextStroke, |
216 | 0 | "Invalid context paint type"); |
217 | 0 | mPaintType = aPaintType; |
218 | 0 | mPaintDefinition.mContextPaint = aContextPaint; |
219 | 0 | } |
220 | | |
221 | | union { |
222 | | nsSVGPaintServerFrame* mPaintServerFrame; |
223 | | SVGContextPaint* mContextPaint; |
224 | | nscolor mColor; |
225 | | } mPaintDefinition; |
226 | | |
227 | | // Initialized (if needed) in SetPaintServer(): |
228 | | MOZ_INIT_OUTSIDE_CTOR nsIFrame* mFrame; |
229 | | // CTM defining the user space for the pattern we will use. |
230 | | gfxMatrix mContextMatrix; |
231 | | nsStyleSVGPaintType mPaintType; |
232 | | |
233 | | // Device-space-to-pattern-space |
234 | | gfxMatrix mPatternMatrix; |
235 | | nsRefPtrHashtable<nsFloatHashKey, gfxPattern> mPatternCache; |
236 | | |
237 | | already_AddRefed<gfxPattern> |
238 | | GetPattern(const DrawTarget* aDrawTarget, |
239 | | float aOpacity, |
240 | | nsStyleSVGPaint nsStyleSVG::*aFillOrStroke, |
241 | | const gfxMatrix& aCTM, |
242 | | imgDrawingParams& aImgParams); |
243 | | }; |
244 | | |
245 | | Paint mFillPaint; |
246 | | Paint mStrokePaint; |
247 | | |
248 | | float mFillOpacity; |
249 | | float mStrokeOpacity; |
250 | | }; |
251 | | |
252 | | /** |
253 | | * This class is used to pass context paint to an SVG image when an element |
254 | | * references that image (e.g. via HTML <img> or SVG <image>, or by referencing |
255 | | * it from a CSS property such as 'background-image'). In this case we only |
256 | | * support context colors and not paint servers. |
257 | | */ |
258 | | class SVGEmbeddingContextPaint : public SVGContextPaint |
259 | | { |
260 | | typedef gfx::Color Color; |
261 | | |
262 | | public: |
263 | | SVGEmbeddingContextPaint() |
264 | | : mFillOpacity(1.0f) |
265 | | , mStrokeOpacity(1.0f) |
266 | 0 | {} |
267 | | |
268 | 0 | bool operator==(const SVGEmbeddingContextPaint& aOther) const { |
269 | 0 | MOZ_ASSERT(GetStrokeWidth() == aOther.GetStrokeWidth() && |
270 | 0 | GetStrokeDashOffset() == aOther.GetStrokeDashOffset() && |
271 | 0 | GetStrokeDashArray() == aOther.GetStrokeDashArray(), |
272 | 0 | "We don't currently include these in the context information " |
273 | 0 | "from an embedding element"); |
274 | 0 | return mFill == aOther.mFill && |
275 | 0 | mStroke == aOther.mStroke && |
276 | 0 | mFillOpacity == aOther.mFillOpacity && |
277 | 0 | mStrokeOpacity == aOther.mStrokeOpacity; |
278 | 0 | } |
279 | | |
280 | 0 | void SetFill(nscolor aFill) { |
281 | 0 | mFill.emplace(gfx::ToDeviceColor(aFill)); |
282 | 0 | } |
283 | 0 | const Maybe<Color>& GetFill() const { |
284 | 0 | return mFill; |
285 | 0 | } |
286 | 0 | void SetStroke(nscolor aStroke) { |
287 | 0 | mStroke.emplace(gfx::ToDeviceColor(aStroke)); |
288 | 0 | } |
289 | 0 | const Maybe<Color>& GetStroke() const { |
290 | 0 | return mStroke; |
291 | 0 | } |
292 | | |
293 | | /** |
294 | | * Returns a pattern of type PatternType::COLOR, or else nullptr. |
295 | | */ |
296 | | already_AddRefed<gfxPattern> |
297 | | GetFillPattern(const DrawTarget* aDrawTarget, float aFillOpacity, |
298 | | const gfxMatrix& aCTM, imgDrawingParams& aImgParams) override; |
299 | | |
300 | | /** |
301 | | * Returns a pattern of type PatternType::COLOR, or else nullptr. |
302 | | */ |
303 | | already_AddRefed<gfxPattern> |
304 | | GetStrokePattern(const DrawTarget* aDrawTarget, float aStrokeOpacity, |
305 | | const gfxMatrix& aCTM, imgDrawingParams& aImgParams) override; |
306 | | |
307 | 0 | void SetFillOpacity(float aOpacity) { |
308 | 0 | mFillOpacity = aOpacity; |
309 | 0 | } |
310 | 0 | float GetFillOpacity() const override { |
311 | 0 | return mFillOpacity; |
312 | 0 | }; |
313 | | |
314 | 0 | void SetStrokeOpacity(float aOpacity) { |
315 | 0 | mStrokeOpacity = aOpacity; |
316 | 0 | } |
317 | 0 | float GetStrokeOpacity() const override { |
318 | 0 | return mStrokeOpacity; |
319 | 0 | }; |
320 | | |
321 | | uint32_t Hash() const override; |
322 | | |
323 | | private: |
324 | | Maybe<Color> mFill; |
325 | | Maybe<Color> mStroke; |
326 | | float mFillOpacity; |
327 | | float mStrokeOpacity; |
328 | | }; |
329 | | |
330 | | } // namespace mozilla |
331 | | |
332 | | #endif // MOZILLA_SVGCONTEXTPAINT_H_ |
333 | | |