Bug 1770025 [wpt PR 34116] - Update wpt metadata, a=testonly
[gecko.git] / layout / svg / SVGIntegrationUtils.h
blob828ee1e00b8eb9fcd68c0e156cd3eed41bb436a9
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"
12 #include "gfxRect.h"
13 #include "nsRegionFwd.h"
14 #include "mozilla/gfx/Rect.h"
15 #include "mozilla/ServoStyleConsts.h"
16 #include "mozilla/webrender/WebRenderTypes.h"
18 class gfxContext;
19 class gfxDrawable;
20 class nsIFrame;
21 struct nsPoint;
22 struct nsRect;
23 struct nsSize;
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
29 // rust.
30 nsTArray<nsTArray<float>> values;
33 namespace mozilla {
34 class nsDisplayList;
35 class nsDisplayListBuilder;
37 namespace gfx {
38 class DrawTarget;
39 } // namespace gfx
41 /**
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;
50 public:
51 /**
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);
57 /**
58 * Returns true if SVG effects are currently applied to this frame.
60 static bool UsingEffectsForFrame(const nsIFrame* aFrame);
62 /**
63 * Returns true if mask or clippath are currently applied to this frame.
65 static bool UsingMaskOrClipPathForFrame(const nsIFrame* aFrame);
67 /**
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);
73 /**
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);
79 /**
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);
89 /**
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
104 * of SVG effects.
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
128 * display item.
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
136 * repaint
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 {
148 gfxContext& ctx;
149 nsIFrame* frame;
150 nsRect dirtyRect;
151 nsRect borderArea;
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,
162 bool aHandleOpacity,
163 imgDrawingParams& aImgParams)
164 : ctx(aCtx),
165 frame(aFrame),
166 dirtyRect(aDirtyRect),
167 borderArea(aBorderArea),
168 builder(aBuilder),
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
196 * system.
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,
215 nsIFrame* aFrame,
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,
226 bool& aInitialized);
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
235 * compositor.
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
243 * rendered
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
249 * the output
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.
258 enum {
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_