Diff
Modified: trunk/LayoutTests/ChangeLog (183955 => 183956)
--- trunk/LayoutTests/ChangeLog 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/LayoutTests/ChangeLog 2015-05-07 22:46:43 UTC (rev 183956)
@@ -1,3 +1,15 @@
+2015-05-07 Said Abou-Hallawa <sabouhall...@apple.com>
+
+ Applying a filter on an SVG element, which is larger than 4096 pixels, causes this element to be rendered shifted to the left
+ https://bugs.webkit.org/show_bug.cgi?id=144335
+
+ Reviewed by Darin Adler.
+
+ * svg/filters/big-sized-off-viewport-filter-expected.svg: Added.
+ * svg/filters/big-sized-off-viewport-filter.svg: Added.
+ Ensure when applying a filter on a large SVG element, the viewport of the
+ SVG includes the correct drawing part of this element.
+
2015-05-07 Yoav Weiss <y...@yoav.ws>
Handle meta viewport in HTMLPreloadScanner
Added: trunk/LayoutTests/svg/filters/big-sized-off-viewport-filter-expected.svg (0 => 183956)
--- trunk/LayoutTests/svg/filters/big-sized-off-viewport-filter-expected.svg (rev 0)
+++ trunk/LayoutTests/svg/filters/big-sized-off-viewport-filter-expected.svg 2015-05-07 22:46:43 UTC (rev 183956)
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 500">
+ <filter id="saturate-back">
+ <feColorMatrix in="SourceGraphic" type="saturate" values="1"/>
+ </filter>
+ <g filter="url(#saturate-back)">
+ <rect x="-500" y="0" width="950" height="100%" fill="green"/>
+ <rect x="550" y="0" width="950" height="100%" fill="green"/>
+ </g>
+ <rect x="450" y="0" width="100" height="100%" fill="none" stroke="white" stroke-width="10"/>
+</svg>
Added: trunk/LayoutTests/svg/filters/big-sized-off-viewport-filter.svg (0 => 183956)
--- trunk/LayoutTests/svg/filters/big-sized-off-viewport-filter.svg (rev 0)
+++ trunk/LayoutTests/svg/filters/big-sized-off-viewport-filter.svg 2015-05-07 22:46:43 UTC (rev 183956)
@@ -0,0 +1,11 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 500">
+ <filter id="saturate-back">
+ <feColorMatrix in="SourceGraphic" type="saturate" values="1"/>
+ </filter>
+ <g filter="url(#saturate-back)">
+ <rect x="-3500" y="0" width="3950" height="100%" fill="green"/>
+ <rect x="550" y="0" width="3950" height="100%" fill="green"/>
+ </g>
+ <!-- Ensure the edges of the rectangles are sharp after clamping the filter image and scaling it up -->
+ <rect x="450" y="0" width="100" height="100%" fill="none" stroke="white" stroke-width="10"/>
+</svg>
Modified: trunk/Source/WebCore/ChangeLog (183955 => 183956)
--- trunk/Source/WebCore/ChangeLog 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/ChangeLog 2015-05-07 22:46:43 UTC (rev 183956)
@@ -1,3 +1,109 @@
+2015-05-07 Said Abou-Hallawa <sabouhall...@apple.com>
+
+ Applying a filter on an SVG element, which is larger than 4096 pixels, causes this element to be rendered shifted to the left
+ https://bugs.webkit.org/show_bug.cgi?id=144335
+
+ Reviewed by Darin Adler.
+
+ When the SVG element is larger than 4096x4096 pixels and it has a filter,
+ a clipper or a masker, the ImageBuffer which is created for drawing the
+ sourceGraphicBuffer has to be clamped to this size. The reason for this
+ clamping is the FilterEffect simply ignores processing any ImageBuffer
+ larger than this size.
+
+ The bug was happening because we did not propagate the clamping logic to
+ the FilterEffect. The FilterEffect result ImageBuffer was not clamped as
+ what we do for drawing the sourceGraphicBuffer. If only the destination
+ point is specified, the GraphicsContext::drawImageBuffer() assumes the
+ source and the destination images have the same size which is not true
+ with the clamping.
+
+ The fix is to add the clamping logic to the FilterEffect. Two places we
+ need to change. (1) FilterEffect::createImageBufferResult() has to apply
+ the same clamping we do in SVGRenderingContext::createImageBuffer(). (2)
+ FilterEffect::drawingRegionOfInputImage() has to consider the clamping
+ when mapping from absolute coordinates to the ImageBuffer coordinates.
+
+ Tests: svg/filters/big-sized-off-viewport-filter.svg
+
+ * platform/graphics/ImageBuffer.cpp:
+ (WebCore::ImageBuffer::isSizeClamped):
+ (WebCore::ImageBuffer::clampedSize):
+ (WebCore::ImageBuffer::clampedRect):
+ * platform/graphics/ImageBuffer.h:
+ (WebCore::ImageBuffer::setSpaceSize): Move all the clamping helper methods
+ from SVGRenderingContext and RenderSVGResourceFilter to the ImageBuffer.
+
+ * platform/graphics/filters/FEColorMatrix.cpp:
+ (WebCore::FEColorMatrix::platformApplySoftware): Use logicalSize() of the
+ result image instead of using absolutePaintRect(). The later returns the
+ rectangle of the element without clamping.
+
+ * platform/graphics/filters/FETile.cpp:
+ (WebCore::FETile::platformApplySoftware):
+ * rendering/svg/RenderSVGResourceClipper.cpp:
+ (WebCore::RenderSVGResourceClipper::applyClippingToContext):
+ * rendering/svg/RenderSVGResourceFilter.cpp:
+ (WebCore::RenderSVGResourceFilter::applyResource):
+ (WebCore::RenderSVGResourceFilter::fitsInMaximumImageSize): Deleted.
+ * rendering/svg/RenderSVGResourceFilter.h:
+ * rendering/svg/RenderSVGResourceGradient.cpp:
+ (WebCore::createMaskAndSwapContextForTextGradient):
+ (WebCore::clipToTextMask):
+ * rendering/svg/RenderSVGResourceMasker.cpp:
+ (WebCore::RenderSVGResourceMasker::applySVGMask):
+ * rendering/svg/RenderSVGResourcePattern.cpp:
+ (WebCore::RenderSVGResourcePattern::buildPattern):
+ (WebCore::RenderSVGResourcePattern::createTileImage): Make the modifications
+ which are needed because of moving the clamping helper methods to ImageBuffer
+ and because of changing the prototype of SVGRenderingContext methods.
+
+ * platform/graphics/filters/FilterEffect.cpp:
+ (WebCore::FilterEffect::drawingRegionOfInputImage): Consider the clamping
+ when mapping from absolute coordinates to the ImageBuffer coordinates.
+
+ (WebCore::FilterEffect::createImageBufferResult): Apply the same clamping
+ we do in SVGRenderingContext::createImageBuffer() when creating the
+ FilterEffect result ImageBuffer.
+
+ (WebCore::FilterEffect::apply):
+ (WebCore::FilterEffect::asUnmultipliedImage):
+ (WebCore::FilterEffect::asPremultipliedImage):
+ (WebCore::FilterEffect::copyUnmultipliedImage):
+ (WebCore::FilterEffect::copyPremultipliedImage):
+ (WebCore::FilterEffect::createUnmultipliedImageResult):
+ (WebCore::FilterEffect::createPremultipliedImageResult):
+ (WebCore::FilterEffect::maxFilterArea): Deleted.
+ (WebCore::FilterEffect::isFilterSizeValid): Deleted.
+ * platform/graphics/filters/FilterEffect.h: Use the new ImageBuffer clamping
+ helper methods and delete the local ones.
+
+ * platform/graphics/transforms/AffineTransform.cpp:
+ (WebCore::AffineTransform::scaleNonUniform):
+ (WebCore::AffineTransform::scale):
+ (WebCore::AffineTransform::translate):
+ * platform/graphics/transforms/AffineTransform.h: Add new scale and translate
+ overloads to AffineTransform.
+
+ * rendering/FilterEffectRenderer.cpp:
+ (WebCore::FilterEffectRenderer::updateBackingStoreRect):
+ (WebCore::FilterEffectRendererHelper::beginFilterEffect): Code clean up.
+
+ * rendering/svg/SVGRenderingContext.cpp:
+ (WebCore::SVGRenderingContext::calculateScreenFontSizeScalingFactor):
+ (WebCore::SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem):
+ Return the AffineTransform instead of passing it through the reference of
+ an argument.
+
+ (WebCore::SVGRenderingContext::createImageBuffer):
+ (WebCore::SVGRenderingContext::createImageBufferForPattern): Deleted.
+ Code clean up and method rename.
+
+ (WebCore::SVGRenderingContext::clampedAbsoluteTargetRect): Deleted.
+ (WebCore::SVGRenderingContext::clampedAbsoluteSize): Deleted.
+ * rendering/svg/SVGRenderingContext.h: Move the clamping helper methods to
+ the ImageBuffer class.
+
2015-05-07 Beth Dakin <bda...@apple.com>
New force-related DOM events should fire in WK1 views
Modified: trunk/Source/WebCore/platform/graphics/ImageBuffer.cpp (183955 => 183956)
--- trunk/Source/WebCore/platform/graphics/ImageBuffer.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/platform/graphics/ImageBuffer.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -33,6 +33,56 @@
namespace WebCore {
+static const float MaxClampedLength = 4096;
+static const float MaxClampedArea = MaxClampedLength * MaxClampedLength;
+
+bool ImageBuffer::isSizeClamped(const FloatSize& size)
+{
+ if (size.width() < 0 && size.height() < 0)
+ return false;
+
+ if (size.isEmpty())
+ return true;
+
+ return floorf(size.height()) * floorf(size.width()) <= MaxClampedArea;
+}
+
+bool ImageBuffer::isSizeClamped(const FloatSize& size, FloatSize& scale)
+{
+ FloatSize scaledSize(size);
+ scaledSize.scale(scale.width(), scale.height());
+
+ if (isSizeClamped(scaledSize))
+ return true;
+
+ // The area of scaled size is bigger than the upper limit, adjust the scale to fit.
+ scale.scale(sqrtf(MaxClampedArea / (scaledSize.width() * scaledSize.height())));
+ ASSERT(isSizeClamped(size, scale));
+ return false;
+}
+
+FloatSize ImageBuffer::clampedSize(const FloatSize& size)
+{
+ return size.shrunkTo(FloatSize(MaxClampedLength, MaxClampedLength));
+}
+
+FloatSize ImageBuffer::clampedSize(const FloatSize& size, FloatSize& scale)
+{
+ if (size.isEmpty())
+ return size;
+
+ FloatSize clampedSize = ImageBuffer::clampedSize(size);
+ scale = FloatSize(clampedSize.width() / size.width(), clampedSize.height() / size.height());
+ ASSERT(isSizeClamped(clampedSize));
+ ASSERT(isSizeClamped(size, scale));
+ return clampedSize;
+}
+
+FloatRect ImageBuffer::clampedRect(const FloatRect& rect)
+{
+ return FloatRect(rect.location(), clampedSize(rect.size()));
+}
+
#if !USE(CG)
void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace)
{
Modified: trunk/Source/WebCore/platform/graphics/ImageBuffer.h (183955 => 183956)
--- trunk/Source/WebCore/platform/graphics/ImageBuffer.h 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/platform/graphics/ImageBuffer.h 2015-05-07 22:46:43 UTC (rev 183956)
@@ -123,11 +123,15 @@
bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC3Denum, bool, bool);
FloatSize spaceSize() const { return m_space; }
- void setSpaceSize(const FloatSize& space)
- {
- m_space = space;
- }
+ void setSpaceSize(const FloatSize& space) { m_space = space; }
+ // These functions are used when clamping the ImageBuffer which is created for filter, masker or clipper.
+ static bool isSizeClamped(const FloatSize&);
+ static bool isSizeClamped(const FloatSize&, FloatSize& scale);
+ static FloatSize clampedSize(const FloatSize&);
+ static FloatSize clampedSize(const FloatSize&, FloatSize& scale);
+ static FloatRect clampedRect(const FloatRect&);
+
private:
#if USE(CG)
// The returned image might be larger than the internalSize(). If you want the smaller
Modified: trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp (183955 => 183956)
--- trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -149,7 +149,7 @@
resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
- IntRect imageRect(IntPoint(), absolutePaintRect().size());
+ IntRect imageRect(IntPoint(), resultImage->logicalSize());
RefPtr<Uint8ClampedArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect);
switch (m_type) {
Modified: trunk/Source/WebCore/platform/graphics/filters/FETile.cpp (183955 => 183956)
--- trunk/Source/WebCore/platform/graphics/filters/FETile.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/platform/graphics/filters/FETile.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -63,8 +63,8 @@
tileRect.scale(filter.filterResolution().width(), filter.filterResolution().height());
}
- std::unique_ptr<ImageBuffer> tileImage;
- if (!SVGRenderingContext::createImageBufferForPattern(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB, filter().renderingMode()))
+ auto tileImage = SVGRenderingContext::createImageBuffer(tileRect, tileRect, ColorSpaceDeviceRGB, filter().renderingMode());
+ if (!tileImage)
return;
GraphicsContext* tileImageContext = tileImage->context();
Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp (183955 => 183956)
--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -36,8 +36,6 @@
namespace WebCore {
-static const float kMaxFilterArea = 4096 * 4096;
-
FilterEffect::FilterEffect(Filter& filter)
: m_alphaImage(false)
, m_filter(filter)
@@ -55,19 +53,6 @@
{
}
-float FilterEffect::maxFilterArea()
-{
- return kMaxFilterArea;
-}
-
-bool FilterEffect::isFilterSizeValid(const FloatRect& rect)
-{
- if (rect.width() < 0 || rect.height() < 0
- || (rect.height() * rect.width() > kMaxFilterArea))
- return false;
- return true;
-}
-
void FilterEffect::determineAbsolutePaintRect()
{
m_absolutePaintRect = IntRect();
@@ -93,8 +78,14 @@
FloatRect FilterEffect::drawingRegionOfInputImage(const IntRect& srcRect) const
{
- return FloatRect(FloatPoint(srcRect.x() - m_absolutePaintRect.x(),
- srcRect.y() - m_absolutePaintRect.y()), srcRect.size());
+ ASSERT(hasResult());
+
+ FloatSize scale;
+ ImageBuffer::clampedSize(m_absolutePaintRect.size(), scale);
+
+ AffineTransform transform;
+ transform.scale(scale).translate(-m_absolutePaintRect.location());
+ return transform.mapRect(srcRect);
}
FilterEffect* FilterEffect::inputEffect(unsigned number) const
@@ -156,7 +147,7 @@
determineAbsolutePaintRect();
setResultColorSpace(m_operatingColorSpace);
- if (!isFilterSizeValid(m_absolutePaintRect))
+ if (m_absolutePaintRect.isEmpty() || !ImageBuffer::isSizeClamped(m_absolutePaintRect.size()))
return;
if (requiresValidPreMultipliedPixels()) {
@@ -321,8 +312,8 @@
PassRefPtr<Uint8ClampedArray> FilterEffect::asUnmultipliedImage(const IntRect& rect)
{
- ASSERT(isFilterSizeValid(rect));
IntSize scaledSize(rect.size());
+ ASSERT(ImageBuffer::isSizeClamped(scaledSize));
scaledSize.scale(m_filter.filterScale());
RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(scaledSize.width() * scaledSize.height() * 4);
copyUnmultipliedImage(imageData.get(), rect);
@@ -331,8 +322,8 @@
PassRefPtr<Uint8ClampedArray> FilterEffect::asPremultipliedImage(const IntRect& rect)
{
- ASSERT(isFilterSizeValid(rect));
IntSize scaledSize(rect.size());
+ ASSERT(ImageBuffer::isSizeClamped(scaledSize));
scaledSize.scale(m_filter.filterScale());
RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(scaledSize.width() * scaledSize.height() * 4);
copyPremultipliedImage(imageData.get(), rect);
@@ -397,8 +388,8 @@
if (m_imageBufferResult)
m_unmultipliedImageResult = m_imageBufferResult->getUnmultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size()));
else {
- ASSERT(isFilterSizeValid(m_absolutePaintRect));
IntSize inputSize(m_absolutePaintRect.size());
+ ASSERT(ImageBuffer::isSizeClamped(inputSize));
inputSize.scale(m_filter.filterScale());
m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4);
unsigned char* sourceComponent = m_premultipliedImageResult->data();
@@ -433,8 +424,8 @@
if (m_imageBufferResult)
m_premultipliedImageResult = m_imageBufferResult->getPremultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size()));
else {
- ASSERT(isFilterSizeValid(m_absolutePaintRect));
IntSize inputSize(m_absolutePaintRect.size());
+ ASSERT(ImageBuffer::isSizeClamped(inputSize));
inputSize.scale(m_filter.filterScale());
m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4);
unsigned char* sourceComponent = m_unmultipliedImageResult->data();
@@ -459,10 +450,13 @@
// Only one result type is allowed.
ASSERT(!hasResult());
if (m_absolutePaintRect.isEmpty())
- return 0;
- m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), m_filter.filterScale(), m_resultColorSpace, m_filter.renderingMode());
+ return nullptr;
+
+ FloatSize clampedSize = ImageBuffer::clampedSize(m_absolutePaintRect.size());
+ m_imageBufferResult = ImageBuffer::create(clampedSize, m_filter.filterScale(), m_resultColorSpace, m_filter.renderingMode());
if (!m_imageBufferResult)
- return 0;
+ return nullptr;
+
ASSERT(m_imageBufferResult->context());
return m_imageBufferResult.get();
}
@@ -471,11 +465,11 @@
{
// Only one result type is allowed.
ASSERT(!hasResult());
- ASSERT(isFilterSizeValid(m_absolutePaintRect));
-
if (m_absolutePaintRect.isEmpty())
- return 0;
+ return nullptr;
+
IntSize resultSize(m_absolutePaintRect.size());
+ ASSERT(ImageBuffer::isSizeClamped(resultSize));
resultSize.scale(m_filter.filterScale());
m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(resultSize.width() * resultSize.height() * 4);
return m_unmultipliedImageResult.get();
@@ -485,11 +479,11 @@
{
// Only one result type is allowed.
ASSERT(!hasResult());
- ASSERT(isFilterSizeValid(m_absolutePaintRect));
-
if (m_absolutePaintRect.isEmpty())
- return 0;
+ return nullptr;
+
IntSize resultSize(m_absolutePaintRect.size());
+ ASSERT(ImageBuffer::isSizeClamped(resultSize));
resultSize.scale(m_filter.filterScale());
m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(resultSize.width() * resultSize.height() * 4);
return m_premultipliedImageResult.get();
Modified: trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h (183955 => 183956)
--- trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/platform/graphics/filters/FilterEffect.h 2015-05-07 22:46:43 UTC (rev 183956)
@@ -58,9 +58,6 @@
public:
virtual ~FilterEffect();
- static bool isFilterSizeValid(const FloatRect&);
- static float maxFilterArea();
-
void clearResult();
void clearResultsRecursive();
Modified: trunk/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp (183955 => 183956)
--- trunk/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/platform/graphics/transforms/AffineTransform.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -172,6 +172,16 @@
return *this;
}
+AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
+{
+ return scale(sx, sy);
+}
+
+AffineTransform& AffineTransform::scale(const FloatSize& s)
+{
+ return scale(s.width(), s.height());
+}
+
// *this = *this * translation
AffineTransform& AffineTransform::translate(double tx, double ty)
{
@@ -186,9 +196,9 @@
return *this;
}
-AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
+AffineTransform& AffineTransform::translate(const FloatPoint& t)
{
- return scale(sx, sy);
+ return translate(t.x(), t.y());
}
AffineTransform& AffineTransform::rotateFromVector(double x, double y)
Modified: trunk/Source/WebCore/platform/graphics/transforms/AffineTransform.h (183955 => 183956)
--- trunk/Source/WebCore/platform/graphics/transforms/AffineTransform.h 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/platform/graphics/transforms/AffineTransform.h 2015-05-07 22:46:43 UTC (rev 183956)
@@ -98,9 +98,11 @@
WEBCORE_EXPORT AffineTransform& scale(double);
AffineTransform& scale(double sx, double sy);
AffineTransform& scaleNonUniform(double sx, double sy);
+ AffineTransform& scale(const FloatSize&);
AffineTransform& rotate(double d);
AffineTransform& rotateFromVector(double x, double y);
WEBCORE_EXPORT AffineTransform& translate(double tx, double ty);
+ AffineTransform& translate(const FloatPoint&);
AffineTransform& shear(double sx, double sy);
AffineTransform& flipX();
WEBCORE_EXPORT AffineTransform& flipY();
@@ -172,7 +174,7 @@
{
return AffineTransform(1, 0, 0, 1, x, y);
}
-
+
// decompose the matrix into its component parts
typedef struct {
double scaleX, scaleY;
Modified: trunk/Source/WebCore/rendering/FilterEffectRenderer.cpp (183955 => 183956)
--- trunk/Source/WebCore/rendering/FilterEffectRenderer.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/FilterEffectRenderer.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -305,14 +305,14 @@
bool FilterEffectRenderer::updateBackingStoreRect(const FloatRect& filterRect)
{
- if (!filterRect.isZero() && FilterEffect::isFilterSizeValid(filterRect)) {
- FloatRect currentSourceRect = sourceImageRect();
- if (filterRect != currentSourceRect) {
- setSourceImageRect(filterRect);
- return true;
- }
- }
- return false;
+ if (filterRect.isEmpty() || !ImageBuffer::isSizeClamped(filterRect.size()))
+ return false;
+
+ if (filterRect == sourceImageRect())
+ return false;
+
+ setSourceImageRect(filterRect);
+ return true;
}
void FilterEffectRenderer::allocateBackingStoreIfNeeded()
@@ -401,7 +401,7 @@
filter->allocateBackingStoreIfNeeded();
// Paint into the context that represents the SourceGraphic of the filter.
GraphicsContext* sourceGraphicsContext = filter->inputContext();
- if (!sourceGraphicsContext || !FilterEffect::isFilterSizeValid(filter->filterRegion())) {
+ if (!sourceGraphicsContext || filter->filterRegion().isEmpty() || !ImageBuffer::isSizeClamped(filter->filterRegion().size())) {
// Disable the filters and continue.
m_haveFilterEffect = false;
return false;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp (183955 => 183956)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -138,11 +138,11 @@
if (shouldCreateClipperMaskImage && pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox))
return true;
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer, absoluteTransform);
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
if (shouldCreateClipperMaskImage && !repaintRect.isEmpty()) {
- if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperMaskImage, ColorSpaceDeviceRGB, Unaccelerated))
+ clipperMaskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceDeviceRGB, Unaccelerated);
+ if (!clipperMaskImage)
return false;
GraphicsContext* maskContext = clipperMaskImage->context();
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp (183955 => 183956)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -96,21 +96,6 @@
return builder;
}
-bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale)
-{
- FloatSize scaledSize(size);
- scaledSize.scale(scale.width(), scale.height());
- float scaledArea = scaledSize.width() * scaledSize.height();
-
- if (scaledArea <= FilterEffect::maxFilterArea())
- return true;
-
- // If area of scaled size is bigger than the upper limit, adjust the scale
- // to fit.
- scale.scale(sqrt(FilterEffect::maxFilterArea() / scaledArea));
- return false;
-}
-
bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const RenderStyle&, GraphicsContext*& context, unsigned short resourceMode)
{
ASSERT(context);
@@ -131,8 +116,7 @@
return false;
// Determine absolute transformation matrix for filter.
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer, absoluteTransform);
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
if (!absoluteTransform.isInvertible())
return false;
@@ -167,8 +151,8 @@
// Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
FloatRect tempSourceRect = absoluteDrawingRegion;
+ ImageBuffer::isSizeClamped(tempSourceRect.size(), scale);
tempSourceRect.scale(scale.width(), scale.height());
- fitsInMaximumImageSize(tempSourceRect.size(), scale);
// Set the scale level in SVGFilter.
filterData->filter->setFilterResolution(scale);
@@ -182,7 +166,7 @@
FloatRect subRegion = lastEffect->maxEffectRect();
// At least one FilterEffect has a too big image size,
// recalculate the effect sizes with new scale factors.
- if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
+ if (!ImageBuffer::isSizeClamped(subRegion.size(), scale)) {
filterData->filter->setFilterResolution(scale);
RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(*lastEffect);
}
@@ -201,9 +185,10 @@
effectiveTransform.scale(scale.width(), scale.height());
effectiveTransform.multiply(filterData->shearFreeAbsoluteTransform);
- std::unique_ptr<ImageBuffer> sourceGraphic;
RenderingMode renderingMode = renderer.frame().settings().acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
- if (!SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
+
+ auto sourceGraphic = SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, ColorSpaceLinearRGB, renderingMode);
+ if (!sourceGraphic) {
ASSERT(!m_filter.contains(&renderer));
filterData->savedContext = context;
m_filter.set(&renderer, WTF::move(filterData));
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h (183955 => 183956)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceFilter.h 2015-05-07 22:46:43 UTC (rev 183956)
@@ -91,8 +91,6 @@
virtual const char* renderName() const override { return "RenderSVGResourceFilter"; }
virtual bool isSVGResourceFilter() const override { return true; }
- bool fitsInMaximumImageSize(const FloatSize&, FloatSize&);
-
HashMap<RenderObject*, std::unique_ptr<FilterData>> m_filter;
};
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp (183955 => 183956)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -58,12 +58,11 @@
auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object);
ASSERT(textRootBlock);
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock, absoluteTransform);
-
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock);
FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates();
- std::unique_ptr<ImageBuffer> maskImage;
- if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskImage, ColorSpaceDeviceRGB, Unaccelerated))
+
+ auto maskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceDeviceRGB, Unaccelerated);
+ if (!maskImage)
return false;
GraphicsContext* maskImageContext = maskImage->context();
@@ -80,10 +79,10 @@
auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object);
ASSERT(textRootBlock);
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock, absoluteTransform);
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock);
targetRect = textRootBlock->repaintRectInLocalCoordinates();
+
SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, targetRect, imageBuffer, false);
AffineTransform matrix;
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp (183955 => 183956)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -63,16 +63,14 @@
m_masker.set(&renderer, std::make_unique<MaskerData>());
MaskerData* maskerData = m_masker.get(&renderer);
-
- AffineTransform absoluteTransform;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer, absoluteTransform);
-
+ AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
FloatRect repaintRect = renderer.repaintRectInLocalCoordinates();
if (!maskerData->maskImage && !repaintRect.isEmpty()) {
const SVGRenderStyle& svgStyle = style().svgStyle();
ColorSpace colorSpace = svgStyle.colorInterpolation() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB;
- if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskerData->maskImage, colorSpace, Unaccelerated))
+ maskerData->maskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, colorSpace, Unaccelerated);
+ if (!maskerData->maskImage)
return false;
if (!drawContentIntoMaskImage(maskerData, colorSpace, &renderer))
Modified: trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp (183955 => 183956)
--- trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -70,20 +70,19 @@
// If we couldn't determine the pattern content element root, stop here.
if (!m_attributes.patternContentElement())
- return 0;
+ return nullptr;
// An empty viewBox disables rendering.
if (m_attributes.hasViewBox() && m_attributes.viewBox().isEmpty())
- return 0;
+ return nullptr;
// Compute all necessary transformations to build the tile image & the pattern.
FloatRect tileBoundaries;
AffineTransform tileImageTransform;
if (!buildTileImageTransform(renderer, m_attributes, patternElement(), tileBoundaries, tileImageTransform))
- return 0;
+ return nullptr;
- AffineTransform absoluteTransformIgnoringRotation;
- SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer, absoluteTransformIgnoringRotation);
+ AffineTransform absoluteTransformIgnoringRotation = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
// Ignore 2D rotation, as it doesn't affect the size of the tile.
SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation);
@@ -95,13 +94,13 @@
static_cast<float>(m_attributes.patternTransform().yScale()));
// Build tile image.
- std::unique_ptr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
+ auto tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
if (!tileImage)
- return 0;
+ return nullptr;
RefPtr<Image> copiedImage = tileImage->copyImage(CopyBackingStore);
if (!copiedImage)
- return 0;
+ return nullptr;
// Build pattern.
auto patternData = std::make_unique<PatternData>();
@@ -233,11 +232,9 @@
std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries) const
{
- clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
-
- std::unique_ptr<ImageBuffer> tileImage;
-
- if (!SVGRenderingContext::createImageBufferForPattern(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB, Unaccelerated))
+ clampedAbsoluteTileBoundaries = ImageBuffer::clampedRect(absoluteTileBoundaries);
+ auto tileImage = SVGRenderingContext::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, ColorSpaceDeviceRGB, Unaccelerated);
+ if (!tileImage)
return nullptr;
GraphicsContext* tileImageContext = tileImage->context();
Modified: trunk/Source/WebCore/rendering/svg/SVGRenderingContext.cpp (183955 => 183956)
--- trunk/Source/WebCore/rendering/svg/SVGRenderingContext.cpp 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderingContext.cpp 2015-05-07 22:46:43 UTC (rev 183956)
@@ -39,8 +39,6 @@
#include "SVGResources.h"
#include "SVGResourcesCache.h"
-static int kMaxImageBufferSize = 4096;
-
namespace WebCore {
static inline bool isRenderingMaskImage(const RenderObject& object)
@@ -204,14 +202,13 @@
float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObject& renderer)
{
- AffineTransform ctm;
- calculateTransformationToOutermostCoordinateSystem(renderer, ctm);
+ AffineTransform ctm = calculateTransformationToOutermostCoordinateSystem(renderer);
return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2));
}
-void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject& renderer, AffineTransform& absoluteTransform)
+AffineTransform SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject& renderer)
{
- absoluteTransform = currentContentTransformation();
+ AffineTransform absoluteTransform = currentContentTransformation();
float deviceScaleFactor = renderer.document().deviceScaleFactor();
// Walk up the render tree, accumulating SVG transforms.
@@ -237,53 +234,53 @@
}
absoluteTransform.scale(deviceScaleFactor);
+ return absoluteTransform;
}
-bool SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, std::unique_ptr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+std::unique_ptr<ImageBuffer> SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, ColorSpace colorSpace, RenderingMode renderingMode)
{
IntRect paintRect = calculateImageBufferRect(targetRect, absoluteTransform);
// Don't create empty ImageBuffers.
if (paintRect.isEmpty())
- return false;
+ return nullptr;
- IntSize clampedSize = clampedAbsoluteSize(paintRect.size());
- std::unique_ptr<ImageBuffer> image = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
- if (!image)
- return false;
+ FloatSize scale;
+ FloatSize clampedSize = ImageBuffer::clampedSize(paintRect.size(), scale);
- GraphicsContext* imageContext = image->context();
- ASSERT(imageContext);
+ auto imageBuffer = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
+ if (!imageBuffer)
+ return nullptr;
- imageContext->scale(FloatSize(static_cast<float>(clampedSize.width()) / paintRect.width(),
- static_cast<float>(clampedSize.height()) / paintRect.height()));
- imageContext->translate(-paintRect.x(), -paintRect.y());
- imageContext->concatCTM(absoluteTransform);
+ AffineTransform transform;
+ transform.scale(scale).translate(-paintRect.location()).multiply(absoluteTransform);
- imageBuffer = WTF::move(image);
- return true;
+ GraphicsContext* imageContext = imageBuffer->context();
+ ASSERT(imageContext);
+ imageContext->concatCTM(transform);
+
+ return imageBuffer;
}
-bool SVGRenderingContext::createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, std::unique_ptr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+std::unique_ptr<ImageBuffer> SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const FloatRect& clampedRect, ColorSpace colorSpace, RenderingMode renderingMode)
{
- IntSize imageSize(roundedIntSize(clampedAbsoluteTargetRect.size()));
- IntSize unclampedImageSize(roundedIntSize(absoluteTargetRect.size()));
+ IntSize clampedSize = roundedIntSize(clampedRect.size());
+ IntSize unclampedSize = roundedIntSize(targetRect.size());
// Don't create empty ImageBuffers.
- if (imageSize.isEmpty())
- return false;
+ if (clampedSize.isEmpty())
+ return nullptr;
- std::unique_ptr<ImageBuffer> image = ImageBuffer::create(imageSize, 1, colorSpace, renderingMode);
- if (!image)
- return false;
+ auto imageBuffer = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
+ if (!imageBuffer)
+ return nullptr;
- GraphicsContext* imageContext = image->context();
+ GraphicsContext* imageContext = imageBuffer->context();
ASSERT(imageContext);
// Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer.
- imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height()));
+ imageContext->scale(FloatSize(unclampedSize.width() / targetRect.width(), unclampedSize.height() / targetRect.height()));
- imageBuffer = WTF::move(image);
- return true;
+ return imageBuffer;
}
void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderElement& item, const AffineTransform& subtreeContentTransformation)
@@ -322,18 +319,6 @@
imageBuffer.reset();
}
-FloatRect SVGRenderingContext::clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect)
-{
- const FloatSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
- return FloatRect(absoluteTargetRect.location(), absoluteTargetRect.size().shrunkTo(maxImageBufferSize));
-}
-
-IntSize SVGRenderingContext::clampedAbsoluteSize(const IntSize& absoluteSize)
-{
- const IntSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
- return absoluteSize.shrunkTo(maxImageBufferSize);
-}
-
void SVGRenderingContext::clear2DRotation(AffineTransform& transform)
{
AffineTransform::DecomposedType decomposition;
Modified: trunk/Source/WebCore/rendering/svg/SVGRenderingContext.h (183955 => 183956)
--- trunk/Source/WebCore/rendering/svg/SVGRenderingContext.h 2015-05-07 22:35:56 UTC (rev 183955)
+++ trunk/Source/WebCore/rendering/svg/SVGRenderingContext.h 2015-05-07 22:46:43 UTC (rev 183956)
@@ -71,17 +71,14 @@
void prepareToRenderSVGContent(RenderElement&, PaintInfo&, NeedsGraphicsContextSave = DontSaveGraphicsContext);
bool isRenderingPrepared() const { return m_renderingFlags & RenderingPrepared; }
- static bool createImageBuffer(const FloatRect& paintRect, const AffineTransform& absoluteTransform, std::unique_ptr<ImageBuffer>&, ColorSpace, RenderingMode);
- // Patterns need a different float-to-integer coordinate mapping.
- static bool createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, std::unique_ptr<ImageBuffer>&, ColorSpace, RenderingMode);
+ static std::unique_ptr<ImageBuffer> createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, ColorSpace, RenderingMode);
+ static std::unique_ptr<ImageBuffer> createImageBuffer(const FloatRect& targetRect, const FloatRect& clampedRect, ColorSpace, RenderingMode);
static void renderSubtreeToImageBuffer(ImageBuffer*, RenderElement&, const AffineTransform&);
static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, std::unique_ptr<ImageBuffer>&, bool safeToClear);
static float calculateScreenFontSizeScalingFactor(const RenderObject&);
- static void calculateTransformationToOutermostCoordinateSystem(const RenderObject&, AffineTransform& absoluteTransform);
- static IntSize clampedAbsoluteSize(const IntSize&);
- static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
+ static AffineTransform calculateTransformationToOutermostCoordinateSystem(const RenderObject&);
static void clear2DRotation(AffineTransform&);
static IntRect calculateImageBufferRect(const FloatRect& targetRect, const AffineTransform& absoluteTransform)