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