mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +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
|
||||
|
||||
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
|
||||
GetSourceIndices(nsSVGFE* aFilterElement,
|
||||
int32_t aCurrentIndex,
|
||||
const nsDataHashtable<nsStringHashKey, int32_t>& aImageTable,
|
||||
nsTArray<int32_t>& aSourceIndices)
|
||||
static int32_t
|
||||
GetLastResultIndex(const nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs)
|
||||
{
|
||||
uint32_t numPrimitiveDescrs = aPrimitiveDescrs.Length();
|
||||
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;
|
||||
aFilterElement->GetSourceImageNames(sources);
|
||||
aPrimitiveElement->GetSourceImageNames(sources);
|
||||
|
||||
for (uint32_t j = 0; j < sources.Length(); j++) {
|
||||
nsAutoString str;
|
||||
@ -316,7 +325,7 @@ GetSourceIndices(nsSVGFE* aFilterElement,
|
||||
|
||||
int32_t sourceIndex = 0;
|
||||
if (str.EqualsLiteral("SourceGraphic")) {
|
||||
sourceIndex = FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic;
|
||||
sourceIndex = mSourceGraphicIndex;
|
||||
} else if (str.EqualsLiteral("SourceAlpha")) {
|
||||
sourceIndex = FilterPrimitiveDescription::kPrimitiveIndexSourceAlpha;
|
||||
} else if (str.EqualsLiteral("FillPaint")) {
|
||||
@ -327,16 +336,13 @@ GetSourceIndices(nsSVGFE* aFilterElement,
|
||||
str.EqualsLiteral("BackgroundAlpha")) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
} else if (str.EqualsLiteral("")) {
|
||||
sourceIndex = aCurrentIndex == 0 ?
|
||||
FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic :
|
||||
aCurrentIndex - 1;
|
||||
sourceIndex = GetLastResultIndex(aPrimitiveDescrs);
|
||||
} else {
|
||||
bool inputExists = aImageTable.Get(str, &sourceIndex);
|
||||
if (!inputExists)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(sourceIndex < aCurrentIndex);
|
||||
aSourceIndices.AppendElement(sourceIndex);
|
||||
}
|
||||
return NS_OK;
|
||||
@ -346,6 +352,9 @@ nsresult
|
||||
nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrimitiveDescrs,
|
||||
nsTArray<mozilla::RefPtr<SourceSurface>>& aInputImages)
|
||||
{
|
||||
mSourceGraphicIndex = GetLastResultIndex(aPrimitiveDescrs);
|
||||
|
||||
// Get the filter primitive elements.
|
||||
nsTArray<nsRefPtr<nsSVGFE> > primitives;
|
||||
for (nsIContent* child = mFilterElement->nsINode::GetFirstChild();
|
||||
child;
|
||||
@ -363,11 +372,13 @@ nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrim
|
||||
// The principal that we check principals of any loaded images against.
|
||||
nsCOMPtr<nsIPrincipal> principal = mTargetFrame->GetContent()->NodePrincipal();
|
||||
|
||||
for (uint32_t i = 0; i < primitives.Length(); ++i) {
|
||||
nsSVGFE* filter = primitives[i];
|
||||
for (uint32_t primitiveElementIndex = 0;
|
||||
primitiveElementIndex < primitives.Length();
|
||||
++primitiveElementIndex) {
|
||||
nsSVGFE* filter = primitives[primitiveElementIndex];
|
||||
|
||||
nsAutoTArray<int32_t,2> sourceIndices;
|
||||
nsresult rv = GetSourceIndices(filter, i, imageTable, sourceIndices);
|
||||
nsresult rv = GetSourceIndices(filter, aPrimitiveDescrs, imageTable, sourceIndices);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
@ -384,14 +395,14 @@ nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrim
|
||||
descr.SetIsTainted(filter->OutputIsTainted(sourcesAreTainted, principal));
|
||||
descr.SetPrimitiveSubregion(primitiveSubregion);
|
||||
|
||||
for (uint32_t j = 0; j < sourceIndices.Length(); j++) {
|
||||
int32_t inputIndex = sourceIndices[j];
|
||||
descr.SetInputPrimitive(j, inputIndex);
|
||||
for (uint32_t i = 0; i < sourceIndices.Length(); i++) {
|
||||
int32_t inputIndex = sourceIndices[i];
|
||||
descr.SetInputPrimitive(i, inputIndex);
|
||||
ColorSpace inputColorSpace =
|
||||
inputIndex < 0 ? SRGB : aPrimitiveDescrs[inputIndex].OutputColorSpace();
|
||||
ColorSpace desiredInputColorSpace = filter->GetInputColorSpace(j, inputColorSpace);
|
||||
descr.SetInputColorSpace(j, desiredInputColorSpace);
|
||||
if (j == 0) {
|
||||
ColorSpace desiredInputColorSpace = filter->GetInputColorSpace(i, inputColorSpace);
|
||||
descr.SetInputColorSpace(i, desiredInputColorSpace);
|
||||
if (i == 0) {
|
||||
// the output color space is whatever in1 is if there is an in1
|
||||
descr.SetOutputColorSpace(desiredInputColorSpace);
|
||||
}
|
||||
@ -402,10 +413,11 @@ nsSVGFilterInstance::BuildPrimitives(nsTArray<FilterPrimitiveDescription>& aPrim
|
||||
}
|
||||
|
||||
aPrimitiveDescrs.AppendElement(descr);
|
||||
uint32_t primitiveDescrIndex = aPrimitiveDescrs.Length() - 1;
|
||||
|
||||
nsAutoString str;
|
||||
filter->GetResultImageName().GetAnimValue(str, filter);
|
||||
imageTable.Put(str, i);
|
||||
imageTable.Put(str, primitiveDescrIndex);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -139,6 +139,18 @@ private:
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -175,6 +187,13 @@ private:
|
||||
*/
|
||||
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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user