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 LAYOUT_SVG_SVGINTEGRATIONUTILS_H_
8 #define LAYOUT_SVG_SVGINTEGRATIONUTILS_H_
10 #include "ImgDrawResult.h"
11 #include "gfxMatrix.h"
13 #include "nsRegionFwd.h"
14 #include "mozilla/gfx/Rect.h"
15 #include "mozilla/ServoStyleConsts.h"
16 #include "mozilla/webrender/WebRenderTypes.h"
25 struct WrFiltersHolder
{
26 nsTArray
<mozilla::wr::FilterOp
> filters
;
27 nsTArray
<mozilla::wr::WrFilterData
> filter_datas
;
28 // This exists just to own the values long enough for them to be copied into
30 nsTArray
<nsTArray
<float>> values
;
35 class nsDisplayListBuilder
;
42 * Integration of SVG effects (clipPath clipping, masking and filters) into
43 * regular display list based painting and hit-testing.
45 class SVGIntegrationUtils final
{
46 using DrawTarget
= gfx::DrawTarget
;
47 using IntRect
= gfx::IntRect
;
48 using imgDrawingParams
= image::imgDrawingParams
;
52 * Returns true if SVG effects that affect the overflow of the given frame
53 * are currently applied to the frame.
55 static bool UsingOverflowAffectingEffects(const nsIFrame
* aFrame
);
58 * Returns true if SVG effects are currently applied to this frame.
60 static bool UsingEffectsForFrame(const nsIFrame
* aFrame
);
63 * Returns true if mask or clippath are currently applied to this frame.
65 static bool UsingMaskOrClipPathForFrame(const nsIFrame
* aFrame
);
68 * Returns true if the element has a clippath that is simple enough to
69 * be represented without a mask in WebRender.
71 static bool UsingSimpleClipPathForFrame(const nsIFrame
* aFrame
);
74 * Returns the size of the union of the border-box rects of all of
75 * aNonSVGFrame's continuations.
77 static nsSize
GetContinuationUnionSize(nsIFrame
* aNonSVGFrame
);
80 * When SVG effects need to resolve percentage, userSpaceOnUse lengths, they
81 * need a coordinate context to resolve them against. This method provides
82 * that coordinate context for non-SVG frames with SVG effects applied to
83 * them. The gfxSize returned is the size of the union of all of the given
84 * frame's continuations' border boxes, converted to SVG user units (equal to
85 * CSS px units), as required by the SVG code.
87 static gfx::Size
GetSVGCoordContextForNonSVGFrame(nsIFrame
* aNonSVGFrame
);
90 * SVG effects such as SVG filters, masking and clipPath may require an SVG
91 * "bbox" for the element they're being applied to in order to make decisions
92 * about positioning, and to resolve various lengths against. This method
93 * provides the "bbox" for non-SVG frames. The bbox returned is in CSS px
94 * units, and aUnionContinuations decide whether bbox contains the area of
95 * current frame only or the union of all aNonSVGFrame's continuations'
96 * overflow areas, relative to the top-left of the union of all aNonSVGFrame's
97 * continuations' border box rects.
99 static gfxRect
GetSVGBBoxForNonSVGFrame(nsIFrame
* aNonSVGFrame
,
100 bool aUnionContinuations
);
103 * Used to adjust a frame's pre-effects ink overflow rect to take account
106 * XXX This method will not do the right thing for frames with continuations.
107 * It really needs all the continuations to have been reflowed before being
108 * called, but we currently call it on each continuation as its overflow
109 * rects are set during the reflow of each particular continuation. Gecko's
110 * current reflow architecture does not allow us to set the overflow rects
111 * for a whole chain of continuations for a given element at the point when
112 * the last continuation is reflowed. See:
113 * http://groups.google.com/group/mozilla.dev.tech.layout/msg/6b179066f3051f65
115 static nsRect
ComputePostEffectsInkOverflowRect(
116 nsIFrame
* aFrame
, const nsRect
& aPreEffectsOverflowRect
);
119 * Used to adjust the area of a frame that needs to be invalidated to take
120 * account of SVG effects.
122 * @param aFrame The effects frame.
123 * @param aToReferenceFrame The offset (in app units) from aFrame to its
124 * reference display item.
125 * @param aInvalidRegion The pre-effects invalid region in pixels relative to
126 * the reference display item.
127 * @return The post-effects invalid rect in pixels relative to the reference
130 static nsIntRegion
AdjustInvalidAreaForSVGEffects(
131 nsIFrame
* aFrame
, const nsPoint
& aToReferenceFrame
,
132 const nsIntRegion
& aInvalidRegion
);
135 * Figure out which area of the source is needed given an area to
138 static nsRect
GetRequiredSourceForInvalidArea(nsIFrame
* aFrame
,
139 const nsRect
& aDirtyRect
);
142 * Returns true if the given point is not clipped out by effects.
143 * @param aPt in appunits relative to aFrame
145 static bool HitTestFrameForEffects(nsIFrame
* aFrame
, const nsPoint
& aPt
);
147 struct MOZ_STACK_CLASS PaintFramesParams
{
152 nsDisplayListBuilder
* builder
;
153 bool handleOpacity
; // If true, PaintMaskAndClipPath/ PaintFilter should
154 // apply css opacity.
155 Maybe
<LayoutDeviceRect
> maskRect
;
156 imgDrawingParams
& imgParams
;
158 explicit PaintFramesParams(gfxContext
& aCtx
, nsIFrame
* aFrame
,
159 const nsRect
& aDirtyRect
,
160 const nsRect
& aBorderArea
,
161 nsDisplayListBuilder
* aBuilder
,
163 imgDrawingParams
& aImgParams
)
166 dirtyRect(aDirtyRect
),
167 borderArea(aBorderArea
),
169 handleOpacity(aHandleOpacity
),
170 imgParams(aImgParams
) {}
173 // This should use FunctionRef instead of std::function because we don't need
174 // to take ownership of the function. See bug 1490781.
175 static void PaintMaskAndClipPath(const PaintFramesParams
& aParams
,
176 const std::function
<void()>& aPaintChild
);
179 * Paint mask of frame onto a given context, aParams.ctx.
180 * aParams.ctx must contain an A8 surface. Returns false if the mask
181 * didn't get painted and should be ignored at the call site.
182 * isMaskComplete is an outparameter returning whether the mask is complete.
183 * Incomplete masks should not be drawn and the proper fallback behaviour
184 * depends on if the masked element is html or svg.
186 static bool PaintMask(const PaintFramesParams
& aParams
,
187 bool& aOutIsMaskComplete
);
190 * Paint the frame contents.
191 * SVG frames will have had matrix propagation set to false already.
192 * Non-SVG frames have to do their own thing.
193 * The caller will do a Save()/Restore() as necessary so feel free
194 * to mess with context state.
195 * The context will be configured to use the "user space" coordinate
197 * @param aDirtyRect the dirty rect *in user space pixels*
198 * @param aTransformRoot the outermost frame whose transform should be taken
199 * into account when painting an SVG glyph
201 using SVGFilterPaintCallback
= std::function
<void(
202 gfxContext
& aContext
, nsIFrame
* aTarget
, const gfxMatrix
& aTransform
,
203 const nsIntRect
* aDirtyRect
, image::imgDrawingParams
& aImgParams
)>;
206 * Paint non-SVG frame with filter and opacity effect.
208 static void PaintFilter(const PaintFramesParams
& aParams
,
209 const SVGFilterPaintCallback
& aCallback
);
212 * Build WebRender filters for a frame with CSS filters applied to it.
214 static bool CreateWebRenderCSSFilters(Span
<const StyleFilter
> aFilters
,
216 WrFiltersHolder
& aWrFilters
);
219 * Try to build WebRender filters for a frame with SVG filters applied to it
220 * if the filters are supported.
222 static bool BuildWebRenderFilters(nsIFrame
* aFilteredFrame
,
223 Span
<const StyleFilter
> aFilters
,
224 WrFiltersHolder
& aWrFilters
,
225 Maybe
<nsRect
>& aPostFilterClip
,
229 * Check if the filters present on |aFrame| are supported by WebRender.
231 static bool CanCreateWebRenderFiltersForFrame(nsIFrame
* aFrame
);
234 * Check if |aFrame| uses any SVG effects that cannot be rendered in the
237 static bool UsesSVGEffectsNotSupportedInCompositor(nsIFrame
* aFrame
);
240 * @param aRenderingContext the target rendering context in which the paint
241 * server will be rendered
242 * @param aTarget the target frame onto which the paint server will be
244 * @param aPaintServer a first-continuation frame to use as the source
245 * @param aFilter a filter to be applied when scaling
246 * @param aDest the area the paint server image should be mapped to
247 * @param aFill the area to be filled with copies of the paint server image
248 * @param aAnchor a point in aFill which we will ensure is pixel-aligned in
250 * @param aDirty pixels outside this area may be skipped
251 * @param aPaintServerSize the size that would be filled when using
252 * background-repeat:no-repeat and background-size:auto. For normal background
253 * images, this would be the intrinsic size of the image; for gradients and
254 * patterns this would be the whole target frame fill area.
255 * @param aFlags pass FLAG_SYNC_DECODE_IMAGES and any images in the paint
256 * server will be decoding synchronously if they are not decoded already.
259 FLAG_SYNC_DECODE_IMAGES
= 0x01,
262 static already_AddRefed
<gfxDrawable
> DrawableFromPaintServer(
263 nsIFrame
* aFrame
, nsIFrame
* aTarget
, const nsSize
& aPaintServerSize
,
264 const gfx::IntSize
& aRenderSize
, const DrawTarget
* aDrawTarget
,
265 const gfxMatrix
& aContextMatrix
, uint32_t aFlags
);
268 * For non-SVG frames, this gives the offset to the frame's "user space".
269 * For SVG frames, this returns a zero offset.
271 static nsPoint
GetOffsetToBoundingBox(nsIFrame
* aFrame
);
274 * The offset between the reference frame and the bounding box of the
275 * target frame in device units.
277 static gfxPoint
GetOffsetToUserSpaceInDevPx(nsIFrame
* aFrame
,
278 const PaintFramesParams
& aParams
);
281 } // namespace mozilla
283 #endif // LAYOUT_SVG_SVGINTEGRATIONUTILS_H_