mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 01:48:05 +00:00
Bug 948265 - Connect the filter graphs of chained SVG filters. r=roc
This commit is contained in:
parent
7f24b975f1
commit
4ea33adaa9
@ -0,0 +1,24 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<filter id="flood-with-yellow">
|
||||||
|
<!-- Turn the black rect into a yellow rect. -->
|
||||||
|
<feFlood x="20" y="20" width="100" height="100" flood-color="#ffff00"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="extract-red-channel">
|
||||||
|
<!-- Turn the yellow rect into a red rect. -->
|
||||||
|
<feComponentTransfer x="0" y="0" width="120" height="120">
|
||||||
|
<feFuncR type="identity"/>
|
||||||
|
<feFuncG type="table" tableValues="0 0"/>
|
||||||
|
<feFuncB type="table" tableValues="0 0"/>
|
||||||
|
<feFuncA type="identity"/>
|
||||||
|
</feComponentTransfer>
|
||||||
|
</filter>
|
||||||
|
<filter id="blur">
|
||||||
|
<!-- Blur the red rect. -->
|
||||||
|
<feGaussianBlur stdDeviation="3" x="10" y="10" width="120" height="120"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="hue-rotate">
|
||||||
|
<!-- Turn the red rect into a green rect. -->
|
||||||
|
<feColorMatrix type="hueRotate" values="90"/>
|
||||||
|
</filter>
|
||||||
|
<rect x="20" y="20" width="100" height="100" filter="url(#flood-with-yellow) url(#extract-red-channel) url(#blur) url(#hue-rotate)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 992 B |
10
layout/reftests/svg/filters/multiple-svg-filters-ref.svg
Normal file
10
layout/reftests/svg/filters/multiple-svg-filters-ref.svg
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<!-- Test multiple SVG filters chained together against a single SVG filter. -->
|
||||||
|
<filter id="blur-and-hue-rotate">
|
||||||
|
<!-- Blur the red rect. -->
|
||||||
|
<feGaussianBlur stdDeviation="3"/>
|
||||||
|
<!-- Turn the red rect into a green rect. -->
|
||||||
|
<feColorMatrix type="hueRotate" values="90"/>
|
||||||
|
</filter>
|
||||||
|
<rect x="20" y="20" width="100" height="100" fill="#ff0000" filter="url(#blur-and-hue-rotate)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 449 B |
@ -0,0 +1,13 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<filter id="blur">
|
||||||
|
<!-- Blur the red rect. -->
|
||||||
|
<feGaussianBlur stdDeviation="3"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="hue-rotate">
|
||||||
|
<feFlood flood-color="#0000ff"/>
|
||||||
|
<!-- Turn the red rect into a green rect. feColorMatrix should use the
|
||||||
|
result of the #blur filter, not feFlood, as its SourceGraphic. -->
|
||||||
|
<feColorMatrix in="SourceGraphic" type="hueRotate" values="90"/>
|
||||||
|
</filter>
|
||||||
|
<rect x="20" y="20" width="100" height="100" fill="#ff0000" filter="url(#blur) url(#hue-rotate)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 549 B |
@ -0,0 +1,20 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<filter id="flood-with-red">
|
||||||
|
<!-- Turn the black rect into a yellow rect. -->
|
||||||
|
<feFlood x="20" y="20" width="100" height="100" flood-color="#ffff00"/>
|
||||||
|
<!-- Turn the yellow rect into a red rect. -->
|
||||||
|
<feComponentTransfer x="0" y="0" width="120" height="120">
|
||||||
|
<feFuncR type="identity"/>
|
||||||
|
<feFuncG type="table" tableValues="0 0"/>
|
||||||
|
<feFuncB type="table" tableValues="0 0"/>
|
||||||
|
<feFuncA type="identity"/>
|
||||||
|
</feComponentTransfer>
|
||||||
|
</filter>
|
||||||
|
<filter id="blur-and-hue-rotate">
|
||||||
|
<!-- Blur the red rect. -->
|
||||||
|
<feGaussianBlur stdDeviation="3" x="10" y="10" width="120" height="120"/>
|
||||||
|
<!-- Turn the red rect into a green rect. -->
|
||||||
|
<feColorMatrix type="hueRotate" values="90"/>
|
||||||
|
</filter>
|
||||||
|
<rect x="20" y="20" width="100" height="100" filter="url(#flood-with-red) url(#blur-and-hue-rotate)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 894 B |
11
layout/reftests/svg/filters/multiple-svg-filters.svg
Normal file
11
layout/reftests/svg/filters/multiple-svg-filters.svg
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<filter id="blur">
|
||||||
|
<!-- Blur the red rect. -->
|
||||||
|
<feGaussianBlur stdDeviation="3"/>
|
||||||
|
</filter>
|
||||||
|
<filter id="hue-rotate">
|
||||||
|
<!-- Turn the red rect into a green rect. -->
|
||||||
|
<feColorMatrix type="hueRotate" values="90"/>
|
||||||
|
</filter>
|
||||||
|
<rect x="20" y="20" width="100" height="100" fill="#ff0000" filter="url(#blur) url(#hue-rotate)"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 392 B |
@ -104,3 +104,7 @@ fuzzy(1,119) == feDiffuseLighting-1.svg feDiffuseLighting-1-ref.svg
|
|||||||
|
|
||||||
skip-if(d2d) == feSpecularLighting-1.svg feSpecularLighting-1-ref.svg
|
skip-if(d2d) == feSpecularLighting-1.svg feSpecularLighting-1-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
|
||||||
|
pref(layout.css.filters.enabled,true) == multiple-svg-filters-with-multiple-primitives.svg multiple-svg-filters-ref.svg
|
||||||
|
@ -301,14 +301,23 @@ nsSVGFilterInstance::GetInputsAreTainted(const nsTArray<FilterPrimitiveDescripti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsresult
|
static int32_t
|
||||||
GetSourceIndices(nsSVGFE* aFilterElement,
|
GetLastResultIndex(const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs)
|
||||||
int32_t aCurrentIndex,
|
{
|
||||||
const nsDataHashtable<nsStringHashKey, int32_t>& aImageTable,
|
uint32_t numPrimitiveDescrs = aPrimitiveDescrs.Length();
|
||||||
nsTArray<int32_t>& aSourceIndices)
|
return !numPrimitiveDescrs ?
|
||||||
|
FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic :
|
||||||
|
numPrimitiveDescrs - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsSVGFilterInstance::GetSourceIndices(nsSVGFE* aPrimitiveElement,
|
||||||
|
const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
|
||||||
|
const nsDataHashtable<nsStringHashKey, int32_t>& aImageTable,
|
||||||
|
nsTArray<int32_t>& aSourceIndices)
|
||||||
{
|
{
|
||||||
nsAutoTArray<nsSVGStringInfo,2> sources;
|
nsAutoTArray<nsSVGStringInfo,2> sources;
|
||||||
aFilterElement->GetSourceImageNames(sources);
|
aPrimitiveElement->GetSourceImageNames(sources);
|
||||||
|
|
||||||
for (uint32_t j = 0; j < sources.Length(); j++) {
|
for (uint32_t j = 0; j < sources.Length(); j++) {
|
||||||
nsAutoString str;
|
nsAutoString str;
|
||||||
@ -316,7 +325,7 @@ GetSourceIndices(nsSVGFE* aFilterElement,
|
|||||||
|
|
||||||
int32_t sourceIndex = 0;
|
int32_t sourceIndex = 0;
|
||||||
if (str.EqualsLiteral("SourceGraphic")) {
|
if (str.EqualsLiteral("SourceGraphic")) {
|
||||||
sourceIndex = FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic;
|
sourceIndex = mSourceGraphicIndex;
|
||||||
} else if (str.EqualsLiteral("SourceAlpha")) {
|
} else if (str.EqualsLiteral("SourceAlpha")) {
|
||||||
sourceIndex = FilterPrimitiveDescription::kPrimitiveIndexSourceAlpha;
|
sourceIndex = FilterPrimitiveDescription::kPrimitiveIndexSourceAlpha;
|
||||||
} else if (str.EqualsLiteral("FillPaint")) {
|
} else if (str.EqualsLiteral("FillPaint")) {
|
||||||
@ -327,16 +336,13 @@ GetSourceIndices(nsSVGFE* aFilterElement,
|
|||||||
str.EqualsLiteral("BackgroundAlpha")) {
|
str.EqualsLiteral("BackgroundAlpha")) {
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
} else if (str.EqualsLiteral("")) {
|
} else if (str.EqualsLiteral("")) {
|
||||||
sourceIndex = aCurrentIndex == 0 ?
|
sourceIndex = GetLastResultIndex(aPrimitiveDescrs);
|
||||||
FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic :
|
|
||||||
aCurrentIndex - 1;
|
|
||||||
} else {
|
} else {
|
||||||
bool inputExists = aImageTable.Get(str, &sourceIndex);
|
bool inputExists = aImageTable.Get(str, &sourceIndex);
|
||||||
if (!inputExists)
|
if (!inputExists)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(sourceIndex < aCurrentIndex);
|
|
||||||
aSourceIndices.AppendElement(sourceIndex);
|
aSourceIndices.AppendElement(sourceIndex);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -346,6 +352,9 @@ nsresult
|
|||||||
nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
|
nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
|
||||||
nsTArray<mozilla::RefPtr<SourceSurface>>& aInputImages)
|
nsTArray<mozilla::RefPtr<SourceSurface>>& aInputImages)
|
||||||
{
|
{
|
||||||
|
mSourceGraphicIndex = GetLastResultIndex(aPrimitiveDescrs);
|
||||||
|
|
||||||
|
// Get the filter primitive elements.
|
||||||
nsTArray<nsRefPtr<nsSVGFE> > primitives;
|
nsTArray<nsRefPtr<nsSVGFE> > primitives;
|
||||||
for (nsIContent* child = mFilterElement->nsINode::GetFirstChild();
|
for (nsIContent* child = mFilterElement->nsINode::GetFirstChild();
|
||||||
child;
|
child;
|
||||||
@ -363,11 +372,13 @@ nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrim
|
|||||||
// The principal that we check principals of any loaded images against.
|
// The principal that we check principals of any loaded images against.
|
||||||
nsCOMPtr<nsIPrincipal> principal = mTargetFrame->GetContent()->NodePrincipal();
|
nsCOMPtr<nsIPrincipal> principal = mTargetFrame->GetContent()->NodePrincipal();
|
||||||
|
|
||||||
for (uint32_t i = 0; i < primitives.Length(); ++i) {
|
for (uint32_t primitiveElementIndex = 0;
|
||||||
nsSVGFE* filter = primitives[i];
|
primitiveElementIndex < primitives.Length();
|
||||||
|
++primitiveElementIndex) {
|
||||||
|
nsSVGFE* filter = primitives[primitiveElementIndex];
|
||||||
|
|
||||||
nsAutoTArray<int32_t,2> sourceIndices;
|
nsAutoTArray<int32_t,2> sourceIndices;
|
||||||
nsresult rv = GetSourceIndices(filter, i, imageTable, sourceIndices);
|
nsresult rv = GetSourceIndices(filter, aPrimitiveDescrs, imageTable, sourceIndices);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
@ -384,14 +395,14 @@ nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrim
|
|||||||
descr.SetIsTainted(filter->OutputIsTainted(sourcesAreTainted, principal));
|
descr.SetIsTainted(filter->OutputIsTainted(sourcesAreTainted, principal));
|
||||||
descr.SetPrimitiveSubregion(primitiveSubregion);
|
descr.SetPrimitiveSubregion(primitiveSubregion);
|
||||||
|
|
||||||
for (uint32_t j = 0; j < sourceIndices.Length(); j++) {
|
for (uint32_t i = 0; i < sourceIndices.Length(); i++) {
|
||||||
int32_t inputIndex = sourceIndices[j];
|
int32_t inputIndex = sourceIndices[i];
|
||||||
descr.SetInputPrimitive(j, inputIndex);
|
descr.SetInputPrimitive(i, inputIndex);
|
||||||
ColorSpace inputColorSpace =
|
ColorSpace inputColorSpace =
|
||||||
inputIndex < 0 ? SRGB : aPrimitiveDescrs[inputIndex].OutputColorSpace();
|
inputIndex < 0 ? SRGB : aPrimitiveDescrs[inputIndex].OutputColorSpace();
|
||||||
ColorSpace desiredInputColorSpace = filter->GetInputColorSpace(j, inputColorSpace);
|
ColorSpace desiredInputColorSpace = filter->GetInputColorSpace(i, inputColorSpace);
|
||||||
descr.SetInputColorSpace(j, desiredInputColorSpace);
|
descr.SetInputColorSpace(i, desiredInputColorSpace);
|
||||||
if (j == 0) {
|
if (i == 0) {
|
||||||
// the output color space is whatever in1 is if there is an in1
|
// the output color space is whatever in1 is if there is an in1
|
||||||
descr.SetOutputColorSpace(desiredInputColorSpace);
|
descr.SetOutputColorSpace(desiredInputColorSpace);
|
||||||
}
|
}
|
||||||
@ -402,10 +413,11 @@ nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrim
|
|||||||
}
|
}
|
||||||
|
|
||||||
aPrimitiveDescrs.AppendElement(descr);
|
aPrimitiveDescrs.AppendElement(descr);
|
||||||
|
uint32_t primitiveDescrIndex = aPrimitiveDescrs.Length() - 1;
|
||||||
|
|
||||||
nsAutoString str;
|
nsAutoString str;
|
||||||
filter->GetResultImageName().GetAnimValue(str, filter);
|
filter->GetResultImageName().GetAnimValue(str, filter);
|
||||||
imageTable.Put(str, i);
|
imageTable.Put(str, primitiveDescrIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -139,6 +139,18 @@ private:
|
|||||||
*/
|
*/
|
||||||
gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const;
|
gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(nsSVGFE* aPrimitiveElement,
|
||||||
|
const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
|
||||||
|
const nsDataHashtable<nsStringHashKey, int32_t>& aImageTable,
|
||||||
|
nsTArray<int32_t>& aSourceIndices);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SVG reference filter originally from the style system.
|
* The SVG reference filter originally from the style system.
|
||||||
*/
|
*/
|
||||||
@ -175,6 +187,13 @@ private:
|
|||||||
*/
|
*/
|
||||||
uint16_t mPrimitiveUnits;
|
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.
|
||||||
|
*/
|
||||||
|
int32_t mSourceGraphicIndex;
|
||||||
|
|
||||||
bool mInitialized;
|
bool mInitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user