Bumping manifests a=b2g-bump
[gecko.git] / layout / svg / nsFilterInstance.h
blobd895349b15c18bc33d52ac01ff9bfbba18cd4ad0
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__
9 #include "gfxMatrix.h"
10 #include "gfxPoint.h"
11 #include "gfxRect.h"
12 #include "nsCOMPtr.h"
13 #include "nsHashKeys.h"
14 #include "nsPoint.h"
15 #include "nsRect.h"
16 #include "nsSize.h"
17 #include "nsSVGFilters.h"
18 #include "nsSVGNumber2.h"
19 #include "nsSVGNumberPair.h"
20 #include "nsTArray.h"
21 #include "nsIFrame.h"
22 #include "mozilla/gfx/2D.h"
24 class gfxContext;
25 class nsIFrame;
26 class nsSVGFilterPaintCallback;
28 namespace mozilla {
29 namespace dom {
30 class UserSpaceMetrics;
34 /**
35 * This class performs all filter processing.
37 * We build a graph of the filter image data flow, essentially
38 * converting the filter graph to SSA. This lets us easily propagate
39 * analysis data (such as bounding-boxes) over the filter primitive graph.
41 * Definition of "filter space": filter space is a coordinate system that is
42 * aligned with the user space of the filtered element, with its origin located
43 * at the top left of the filter region, and with one unit equal in size to one
44 * pixel of the offscreen surface into which the filter output would/will be
45 * painted.
47 * The definition of "filter region" can be found here:
48 * http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion
50 class nsFilterInstance
52 typedef mozilla::gfx::IntRect IntRect;
53 typedef mozilla::gfx::SourceSurface SourceSurface;
54 typedef mozilla::gfx::DrawTarget DrawTarget;
55 typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
56 typedef mozilla::gfx::FilterDescription FilterDescription;
57 typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics;
59 public:
60 /**
61 * Create a FilterDescription for the supplied filter. All coordinates in
62 * the description are in filter space.
63 * @param aOutAdditionalImages Will contain additional images needed to
64 * render the filter (from feImage primitives).
65 * @return A FilterDescription describing the filter.
67 static FilterDescription GetFilterDescription(nsIContent* aFilteredElement,
68 const nsTArray<nsStyleFilter>& aFilterChain,
69 const UserSpaceMetrics& aMetrics,
70 const gfxRect& aBBox,
71 nsTArray<mozilla::RefPtr<SourceSurface>>& aOutAdditionalImages);
73 /**
74 * Paint the given filtered frame.
75 * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's
76 * frame space (i.e. relative to its origin, the top-left corner of its
77 * border box).
79 static nsresult PaintFilteredFrame(nsIFrame *aFilteredFrame,
80 gfxContext& aContext,
81 const gfxMatrix& aTransform,
82 nsSVGFilterPaintCallback *aPaintCallback,
83 const nsRegion* aDirtyArea);
85 /**
86 * Returns the post-filter area that could be dirtied when the given
87 * pre-filter area of aFilteredFrame changes.
88 * @param aPreFilterDirtyRegion The pre-filter area of aFilteredFrame that has
89 * changed, relative to aFilteredFrame, in app units.
91 static nsRegion GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
92 const nsRegion& aPreFilterDirtyRegion);
94 /**
95 * Returns the pre-filter area that is needed from aFilteredFrame when the
96 * given post-filter area needs to be repainted.
97 * @param aPostFilterDirtyRegion The post-filter area that is dirty, relative
98 * to aFilteredFrame, in app units.
100 static nsRegion GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
101 const nsRegion& aPostFilterDirtyRegion);
104 * Returns the post-filter visual overflow rect (paint bounds) of
105 * aFilteredFrame.
106 * @param aOverrideBBox A user space rect, in user units, that should be used
107 * as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null.
108 * @param aPreFilterBounds The pre-filter visual overflow rect of
109 * aFilteredFrame, if non-null.
111 static nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame,
112 const gfxRect *aOverrideBBox = nullptr,
113 const nsRect *aPreFilterBounds = nullptr);
116 * @param aTargetFrame The frame of the filtered element under consideration,
117 * may be null.
118 * @param aTargetContent The filtered element itself.
119 * @param aMetrics The metrics to resolve SVG lengths against.
120 * @param aFilterChain The list of filters to apply.
121 * @param aPaintCallback [optional] The callback that Render() should use to
122 * paint. Only required if you will call Render().
123 * @param aPaintTransform The transform to apply to convert to
124 * aTargetFrame's SVG user space. Only used when painting.
125 * @param aPostFilterDirtyRegion [optional] The post-filter area
126 * that has to be repainted, in app units. Only required if you will
127 * call ComputeSourceNeededRect() or Render().
128 * @param aPreFilterDirtyRegion [optional] The pre-filter area of
129 * the filtered element that changed, in app units. Only required if you
130 * will call ComputePostFilterDirtyRegion().
131 * @param aOverridePreFilterVisualOverflowRect [optional] Use a different
132 * visual overflow rect for the target element.
133 * @param aOverrideBBox [optional] Use a different SVG bbox for the target
134 * element. Must be non-null if aTargetFrame is null.
136 nsFilterInstance(nsIFrame *aTargetFrame,
137 nsIContent* aTargetContent,
138 const UserSpaceMetrics& aMetrics,
139 const nsTArray<nsStyleFilter>& aFilterChain,
140 nsSVGFilterPaintCallback *aPaintCallback,
141 const gfxMatrix& aPaintTransform,
142 const nsRegion *aPostFilterDirtyRegion = nullptr,
143 const nsRegion *aPreFilterDirtyRegion = nullptr,
144 const nsRect *aOverridePreFilterVisualOverflowRect = nullptr,
145 const gfxRect *aOverrideBBox = nullptr);
148 * Returns true if the filter instance was created successfully.
150 bool IsInitialized() const { return mInitialized; }
153 * Draws the filter output into aContext. The area that
154 * needs to be painted must have been specified before calling this method
155 * by passing it as the aPostFilterDirtyRegion argument to the
156 * nsFilterInstance constructor.
158 nsresult Render(gfxContext* aContext);
160 const FilterDescription& ExtractDescriptionAndAdditionalImages(nsTArray<mozilla::RefPtr<SourceSurface>>& aOutAdditionalImages)
162 mInputImages.SwapElements(aOutAdditionalImages);
163 return mFilterDescription;
167 * Sets the aPostFilterDirtyRegion outparam to the post-filter area in frame
168 * space that would be dirtied by mTargetFrame when a given
169 * pre-filter area of mTargetFrame is dirtied. The pre-filter area must have
170 * been specified before calling this method by passing it as the
171 * aPreFilterDirtyRegion argument to the nsFilterInstance constructor.
173 nsRegion ComputePostFilterDirtyRegion();
176 * Sets the aPostFilterExtents outparam to the post-filter bounds in frame
177 * space for the whole filter output. This is not necessarily equivalent to
178 * the area that would be dirtied in the result when the entire pre-filter
179 * area is dirtied, because some filter primitives can generate output
180 * without any input.
182 nsRect ComputePostFilterExtents();
185 * Sets the aDirty outparam to the pre-filter bounds in frame space of the
186 * area of mTargetFrame that is needed in order to paint the filtered output
187 * for a given post-filter dirtied area. The post-filter area must have been
188 * specified before calling this method by passing it as the aPostFilterDirtyRegion
189 * argument to the nsFilterInstance constructor.
191 nsRect ComputeSourceNeededRect();
195 * Returns the transform from filter space to outer-<svg> device space.
197 gfxMatrix GetFilterSpaceToDeviceSpaceTransform() const {
198 return mFilterSpaceToDeviceSpaceTransform;
201 private:
202 struct SourceInfo {
203 // Specifies which parts of the source need to be rendered.
204 // Set by ComputeNeededBoxes().
205 nsIntRect mNeededBounds;
207 // The surface that contains the input rendering.
208 // Set by BuildSourceImage / BuildSourcePaint.
209 mozilla::RefPtr<SourceSurface> mSourceSurface;
211 // The position and size of mSourceSurface in filter space.
212 // Set by BuildSourceImage / BuildSourcePaint.
213 IntRect mSurfaceRect;
217 * Creates a SourceSurface for either the FillPaint or StrokePaint graph
218 * nodes
220 nsresult BuildSourcePaint(SourceInfo *aPrimitive,
221 DrawTarget* aTargetDT);
224 * Creates a SourceSurface for either the FillPaint and StrokePaint graph
225 * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and
226 * mStrokePaint.mSourceSurface respectively.
228 nsresult BuildSourcePaints(DrawTarget* aTargetDT);
231 * Creates the SourceSurface for the SourceGraphic graph node, paints its
232 * contents, and assigns it to mSourceGraphic.mSourceSurface.
234 nsresult BuildSourceImage(DrawTarget* aTargetDT);
237 * Build the list of FilterPrimitiveDescriptions that describes the filter's
238 * filter primitives and their connections. This populates
239 * mPrimitiveDescriptions and mInputImages.
241 nsresult BuildPrimitives(const nsTArray<nsStyleFilter>& aFilterChain);
244 * Add to the list of FilterPrimitiveDescriptions for a particular SVG
245 * reference filter or CSS filter. This populates mPrimitiveDescrs and
246 * mInputImages.
248 nsresult BuildPrimitivesForFilter(const nsStyleFilter& aFilter);
251 * Computes the filter space bounds of the areas that we actually *need* from
252 * the filter sources, based on the value of mPostFilterDirtyRegion.
253 * This sets mNeededBounds on the corresponding SourceInfo structs.
255 void ComputeNeededBoxes();
258 * Returns the output bounds of the final FilterPrimitiveDescription.
260 nsIntRect OutputFilterSpaceBounds() const;
263 * Compute the scale factors between user space and filter space.
265 nsresult ComputeUserSpaceToFilterSpaceScale();
268 * Transform a rect between user space and filter space.
270 gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpace) const;
271 gfxRect FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const;
274 * Converts an nsRect or an nsRegion that is relative to a filtered frame's
275 * origin (i.e. the top-left corner of its border box) into filter space,
276 * rounding out.
277 * Returns the entire filter region if aRect / aRegion is null, or if the
278 * result is too large to be stored in an nsIntRect.
280 nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const;
281 nsIntRegion FrameSpaceToFilterSpace(const nsRegion* aRegion) const;
284 * Converts an nsIntRect or an nsIntRegion from filter space into the space
285 * that is relative to a filtered frame's origin (i.e. the top-left corner
286 * of its border box) in app units, rounding out.
288 nsRect FilterSpaceToFrameSpace(const nsIntRect& aRect) const;
289 nsRegion FilterSpaceToFrameSpace(const nsIntRegion& aRegion) const;
292 * Returns the transform from frame space to the coordinate space that
293 * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the
294 * top-left corner of its border box, aka the top left corner of its mRect.
296 gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const;
299 * The frame for the element that is currently being filtered.
301 nsIFrame* mTargetFrame;
304 * The filtered element.
306 nsIContent* mTargetContent;
309 * The user space metrics of the filtered frame.
311 const UserSpaceMetrics& mMetrics;
313 nsSVGFilterPaintCallback* mPaintCallback;
316 * The SVG bbox of the element that is being filtered, in user space.
318 gfxRect mTargetBBox;
321 * The SVG bbox of the element that is being filtered, in filter space.
323 nsIntRect mTargetBBoxInFilterSpace;
326 * The transform from filter space to outer-<svg> device space.
328 gfxMatrix mFilterSpaceToDeviceSpaceTransform;
331 * Transform rects between filter space and frame space in CSS pixels.
333 gfxMatrix mFilterSpaceToFrameSpaceInCSSPxTransform;
334 gfxMatrix mFrameSpaceInCSSPxToFilterSpaceTransform;
337 * The scale factors between user space and filter space.
339 gfxSize mUserSpaceToFilterSpaceScale;
340 gfxSize mFilterSpaceToUserSpaceScale;
343 * Pre-filter paint bounds of the element that is being filtered, in filter
344 * space.
346 nsIntRect mTargetBounds;
349 * The dirty area that needs to be repainted, in filter space.
351 nsIntRegion mPostFilterDirtyRegion;
354 * The pre-filter area of the filtered element that changed, in filter space.
356 nsIntRegion mPreFilterDirtyRegion;
358 SourceInfo mSourceGraphic;
359 SourceInfo mFillPaint;
360 SourceInfo mStrokePaint;
363 * The transform to the SVG user space of mTargetFrame.
365 gfxMatrix mPaintTransform;
367 nsTArray<mozilla::RefPtr<SourceSurface>> mInputImages;
368 nsTArray<FilterPrimitiveDescription> mPrimitiveDescriptions;
369 FilterDescription mFilterDescription;
370 bool mInitialized;
373 #endif