зеркало из https://github.com/mozilla/gecko-dev.git
Bug 948265 - Rename intermediate space to filter space and change filter space origin to user space origin. r=mstange, r=longsonr
This commit is contained in:
Родитель
6b12580552
Коммит
b79c737e9a
|
@ -0,0 +1,17 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<!--
|
||||
Place the filtered rect and the filter region at (0, 0) in user space.
|
||||
Remove the filter output before (50, 50) using a clipPath.
|
||||
-->
|
||||
<filter id="f" x="0%" y="0%" width="100%" height="100%">
|
||||
<feTurbulence type="turbulence" baseFrequency="0.01" numOctaves="1"></feTurbulence>
|
||||
</filter>
|
||||
<clipPath id="clip-top-left">
|
||||
<rect x="50" y="50" width="100" height="100"/>
|
||||
</clipPath>
|
||||
<rect x="0" y="0" width="150" height="150" filter="url(#f)" clip-path="url(#clip-top-left)"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 669 B |
|
@ -0,0 +1,20 @@
|
|||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!--
|
||||
This test verifies that feTurbulence creates a noise image that remains
|
||||
anchored at the user space origin, not the filter region origin. The filter
|
||||
region should act as a viewport into the anchored noise image.
|
||||
-->
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<!--
|
||||
Place the filtered rect at (75, 75) in user space.
|
||||
Make the filter region start at (-25, -25) from the top left corner of the rect.
|
||||
Thus, the filter output should start at (50, 50).
|
||||
-->
|
||||
<filter id="f" x="-25%" y="-25%" width="100%" height="100%">
|
||||
<feTurbulence type="turbulence" baseFrequency="0.01" numOctaves="1"></feTurbulence>
|
||||
</filter>
|
||||
<rect x="75" y="75" width="100" height="100" filter="url(#f)"/>
|
||||
</svg>
|
После Ширина: | Высота: | Размер: 837 B |
|
@ -101,6 +101,8 @@ fuzzy(2,2659) skip-if(d2d) == feSpecularLighting-1.svg feSpecularLighting-1-ref.
|
|||
|
||||
== fePointLight-zoomed-page.svg fePointLight-zoomed-page-ref.svg
|
||||
|
||||
== feTurbulence-offset.svg feTurbulence-offset-ref.svg
|
||||
|
||||
pref(layout.css.filters.enabled,true) == multiple-svg-filters.svg multiple-svg-filters-ref.svg
|
||||
pref(layout.css.filters.enabled,true) == multiple-svg-filters-long-chain.svg multiple-svg-filters-ref.svg
|
||||
pref(layout.css.filters.enabled,true) == multiple-svg-filters-second-uses-SourceGraphic.svg multiple-svg-filters-ref.svg
|
||||
|
|
|
@ -95,7 +95,7 @@ skip-if(B2G) == dynamic-pattern-02.svg pass.svg
|
|||
skip-if(B2G) == dynamic-pattern-contents-01.svg pass.svg
|
||||
skip-if(B2G) == dynamic-pattern-contents-02.svg pass.svg
|
||||
== dynamic-rect-01.svg dynamic-rect-01-ref.svg
|
||||
== dynamic-rect-02.svg dynamic-rect-02-ref.svg
|
||||
fuzzy-if(d2d&&layersGPUAccelerated,3,1200) == dynamic-rect-02.svg dynamic-rect-02-ref.svg # bug 776038 for Win7, Win8
|
||||
== dynamic-rect-03.svg dynamic-rect-03-ref.svg
|
||||
== dynamic-rect-04.xhtml pass.svg
|
||||
== dynamic-rect-05.svg pass.svg
|
||||
|
@ -107,7 +107,7 @@ skip-if(B2G) == dynamic-pattern-contents-02.svg pass.svg
|
|||
== dynamic-stroke-width-01.svg pass.svg
|
||||
== dynamic-switch-01.svg pass.svg
|
||||
== dynamic-text-01.svg dynamic-text-01-ref.svg
|
||||
fuzzy-if(d2d&&layersGPUAccelerated,2,12739) == dynamic-text-02.svg dynamic-text-02-ref.svg # bug 776038 for Win7
|
||||
fuzzy-if(d2d&&layersGPUAccelerated,3,12739) == dynamic-text-02.svg dynamic-text-02-ref.svg # bug 776038 for Win7, Win8
|
||||
fuzzy-if(d2d&&layersGPUAccelerated,2,10539) == dynamic-text-03.svg dynamic-text-03-ref.svg # bug 776038 for Win7
|
||||
random-if(/^Windows\x20NT\x205\.1/.test(http.oscpu)) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),47,89) == dynamic-text-04.svg dynamic-text-04-ref.svg # bug 421587 for WinXP, bug 776038 for Win7
|
||||
skip-if(B2G) == dynamic-text-05.svg pass.svg
|
||||
|
|
|
@ -118,7 +118,12 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame,
|
|||
mTargetBBox = aOverrideBBox ?
|
||||
*aOverrideBBox : nsSVGUtils::GetBBox(mTargetFrame);
|
||||
|
||||
nsresult rv = BuildPrimitives();
|
||||
nsresult rv = ComputeUserSpaceToFilterSpaceScale();
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = BuildPrimitives();
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
@ -130,9 +135,9 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame,
|
|||
|
||||
// Get various transforms:
|
||||
|
||||
gfxMatrix filterToUserSpace(mFilterRegion.Width() / mFilterSpaceBounds.width, 0.0f,
|
||||
0.0f, mFilterRegion.Height() / mFilterSpaceBounds.height,
|
||||
mFilterRegion.X(), mFilterRegion.Y());
|
||||
gfxMatrix filterToUserSpace(mFilterSpaceToUserSpaceScale.width, 0.0f,
|
||||
0.0f, mFilterSpaceToUserSpaceScale.height,
|
||||
0.0f, 0.0f);
|
||||
|
||||
// Only used (so only set) when we paint:
|
||||
if (mPaintCallback) {
|
||||
|
@ -164,23 +169,44 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame,
|
|||
mInitialized = true;
|
||||
}
|
||||
|
||||
gfxRect
|
||||
nsFilterInstance::UserSpaceToFilterSpace(const gfxRect& aRect) const
|
||||
nsresult
|
||||
nsFilterInstance::ComputeUserSpaceToFilterSpaceScale()
|
||||
{
|
||||
gfxRect r = aRect - mFilterRegion.TopLeft();
|
||||
r.Scale(mFilterSpaceBounds.width / mFilterRegion.Width(),
|
||||
mFilterSpaceBounds.height / mFilterRegion.Height());
|
||||
return r;
|
||||
gfxMatrix canvasTransform =
|
||||
nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_OUTERSVG_TM);
|
||||
if (canvasTransform.IsSingular()) {
|
||||
// Nothing should be rendered.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mUserSpaceToFilterSpaceScale = canvasTransform.ScaleFactors(true);
|
||||
if (mUserSpaceToFilterSpaceScale.width <= 0.0f ||
|
||||
mUserSpaceToFilterSpaceScale.height <= 0.0f) {
|
||||
// Nothing should be rendered.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mFilterSpaceToUserSpaceScale = gfxSize(1.0f / mUserSpaceToFilterSpaceScale.width,
|
||||
1.0f / mUserSpaceToFilterSpaceScale.height);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
gfxMatrix
|
||||
nsFilterInstance::GetUserSpaceToFilterSpaceTransform() const
|
||||
gfxRect
|
||||
nsFilterInstance::UserSpaceToFilterSpace(const gfxRect& aUserSpaceRect) const
|
||||
{
|
||||
gfxFloat widthScale = mFilterSpaceBounds.width / mFilterRegion.Width();
|
||||
gfxFloat heightScale = mFilterSpaceBounds.height / mFilterRegion.Height();
|
||||
return gfxMatrix(widthScale, 0.0f,
|
||||
0.0f, heightScale,
|
||||
-mFilterRegion.X() * widthScale, -mFilterRegion.Y() * heightScale);
|
||||
gfxRect filterSpaceRect = aUserSpaceRect;
|
||||
filterSpaceRect.Scale(mUserSpaceToFilterSpaceScale.width,
|
||||
mUserSpaceToFilterSpaceScale.height);
|
||||
return filterSpaceRect;
|
||||
}
|
||||
|
||||
gfxRect
|
||||
nsFilterInstance::FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const
|
||||
{
|
||||
gfxRect userSpaceRect = aFilterSpaceRect;
|
||||
userSpaceRect.Scale(mFilterSpaceToUserSpaceScale.width,
|
||||
mFilterSpaceToUserSpaceScale.height);
|
||||
return userSpaceRect;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -202,9 +228,15 @@ nsFilterInstance::BuildPrimitives()
|
|||
nsresult
|
||||
nsFilterInstance::BuildPrimitivesForFilter(const nsStyleFilter& aFilter)
|
||||
{
|
||||
NS_ASSERTION(mUserSpaceToFilterSpaceScale.width > 0.0f &&
|
||||
mFilterSpaceToUserSpaceScale.height > 0.0f,
|
||||
"scale factors between spaces should be positive values");
|
||||
|
||||
if (aFilter.GetType() == NS_STYLE_FILTER_URL) {
|
||||
// Build primitives for an SVG filter.
|
||||
nsSVGFilterInstance svgFilterInstance(aFilter, mTargetFrame, mTargetBBox);
|
||||
nsSVGFilterInstance svgFilterInstance(aFilter, mTargetFrame, mTargetBBox,
|
||||
mUserSpaceToFilterSpaceScale,
|
||||
mFilterSpaceToUserSpaceScale);
|
||||
if (!svgFilterInstance.IsInitialized()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -212,7 +244,7 @@ nsFilterInstance::BuildPrimitivesForFilter(const nsStyleFilter& aFilter)
|
|||
// For now, we use the last SVG filter region as the overall filter region
|
||||
// for the filter chain. Eventually, we will compute the overall filter
|
||||
// using all of the generated FilterPrimitiveDescriptions.
|
||||
mFilterRegion = svgFilterInstance.GetFilterRegion();
|
||||
mUserSpaceBounds = svgFilterInstance.GetFilterRegion();
|
||||
mFilterSpaceBounds = svgFilterInstance.GetFilterSpaceBounds();
|
||||
|
||||
// If this overflows, we can at least paint the maximum surface size.
|
||||
|
@ -289,10 +321,6 @@ nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
|
|||
nsRenderingContext tmpCtx;
|
||||
tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx);
|
||||
|
||||
gfxMatrix m = GetUserSpaceToFilterSpaceTransform();
|
||||
m.Invert();
|
||||
gfxRect r = m.TransformBounds(mFilterSpaceBounds);
|
||||
|
||||
gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert();
|
||||
gfxContext *gfx = tmpCtx.ThebesContext();
|
||||
gfx->Multiply(deviceToFilterSpace);
|
||||
|
@ -304,7 +332,7 @@ nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
|
|||
mTransformRoot);
|
||||
if (!matrix.IsSingular()) {
|
||||
gfx->Multiply(matrix);
|
||||
gfx->Rectangle(r);
|
||||
gfx->Rectangle(mUserSpaceBounds);
|
||||
if ((aSource == &mFillPaint &&
|
||||
nsSVGUtils::SetupCairoFillPaint(mTargetFrame, gfx)) ||
|
||||
(aSource == &mStrokePaint &&
|
||||
|
@ -376,9 +404,7 @@ nsFilterInstance::BuildSourceImage(gfxASurface* aTargetSurface,
|
|||
nsRenderingContext tmpCtx;
|
||||
tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx);
|
||||
|
||||
gfxMatrix m = GetUserSpaceToFilterSpaceTransform();
|
||||
m.Invert();
|
||||
gfxRect r = m.TransformBounds(neededRect);
|
||||
gfxRect r = FilterSpaceToUserSpace(neededRect);
|
||||
r.RoundOut();
|
||||
nsIntRect dirty;
|
||||
if (!gfxUtils::GfxRectToIntRect(r, &dirty))
|
||||
|
|
|
@ -155,11 +155,6 @@ public:
|
|||
*/
|
||||
nsresult ComputeSourceNeededRect(nsRect* aDirty);
|
||||
|
||||
/**
|
||||
* Returns the transform from the filtered element's user space to filter
|
||||
* space. This will be a simple translation and/or scale.
|
||||
*/
|
||||
gfxMatrix GetUserSpaceToFilterSpaceTransform() const;
|
||||
|
||||
/**
|
||||
* Returns the transform from filter space to outer-<svg> device space.
|
||||
|
@ -227,7 +222,16 @@ private:
|
|||
*/
|
||||
void ComputeNeededBoxes();
|
||||
|
||||
/**
|
||||
* Compute the scale factors between user space and filter space.
|
||||
*/
|
||||
nsresult ComputeUserSpaceToFilterSpaceScale();
|
||||
|
||||
/**
|
||||
* Transform a rect between user space and filter space.
|
||||
*/
|
||||
gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpace) const;
|
||||
gfxRect FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const;
|
||||
|
||||
/**
|
||||
* Converts an nsRect that is relative to a filtered frame's origin (i.e. the
|
||||
|
@ -271,9 +275,15 @@ private:
|
|||
/**
|
||||
* The "filter region", in the filtered element's user space.
|
||||
*/
|
||||
gfxRect mFilterRegion;
|
||||
gfxRect mUserSpaceBounds;
|
||||
nsIntRect mFilterSpaceBounds;
|
||||
|
||||
/**
|
||||
* The scale factors between user space and filter space.
|
||||
*/
|
||||
gfxSize mUserSpaceToFilterSpaceScale;
|
||||
gfxSize mFilterSpaceToUserSpaceScale;
|
||||
|
||||
/**
|
||||
* Pre-filter paint bounds of the element that is being filtered, in filter
|
||||
* space.
|
||||
|
|
|
@ -26,10 +26,14 @@ using namespace mozilla::gfx;
|
|||
|
||||
nsSVGFilterInstance::nsSVGFilterInstance(const nsStyleFilter& aFilter,
|
||||
nsIFrame *aTargetFrame,
|
||||
const gfxRect& aTargetBBox) :
|
||||
const gfxRect& aTargetBBox,
|
||||
const gfxSize& aUserSpaceToFilterSpaceScale,
|
||||
const gfxSize& aFilterSpaceToUserSpaceScale) :
|
||||
mFilter(aFilter),
|
||||
mTargetFrame(aTargetFrame),
|
||||
mTargetBBox(aTargetBBox),
|
||||
mUserSpaceToFilterSpaceScale(aUserSpaceToFilterSpaceScale),
|
||||
mFilterSpaceToUserSpaceScale(aFilterSpaceToUserSpaceScale),
|
||||
mInitialized(false) {
|
||||
|
||||
// Get the filter frame.
|
||||
|
@ -48,12 +52,7 @@ nsSVGFilterInstance::nsSVGFilterInstance(const nsStyleFilter& aFilter,
|
|||
mPrimitiveUnits =
|
||||
mFilterFrame->GetEnumValue(SVGFilterElement::PRIMITIVEUNITS);
|
||||
|
||||
nsresult rv = ComputeUserSpaceToIntermediateSpaceScale();
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = ComputeBounds();
|
||||
nsresult rv = ComputeBounds();
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
@ -61,21 +60,6 @@ nsSVGFilterInstance::nsSVGFilterInstance(const nsStyleFilter& aFilter,
|
|||
mInitialized = true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGFilterInstance::ComputeUserSpaceToIntermediateSpaceScale()
|
||||
{
|
||||
gfxMatrix canvasTransform =
|
||||
nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_OUTERSVG_TM);
|
||||
if (canvasTransform.IsSingular()) {
|
||||
// Nothing should be rendered.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mUserSpaceToIntermediateSpaceScale = canvasTransform.ScaleFactors(true);
|
||||
mIntermediateSpaceToUserSpaceScale = gfxSize(1.0 / mUserSpaceToIntermediateSpaceScale.width,
|
||||
1.0 / mUserSpaceToIntermediateSpaceScale.height);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsSVGFilterInstance::ComputeBounds()
|
||||
{
|
||||
|
@ -104,10 +88,10 @@ nsSVGFilterInstance::ComputeBounds()
|
|||
mUserSpaceBounds = nsSVGUtils::GetRelativeRect(filterUnits,
|
||||
XYWH, mTargetBBox, mTargetFrame);
|
||||
|
||||
// Temporarily transform the user space bounds to intermediate space, so we
|
||||
// Temporarily transform the user space bounds to filter space, so we
|
||||
// can align them with the pixel boundries of the offscreen surface.
|
||||
// The offscreen surface has the same scale as intermediate space.
|
||||
mUserSpaceBounds = UserSpaceToIntermediateSpace(mUserSpaceBounds);
|
||||
// The offscreen surface has the same scale as filter space.
|
||||
mUserSpaceBounds = UserSpaceToFilterSpace(mUserSpaceBounds);
|
||||
mUserSpaceBounds.RoundOut();
|
||||
if (mUserSpaceBounds.Width() <= 0 || mUserSpaceBounds.Height() <= 0) {
|
||||
// 0 disables rendering, < 0 is error. dispatch error console warning
|
||||
|
@ -115,18 +99,14 @@ nsSVGFilterInstance::ComputeBounds()
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Set the intermediate space bounds.
|
||||
if (!gfxUtils::GfxRectToIntRect(mUserSpaceBounds, &mIntermediateSpaceBounds)) {
|
||||
// Set the filter space bounds.
|
||||
if (!gfxUtils::GfxRectToIntRect(mUserSpaceBounds, &mFilterSpaceBounds)) {
|
||||
// The filter region is way too big if there is float -> int overflow.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Set the filter space bounds.
|
||||
mFilterSpaceBounds = mIntermediateSpaceBounds;
|
||||
mFilterSpaceBounds.MoveTo(0, 0);
|
||||
|
||||
// Undo the temporary transformation of the user space bounds.
|
||||
mUserSpaceBounds = IntermediateSpaceToUserSpace(mUserSpaceBounds);
|
||||
mUserSpaceBounds = FilterSpaceToUserSpace(mUserSpaceBounds);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -189,14 +169,14 @@ nsSVGFilterInstance::GetPrimitiveNumber(uint8_t aCtxType, float aValue) const
|
|||
|
||||
switch (aCtxType) {
|
||||
case SVGContentUtils::X:
|
||||
return value * mUserSpaceToIntermediateSpaceScale.width;
|
||||
return value * mUserSpaceToFilterSpaceScale.width;
|
||||
case SVGContentUtils::Y:
|
||||
return value * mUserSpaceToIntermediateSpaceScale.height;
|
||||
return value * mUserSpaceToFilterSpaceScale.height;
|
||||
case SVGContentUtils::XY:
|
||||
default:
|
||||
return value * SVGContentUtils::ComputeNormalizedHypotenuse(
|
||||
mUserSpaceToIntermediateSpaceScale.width,
|
||||
mUserSpaceToIntermediateSpaceScale.height);
|
||||
mUserSpaceToFilterSpaceScale.width,
|
||||
mUserSpaceToFilterSpaceScale.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,24 +203,18 @@ nsSVGFilterInstance::ConvertLocation(const Point3D& aPoint) const
|
|||
gfxRect
|
||||
nsSVGFilterInstance::UserSpaceToFilterSpace(const gfxRect& aUserSpaceRect) const
|
||||
{
|
||||
return UserSpaceToIntermediateSpace(aUserSpaceRect - mUserSpaceBounds.TopLeft());
|
||||
gfxRect filterSpaceRect = aUserSpaceRect;
|
||||
filterSpaceRect.Scale(mUserSpaceToFilterSpaceScale.width,
|
||||
mUserSpaceToFilterSpaceScale.height);
|
||||
return filterSpaceRect;
|
||||
}
|
||||
|
||||
gfxRect
|
||||
nsSVGFilterInstance::UserSpaceToIntermediateSpace(const gfxRect& aUserSpaceRect) const
|
||||
nsSVGFilterInstance::FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const
|
||||
{
|
||||
gfxRect intermediateSpaceRect = aUserSpaceRect;
|
||||
intermediateSpaceRect.Scale(mUserSpaceToIntermediateSpaceScale.width,
|
||||
mUserSpaceToIntermediateSpaceScale.height);
|
||||
return intermediateSpaceRect;
|
||||
}
|
||||
|
||||
gfxRect
|
||||
nsSVGFilterInstance::IntermediateSpaceToUserSpace(const gfxRect& aIntermediateSpaceRect) const
|
||||
{
|
||||
gfxRect userSpaceRect = aIntermediateSpaceRect;
|
||||
userSpaceRect.Scale(mIntermediateSpaceToUserSpaceScale.width,
|
||||
mIntermediateSpaceToUserSpaceScale.height);
|
||||
gfxRect userSpaceRect = aFilterSpaceRect;
|
||||
userSpaceRect.Scale(mFilterSpaceToUserSpaceScale.width,
|
||||
mFilterSpaceToUserSpaceScale.height);
|
||||
return userSpaceRect;
|
||||
}
|
||||
|
||||
|
|
|
@ -39,20 +39,15 @@ class SVGFilterElement;
|
|||
* CSS pixel space. The origin for an HTML element is the top left corner of
|
||||
* its border box.
|
||||
*
|
||||
* "intermediate space"
|
||||
* "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
|
||||
* intermediate space.
|
||||
* filter space.
|
||||
*
|
||||
* "filter space"
|
||||
* Intermediate space translated to the origin of this SVG filter's
|
||||
* filter region. This space may be different for each filter in a chain.
|
||||
*
|
||||
* To understand the spaces better, let's take an example filter that defines a
|
||||
* filter region:
|
||||
* <filter id="f" x="-15" y="-15" width="130" height="130">...</filter>
|
||||
* 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>
|
||||
|
@ -65,21 +60,10 @@ class SVGFilterElement;
|
|||
* 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 intermediate space:
|
||||
* "intermediate space point" = "user space point" * "device pixels per CSS pixel"
|
||||
* "intermediate space point" = (10, 10) * 2
|
||||
* "intermediate space point" = (20, 20)
|
||||
*
|
||||
* Next, let's transform the point from user space to filter space:
|
||||
* "filter space point" = ("user space point" - "filter region position in user space") * "device pixels per CSS pixel"
|
||||
* "filter space point" = ((10, 10) - (-15, -15)) * 2
|
||||
* "filter space point" = (50, 50)
|
||||
*
|
||||
* Similarly, we can convert the point from intermediate space to filter space:
|
||||
* "filter space point" = "intermediate space point" - "filter region position in intermediate space"
|
||||
* "filter space point" = "intermediate space point" - ("filter region position in user space" * "device pixels per CSS pixel")
|
||||
* "filter space point" = (20, 20) - ((-15, -15) * 2)
|
||||
* "filter space point" = (50, 50)
|
||||
* 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 nsSVGFilterInstance
|
||||
{
|
||||
|
@ -97,7 +81,9 @@ public:
|
|||
*/
|
||||
nsSVGFilterInstance(const nsStyleFilter& aFilter,
|
||||
nsIFrame *aTargetFrame,
|
||||
const gfxRect& aTargetBBox);
|
||||
const gfxRect& aTargetBBox,
|
||||
const gfxSize& aUserSpaceToFilterSpaceScale,
|
||||
const gfxSize& aFilterSpaceToUserSpaceScale);
|
||||
|
||||
/**
|
||||
* Returns true if the filter instance was created successfully.
|
||||
|
@ -176,10 +162,9 @@ private:
|
|||
float GetPrimitiveNumber(uint8_t aCtxType, float aValue) const;
|
||||
|
||||
/**
|
||||
* Transform a rect between user space and intermediate space.
|
||||
* Transform a rect between user space and filter space.
|
||||
*/
|
||||
gfxRect UserSpaceToIntermediateSpace(const gfxRect& aUserSpaceRect) const;
|
||||
gfxRect IntermediateSpaceToUserSpace(const gfxRect& aIntermediateSpaceRect) const;
|
||||
gfxRect FilterSpaceToUserSpace(const gfxRect& aFilterSpaceRect) const;
|
||||
|
||||
/**
|
||||
* Returns the transform from frame space to the coordinate space that
|
||||
|
@ -201,12 +186,7 @@ private:
|
|||
nsTArray<int32_t>& aSourceIndices);
|
||||
|
||||
/**
|
||||
* Compute the scale factors between user space and intermediate space.
|
||||
*/
|
||||
nsresult ComputeUserSpaceToIntermediateSpaceScale();
|
||||
|
||||
/**
|
||||
* Compute the filter region in user space, intermediate space, and filter
|
||||
* Compute the filter region in user space, filter space, and filter
|
||||
* space.
|
||||
*/
|
||||
nsresult ComputeBounds();
|
||||
|
@ -240,14 +220,13 @@ private:
|
|||
* The "filter region" in various spaces.
|
||||
*/
|
||||
gfxRect mUserSpaceBounds;
|
||||
nsIntRect mIntermediateSpaceBounds;
|
||||
nsIntRect mFilterSpaceBounds;
|
||||
|
||||
/**
|
||||
* The scale factors between user space and intermediate space.
|
||||
* The scale factors between user space and filter space.
|
||||
*/
|
||||
gfxSize mUserSpaceToIntermediateSpaceScale;
|
||||
gfxSize mIntermediateSpaceToUserSpaceScale;
|
||||
gfxSize mUserSpaceToFilterSpaceScale;
|
||||
gfxSize mFilterSpaceToUserSpaceScale;
|
||||
|
||||
/**
|
||||
* The 'primitiveUnits' attribute value (objectBoundingBox or userSpaceOnUse).
|
||||
|
|
Загрузка…
Ссылка в новой задаче