1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/svg/nsSVGFilterInstance.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,246 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef __NS_SVGFILTERINSTANCE_H__ 1.10 +#define __NS_SVGFILTERINSTANCE_H__ 1.11 + 1.12 +#include "gfxMatrix.h" 1.13 +#include "gfxRect.h" 1.14 +#include "nsSVGFilters.h" 1.15 +#include "nsSVGNumber2.h" 1.16 +#include "nsSVGNumberPair.h" 1.17 +#include "nsTArray.h" 1.18 +#include "nsIFrame.h" 1.19 + 1.20 +class nsIFrame; 1.21 +class nsSVGFilterFrame; 1.22 +class nsSVGFilterPaintCallback; 1.23 + 1.24 +namespace mozilla { 1.25 +namespace dom { 1.26 +class SVGFilterElement; 1.27 +} 1.28 +} 1.29 + 1.30 +/** 1.31 + * This class helps nsFilterInstance build its filter graph by processing a 1.32 + * single SVG reference filter. 1.33 + * 1.34 + * In BuildPrimitives, this class iterates through the referenced <filter> 1.35 + * element's primitive elements, creating a FilterPrimitiveDescription for 1.36 + * each one. 1.37 + * 1.38 + * This class uses several different coordinate spaces, defined as follows: 1.39 + * 1.40 + * "user space" 1.41 + * The filtered SVG element's user space or the filtered HTML element's 1.42 + * CSS pixel space. The origin for an HTML element is the top left corner of 1.43 + * its border box. 1.44 + * 1.45 + * "filter space" 1.46 + * User space scaled to device pixels. Shares the same origin as user space. 1.47 + * This space is the same across chained SVG and CSS filters. To compute the 1.48 + * overall filter space for a chain, we first need to build each filter's 1.49 + * FilterPrimitiveDescriptions in some common space. That space is 1.50 + * filter space. 1.51 + * 1.52 + * To understand the spaces better, let's take an example filter: 1.53 + * <filter id="f">...</filter> 1.54 + * 1.55 + * And apply the filter to a div element: 1.56 + * <div style="filter: url(#f); ...">...</div> 1.57 + * 1.58 + * And let's say there are 2 device pixels for every 1 CSS pixel. 1.59 + * 1.60 + * Finally, let's define an arbitrary point in user space: 1.61 + * "user space point" = (10, 10) 1.62 + * 1.63 + * The point will be inset 10 CSS pixels from both the top and left edges of the 1.64 + * div element's border box. 1.65 + * 1.66 + * Now, let's transform the point from user space to filter space: 1.67 + * "filter space point" = "user space point" * "device pixels per CSS pixel" 1.68 + * "filter space point" = (10, 10) * 2 1.69 + * "filter space point" = (20, 20) 1.70 + */ 1.71 +class nsSVGFilterInstance 1.72 +{ 1.73 + typedef mozilla::gfx::Point3D Point3D; 1.74 + typedef mozilla::gfx::IntRect IntRect; 1.75 + typedef mozilla::gfx::SourceSurface SourceSurface; 1.76 + typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription; 1.77 + 1.78 +public: 1.79 + /** 1.80 + * @param aFilter The SVG reference filter to process. 1.81 + * @param aTargetFrame The frame of the filtered element under consideration. 1.82 + * @param aTargetBBox The SVG bbox to use for the target frame, computed by 1.83 + * the caller. The caller may decide to override the actual SVG bbox. 1.84 + */ 1.85 + nsSVGFilterInstance(const nsStyleFilter& aFilter, 1.86 + nsIFrame *aTargetFrame, 1.87 + const gfxRect& aTargetBBox, 1.88 + const gfxSize& aUserSpaceToFilterSpaceScale, 1.89 + const gfxSize& aFilterSpaceToUserSpaceScale); 1.90 + 1.91 + /** 1.92 + * Returns true if the filter instance was created successfully. 1.93 + */ 1.94 + bool IsInitialized() const { return mInitialized; } 1.95 + 1.96 + /** 1.97 + * Iterates through the <filter> element's primitive elements, creating a 1.98 + * FilterPrimitiveDescription for each one. Appends the new 1.99 + * FilterPrimitiveDescription(s) to the aPrimitiveDescrs list. Also, appends 1.100 + * new images from feImage filter primitive elements to the aInputImages list. 1.101 + */ 1.102 + nsresult BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, 1.103 + nsTArray<mozilla::RefPtr<SourceSurface>>& aInputImages); 1.104 + 1.105 + /** 1.106 + * Returns the user specified "filter region", in the filtered element's user 1.107 + * space, after it has been adjusted out (if necessary) so that its edges 1.108 + * coincide with pixel boundaries of the offscreen surface into which the 1.109 + * filtered output would/will be painted. 1.110 + */ 1.111 + gfxRect GetFilterRegion() const { return mUserSpaceBounds; } 1.112 + 1.113 + /** 1.114 + * Returns the size of the user specified "filter region", in filter space. 1.115 + */ 1.116 + nsIntRect GetFilterSpaceBounds() const { return mFilterSpaceBounds; } 1.117 + 1.118 + float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumber2 *aNumber) const 1.119 + { 1.120 + return GetPrimitiveNumber(aCtxType, aNumber->GetAnimValue()); 1.121 + } 1.122 + float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumberPair *aNumberPair, 1.123 + nsSVGNumberPair::PairIndex aIndex) const 1.124 + { 1.125 + return GetPrimitiveNumber(aCtxType, aNumberPair->GetAnimValue(aIndex)); 1.126 + } 1.127 + 1.128 + /** 1.129 + * Converts a userSpaceOnUse/objectBoundingBoxUnits unitless point 1.130 + * into filter space, depending on the value of mPrimitiveUnits. (For 1.131 + * objectBoundingBoxUnits, the bounding box offset is applied to the point.) 1.132 + */ 1.133 + Point3D ConvertLocation(const Point3D& aPoint) const; 1.134 + 1.135 + /** 1.136 + * Transform a rect between user space and filter space. 1.137 + */ 1.138 + gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpaceRect) const; 1.139 + 1.140 +private: 1.141 + /** 1.142 + * Finds the filter frame associated with this SVG filter. 1.143 + */ 1.144 + nsSVGFilterFrame* GetFilterFrame(); 1.145 + 1.146 + /** 1.147 + * Computes the filter primitive subregion for the given primitive. 1.148 + */ 1.149 + IntRect ComputeFilterPrimitiveSubregion(nsSVGFE* aFilterElement, 1.150 + const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, 1.151 + const nsTArray<int32_t>& aInputIndices); 1.152 + 1.153 + /** 1.154 + * Takes the input indices of a filter primitive and returns for each input 1.155 + * whether the input's output is tainted. 1.156 + */ 1.157 + void GetInputsAreTainted(const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, 1.158 + const nsTArray<int32_t>& aInputIndices, 1.159 + nsTArray<bool>& aOutInputsAreTainted); 1.160 + 1.161 + /** 1.162 + * Scales a numeric filter primitive length in the X, Y or "XY" directions 1.163 + * into a length in filter space (no offset is applied). 1.164 + */ 1.165 + float GetPrimitiveNumber(uint8_t aCtxType, float aValue) const; 1.166 + 1.167 + /** 1.168 + * Transform a rect between user space and filter space. 1.169 + */ 1.170 + gfxRect FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const; 1.171 + 1.172 + /** 1.173 + * Returns the transform from frame space to the coordinate space that 1.174 + * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the 1.175 + * top-left corner of its border box, aka the top left corner of its mRect. 1.176 + */ 1.177 + gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const; 1.178 + 1.179 + /** 1.180 + * Finds the index in aPrimitiveDescrs of each input to aPrimitiveElement. 1.181 + * For example, if aPrimitiveElement is: 1.182 + * <feGaussianBlur in="another-primitive" .../> 1.183 + * Then, the resulting aSourceIndices will contain the index of the 1.184 + * FilterPrimitiveDescription representing "another-primitive". 1.185 + */ 1.186 + nsresult GetSourceIndices(nsSVGFE* aPrimitiveElement, 1.187 + const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs, 1.188 + const nsDataHashtable<nsStringHashKey, int32_t>& aImageTable, 1.189 + nsTArray<int32_t>& aSourceIndices); 1.190 + 1.191 + /** 1.192 + * Compute the filter region in user space, filter space, and filter 1.193 + * space. 1.194 + */ 1.195 + nsresult ComputeBounds(); 1.196 + 1.197 + /** 1.198 + * The SVG reference filter originally from the style system. 1.199 + */ 1.200 + const nsStyleFilter mFilter; 1.201 + 1.202 + /** 1.203 + * The frame for the element that is currently being filtered. 1.204 + */ 1.205 + nsIFrame* mTargetFrame; 1.206 + 1.207 + /** 1.208 + * The filter element referenced by mTargetFrame's element. 1.209 + */ 1.210 + const mozilla::dom::SVGFilterElement* mFilterElement; 1.211 + 1.212 + /** 1.213 + * The frame for the SVG filter element. 1.214 + */ 1.215 + nsSVGFilterFrame* mFilterFrame; 1.216 + 1.217 + /** 1.218 + * The SVG bbox of the element that is being filtered, in user space. 1.219 + */ 1.220 + gfxRect mTargetBBox; 1.221 + 1.222 + /** 1.223 + * The "filter region" in various spaces. 1.224 + */ 1.225 + gfxRect mUserSpaceBounds; 1.226 + nsIntRect mFilterSpaceBounds; 1.227 + 1.228 + /** 1.229 + * The scale factors between user space and filter space. 1.230 + */ 1.231 + gfxSize mUserSpaceToFilterSpaceScale; 1.232 + gfxSize mFilterSpaceToUserSpaceScale; 1.233 + 1.234 + /** 1.235 + * The 'primitiveUnits' attribute value (objectBoundingBox or userSpaceOnUse). 1.236 + */ 1.237 + uint16_t mPrimitiveUnits; 1.238 + 1.239 + /** 1.240 + * The index of the FilterPrimitiveDescription that this SVG filter should use 1.241 + * as its SourceGraphic, or the SourceGraphic keyword index if this is the 1.242 + * first filter in a chain. 1.243 + */ 1.244 + int32_t mSourceGraphicIndex; 1.245 + 1.246 + bool mInitialized; 1.247 +}; 1.248 + 1.249 +#endif