Coverage Report

Created: 2018-09-25 14:53

/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