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; };