Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
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 gfxASurface;
25 class nsIFrame;
26 class nsSVGFilterPaintCallback;
28 /**
29 * This class performs all filter processing.
30 *
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.
34 *
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
39 * painted.
40 *
41 * The definition of "filter region" can be found here:
42 * http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion
43 */
44 class nsFilterInstance
45 {
46 typedef mozilla::gfx::IntRect IntRect;
47 typedef mozilla::gfx::SourceSurface SourceSurface;
48 typedef mozilla::gfx::DrawTarget DrawTarget;
49 typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
51 public:
52 /**
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
56 * border box).
57 */
58 static nsresult PaintFilteredFrame(nsRenderingContext *aContext,
59 nsIFrame *aFilteredFrame,
60 nsSVGFilterPaintCallback *aPaintCallback,
61 const nsRegion* aDirtyArea,
62 nsIFrame* aTransformRoot = nullptr);
64 /**
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.
69 */
70 static nsRegion GetPostFilterDirtyArea(nsIFrame *aFilteredFrame,
71 const nsRegion& aPreFilterDirtyRegion);
73 /**
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.
78 */
79 static nsRegion GetPreFilterNeededArea(nsIFrame *aFilteredFrame,
80 const nsRegion& aPostFilterDirtyRegion);
82 /**
83 * Returns the post-filter visual overflow rect (paint bounds) of
84 * aFilteredFrame.
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.
89 */
90 static nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame,
91 const gfxRect *aOverrideBBox = nullptr,
92 const nsRect *aPreFilterBounds = nullptr);
94 /**
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
107 * element.
108 * @param aTransformRoot [optional] The transform root frame for painting.
109 */
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);
118 /**
119 * Returns true if the filter instance was created successfully.
120 */
121 bool IsInitialized() const { return mInitialized; }
123 /**
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.
128 */
129 nsresult Render(gfxContext* aContext);
131 /**
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.
137 */
138 nsresult ComputePostFilterDirtyRegion(nsRegion* aPostFilterDirtyRegion);
140 /**
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
145 * without any input.
146 */
147 nsresult ComputePostFilterExtents(nsRect* aPostFilterExtents);
149 /**
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.
155 */
156 nsresult ComputeSourceNeededRect(nsRect* aDirty);
159 /**
160 * Returns the transform from filter space to outer-<svg> device space.
161 */
162 gfxMatrix GetFilterSpaceToDeviceSpaceTransform() const {
163 return mFilterSpaceToDeviceSpaceTransform;
164 }
166 private:
167 struct SourceInfo {
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;
179 };
181 /**
182 * Creates a SourceSurface for either the FillPaint or StrokePaint graph
183 * nodes
184 */
185 nsresult BuildSourcePaint(SourceInfo *aPrimitive,
186 gfxASurface* aTargetSurface,
187 DrawTarget* aTargetDT);
189 /**
190 * Creates a SourceSurface for either the FillPaint and StrokePaint graph
191 * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and
192 * mStrokePaint.mSourceSurface respectively.
193 */
194 nsresult BuildSourcePaints(gfxASurface* aTargetSurface,
195 DrawTarget* aTargetDT);
197 /**
198 * Creates the SourceSurface for the SourceGraphic graph node, paints its
199 * contents, and assigns it to mSourceGraphic.mSourceSurface.
200 */
201 nsresult BuildSourceImage(gfxASurface* aTargetSurface,
202 DrawTarget* aTargetDT);
204 /**
205 * Build the list of FilterPrimitiveDescriptions that describes the filter's
206 * filter primitives and their connections. This populates
207 * mPrimitiveDescriptions and mInputImages.
208 */
209 nsresult BuildPrimitives();
211 /**
212 * Add to the list of FilterPrimitiveDescriptions for a particular SVG
213 * reference filter or CSS filter. This populates mPrimitiveDescrs and
214 * mInputImages.
215 */
216 nsresult BuildPrimitivesForFilter(const nsStyleFilter& aFilter);
218 /**
219 * Computes the filter space bounds of the areas that we actually *need* from
220 * the filter sources, based on the value of mPostFilterDirtyRegion.
221 * This sets mNeededBounds on the corresponding SourceInfo structs.
222 */
223 void ComputeNeededBoxes();
225 /**
226 * Compute the scale factors between user space and filter space.
227 */
228 nsresult ComputeUserSpaceToFilterSpaceScale();
230 /**
231 * Transform a rect between user space and filter space.
232 */
233 gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpace) const;
234 gfxRect FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const;
236 /**
237 * Converts an nsRect or an nsRegion that is relative to a filtered frame's
238 * origin (i.e. the top-left corner of its border box) into filter space,
239 * rounding out.
240 * Returns the entire filter region if aRect / aRegion is null, or if the
241 * result is too large to be stored in an nsIntRect.
242 */
243 nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const;
244 nsIntRegion FrameSpaceToFilterSpace(const nsRegion* aRegion) const;
246 /**
247 * Converts an nsIntRect or an nsIntRegion from filter space into the space
248 * that is relative to a filtered frame's origin (i.e. the top-left corner
249 * of its border box) in app units, rounding out.
250 */
251 nsRect FilterSpaceToFrameSpace(const nsIntRect& aRect) const;
252 nsRegion FilterSpaceToFrameSpace(const nsIntRegion& aRegion) const;
254 /**
255 * Returns the transform from frame space to the coordinate space that
256 * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the
257 * top-left corner of its border box, aka the top left corner of its mRect.
258 */
259 gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const;
261 /**
262 * The frame for the element that is currently being filtered.
263 */
264 nsIFrame* mTargetFrame;
266 nsSVGFilterPaintCallback* mPaintCallback;
268 /**
269 * The SVG bbox of the element that is being filtered, in user space.
270 */
271 gfxRect mTargetBBox;
273 /**
274 * The transform from filter space to outer-<svg> device space.
275 */
276 gfxMatrix mFilterSpaceToDeviceSpaceTransform;
278 /**
279 * Transform rects between filter space and frame space in CSS pixels.
280 */
281 gfxMatrix mFilterSpaceToFrameSpaceInCSSPxTransform;
282 gfxMatrix mFrameSpaceInCSSPxToFilterSpaceTransform;
284 /**
285 * The "filter region", in the filtered element's user space.
286 */
287 gfxRect mUserSpaceBounds;
288 nsIntRect mFilterSpaceBounds;
290 /**
291 * The scale factors between user space and filter space.
292 */
293 gfxSize mUserSpaceToFilterSpaceScale;
294 gfxSize mFilterSpaceToUserSpaceScale;
296 /**
297 * Pre-filter paint bounds of the element that is being filtered, in filter
298 * space.
299 */
300 nsIntRect mTargetBounds;
302 /**
303 * The dirty area that needs to be repainted, in filter space.
304 */
305 nsIntRegion mPostFilterDirtyRegion;
307 /**
308 * The pre-filter area of the filtered element that changed, in filter space.
309 */
310 nsIntRegion mPreFilterDirtyRegion;
312 SourceInfo mSourceGraphic;
313 SourceInfo mFillPaint;
314 SourceInfo mStrokePaint;
315 nsIFrame* mTransformRoot;
316 nsTArray<mozilla::RefPtr<SourceSurface>> mInputImages;
317 nsTArray<FilterPrimitiveDescription> mPrimitiveDescriptions;
318 int32_t mAppUnitsPerCSSPx;
319 bool mInitialized;
320 };
322 #endif