Coverage Report

Created: 2018-09-25 14:53

/work/obj-fuzz/dist/include/nsImageRenderer.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 nsImageRenderer_h__
8
#define nsImageRenderer_h__
9
10
#include "nsLayoutUtils.h"
11
#include "nsStyleStruct.h"
12
#include "Units.h"
13
14
class gfxDrawable;
15
namespace mozilla {
16
17
namespace layers {
18
class StackingContextHelper;
19
class WebRenderParentCommand;
20
class WebRenderLayerManager;
21
} // namespace layers
22
23
namespace wr {
24
class DisplayListBuilder;
25
class IpcResourceUpdateQueue;
26
} // namespace wr
27
28
// A CSSSizeOrRatio represents a (possibly partially specified) size for use
29
// in computing image sizes. Either or both of the width and height might be
30
// given. A ratio of width to height may also be given. If we at least two
31
// of these then we can compute a concrete size, that is a width and height.
32
struct CSSSizeOrRatio
33
{
34
  CSSSizeOrRatio()
35
    : mRatio(0, 0)
36
    , mWidth(0)
37
    , mHeight(0)
38
    , mHasWidth(false)
39
    , mHasHeight(false)
40
  {
41
  }
42
43
  bool CanComputeConcreteSize() const
44
  {
45
    return mHasWidth + mHasHeight + HasRatio() >= 2;
46
  }
47
  bool IsConcrete() const { return mHasWidth && mHasHeight; }
48
  bool HasRatio() const { return mRatio.width > 0 && mRatio.height > 0; }
49
  bool IsEmpty() const
50
0
  {
51
0
    return (mHasWidth && mWidth <= 0) || (mHasHeight && mHeight <= 0) ||
52
0
           mRatio.width <= 0 || mRatio.height <= 0;
53
0
  }
54
55
  // CanComputeConcreteSize must return true when ComputeConcreteSize is
56
  // called.
57
  nsSize ComputeConcreteSize() const;
58
59
  void SetWidth(nscoord aWidth)
60
  {
61
    mWidth = aWidth;
62
    mHasWidth = true;
63
    if (mHasHeight) {
64
      mRatio = nsSize(mWidth, mHeight);
65
    }
66
  }
67
  void SetHeight(nscoord aHeight)
68
  {
69
    mHeight = aHeight;
70
    mHasHeight = true;
71
    if (mHasWidth) {
72
      mRatio = nsSize(mWidth, mHeight);
73
    }
74
  }
75
  void SetSize(const nsSize& aSize)
76
  {
77
    mWidth = aSize.width;
78
    mHeight = aSize.height;
79
    mHasWidth = true;
80
    mHasHeight = true;
81
    mRatio = aSize;
82
  }
83
  void SetRatio(const nsSize& aRatio)
84
0
  {
85
0
    MOZ_ASSERT(
86
0
      !mHasWidth || !mHasHeight,
87
0
      "Probably shouldn't be setting a ratio if we have a concrete size");
88
0
    mRatio = aRatio;
89
0
  }
90
91
  nsSize mRatio;
92
  nscoord mWidth;
93
  nscoord mHeight;
94
  bool mHasWidth;
95
  bool mHasHeight;
96
};
97
98
/**
99
 * This is a small wrapper class to encapsulate image drawing that can draw an
100
 * nsStyleImage image, which may internally be a real image, a sub image, or a
101
 * CSS gradient.
102
 *
103
 * @note Always call the member functions in the order of PrepareImage(),
104
 * SetSize(), and Draw*().
105
 */
106
class nsImageRenderer
107
{
108
public:
109
  typedef mozilla::image::ImgDrawResult ImgDrawResult;
110
  typedef mozilla::layers::LayerManager LayerManager;
111
  typedef mozilla::layers::ImageContainer ImageContainer;
112
113
  enum
114
  {
115
    FLAG_SYNC_DECODE_IMAGES = 0x01,
116
    FLAG_PAINTING_TO_WINDOW = 0x02
117
  };
118
  enum FitType
119
  {
120
    CONTAIN,
121
    COVER
122
  };
123
124
  nsImageRenderer(nsIFrame* aForFrame,
125
                  const nsStyleImage* aImage,
126
                  uint32_t aFlags);
127
  ~nsImageRenderer() = default;
128
  /**
129
   * Populates member variables to get ready for rendering.
130
   * @return true iff the image is ready, and there is at least a pixel to
131
   * draw.
132
   */
133
  bool PrepareImage();
134
135
  /**
136
   * The three Compute*Size functions correspond to the sizing algorthms and
137
   * definitions from the CSS Image Values and Replaced Content spec. See
138
   * http://dev.w3.org/csswg/css-images-3/#sizing .
139
   */
140
141
  /**
142
   * Compute the intrinsic size of the image as defined in the CSS Image Values
143
   * spec. The intrinsic size is the unscaled size which the image would ideally
144
   * like to be in app units.
145
   */
146
  mozilla::CSSSizeOrRatio ComputeIntrinsicSize();
147
148
  /**
149
   * Computes the placement for a background image, or for the image data
150
   * inside of a replaced element.
151
   *
152
   * @param aPos The CSS <position> value that specifies the image's position.
153
   * @param aOriginBounds The box to which the tiling position should be
154
   *          relative. For background images, this should correspond to
155
   *          'background-origin' for the frame, except when painting on the
156
   *          canvas, in which case the origin bounds should be the bounds
157
   *          of the root element's frame. For a replaced element, this should
158
   *          be the element's content-box.
159
   * @param aTopLeft [out] The top-left corner where an image tile should be
160
   *          drawn.
161
   * @param aAnchorPoint [out] A point which should be pixel-aligned by
162
   *          nsLayoutUtils::DrawImage. This is the same as aTopLeft, unless
163
   *          CSS specifies a percentage (including 'right' or 'bottom'), in
164
   *          which case it's that percentage within of aOriginBounds. So
165
   *          'right' would set aAnchorPoint.x to aOriginBounds.XMost().
166
   *
167
   * Points are returned relative to aOriginBounds.
168
   */
169
  static void ComputeObjectAnchorPoint(const mozilla::Position& aPos,
170
                                       const nsSize& aOriginBounds,
171
                                       const nsSize& aImageSize,
172
                                       nsPoint* aTopLeft,
173
                                       nsPoint* aAnchorPoint);
174
175
  /**
176
   * Compute the size of the rendered image using either the 'cover' or
177
   * 'contain' constraints (aFitType).
178
   * aIntrinsicRatio may be an invalid ratio, that is one or both of its
179
   * dimensions can be less than or equal to zero.
180
   */
181
  static nsSize ComputeConstrainedSize(const nsSize& aConstrainingSize,
182
                                       const nsSize& aIntrinsicRatio,
183
                                       FitType aFitType);
184
  /**
185
   * Compute the size of the rendered image (the concrete size) where no cover/
186
   * contain constraints are given. The 'default algorithm' from the CSS Image
187
   * Values spec.
188
   */
189
  static nsSize ComputeConcreteSize(
190
    const mozilla::CSSSizeOrRatio& aSpecifiedSize,
191
    const mozilla::CSSSizeOrRatio& aIntrinsicSize,
192
    const nsSize& aDefaultSize);
193
194
  /**
195
   * Set this image's preferred size. This will be its intrinsic size where
196
   * specified and the default size where it is not. Used as the unscaled size
197
   * when rendering the image.
198
   */
199
  void SetPreferredSize(const mozilla::CSSSizeOrRatio& aIntrinsicSize,
200
                        const nsSize& aDefaultSize);
201
202
  /**
203
   * Draws the image to the target rendering context using
204
   * {background|mask}-specific arguments.
205
   * @see nsLayoutUtils::DrawImage() for parameters.
206
   */
207
  ImgDrawResult DrawLayer(nsPresContext* aPresContext,
208
                          gfxContext& aRenderingContext,
209
                          const nsRect& aDest,
210
                          const nsRect& aFill,
211
                          const nsPoint& aAnchor,
212
                          const nsRect& aDirty,
213
                          const nsSize& aRepeatSize,
214
                          float aOpacity);
215
216
  /**
217
   * Builds WebRender DisplayItems for an image using
218
   * {background|mask}-specific arguments.
219
   * @see nsLayoutUtils::DrawImage() for parameters.
220
   */
221
  ImgDrawResult BuildWebRenderDisplayItemsForLayer(
222
    nsPresContext* aPresContext,
223
    mozilla::wr::DisplayListBuilder& aBuilder,
224
    mozilla::wr::IpcResourceUpdateQueue& aResource,
225
    const mozilla::layers::StackingContextHelper& aSc,
226
    mozilla::layers::WebRenderLayerManager* aManager,
227
    nsDisplayItem* aItem,
228
    const nsRect& aDest,
229
    const nsRect& aFill,
230
    const nsPoint& aAnchor,
231
    const nsRect& aDirty,
232
    const nsSize& aRepeatSize,
233
    float aOpacity);
234
235
  /**
236
   * Draw the image to a single component of a border-image style rendering.
237
   * aFill The destination rect to be drawn into
238
   * aSrc is the part of the image to be rendered into a tile (aUnitSize in
239
   * aFill), if aSrc and the dest tile are different sizes, the image will be
240
   * scaled to map aSrc onto the dest tile.
241
   * aHFill and aVFill are the repeat patterns for the component -
242
   * NS_STYLE_BORDER_IMAGE_REPEAT_*
243
   * aUnitSize The scaled size of a single source rect (in destination coords)
244
   * aIndex identifies the component: 0 1 2
245
   *                                  3 4 5
246
   *                                  6 7 8
247
   * aSVGViewportSize The image size evaluated by default sizing algorithm.
248
   * Pass Nothing() if we can read a valid viewport size or aspect-ratio from
249
   * the drawing image directly, otherwise, pass Some() with viewport size
250
   * evaluated from default sizing algorithm.
251
   * aHasIntrinsicRatio is used to record if the source image has fixed
252
   * intrinsic ratio.
253
   */
254
  ImgDrawResult DrawBorderImageComponent(
255
    nsPresContext* aPresContext,
256
    gfxContext& aRenderingContext,
257
    const nsRect& aDirtyRect,
258
    const nsRect& aFill,
259
    const mozilla::CSSIntRect& aSrc,
260
    mozilla::StyleBorderImageRepeat aHFill,
261
    mozilla::StyleBorderImageRepeat aVFill,
262
    const nsSize& aUnitSize,
263
    uint8_t aIndex,
264
    const mozilla::Maybe<nsSize>& aSVGViewportSize,
265
    const bool aHasIntrinsicRatio);
266
267
  /**
268
   * Draw the image to aRenderingContext which can be used to define the
269
   * float area in the presence of "shape-outside: <image>".
270
   */
271
  ImgDrawResult DrawShapeImage(nsPresContext* aPresContext,
272
                               gfxContext& aRenderingContext);
273
274
  bool IsRasterImage();
275
  bool IsAnimatedImage();
276
277
  /// Retrieves the image associated with this nsImageRenderer, if there is one.
278
  already_AddRefed<imgIContainer> GetImage();
279
280
  bool IsImageContainerAvailable(layers::LayerManager* aManager,
281
                                 uint32_t aFlags);
282
  bool IsReady() const { return mPrepareResult == ImgDrawResult::SUCCESS; }
283
  ImgDrawResult PrepareResult() const { return mPrepareResult; }
284
  void SetExtendMode(mozilla::gfx::ExtendMode aMode) { mExtendMode = aMode; }
285
  void SetMaskOp(uint8_t aMaskOp) { mMaskOp = aMaskOp; }
286
  void PurgeCacheForViewportChange(
287
    const mozilla::Maybe<nsSize>& aSVGViewportSize,
288
    const bool aHasRatio);
289
  nsStyleImageType GetType() const { return mType; }
290
  already_AddRefed<nsStyleGradient> GetGradientData();
291
292
private:
293
  /**
294
   * Draws the image to the target rendering context.
295
   * aSrc is a rect on the source image which will be mapped to aDest; it's
296
   * currently only used for gradients.
297
   *
298
   * @see nsLayoutUtils::DrawImage() for other parameters.
299
   */
300
  ImgDrawResult Draw(nsPresContext* aPresContext,
301
                     gfxContext& aRenderingContext,
302
                     const nsRect& aDirtyRect,
303
                     const nsRect& aDest,
304
                     const nsRect& aFill,
305
                     const nsPoint& aAnchor,
306
                     const nsSize& aRepeatSize,
307
                     const mozilla::CSSIntRect& aSrc,
308
                     float aOpacity = 1.0);
309
310
  /**
311
   * Builds WebRender DisplayItems for the image.
312
   * aSrc is a rect on the source image which will be mapped to aDest; it's
313
   * currently only used for gradients.
314
   *
315
   * @see nsLayoutUtils::DrawImage() for other parameters.
316
   */
317
  ImgDrawResult BuildWebRenderDisplayItems(
318
    nsPresContext* aPresContext,
319
    mozilla::wr::DisplayListBuilder& aBuilder,
320
    mozilla::wr::IpcResourceUpdateQueue& aResources,
321
    const mozilla::layers::StackingContextHelper& aSc,
322
    mozilla::layers::WebRenderLayerManager* aManager,
323
    nsDisplayItem* aItem,
324
    const nsRect& aDirtyRect,
325
    const nsRect& aDest,
326
    const nsRect& aFill,
327
    const nsPoint& aAnchor,
328
    const nsSize& aRepeatSize,
329
    const mozilla::CSSIntRect& aSrc,
330
    float aOpacity = 1.0);
331
332
  /**
333
   * Helper method for creating a gfxDrawable from mPaintServerFrame or
334
   * mImageElementSurface.
335
   * Requires mType is eStyleImageType_Element.
336
   * Returns null if we cannot create the drawable.
337
   */
338
  already_AddRefed<gfxDrawable> DrawableForElement(const nsRect& aImageRect,
339
                                                   gfxContext& aContext);
340
341
  nsIFrame* mForFrame;
342
  const nsStyleImage* mImage;
343
  nsStyleImageType mType;
344
  nsCOMPtr<imgIContainer> mImageContainer;
345
  RefPtr<nsStyleGradient> mGradientData;
346
  nsIFrame* mPaintServerFrame;
347
  nsLayoutUtils::SurfaceFromElementResult mImageElementSurface;
348
  ImgDrawResult mPrepareResult;
349
  nsSize mSize; // unscaled size of the image, in app units
350
  uint32_t mFlags;
351
  mozilla::gfx::ExtendMode mExtendMode;
352
  uint8_t mMaskOp;
353
};
354
355
} // namespace mozilla
356
357
#endif /* nsImageRenderer_h__ */