Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #ifndef __NS_FILTERINSTANCE_H__ |
michael@0 | 7 | #define __NS_FILTERINSTANCE_H__ |
michael@0 | 8 | |
michael@0 | 9 | #include "gfxMatrix.h" |
michael@0 | 10 | #include "gfxPoint.h" |
michael@0 | 11 | #include "gfxRect.h" |
michael@0 | 12 | #include "nsCOMPtr.h" |
michael@0 | 13 | #include "nsHashKeys.h" |
michael@0 | 14 | #include "nsPoint.h" |
michael@0 | 15 | #include "nsRect.h" |
michael@0 | 16 | #include "nsSize.h" |
michael@0 | 17 | #include "nsSVGFilters.h" |
michael@0 | 18 | #include "nsSVGNumber2.h" |
michael@0 | 19 | #include "nsSVGNumberPair.h" |
michael@0 | 20 | #include "nsTArray.h" |
michael@0 | 21 | #include "nsIFrame.h" |
michael@0 | 22 | #include "mozilla/gfx/2D.h" |
michael@0 | 23 | |
michael@0 | 24 | class gfxASurface; |
michael@0 | 25 | class nsIFrame; |
michael@0 | 26 | class nsSVGFilterPaintCallback; |
michael@0 | 27 | |
michael@0 | 28 | /** |
michael@0 | 29 | * This class performs all filter processing. |
michael@0 | 30 | * |
michael@0 | 31 | * We build a graph of the filter image data flow, essentially |
michael@0 | 32 | * converting the filter graph to SSA. This lets us easily propagate |
michael@0 | 33 | * analysis data (such as bounding-boxes) over the filter primitive graph. |
michael@0 | 34 | * |
michael@0 | 35 | * Definition of "filter space": filter space is a coordinate system that is |
michael@0 | 36 | * aligned with the user space of the filtered element, with its origin located |
michael@0 | 37 | * at the top left of the filter region, and with one unit equal in size to one |
michael@0 | 38 | * pixel of the offscreen surface into which the filter output would/will be |
michael@0 | 39 | * painted. |
michael@0 | 40 | * |
michael@0 | 41 | * The definition of "filter region" can be found here: |
michael@0 | 42 | * http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion |
michael@0 | 43 | */ |
michael@0 | 44 | class nsFilterInstance |
michael@0 | 45 | { |
michael@0 | 46 | typedef mozilla::gfx::IntRect IntRect; |
michael@0 | 47 | typedef mozilla::gfx::SourceSurface SourceSurface; |
michael@0 | 48 | typedef mozilla::gfx::DrawTarget DrawTarget; |
michael@0 | 49 | typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription; |
michael@0 | 50 | |
michael@0 | 51 | public: |
michael@0 | 52 | /** |
michael@0 | 53 | * Paint the given filtered frame. |
michael@0 | 54 | * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's |
michael@0 | 55 | * frame space (i.e. relative to its origin, the top-left corner of its |
michael@0 | 56 | * border box). |
michael@0 | 57 | */ |
michael@0 | 58 | static nsresult PaintFilteredFrame(nsRenderingContext *aContext, |
michael@0 | 59 | nsIFrame *aFilteredFrame, |
michael@0 | 60 | nsSVGFilterPaintCallback *aPaintCallback, |
michael@0 | 61 | const nsRegion* aDirtyArea, |
michael@0 | 62 | nsIFrame* aTransformRoot = nullptr); |
michael@0 | 63 | |
michael@0 | 64 | /** |
michael@0 | 65 | * Returns the post-filter area that could be dirtied when the given |
michael@0 | 66 | * pre-filter area of aFilteredFrame changes. |
michael@0 | 67 | * @param aPreFilterDirtyRegion The pre-filter area of aFilteredFrame that has |
michael@0 | 68 | * changed, relative to aFilteredFrame, in app units. |
michael@0 | 69 | */ |
michael@0 | 70 | static nsRegion GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, |
michael@0 | 71 | const nsRegion& aPreFilterDirtyRegion); |
michael@0 | 72 | |
michael@0 | 73 | /** |
michael@0 | 74 | * Returns the pre-filter area that is needed from aFilteredFrame when the |
michael@0 | 75 | * given post-filter area needs to be repainted. |
michael@0 | 76 | * @param aPostFilterDirtyRegion The post-filter area that is dirty, relative |
michael@0 | 77 | * to aFilteredFrame, in app units. |
michael@0 | 78 | */ |
michael@0 | 79 | static nsRegion GetPreFilterNeededArea(nsIFrame *aFilteredFrame, |
michael@0 | 80 | const nsRegion& aPostFilterDirtyRegion); |
michael@0 | 81 | |
michael@0 | 82 | /** |
michael@0 | 83 | * Returns the post-filter visual overflow rect (paint bounds) of |
michael@0 | 84 | * aFilteredFrame. |
michael@0 | 85 | * @param aOverrideBBox A user space rect, in user units, that should be used |
michael@0 | 86 | * as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null. |
michael@0 | 87 | * @param aPreFilterBounds The pre-filter visual overflow rect of |
michael@0 | 88 | * aFilteredFrame, if non-null. |
michael@0 | 89 | */ |
michael@0 | 90 | static nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame, |
michael@0 | 91 | const gfxRect *aOverrideBBox = nullptr, |
michael@0 | 92 | const nsRect *aPreFilterBounds = nullptr); |
michael@0 | 93 | |
michael@0 | 94 | /** |
michael@0 | 95 | * @param aTargetFrame The frame of the filtered element under consideration. |
michael@0 | 96 | * @param aPaintCallback [optional] The callback that Render() should use to |
michael@0 | 97 | * paint. Only required if you will call Render(). |
michael@0 | 98 | * @param aPostFilterDirtyRegion [optional] The post-filter area |
michael@0 | 99 | * that has to be repainted, in app units. Only required if you will |
michael@0 | 100 | * call ComputeSourceNeededRect() or Render(). |
michael@0 | 101 | * @param aPreFilterDirtyRegion [optional] The pre-filter area of |
michael@0 | 102 | * the filtered element that changed, in app units. Only required if you |
michael@0 | 103 | * will call ComputePostFilterDirtyRegion(). |
michael@0 | 104 | * @param aOverridePreFilterVisualOverflowRect [optional] Use a different |
michael@0 | 105 | * visual overflow rect for the target element. |
michael@0 | 106 | * @param aOverrideBBox [optional] Use a different SVG bbox for the target |
michael@0 | 107 | * element. |
michael@0 | 108 | * @param aTransformRoot [optional] The transform root frame for painting. |
michael@0 | 109 | */ |
michael@0 | 110 | nsFilterInstance(nsIFrame *aTargetFrame, |
michael@0 | 111 | nsSVGFilterPaintCallback *aPaintCallback, |
michael@0 | 112 | const nsRegion *aPostFilterDirtyRegion = nullptr, |
michael@0 | 113 | const nsRegion *aPreFilterDirtyRegion = nullptr, |
michael@0 | 114 | const nsRect *aOverridePreFilterVisualOverflowRect = nullptr, |
michael@0 | 115 | const gfxRect *aOverrideBBox = nullptr, |
michael@0 | 116 | nsIFrame* aTransformRoot = nullptr); |
michael@0 | 117 | |
michael@0 | 118 | /** |
michael@0 | 119 | * Returns true if the filter instance was created successfully. |
michael@0 | 120 | */ |
michael@0 | 121 | bool IsInitialized() const { return mInitialized; } |
michael@0 | 122 | |
michael@0 | 123 | /** |
michael@0 | 124 | * Draws the filter output into aContext. The area that |
michael@0 | 125 | * needs to be painted must have been specified before calling this method |
michael@0 | 126 | * by passing it as the aPostFilterDirtyRegion argument to the |
michael@0 | 127 | * nsFilterInstance constructor. |
michael@0 | 128 | */ |
michael@0 | 129 | nsresult Render(gfxContext* aContext); |
michael@0 | 130 | |
michael@0 | 131 | /** |
michael@0 | 132 | * Sets the aPostFilterDirtyRegion outparam to the post-filter area in frame |
michael@0 | 133 | * space that would be dirtied by mTargetFrame when a given |
michael@0 | 134 | * pre-filter area of mTargetFrame is dirtied. The pre-filter area must have |
michael@0 | 135 | * been specified before calling this method by passing it as the |
michael@0 | 136 | * aPreFilterDirtyRegion argument to the nsFilterInstance constructor. |
michael@0 | 137 | */ |
michael@0 | 138 | nsresult ComputePostFilterDirtyRegion(nsRegion* aPostFilterDirtyRegion); |
michael@0 | 139 | |
michael@0 | 140 | /** |
michael@0 | 141 | * Sets the aPostFilterExtents outparam to the post-filter bounds in frame |
michael@0 | 142 | * space for the whole filter output. This is not necessarily equivalent to |
michael@0 | 143 | * the area that would be dirtied in the result when the entire pre-filter |
michael@0 | 144 | * area is dirtied, because some filter primitives can generate output |
michael@0 | 145 | * without any input. |
michael@0 | 146 | */ |
michael@0 | 147 | nsresult ComputePostFilterExtents(nsRect* aPostFilterExtents); |
michael@0 | 148 | |
michael@0 | 149 | /** |
michael@0 | 150 | * Sets the aDirty outparam to the pre-filter bounds in frame space of the |
michael@0 | 151 | * area of mTargetFrame that is needed in order to paint the filtered output |
michael@0 | 152 | * for a given post-filter dirtied area. The post-filter area must have been |
michael@0 | 153 | * specified before calling this method by passing it as the aPostFilterDirtyRegion |
michael@0 | 154 | * argument to the nsFilterInstance constructor. |
michael@0 | 155 | */ |
michael@0 | 156 | nsresult ComputeSourceNeededRect(nsRect* aDirty); |
michael@0 | 157 | |
michael@0 | 158 | |
michael@0 | 159 | /** |
michael@0 | 160 | * Returns the transform from filter space to outer-<svg> device space. |
michael@0 | 161 | */ |
michael@0 | 162 | gfxMatrix GetFilterSpaceToDeviceSpaceTransform() const { |
michael@0 | 163 | return mFilterSpaceToDeviceSpaceTransform; |
michael@0 | 164 | } |
michael@0 | 165 | |
michael@0 | 166 | private: |
michael@0 | 167 | struct SourceInfo { |
michael@0 | 168 | // Specifies which parts of the source need to be rendered. |
michael@0 | 169 | // Set by ComputeNeededBoxes(). |
michael@0 | 170 | nsIntRect mNeededBounds; |
michael@0 | 171 | |
michael@0 | 172 | // The surface that contains the input rendering. |
michael@0 | 173 | // Set by BuildSourceImage / BuildSourcePaint. |
michael@0 | 174 | mozilla::RefPtr<SourceSurface> mSourceSurface; |
michael@0 | 175 | |
michael@0 | 176 | // The position and size of mSourceSurface in filter space. |
michael@0 | 177 | // Set by BuildSourceImage / BuildSourcePaint. |
michael@0 | 178 | IntRect mSurfaceRect; |
michael@0 | 179 | }; |
michael@0 | 180 | |
michael@0 | 181 | /** |
michael@0 | 182 | * Creates a SourceSurface for either the FillPaint or StrokePaint graph |
michael@0 | 183 | * nodes |
michael@0 | 184 | */ |
michael@0 | 185 | nsresult BuildSourcePaint(SourceInfo *aPrimitive, |
michael@0 | 186 | gfxASurface* aTargetSurface, |
michael@0 | 187 | DrawTarget* aTargetDT); |
michael@0 | 188 | |
michael@0 | 189 | /** |
michael@0 | 190 | * Creates a SourceSurface for either the FillPaint and StrokePaint graph |
michael@0 | 191 | * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and |
michael@0 | 192 | * mStrokePaint.mSourceSurface respectively. |
michael@0 | 193 | */ |
michael@0 | 194 | nsresult BuildSourcePaints(gfxASurface* aTargetSurface, |
michael@0 | 195 | DrawTarget* aTargetDT); |
michael@0 | 196 | |
michael@0 | 197 | /** |
michael@0 | 198 | * Creates the SourceSurface for the SourceGraphic graph node, paints its |
michael@0 | 199 | * contents, and assigns it to mSourceGraphic.mSourceSurface. |
michael@0 | 200 | */ |
michael@0 | 201 | nsresult BuildSourceImage(gfxASurface* aTargetSurface, |
michael@0 | 202 | DrawTarget* aTargetDT); |
michael@0 | 203 | |
michael@0 | 204 | /** |
michael@0 | 205 | * Build the list of FilterPrimitiveDescriptions that describes the filter's |
michael@0 | 206 | * filter primitives and their connections. This populates |
michael@0 | 207 | * mPrimitiveDescriptions and mInputImages. |
michael@0 | 208 | */ |
michael@0 | 209 | nsresult BuildPrimitives(); |
michael@0 | 210 | |
michael@0 | 211 | /** |
michael@0 | 212 | * Add to the list of FilterPrimitiveDescriptions for a particular SVG |
michael@0 | 213 | * reference filter or CSS filter. This populates mPrimitiveDescrs and |
michael@0 | 214 | * mInputImages. |
michael@0 | 215 | */ |
michael@0 | 216 | nsresult BuildPrimitivesForFilter(const nsStyleFilter& aFilter); |
michael@0 | 217 | |
michael@0 | 218 | /** |
michael@0 | 219 | * Computes the filter space bounds of the areas that we actually *need* from |
michael@0 | 220 | * the filter sources, based on the value of mPostFilterDirtyRegion. |
michael@0 | 221 | * This sets mNeededBounds on the corresponding SourceInfo structs. |
michael@0 | 222 | */ |
michael@0 | 223 | void ComputeNeededBoxes(); |
michael@0 | 224 | |
michael@0 | 225 | /** |
michael@0 | 226 | * Compute the scale factors between user space and filter space. |
michael@0 | 227 | */ |
michael@0 | 228 | nsresult ComputeUserSpaceToFilterSpaceScale(); |
michael@0 | 229 | |
michael@0 | 230 | /** |
michael@0 | 231 | * Transform a rect between user space and filter space. |
michael@0 | 232 | */ |
michael@0 | 233 | gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpace) const; |
michael@0 | 234 | gfxRect FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const; |
michael@0 | 235 | |
michael@0 | 236 | /** |
michael@0 | 237 | * Converts an nsRect or an nsRegion that is relative to a filtered frame's |
michael@0 | 238 | * origin (i.e. the top-left corner of its border box) into filter space, |
michael@0 | 239 | * rounding out. |
michael@0 | 240 | * Returns the entire filter region if aRect / aRegion is null, or if the |
michael@0 | 241 | * result is too large to be stored in an nsIntRect. |
michael@0 | 242 | */ |
michael@0 | 243 | nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const; |
michael@0 | 244 | nsIntRegion FrameSpaceToFilterSpace(const nsRegion* aRegion) const; |
michael@0 | 245 | |
michael@0 | 246 | /** |
michael@0 | 247 | * Converts an nsIntRect or an nsIntRegion from filter space into the space |
michael@0 | 248 | * that is relative to a filtered frame's origin (i.e. the top-left corner |
michael@0 | 249 | * of its border box) in app units, rounding out. |
michael@0 | 250 | */ |
michael@0 | 251 | nsRect FilterSpaceToFrameSpace(const nsIntRect& aRect) const; |
michael@0 | 252 | nsRegion FilterSpaceToFrameSpace(const nsIntRegion& aRegion) const; |
michael@0 | 253 | |
michael@0 | 254 | /** |
michael@0 | 255 | * Returns the transform from frame space to the coordinate space that |
michael@0 | 256 | * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the |
michael@0 | 257 | * top-left corner of its border box, aka the top left corner of its mRect. |
michael@0 | 258 | */ |
michael@0 | 259 | gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const; |
michael@0 | 260 | |
michael@0 | 261 | /** |
michael@0 | 262 | * The frame for the element that is currently being filtered. |
michael@0 | 263 | */ |
michael@0 | 264 | nsIFrame* mTargetFrame; |
michael@0 | 265 | |
michael@0 | 266 | nsSVGFilterPaintCallback* mPaintCallback; |
michael@0 | 267 | |
michael@0 | 268 | /** |
michael@0 | 269 | * The SVG bbox of the element that is being filtered, in user space. |
michael@0 | 270 | */ |
michael@0 | 271 | gfxRect mTargetBBox; |
michael@0 | 272 | |
michael@0 | 273 | /** |
michael@0 | 274 | * The transform from filter space to outer-<svg> device space. |
michael@0 | 275 | */ |
michael@0 | 276 | gfxMatrix mFilterSpaceToDeviceSpaceTransform; |
michael@0 | 277 | |
michael@0 | 278 | /** |
michael@0 | 279 | * Transform rects between filter space and frame space in CSS pixels. |
michael@0 | 280 | */ |
michael@0 | 281 | gfxMatrix mFilterSpaceToFrameSpaceInCSSPxTransform; |
michael@0 | 282 | gfxMatrix mFrameSpaceInCSSPxToFilterSpaceTransform; |
michael@0 | 283 | |
michael@0 | 284 | /** |
michael@0 | 285 | * The "filter region", in the filtered element's user space. |
michael@0 | 286 | */ |
michael@0 | 287 | gfxRect mUserSpaceBounds; |
michael@0 | 288 | nsIntRect mFilterSpaceBounds; |
michael@0 | 289 | |
michael@0 | 290 | /** |
michael@0 | 291 | * The scale factors between user space and filter space. |
michael@0 | 292 | */ |
michael@0 | 293 | gfxSize mUserSpaceToFilterSpaceScale; |
michael@0 | 294 | gfxSize mFilterSpaceToUserSpaceScale; |
michael@0 | 295 | |
michael@0 | 296 | /** |
michael@0 | 297 | * Pre-filter paint bounds of the element that is being filtered, in filter |
michael@0 | 298 | * space. |
michael@0 | 299 | */ |
michael@0 | 300 | nsIntRect mTargetBounds; |
michael@0 | 301 | |
michael@0 | 302 | /** |
michael@0 | 303 | * The dirty area that needs to be repainted, in filter space. |
michael@0 | 304 | */ |
michael@0 | 305 | nsIntRegion mPostFilterDirtyRegion; |
michael@0 | 306 | |
michael@0 | 307 | /** |
michael@0 | 308 | * The pre-filter area of the filtered element that changed, in filter space. |
michael@0 | 309 | */ |
michael@0 | 310 | nsIntRegion mPreFilterDirtyRegion; |
michael@0 | 311 | |
michael@0 | 312 | SourceInfo mSourceGraphic; |
michael@0 | 313 | SourceInfo mFillPaint; |
michael@0 | 314 | SourceInfo mStrokePaint; |
michael@0 | 315 | nsIFrame* mTransformRoot; |
michael@0 | 316 | nsTArray<mozilla::RefPtr<SourceSurface>> mInputImages; |
michael@0 | 317 | nsTArray<FilterPrimitiveDescription> mPrimitiveDescriptions; |
michael@0 | 318 | int32_t mAppUnitsPerCSSPx; |
michael@0 | 319 | bool mInitialized; |
michael@0 | 320 | }; |
michael@0 | 321 | |
michael@0 | 322 | #endif |