| Index: Source/core/platform/graphics/filters/FilterEffect.cpp | 
| diff --git a/Source/core/platform/graphics/filters/FilterEffect.cpp b/Source/core/platform/graphics/filters/FilterEffect.cpp | 
| index 920ae250b7d557dae9c5e4874e9afab671c777d9..cded7876af158d7325472f74dda3efbf945e726b 100644 | 
| --- a/Source/core/platform/graphics/filters/FilterEffect.cpp | 
| +++ b/Source/core/platform/graphics/filters/FilterEffect.cpp | 
| @@ -77,6 +77,45 @@ void FilterEffect::determineAbsolutePaintRect() | 
|  | 
| } | 
|  | 
| +FloatRect FilterEffect::mapRectRecursive(const FloatRect& rect) | 
| +{ | 
| +    FloatRect result; | 
| +    if (m_inputEffects.size() > 0) { | 
| +        result = m_inputEffects.at(0)->mapRectRecursive(rect); | 
| +        for (unsigned i = 1; i < m_inputEffects.size(); ++i) | 
| +            result.unite(m_inputEffects.at(i)->mapRectRecursive(rect)); | 
| +    } else | 
| +        result = rect; | 
| +    return mapRect(result); | 
| +} | 
| + | 
| +FloatRect FilterEffect::getSourceRect(const FloatRect& destRect, const FloatRect& destClipRect) | 
| +{ | 
| +    FloatRect sourceRect = mapRect(destRect, false); | 
| +    FloatRect sourceClipRect = mapRect(destClipRect, false); | 
| + | 
| +    FloatRect boundaries = effectBoundaries(); | 
| +    if (hasX()) | 
| +        sourceClipRect.setX(boundaries.x()); | 
| +    if (hasY()) | 
| +        sourceClipRect.setY(boundaries.y()); | 
| +    if (hasWidth()) | 
| +        sourceClipRect.setWidth(boundaries.width()); | 
| +    if (hasHeight()) | 
| +        sourceClipRect.setHeight(boundaries.height()); | 
| + | 
| +    FloatRect result; | 
| +    if (m_inputEffects.size() > 0) { | 
| +        result = m_inputEffects.at(0)->getSourceRect(sourceRect, sourceClipRect); | 
| +        for (unsigned i = 1; i < m_inputEffects.size(); ++i) | 
| +            result.unite(m_inputEffects.at(i)->getSourceRect(sourceRect, sourceClipRect)); | 
| +    } else { | 
| +        result = sourceRect; | 
| +        result.intersect(sourceClipRect); | 
| +    } | 
| +    return result; | 
| +} | 
| + | 
| IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect) const | 
| { | 
| ASSERT(hasResult()); | 
| @@ -398,4 +437,43 @@ TextStream& FilterEffect::externalRepresentation(TextStream& ts, int) const | 
| return ts; | 
| } | 
|  | 
| +FloatRect FilterEffect::determineFilterPrimitiveSubregion() | 
| +{ | 
| +    ASSERT(filter()); | 
| + | 
| +    // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect. | 
| +    FloatRect subregion; | 
| +    if (unsigned numberOfInputEffects = inputEffects().size()) { | 
| +        subregion = inputEffect(0)->determineFilterPrimitiveSubregion(); | 
| +        for (unsigned i = 1; i < numberOfInputEffects; ++i) | 
| +            subregion.unite(inputEffect(i)->determineFilterPrimitiveSubregion()); | 
| +    } else | 
| +        subregion = filter()->filterRegion(); | 
| + | 
| +    // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>. | 
| +    if (filterEffectType() == FilterEffectTypeTile) | 
| +        subregion = filter()->filterRegion(); | 
| + | 
| +    subregion = mapRect(subregion); | 
| + | 
| +    FloatRect boundaries = effectBoundaries(); | 
| +    if (hasX()) | 
| +        subregion.setX(boundaries.x()); | 
| +    if (hasY()) | 
| +        subregion.setY(boundaries.y()); | 
| +    if (hasWidth()) | 
| +        subregion.setWidth(boundaries.width()); | 
| +    if (hasHeight()) | 
| +        subregion.setHeight(boundaries.height()); | 
| + | 
| +    setFilterPrimitiveSubregion(subregion); | 
| + | 
| +    FloatRect absoluteSubregion = filter()->absoluteTransform().mapRect(subregion); | 
| +    FloatSize filterResolution = filter()->filterResolution(); | 
| +    absoluteSubregion.scale(filterResolution.width(), filterResolution.height()); | 
| + | 
| +    setMaxEffectRect(absoluteSubregion); | 
| +    return subregion; | 
| +} | 
| + | 
| } // namespace WebCore | 
|  |