diff --git a/layout/reftests/svg/filters/multiple-svg-filters-long-chain.svg b/layout/reftests/svg/filters/multiple-svg-filters-long-chain.svg
new file mode 100644
index 000000000000..f433f2484602
--- /dev/null
+++ b/layout/reftests/svg/filters/multiple-svg-filters-long-chain.svg
@@ -0,0 +1,24 @@
+
diff --git a/layout/reftests/svg/filters/multiple-svg-filters-ref.svg b/layout/reftests/svg/filters/multiple-svg-filters-ref.svg
new file mode 100644
index 000000000000..743e1ca1575d
--- /dev/null
+++ b/layout/reftests/svg/filters/multiple-svg-filters-ref.svg
@@ -0,0 +1,10 @@
+
diff --git a/layout/reftests/svg/filters/multiple-svg-filters-second-uses-SourceGraphic.svg b/layout/reftests/svg/filters/multiple-svg-filters-second-uses-SourceGraphic.svg
new file mode 100644
index 000000000000..d113109cba0c
--- /dev/null
+++ b/layout/reftests/svg/filters/multiple-svg-filters-second-uses-SourceGraphic.svg
@@ -0,0 +1,13 @@
+
diff --git a/layout/reftests/svg/filters/multiple-svg-filters-with-multiple-primitives.svg b/layout/reftests/svg/filters/multiple-svg-filters-with-multiple-primitives.svg
new file mode 100644
index 000000000000..6335f93c3162
--- /dev/null
+++ b/layout/reftests/svg/filters/multiple-svg-filters-with-multiple-primitives.svg
@@ -0,0 +1,20 @@
+
diff --git a/layout/reftests/svg/filters/multiple-svg-filters.svg b/layout/reftests/svg/filters/multiple-svg-filters.svg
new file mode 100644
index 000000000000..ac07211b7cc3
--- /dev/null
+++ b/layout/reftests/svg/filters/multiple-svg-filters.svg
@@ -0,0 +1,11 @@
+
diff --git a/layout/reftests/svg/filters/reftest.list b/layout/reftests/svg/filters/reftest.list
index 8001d7b7f082..28da091d207f 100644
--- a/layout/reftests/svg/filters/reftest.list
+++ b/layout/reftests/svg/filters/reftest.list
@@ -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
diff --git a/layout/svg/nsSVGFilterInstance.cpp b/layout/svg/nsSVGFilterInstance.cpp
index 226c2649e1a5..82c3dbccd380 100644
--- a/layout/svg/nsSVGFilterInstance.cpp
+++ b/layout/svg/nsSVGFilterInstance.cpp
@@ -301,14 +301,23 @@ nsSVGFilterInstance::GetInputsAreTainted(const nsTArray& aImageTable,
- nsTArray& aSourceIndices)
+static int32_t
+GetLastResultIndex(const nsTArray& aPrimitiveDescrs)
+{
+ uint32_t numPrimitiveDescrs = aPrimitiveDescrs.Length();
+ return !numPrimitiveDescrs ?
+ FilterPrimitiveDescription::kPrimitiveIndexSourceGraphic :
+ numPrimitiveDescrs - 1;
+}
+
+nsresult
+nsSVGFilterInstance::GetSourceIndices(nsSVGFE* aPrimitiveElement,
+ const nsTArray& aPrimitiveDescrs,
+ const nsDataHashtable& aImageTable,
+ nsTArray& aSourceIndices)
{
nsAutoTArray 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& aPrimitiveDescrs,
nsTArray>& aInputImages)
{
+ mSourceGraphicIndex = GetLastResultIndex(aPrimitiveDescrs);
+
+ // Get the filter primitive elements.
nsTArray > primitives;
for (nsIContent* child = mFilterElement->nsINode::GetFirstChild();
child;
@@ -363,11 +372,13 @@ nsSVGFilterInstance::BuildPrimitives(nsTArray& aPrim
// The principal that we check principals of any loaded images against.
nsCOMPtr 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 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& 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& 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;
diff --git a/layout/svg/nsSVGFilterInstance.h b/layout/svg/nsSVGFilterInstance.h
index 496099af707f..5a5d179b2624 100644
--- a/layout/svg/nsSVGFilterInstance.h
+++ b/layout/svg/nsSVGFilterInstance.h
@@ -139,6 +139,18 @@ private:
*/
gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const;
+ /**
+ * Finds the index in aPrimitiveDescrs of each input to aPrimitiveElement.
+ * For example, if aPrimitiveElement is:
+ *
+ * Then, the resulting aSourceIndices will contain the index of the
+ * FilterPrimitiveDescription representing "another-primitive".
+ */
+ nsresult GetSourceIndices(nsSVGFE* aPrimitiveElement,
+ const nsTArray& aPrimitiveDescrs,
+ const nsDataHashtable& aImageTable,
+ nsTArray& 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;
};