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 nsImageRenderer_h__
8 #define nsImageRenderer_h__
10 #include "nsStyleStruct.h"
12 #include "mozilla/AspectRatio.h"
13 #include "mozilla/SurfaceFromElementResult.h"
21 class StackingContextHelper
;
22 class WebRenderParentCommand
;
23 class RenderRootStateManager
;
27 class DisplayListBuilder
;
28 class IpcResourceUpdateQueue
;
31 // A CSSSizeOrRatio represents a (possibly partially specified) size for use
32 // in computing image sizes. Either or both of the width and height might be
33 // given. A ratio of width to height may also be given. If we at least two
34 // of these then we can compute a concrete size, that is a width and height.
35 struct CSSSizeOrRatio
{
37 : mWidth(0), mHeight(0), mHasWidth(false), mHasHeight(false) {}
39 bool CanComputeConcreteSize() const {
40 return mHasWidth
+ mHasHeight
+ HasRatio() >= 2;
42 bool IsConcrete() const { return mHasWidth
&& mHasHeight
; }
43 bool HasRatio() const { return !!mRatio
; }
44 bool IsEmpty() const {
45 return (mHasWidth
&& mWidth
<= 0) || (mHasHeight
&& mHeight
<= 0) ||
49 // CanComputeConcreteSize must return true when ComputeConcreteSize is
51 nsSize
ComputeConcreteSize() const;
53 void SetWidth(nscoord aWidth
) {
57 mRatio
= AspectRatio::FromSize(mWidth
, mHeight
);
60 void SetHeight(nscoord aHeight
) {
64 mRatio
= AspectRatio::FromSize(mWidth
, mHeight
);
67 void SetSize(const nsSize
& aSize
) {
69 mHeight
= aSize
.height
;
72 mRatio
= AspectRatio::FromSize(mWidth
, mHeight
);
74 void SetRatio(const AspectRatio
& aRatio
) {
76 !mHasWidth
|| !mHasHeight
,
77 "Probably shouldn't be setting a ratio if we have a concrete size");
89 * This is a small wrapper class to encapsulate image drawing that can draw an
90 * StyleImage image, which may internally be a real image, a sub image, or a CSS
93 * @note Always call the member functions in the order of PrepareImage(),
94 * SetSize(), and Draw*().
96 class nsImageRenderer
{
98 typedef mozilla::image::ImgDrawResult ImgDrawResult
;
99 typedef mozilla::layers::ImageContainer ImageContainer
;
102 FLAG_SYNC_DECODE_IMAGES
= 0x01,
103 FLAG_PAINTING_TO_WINDOW
= 0x02,
104 FLAG_HIGH_QUALITY_SCALING
= 0x04,
105 FLAG_DRAW_PARTIAL_FRAMES
= 0x08
107 enum FitType
{ CONTAIN
, COVER
};
109 nsImageRenderer(nsIFrame
* aForFrame
, const mozilla::StyleImage
* aImage
,
111 ~nsImageRenderer() = default;
113 * Populates member variables to get ready for rendering.
114 * @return true iff the image is ready, and there is at least a pixel to
120 * The three Compute*Size functions correspond to the sizing algorthms and
121 * definitions from the CSS Image Values and Replaced Content spec. See
122 * http://dev.w3.org/csswg/css-images-3/#sizing .
126 * Compute the intrinsic size of the image as defined in the CSS Image Values
127 * spec. The intrinsic size is the unscaled size which the image would ideally
128 * like to be in app units.
130 mozilla::CSSSizeOrRatio
ComputeIntrinsicSize();
133 * Computes the placement for a background image, or for the image data
134 * inside of a replaced element.
136 * @param aPos The CSS <position> value that specifies the image's position.
137 * @param aOriginBounds The box to which the tiling position should be
138 * relative. For background images, this should correspond to
139 * 'background-origin' for the frame, except when painting on the
140 * canvas, in which case the origin bounds should be the bounds
141 * of the root element's frame. For a replaced element, this should
142 * be the element's content-box.
143 * @param aTopLeft [out] The top-left corner where an image tile should be
145 * @param aAnchorPoint [out] A point which should be pixel-aligned by
146 * nsLayoutUtils::DrawImage. This is the same as aTopLeft, unless
147 * CSS specifies a percentage (including 'right' or 'bottom'), in
148 * which case it's that percentage within of aOriginBounds. So
149 * 'right' would set aAnchorPoint.x to aOriginBounds.XMost().
151 * Points are returned relative to aOriginBounds.
153 static void ComputeObjectAnchorPoint(const mozilla::Position
& aPos
,
154 const nsSize
& aOriginBounds
,
155 const nsSize
& aImageSize
,
157 nsPoint
* aAnchorPoint
);
160 * Compute the size of the rendered image using either the 'cover' or
161 * 'contain' constraints (aFitType).
163 static nsSize
ComputeConstrainedSize(
164 const nsSize
& aConstrainingSize
,
165 const mozilla::AspectRatio
& aIntrinsicRatio
, FitType aFitType
);
167 * Compute the size of the rendered image (the concrete size) where no cover/
168 * contain constraints are given. The 'default algorithm' from the CSS Image
171 static nsSize
ComputeConcreteSize(
172 const mozilla::CSSSizeOrRatio
& aSpecifiedSize
,
173 const mozilla::CSSSizeOrRatio
& aIntrinsicSize
,
174 const nsSize
& aDefaultSize
);
177 * Set this image's preferred size. This will be its intrinsic size where
178 * specified and the default size where it is not. Used as the unscaled size
179 * when rendering the image.
181 void SetPreferredSize(const mozilla::CSSSizeOrRatio
& aIntrinsicSize
,
182 const nsSize
& aDefaultSize
);
185 * Draws the image to the target rendering context using
186 * {background|mask}-specific arguments.
187 * @see nsLayoutUtils::DrawImage() for parameters.
189 ImgDrawResult
DrawLayer(nsPresContext
* aPresContext
,
190 gfxContext
& aRenderingContext
, const nsRect
& aDest
,
191 const nsRect
& aFill
, const nsPoint
& aAnchor
,
192 const nsRect
& aDirty
, const nsSize
& aRepeatSize
,
196 * Builds WebRender DisplayItems for an image using
197 * {background|mask}-specific arguments.
198 * @see nsLayoutUtils::DrawImage() for parameters.
200 ImgDrawResult
BuildWebRenderDisplayItemsForLayer(
201 nsPresContext
* aPresContext
, mozilla::wr::DisplayListBuilder
& aBuilder
,
202 mozilla::wr::IpcResourceUpdateQueue
& aResource
,
203 const mozilla::layers::StackingContextHelper
& aSc
,
204 mozilla::layers::RenderRootStateManager
* aManager
, nsDisplayItem
* aItem
,
205 const nsRect
& aDest
, const nsRect
& aFill
, const nsPoint
& aAnchor
,
206 const nsRect
& aDirty
, const nsSize
& aRepeatSize
, float aOpacity
);
209 * Draw the image to a single component of a border-image style rendering.
210 * aFill The destination rect to be drawn into
211 * aSrc is the part of the image to be rendered into a tile (aUnitSize in
212 * aFill), if aSrc and the dest tile are different sizes, the image will be
213 * scaled to map aSrc onto the dest tile.
214 * aHFill and aVFill are the repeat patterns for the component -
215 * NS_STYLE_BORDER_IMAGE_REPEAT_*
216 * aUnitSize The scaled size of a single source rect (in destination coords)
217 * aIndex identifies the component: 0 1 2
220 * aSVGViewportSize The image size evaluated by default sizing algorithm.
221 * Pass Nothing() if we can read a valid viewport size or aspect-ratio from
222 * the drawing image directly, otherwise, pass Some() with viewport size
223 * evaluated from default sizing algorithm.
224 * aHasIntrinsicRatio is used to record if the source image has fixed
227 ImgDrawResult
DrawBorderImageComponent(
228 nsPresContext
* aPresContext
, gfxContext
& aRenderingContext
,
229 const nsRect
& aDirtyRect
, const nsRect
& aFill
,
230 const mozilla::CSSIntRect
& aSrc
, mozilla::StyleBorderImageRepeat aHFill
,
231 mozilla::StyleBorderImageRepeat aVFill
, const nsSize
& aUnitSize
,
232 uint8_t aIndex
, const mozilla::Maybe
<nsSize
>& aSVGViewportSize
,
233 const bool aHasIntrinsicRatio
);
236 * Draw the image to aRenderingContext which can be used to define the
237 * float area in the presence of "shape-outside: <image>".
239 ImgDrawResult
DrawShapeImage(nsPresContext
* aPresContext
,
240 gfxContext
& aRenderingContext
);
242 bool IsRasterImage();
244 /// Retrieves the image associated with this nsImageRenderer, if there is one.
245 already_AddRefed
<imgIContainer
> GetImage();
247 bool IsReady() const { return mPrepareResult
== ImgDrawResult::SUCCESS
; }
248 ImgDrawResult
PrepareResult() const { return mPrepareResult
; }
249 void SetExtendMode(mozilla::gfx::ExtendMode aMode
) { mExtendMode
= aMode
; }
250 void SetMaskOp(mozilla::StyleMaskMode aMaskOp
) { mMaskOp
= aMaskOp
; }
251 const nsSize
& GetSize() const { return mSize
; }
252 mozilla::StyleImage::Tag
GetType() const { return mType
; }
253 const mozilla::StyleGradient
* GetGradientData() const {
254 return mGradientData
;
259 * Draws the image to the target rendering context.
260 * aSrc is a rect on the source image which will be mapped to aDest; it's
261 * currently only used for gradients.
263 * @see nsLayoutUtils::DrawImage() for other parameters.
265 ImgDrawResult
Draw(nsPresContext
* aPresContext
, gfxContext
& aRenderingContext
,
266 const nsRect
& aDirtyRect
, const nsRect
& aDest
,
267 const nsRect
& aFill
, const nsPoint
& aAnchor
,
268 const nsSize
& aRepeatSize
, const mozilla::CSSIntRect
& aSrc
,
269 float aOpacity
= 1.0);
272 * Builds WebRender DisplayItems for the image.
273 * aSrc is a rect on the source image which will be mapped to aDest; it's
274 * currently only used for gradients.
276 * @see nsLayoutUtils::DrawImage() for other parameters.
278 ImgDrawResult
BuildWebRenderDisplayItems(
279 nsPresContext
* aPresContext
, mozilla::wr::DisplayListBuilder
& aBuilder
,
280 mozilla::wr::IpcResourceUpdateQueue
& aResources
,
281 const mozilla::layers::StackingContextHelper
& aSc
,
282 mozilla::layers::RenderRootStateManager
* aManager
, nsDisplayItem
* aItem
,
283 const nsRect
& aDirtyRect
, const nsRect
& aDest
, const nsRect
& aFill
,
284 const nsPoint
& aAnchor
, const nsSize
& aRepeatSize
,
285 const mozilla::CSSIntRect
& aSrc
, float aOpacity
= 1.0);
288 * Helper method for creating a gfxDrawable from mPaintServerFrame or
289 * mImageElementSurface.
290 * Requires mType to be Element.
291 * Returns null if we cannot create the drawable.
293 already_AddRefed
<gfxDrawable
> DrawableForElement(const nsRect
& aImageRect
,
294 gfxContext
& aContext
);
297 const mozilla::StyleImage
* mImage
;
298 ImageResolution mImageResolution
;
299 mozilla::StyleImage::Tag mType
;
300 nsCOMPtr
<imgIContainer
> mImageContainer
;
301 const mozilla::StyleGradient
* mGradientData
;
302 nsIFrame
* mPaintServerFrame
;
303 SurfaceFromElementResult mImageElementSurface
;
304 ImgDrawResult mPrepareResult
;
305 nsSize mSize
; // unscaled size of the image, in app units
307 mozilla::gfx::ExtendMode mExtendMode
;
308 mozilla::StyleMaskMode mMaskOp
;
311 } // namespace mozilla
313 #endif /* nsImageRenderer_h__ */