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/. */
6 #ifndef __NS_FILTERINSTANCE_H__
7 #define __NS_FILTERINSTANCE_H__
13 #include "nsHashKeys.h"
17 #include "nsSVGFilters.h"
18 #include "nsSVGNumber2.h"
19 #include "nsSVGNumberPair.h"
22 #include "mozilla/gfx/2D.h"
26 class nsSVGFilterPaintCallback
;
29 * This class performs all filter processing.
31 * We build a graph of the filter image data flow, essentially
32 * converting the filter graph to SSA. This lets us easily propagate
33 * analysis data (such as bounding-boxes) over the filter primitive graph.
35 * Definition of "filter space": filter space is a coordinate system that is
36 * aligned with the user space of the filtered element, with its origin located
37 * at the top left of the filter region, and with one unit equal in size to one
38 * pixel of the offscreen surface into which the filter output would/will be
41 * The definition of "filter region" can be found here:
42 * http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion
44 class nsFilterInstance
46 typedef mozilla::gfx::IntRect IntRect
;
47 typedef mozilla::gfx::SourceSurface SourceSurface
;
48 typedef mozilla::gfx::DrawTarget DrawTarget
;
49 typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription
;
53 * Paint the given filtered frame.
54 * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
55 * frame space (i.e. relative to its origin, the top-left corner of its
58 static nsresult
PaintFilteredFrame(nsRenderingContext
*aContext
,
59 nsIFrame
*aFilteredFrame
,
60 nsSVGFilterPaintCallback
*aPaintCallback
,
61 const nsRegion
* aDirtyArea
,
62 nsIFrame
* aTransformRoot
= nullptr);
65 * Returns the post-filter area that could be dirtied when the given
66 * pre-filter area of aFilteredFrame changes.
67 * @param aPreFilterDirtyRegion The pre-filter area of aFilteredFrame that has
68 * changed, relative to aFilteredFrame, in app units.
70 static nsRegion
GetPostFilterDirtyArea(nsIFrame
*aFilteredFrame
,
71 const nsRegion
& aPreFilterDirtyRegion
);
74 * Returns the pre-filter area that is needed from aFilteredFrame when the
75 * given post-filter area needs to be repainted.
76 * @param aPostFilterDirtyRegion The post-filter area that is dirty, relative
77 * to aFilteredFrame, in app units.
79 static nsRegion
GetPreFilterNeededArea(nsIFrame
*aFilteredFrame
,
80 const nsRegion
& aPostFilterDirtyRegion
);
83 * Returns the post-filter visual overflow rect (paint bounds) of
85 * @param aOverrideBBox A user space rect, in user units, that should be used
86 * as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null.
87 * @param aPreFilterBounds The pre-filter visual overflow rect of
88 * aFilteredFrame, if non-null.
90 static nsRect
GetPostFilterBounds(nsIFrame
*aFilteredFrame
,
91 const gfxRect
*aOverrideBBox
= nullptr,
92 const nsRect
*aPreFilterBounds
= nullptr);
95 * @param aTargetFrame The frame of the filtered element under consideration.
96 * @param aPaintCallback [optional] The callback that Render() should use to
97 * paint. Only required if you will call Render().
98 * @param aPostFilterDirtyRegion [optional] The post-filter area
99 * that has to be repainted, in app units. Only required if you will
100 * call ComputeSourceNeededRect() or Render().
101 * @param aPreFilterDirtyRegion [optional] The pre-filter area of
102 * the filtered element that changed, in app units. Only required if you
103 * will call ComputePostFilterDirtyRegion().
104 * @param aOverridePreFilterVisualOverflowRect [optional] Use a different
105 * visual overflow rect for the target element.
106 * @param aOverrideBBox [optional] Use a different SVG bbox for the target
108 * @param aTransformRoot [optional] The transform root frame for painting.
110 nsFilterInstance(nsIFrame
*aTargetFrame
,
111 nsSVGFilterPaintCallback
*aPaintCallback
,
112 const nsRegion
*aPostFilterDirtyRegion
= nullptr,
113 const nsRegion
*aPreFilterDirtyRegion
= nullptr,
114 const nsRect
*aOverridePreFilterVisualOverflowRect
= nullptr,
115 const gfxRect
*aOverrideBBox
= nullptr,
116 nsIFrame
* aTransformRoot
= nullptr);
119 * Returns true if the filter instance was created successfully.
121 bool IsInitialized() const { return mInitialized
; }
124 * Draws the filter output into aContext. The area that
125 * needs to be painted must have been specified before calling this method
126 * by passing it as the aPostFilterDirtyRegion argument to the
127 * nsFilterInstance constructor.
129 nsresult
Render(gfxContext
* aContext
);
132 * Sets the aPostFilterDirtyRegion outparam to the post-filter area in frame
133 * space that would be dirtied by mTargetFrame when a given
134 * pre-filter area of mTargetFrame is dirtied. The pre-filter area must have
135 * been specified before calling this method by passing it as the
136 * aPreFilterDirtyRegion argument to the nsFilterInstance constructor.
138 nsresult
ComputePostFilterDirtyRegion(nsRegion
* aPostFilterDirtyRegion
);
141 * Sets the aPostFilterExtents outparam to the post-filter bounds in frame
142 * space for the whole filter output. This is not necessarily equivalent to
143 * the area that would be dirtied in the result when the entire pre-filter
144 * area is dirtied, because some filter primitives can generate output
147 nsresult
ComputePostFilterExtents(nsRect
* aPostFilterExtents
);
150 * Sets the aDirty outparam to the pre-filter bounds in frame space of the
151 * area of mTargetFrame that is needed in order to paint the filtered output
152 * for a given post-filter dirtied area. The post-filter area must have been
153 * specified before calling this method by passing it as the aPostFilterDirtyRegion
154 * argument to the nsFilterInstance constructor.
156 nsresult
ComputeSourceNeededRect(nsRect
* aDirty
);
160 * Returns the transform from filter space to outer-<svg> device space.
162 gfxMatrix
GetFilterSpaceToDeviceSpaceTransform() const {
163 return mFilterSpaceToDeviceSpaceTransform
;
168 // Specifies which parts of the source need to be rendered.
169 // Set by ComputeNeededBoxes().
170 nsIntRect mNeededBounds
;
172 // The surface that contains the input rendering.
173 // Set by BuildSourceImage / BuildSourcePaint.
174 mozilla::RefPtr
<SourceSurface
> mSourceSurface
;
176 // The position and size of mSourceSurface in filter space.
177 // Set by BuildSourceImage / BuildSourcePaint.
178 IntRect mSurfaceRect
;
182 * Creates a SourceSurface for either the FillPaint or StrokePaint graph
185 nsresult
BuildSourcePaint(SourceInfo
*aPrimitive
,
186 DrawTarget
* aTargetDT
);
189 * Creates a SourceSurface for either the FillPaint and StrokePaint graph
190 * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and
191 * mStrokePaint.mSourceSurface respectively.
193 nsresult
BuildSourcePaints(DrawTarget
* aTargetDT
);
196 * Creates the SourceSurface for the SourceGraphic graph node, paints its
197 * contents, and assigns it to mSourceGraphic.mSourceSurface.
199 nsresult
BuildSourceImage(DrawTarget
* aTargetDT
);
202 * Build the list of FilterPrimitiveDescriptions that describes the filter's
203 * filter primitives and their connections. This populates
204 * mPrimitiveDescriptions and mInputImages.
206 nsresult
BuildPrimitives();
209 * Add to the list of FilterPrimitiveDescriptions for a particular SVG
210 * reference filter or CSS filter. This populates mPrimitiveDescrs and
213 nsresult
BuildPrimitivesForFilter(const nsStyleFilter
& aFilter
);
216 * Computes the filter space bounds of the areas that we actually *need* from
217 * the filter sources, based on the value of mPostFilterDirtyRegion.
218 * This sets mNeededBounds on the corresponding SourceInfo structs.
220 void ComputeNeededBoxes();
223 * Returns the output bounds of the final FilterPrimitiveDescription.
225 nsIntRect
OutputFilterSpaceBounds() const;
228 * Compute the scale factors between user space and filter space.
230 nsresult
ComputeUserSpaceToFilterSpaceScale();
233 * Transform a rect between user space and filter space.
235 gfxRect
UserSpaceToFilterSpace(const gfxRect
& aUserSpace
) const;
236 gfxRect
FilterSpaceToUserSpace(const gfxRect
& aFilterSpaceRect
) const;
239 * Converts an nsRect or an nsRegion that is relative to a filtered frame's
240 * origin (i.e. the top-left corner of its border box) into filter space,
242 * Returns the entire filter region if aRect / aRegion is null, or if the
243 * result is too large to be stored in an nsIntRect.
245 nsIntRect
FrameSpaceToFilterSpace(const nsRect
* aRect
) const;
246 nsIntRegion
FrameSpaceToFilterSpace(const nsRegion
* aRegion
) const;
249 * Converts an nsIntRect or an nsIntRegion from filter space into the space
250 * that is relative to a filtered frame's origin (i.e. the top-left corner
251 * of its border box) in app units, rounding out.
253 nsRect
FilterSpaceToFrameSpace(const nsIntRect
& aRect
) const;
254 nsRegion
FilterSpaceToFrameSpace(const nsIntRegion
& aRegion
) const;
257 * Returns the transform from frame space to the coordinate space that
258 * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the
259 * top-left corner of its border box, aka the top left corner of its mRect.
261 gfxMatrix
GetUserSpaceToFrameSpaceInCSSPxTransform() const;
264 * The frame for the element that is currently being filtered.
266 nsIFrame
* mTargetFrame
;
268 nsSVGFilterPaintCallback
* mPaintCallback
;
271 * The SVG bbox of the element that is being filtered, in user space.
276 * The SVG bbox of the element that is being filtered, in filter space.
278 nsIntRect mTargetBBoxInFilterSpace
;
281 * The transform from filter space to outer-<svg> device space.
283 gfxMatrix mFilterSpaceToDeviceSpaceTransform
;
286 * Transform rects between filter space and frame space in CSS pixels.
288 gfxMatrix mFilterSpaceToFrameSpaceInCSSPxTransform
;
289 gfxMatrix mFrameSpaceInCSSPxToFilterSpaceTransform
;
292 * The scale factors between user space and filter space.
294 gfxSize mUserSpaceToFilterSpaceScale
;
295 gfxSize mFilterSpaceToUserSpaceScale
;
298 * Pre-filter paint bounds of the element that is being filtered, in filter
301 nsIntRect mTargetBounds
;
304 * The dirty area that needs to be repainted, in filter space.
306 nsIntRegion mPostFilterDirtyRegion
;
309 * The pre-filter area of the filtered element that changed, in filter space.
311 nsIntRegion mPreFilterDirtyRegion
;
313 SourceInfo mSourceGraphic
;
314 SourceInfo mFillPaint
;
315 SourceInfo mStrokePaint
;
316 nsIFrame
* mTransformRoot
;
317 nsTArray
<mozilla::RefPtr
<SourceSurface
>> mInputImages
;
318 nsTArray
<FilterPrimitiveDescription
> mPrimitiveDescriptions
;
319 int32_t mAppUnitsPerCSSPx
;