| Index: Source/WebCore/svg/graphics/SVGImage.cpp | 
| =================================================================== | 
| --- Source/WebCore/svg/graphics/SVGImage.cpp	(revision 143954) | 
| +++ Source/WebCore/svg/graphics/SVGImage.cpp	(working copy) | 
| @@ -34,6 +34,7 @@ | 
| #include "FrameView.h" | 
| #include "ImageBuffer.h" | 
| #include "ImageObserver.h" | 
| +#include "IntRect.h" | 
| #include "RenderSVGRoot.h" | 
| #include "SVGDocument.h" | 
| #include "SVGImageChromeClient.h" | 
| @@ -59,10 +60,23 @@ | 
| ASSERT(!m_chromeClient || !m_chromeClient->image()); | 
| } | 
|  | 
| -void SVGImage::setContainerSize(const IntSize&) | 
| +void SVGImage::setContainerSize(const IntSize& size) | 
| { | 
| -    // SVGImageCache already intercepted this call, as it stores & caches the desired container sizes & zoom levels. | 
| -    ASSERT_NOT_REACHED(); | 
| +    if (!m_page || !usesContainerSize()) | 
| +        return; | 
| + | 
| +    Frame* frame = m_page->mainFrame(); | 
| +    SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); | 
| +    if (!rootElement) | 
| +        return; | 
| +    RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()); | 
| +    if (!renderer) | 
| +        return; | 
| + | 
| +    FrameView* view = frameView(); | 
| +    view->resize(this->size()); | 
| + | 
| +    renderer->setContainerSize(size); | 
| } | 
|  | 
| IntSize SVGImage::size() const | 
| @@ -99,56 +113,46 @@ | 
| return IntSize(300, 150); | 
| } | 
|  | 
| -void SVGImage::drawSVGToImageBuffer(ImageBuffer* buffer, const FloatSize& size, float zoomAndScale, ShouldClearBuffer shouldClear) | 
| +void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& dstRect, | 
| +    const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, BlendMode blendMode) | 
| { | 
| -    // FIXME: This doesn't work correctly with animations. If an image contains animations, that say run for 2 seconds, | 
| -    // and we currently have one <img> that displays us. If we open another document referencing the same SVGImage it | 
| -    // will display the document at a time where animations already ran - even though it has its own ImageBuffer. | 
| -    // We currently don't implement SVGSVGElement::setCurrentTime, and can NOT go back in time, once animations started. | 
| -    // There's no way to fix this besides avoiding style/attribute mutations from SVGAnimationElement. | 
| -    ASSERT(buffer); | 
| -    ASSERT(!size.isEmpty()); | 
| - | 
| if (!m_page) | 
| return; | 
|  | 
| -    Frame* frame = m_page->mainFrame(); | 
| -    SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); | 
| -    if (!rootElement) | 
| -        return; | 
| -    RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()); | 
| -    if (!renderer) | 
| -        return; | 
| - | 
| -    // Draw image at requested size. | 
| ImageObserver* observer = imageObserver(); | 
| ASSERT(observer); | 
|  | 
| // Temporarily reset image observer, we don't want to receive any changeInRect() calls due to this relayout. | 
| setImageObserver(0); | 
|  | 
| -    // Disable repainting; we don't want deferred repaints to schedule any timers due to this relayout. | 
| -    frame->view()->beginDisableRepaints(); | 
| +    IntSize roundedContainerSize = roundedIntSize(containerSize); | 
| +    setContainerSize(roundedContainerSize); | 
|  | 
| -    IntSize containerSize = roundedIntSize(size); | 
| -    renderer->setContainerSize(containerSize); | 
| -    frame->view()->resize(this->size()); | 
| +    FloatRect scaledSrc = srcRect; | 
| +    scaledSrc.scale(1 / zoom); | 
|  | 
| -    FloatSize scaledContainerSize(size); | 
| -    scaledContainerSize.scale(zoomAndScale); | 
| -    IntRect destRect = IntRect(IntPoint(), expandedIntSize(scaledContainerSize)); | 
| -    if (shouldClear == ClearImageBuffer) | 
| -        buffer->context()->clearRect(destRect); | 
| +    // Compensate for the container size rounding by adjusting the source rect. | 
| +    FloatSize adjustedSrcSize = scaledSrc.size(); | 
| +    adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height()); | 
| +    scaledSrc.setSize(adjustedSrcSize); | 
|  | 
| -    // Draw SVG on top of ImageBuffer. | 
| -    draw(buffer->context(), destRect, IntRect(IntPoint(), containerSize), ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal); | 
| +    draw(context, dstRect, scaledSrc, colorSpace, compositeOp, blendMode); | 
|  | 
| -    if (frame->view()->needsLayout()) | 
| -        frame->view()->layout(); | 
| - | 
| setImageObserver(observer); | 
| +} | 
|  | 
| -    frame->view()->endDisableRepaints(); | 
| +void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize containerSize, float pageScale, float zoom, const FloatRect& srcRect, | 
| +    const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace colorSpace, CompositeOperator compositeOp, const FloatRect& dstRect) | 
| +{ | 
| +    FloatSize zoomedContainerSize(containerSize); | 
| +    zoomedContainerSize.scale(zoom); | 
| +    FloatRect zoomedContainerRect = FloatRect(FloatPoint(), zoomedContainerSize); | 
| + | 
| +    OwnPtr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(zoomedContainerSize), pageScale); | 
| +    drawForContainer(buffer->context(), containerSize, zoom, zoomedContainerRect, zoomedContainerRect, ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal); | 
| + | 
| +    RefPtr<Image> image = buffer->copyImage(CopyBackingStore); | 
| +    image->drawPattern(context, srcRect, patternTransform, phase, colorSpace, compositeOp, dstRect); | 
| } | 
|  | 
| void SVGImage::draw(GraphicsContext* context, const FloatRect& dstRect, const FloatRect& srcRect, ColorSpace, CompositeOperator compositeOp, BlendMode) | 
| @@ -250,23 +254,36 @@ | 
| intrinsicRatio = FloatSize(floatValueForLength(intrinsicWidth, 0), floatValueForLength(intrinsicHeight, 0)); | 
| } | 
|  | 
| -NativeImagePtr SVGImage::nativeImageForCurrentFrame() | 
| +// FIXME: support catchUpIfNecessary. | 
| +void SVGImage::startAnimation(bool /* catchUpIfNecessary */) | 
| { | 
| -    // FIXME: In order to support dynamic SVGs we need to have a way to invalidate this | 
| -    // frame cache, or better yet, not use a cache for tiled drawing at all, instead | 
| -    // having a tiled drawing callback (hopefully non-virtual). | 
| -    if (!m_frameCache) { | 
| -        if (!m_page) | 
| -            return 0; | 
| -        OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size(), 1); | 
| -        if (!buffer) // failed to allocate image | 
| -            return 0; | 
| -        draw(buffer->context(), rect(), rect(), ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal); | 
| -        m_frameCache = buffer->copyImage(CopyBackingStore); | 
| -    } | 
| -    return m_frameCache->nativeImageForCurrentFrame(); | 
| +    if (!m_page) | 
| +        return; | 
| +    Frame* frame = m_page->mainFrame(); | 
| +    SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); | 
| +    if (!rootElement) | 
| +        return; | 
| +    rootElement->unpauseAnimations(); | 
| +    rootElement->setCurrentTime(0); | 
| } | 
|  | 
| +void SVGImage::stopAnimation() | 
| +{ | 
| +    if (!m_page) | 
| +        return; | 
| +    Frame* frame = m_page->mainFrame(); | 
| +    SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); | 
| +    if (!rootElement) | 
| +        return; | 
| +    rootElement->pauseAnimations(); | 
| +} | 
| + | 
| +void SVGImage::resetAnimation() | 
| +{ | 
| +    stopAnimation(); | 
| +    startAnimation(); | 
| +} | 
| + | 
| bool SVGImage::dataChanged(bool allDataReceived) | 
| { | 
| // Don't do anything if is an empty image. | 
| @@ -322,7 +339,6 @@ | 
| Image::reportMemoryUsage(memoryObjectInfo); | 
| info.addMember(m_chromeClient, "chromeClient"); | 
| info.addMember(m_page, "page"); | 
| -    info.addMember(m_frameCache, "frameCache"); | 
| } | 
|  | 
| } | 
|  |