summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering/RenderSVGResourceGradient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering/RenderSVGResourceGradient.cpp')
-rw-r--r--WebCore/rendering/RenderSVGResourceGradient.cpp67
1 files changed, 25 insertions, 42 deletions
diff --git a/WebCore/rendering/RenderSVGResourceGradient.cpp b/WebCore/rendering/RenderSVGResourceGradient.cpp
index 73b2ab6..d29192a 100644
--- a/WebCore/rendering/RenderSVGResourceGradient.cpp
+++ b/WebCore/rendering/RenderSVGResourceGradient.cpp
@@ -28,6 +28,7 @@
#include "GradientAttributes.h"
#include "GraphicsContext.h"
+#include "SVGImageBufferTools.h"
#include "SVGRenderSupport.h"
#include <wtf/UnusedParam.h>
@@ -50,81 +51,64 @@ RenderSVGResourceGradient::~RenderSVGResourceGradient()
m_gradient.clear();
}
-void RenderSVGResourceGradient::invalidateClients()
+void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidation)
{
if (!m_gradient.isEmpty()) {
deleteAllValues(m_gradient);
m_gradient.clear();
}
- markAllClientsForInvalidation(RepaintInvalidation);
+ markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
}
-void RenderSVGResourceGradient::invalidateClient(RenderObject* client)
+void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool markForInvalidation)
{
ASSERT(client);
- ASSERT(client->selfNeedsLayout());
if (m_gradient.contains(client))
delete m_gradient.take(client);
- markClientForInvalidation(client, RepaintInvalidation);
+ markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
}
#if PLATFORM(CG)
-static inline AffineTransform absoluteTransformFromContext(GraphicsContext* context)
-{
- // Extract current transformation matrix used in the original context. Note that this coordinate
- // system is flipped compared to SVGs internal coordinate system, done in WebKit level. Fix
- // this transformation by flipping the y component.
- return context->getCTM() * AffineTransform().flipY();
-}
-
static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& context,
GraphicsContext*& savedContext,
OwnPtr<ImageBuffer>& imageBuffer,
const RenderObject* object)
{
const RenderObject* textRootBlock = SVGRenderSupport::findTextRootObject(object);
+ ASSERT(textRootBlock);
- AffineTransform transform(absoluteTransformFromContext(context));
- FloatRect maskAbsoluteBoundingBox = transform.mapRect(textRootBlock->repaintRectInLocalCoordinates());
+ AffineTransform absoluteTransform(SVGImageBufferTools::absoluteTransformFromContext(context));
+ FloatRect absoluteTargetRect = absoluteTransform.mapRect(textRootBlock->repaintRectInLocalCoordinates());
- IntRect maskImageRect = enclosingIntRect(maskAbsoluteBoundingBox);
- if (maskImageRect.isEmpty())
+ OwnPtr<ImageBuffer> maskImage;
+ if (!SVGImageBufferTools::createImageBuffer(absoluteTransform, absoluteTargetRect, maskImage, DeviceRGB))
return false;
- // Allocate an image buffer as big as the absolute unclipped size of the object
- OwnPtr<ImageBuffer> maskImage = ImageBuffer::create(maskImageRect.size());
- if (!maskImage)
- return false;
-
- GraphicsContext* maskImageContext = maskImage->context();
-
- // Transform the mask image coordinate system to absolute screen coordinates
- maskImageContext->translate(-maskAbsoluteBoundingBox.x(), -maskAbsoluteBoundingBox.y());
- maskImageContext->concatCTM(transform);
-
- imageBuffer = maskImage.release();
+ ASSERT(maskImage);
savedContext = context;
- context = maskImageContext;
-
+ context = maskImage->context();
+ imageBuffer = maskImage.release();
return true;
}
static inline AffineTransform clipToTextMask(GraphicsContext* context,
OwnPtr<ImageBuffer>& imageBuffer,
+ FloatRect& repaintRect,
const RenderObject* object,
GradientData* gradientData)
{
const RenderObject* textRootBlock = SVGRenderSupport::findTextRootObject(object);
+ ASSERT(textRootBlock);
- // The mask image has been created in the device coordinate space, as the image should not be scaled.
- // So the actual masking process has to be done in the device coordinate space as well.
- AffineTransform transform(absoluteTransformFromContext(context));
- context->concatCTM(transform.inverse());
- context->clipToImageBuffer(transform.mapRect(textRootBlock->repaintRectInLocalCoordinates()), imageBuffer.get());
- context->concatCTM(transform);
+ repaintRect = textRootBlock->repaintRectInLocalCoordinates();
+
+ AffineTransform absoluteTransform(SVGImageBufferTools::absoluteTransformFromContext(context));
+ FloatRect absoluteTargetRect = absoluteTransform.mapRect(repaintRect);
+
+ SVGImageBufferTools::clipToImageBuffer(context, absoluteTransform, absoluteTargetRect, imageBuffer.get());
AffineTransform matrix;
if (gradientData->boundingBoxMode) {
@@ -146,7 +130,7 @@ bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle*
// Be sure to synchronize all SVG properties on the gradientElement _before_ processing any further.
// Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property
- // synchronization to kick in, which causes invalidateClients() to be called, which in turn deletes our
+ // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our
// GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash.
SVGGradientElement* gradientElement = static_cast<SVGGradientElement*>(node());
if (!gradientElement)
@@ -232,12 +216,11 @@ void RenderSVGResourceGradient::postApplyResource(RenderObject* object, Graphics
context = m_savedContext;
m_savedContext = 0;
- gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, object, gradientData));
+ FloatRect repaintRect;
+ gradientData->gradient->setGradientSpaceTransform(clipToTextMask(context, m_imageBuffer, repaintRect, object, gradientData));
context->setFillGradient(gradientData->gradient);
- const RenderObject* textRootBlock = SVGRenderSupport::findTextRootObject(object);
- context->fillRect(textRootBlock->repaintRectInLocalCoordinates());
-
+ context->fillRect(repaintRect);
m_imageBuffer.clear();
}
#else