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