summaryrefslogtreecommitdiffstats
path: root/layout/svg/SVGFilterInstance.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/svg/SVGFilterInstance.h')
-rw-r--r--layout/svg/SVGFilterInstance.h262
1 files changed, 262 insertions, 0 deletions
diff --git a/layout/svg/SVGFilterInstance.h b/layout/svg/SVGFilterInstance.h
new file mode 100644
index 0000000000..3c67db308f
--- /dev/null
+++ b/layout/svg/SVGFilterInstance.h
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef LAYOUT_SVG_SVGFILTERINSTANCE_H_
+#define LAYOUT_SVG_SVGFILTERINSTANCE_H_
+
+#include "gfxMatrix.h"
+#include "gfxRect.h"
+#include "SVGAnimatedNumber.h"
+#include "SVGAnimatedNumberPair.h"
+#include "SVGFilters.h"
+#include "mozilla/ServoStyleConsts.h"
+
+namespace mozilla {
+class SVGFilterFrame;
+
+namespace dom {
+class SVGFilterElement;
+} // namespace dom
+
+/**
+ * This class helps FilterInstance build its filter graph by processing a
+ * single SVG reference filter.
+ *
+ * In BuildPrimitives, this class iterates through the referenced <filter>
+ * element's primitive elements, creating a FilterPrimitiveDescription for
+ * each one.
+ *
+ * This class uses several different coordinate spaces, defined as follows:
+ *
+ * "user space"
+ * The filtered SVG element's user space or the filtered HTML element's
+ * CSS pixel space. The origin for an HTML element is the top left corner of
+ * its border box.
+ *
+ * "filter space"
+ * User space scaled to device pixels. Shares the same origin as user space.
+ * This space is the same across chained SVG and CSS filters. To compute the
+ * overall filter space for a chain, we first need to build each filter's
+ * FilterPrimitiveDescriptions in some common space. That space is
+ * filter space.
+ *
+ * To understand the spaces better, let's take an example filter:
+ * <filter id="f">...</filter>
+ *
+ * And apply the filter to a div element:
+ * <div style="filter: url(#f); ...">...</div>
+ *
+ * And let's say there are 2 device pixels for every 1 CSS pixel.
+ *
+ * Finally, let's define an arbitrary point in user space:
+ * "user space point" = (10, 10)
+ *
+ * The point will be inset 10 CSS pixels from both the top and left edges of the
+ * div element's border box.
+ *
+ * Now, let's transform the point from user space to filter space:
+ * "filter space point" = "user space point" * "device pixels per CSS pixel"
+ * "filter space point" = (10, 10) * 2
+ * "filter space point" = (20, 20)
+ */
+class SVGFilterInstance {
+ using Point3D = gfx::Point3D;
+ using IntRect = gfx::IntRect;
+ using SourceSurface = gfx::SourceSurface;
+ using FilterPrimitiveDescription = gfx::FilterPrimitiveDescription;
+ using SVGFilterPrimitiveElement = dom::SVGFilterPrimitiveElement;
+ using UserSpaceMetrics = dom::UserSpaceMetrics;
+
+ public:
+ /**
+ * @param aFilter The SVG filter reference from the style system. This class
+ * stores aFilter by reference, so callers should avoid modifying or
+ * deleting aFilter during the lifetime of SVGFilterInstance.
+ * @param aTargetContent The filtered element.
+ * @param aTargetBBox The SVG bbox to use for the target frame, computed by
+ * the caller. The caller may decide to override the actual SVG bbox.
+ */
+ SVGFilterInstance(
+ const StyleFilter& aFilter, SVGFilterFrame* aFilterFrame,
+ nsIContent* aTargetContent, const UserSpaceMetrics& aMetrics,
+ const gfxRect& aTargetBBox,
+ const gfx::MatrixScalesDouble& aUserSpaceToFilterSpaceScale);
+
+ /**
+ * Returns true if the filter instance was created successfully.
+ */
+ bool IsInitialized() const { return mInitialized; }
+
+ /**
+ * Iterates through the <filter> element's primitive elements, creating a
+ * FilterPrimitiveDescription for each one. Appends the new
+ * FilterPrimitiveDescription(s) to the aPrimitiveDescrs list. Also, appends
+ * new images from feImage filter primitive elements to the aInputImages list.
+ * aInputIsTainted describes whether the input to this filter is tainted, i.e.
+ * whether it contains security-sensitive content. This is needed to propagate
+ * taintedness to the FilterPrimitive that take tainted inputs. Something
+ * being tainted means that it contains security sensitive content. The input
+ * to this filter is the previous filter's output, i.e. the last element in
+ * aPrimitiveDescrs, or the SourceGraphic input if this is the first filter in
+ * the filter chain.
+ */
+ nsresult BuildPrimitives(
+ nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
+ nsTArray<RefPtr<SourceSurface>>& aInputImages, bool aInputIsTainted);
+
+ float GetPrimitiveNumber(uint8_t aCtxType,
+ const SVGAnimatedNumber* aNumber) const {
+ return GetPrimitiveNumber(aCtxType, aNumber->GetAnimValue());
+ }
+ float GetPrimitiveNumber(uint8_t aCtxType,
+ const SVGAnimatedNumberPair* aNumberPair,
+ SVGAnimatedNumberPair::PairIndex aIndex) const {
+ return GetPrimitiveNumber(aCtxType, aNumberPair->GetAnimValue(aIndex));
+ }
+
+ /**
+ * Converts a userSpaceOnUse/objectBoundingBoxUnits unitless point
+ * into filter space, depending on the value of mPrimitiveUnits. (For
+ * objectBoundingBoxUnits, the bounding box offset is applied to the point.)
+ */
+ Point3D ConvertLocation(const Point3D& aPoint) const;
+
+ /**
+ * Transform a rect between user space and filter space.
+ */
+ gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpaceRect) const;
+
+ private:
+ /**
+ * Computes the filter primitive subregion for the given primitive.
+ */
+ IntRect ComputeFilterPrimitiveSubregion(
+ SVGFilterPrimitiveElement* aFilterElement,
+ const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
+ const nsTArray<int32_t>& aInputIndices);
+
+ /**
+ * Takes the input indices of a filter primitive and returns for each input
+ * whether the input's output is tainted.
+ */
+ void GetInputsAreTainted(
+ const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
+ const nsTArray<int32_t>& aInputIndices, bool aFilterInputIsTainted,
+ nsTArray<bool>& aOutInputsAreTainted);
+
+ /**
+ * Scales a numeric filter primitive length in the X, Y or "XY" directions
+ * into a length in filter space (no offset is applied).
+ */
+ float GetPrimitiveNumber(uint8_t aCtxType, float aValue) const;
+
+ /**
+ * Returns the transform from frame space to the coordinate space that
+ * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the
+ * top-left corner of its border box, aka the top left corner of its mRect.
+ */
+ gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const;
+
+ /**
+ * Appends a new FilterPrimitiveDescription to aPrimitiveDescrs that
+ * converts the FilterPrimitiveDescription at mSourceGraphicIndex into
+ * a SourceAlpha input for the next FilterPrimitiveDescription.
+ *
+ * The new FilterPrimitiveDescription zeros out the SourceGraphic's RGB
+ * channels and keeps the alpha channel intact.
+ */
+ int32_t GetOrCreateSourceAlphaIndex(
+ nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs);
+
+ /**
+ * Finds the index in aPrimitiveDescrs of each input to aPrimitiveElement.
+ * For example, if aPrimitiveElement is:
+ * <feGaussianBlur in="another-primitive" .../>
+ * Then, the resulting aSourceIndices will contain the index of the
+ * FilterPrimitiveDescription representing "another-primitive".
+ */
+ nsresult GetSourceIndices(
+ SVGFilterPrimitiveElement* aPrimitiveElement,
+ nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
+ const nsTHashMap<nsStringHashKey, int32_t>& aImageTable,
+ nsTArray<int32_t>& aSourceIndices);
+
+ /**
+ * Compute the filter region in user space, filter space, and filter
+ * space.
+ */
+ bool ComputeBounds();
+
+ /**
+ * The SVG reference filter originally from the style system.
+ */
+ const StyleFilter& mFilter;
+
+ /**
+ * The filtered element.
+ */
+ nsIContent* mTargetContent;
+
+ /**
+ * The SVG user space metrics that SVG lengths are resolved against.
+ */
+ const UserSpaceMetrics& mMetrics;
+
+ /**
+ * The filter element referenced by mTargetFrame's element.
+ */
+ const dom::SVGFilterElement* mFilterElement;
+
+ /**
+ * The frame for the SVG filter element.
+ */
+ SVGFilterFrame* mFilterFrame;
+
+ /**
+ * The SVG bbox of the element that is being filtered, in user space.
+ */
+ gfxRect mTargetBBox;
+
+ /**
+ * The "filter region" in various spaces.
+ */
+ nsIntRect mFilterSpaceBounds;
+
+ /**
+ * The scale factors between user space and filter space.
+ */
+ gfx::MatrixScalesDouble mUserSpaceToFilterSpaceScale;
+
+ /**
+ * The 'primitiveUnits' attribute value (objectBoundingBox or userSpaceOnUse).
+ */
+ uint16_t mPrimitiveUnits;
+
+ /**
+ * The index of the FilterPrimitiveDescription that this SVG filter should use
+ * as its SourceGraphic, or the SourceGraphic keyword index if this is the
+ * first filter in a chain. Initialized in BuildPrimitives
+ */
+ MOZ_INIT_OUTSIDE_CTOR int32_t mSourceGraphicIndex;
+
+ /**
+ * The index of the FilterPrimitiveDescription that this SVG filter should use
+ * as its SourceAlpha, or the SourceAlpha keyword index if this is the first
+ * filter in a chain. Initialized in BuildPrimitives
+ */
+ MOZ_INIT_OUTSIDE_CTOR int32_t mSourceAlphaIndex;
+
+ /**
+ * SourceAlpha is available if GetOrCreateSourceAlphaIndex has been called.
+ */
+ int32_t mSourceAlphaAvailable;
+
+ bool mInitialized;
+};
+
+} // namespace mozilla
+
+#endif // LAYOUT_SVG_SVGFILTERINSTANCE_H_