| Index: Source/WebCore/svg/graphics/SVGImageCache.cpp
|
| ===================================================================
|
| --- Source/WebCore/svg/graphics/SVGImageCache.cpp (revision 143954)
|
| +++ Source/WebCore/svg/graphics/SVGImageCache.cpp (working copy)
|
| @@ -29,50 +29,27 @@
|
| #include "Page.h"
|
| #include "RenderSVGRoot.h"
|
| #include "SVGImage.h"
|
| +#include "SVGImageForContainer.h"
|
|
|
| namespace WebCore {
|
|
|
| -static const int timeToKeepCachedBitmapsAfterLastUseInSeconds = 30;
|
| -
|
| SVGImageCache::SVGImageCache(SVGImage* svgImage)
|
| : m_svgImage(svgImage)
|
| - , m_redrawTimer(this, &SVGImageCache::redrawTimerFired)
|
| - , m_cacheClearTimer(this, &SVGImageCache::cacheClearTimerFired, timeToKeepCachedBitmapsAfterLastUseInSeconds)
|
| {
|
| ASSERT(m_svgImage);
|
| }
|
|
|
| SVGImageCache::~SVGImageCache()
|
| {
|
| - m_sizeAndScalesMap.clear();
|
| - clearBitmapCache();
|
| + m_imageForContainerMap.clear();
|
| }
|
|
|
| -void SVGImageCache::clearBitmapCache()
|
| -{
|
| - ImageDataMap::iterator end = m_imageDataMap.end();
|
| - for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it) {
|
| - // Checks if the client (it->key) is still valid. The client should remove itself from this
|
| - // cache before its end of life, otherwise the following ASSERT will crash on pure virtual
|
| - // function call or a general crash.
|
| - ASSERT(it->key->resourceClientType() == CachedImageClient::expectedType());
|
| - delete it->value.buffer;
|
| - }
|
| -
|
| - m_imageDataMap.clear();
|
| -}
|
| -
|
| void SVGImageCache::removeClientFromCache(const CachedImageClient* client)
|
| {
|
| ASSERT(client);
|
| - m_sizeAndScalesMap.remove(client);
|
|
|
| - ImageDataMap::iterator it = m_imageDataMap.find(client);
|
| - if (it == m_imageDataMap.end())
|
| - return;
|
| -
|
| - delete it->value.buffer;
|
| - m_imageDataMap.remove(it);
|
| + if (m_imageForContainerMap.contains(client))
|
| + m_imageForContainerMap.remove(client);
|
| }
|
|
|
| void SVGImageCache::setContainerSizeForRenderer(const CachedImageClient* client, const IntSize& containerSize, float containerZoom)
|
| @@ -82,135 +59,58 @@
|
|
|
| FloatSize containerSizeWithoutZoom(containerSize);
|
| containerSizeWithoutZoom.scale(1 / containerZoom);
|
| - m_sizeAndScalesMap.set(client, SizeAndScales(containerSizeWithoutZoom, containerZoom));
|
| +
|
| + ImageForContainerMap::iterator imageIt = m_imageForContainerMap.find(client);
|
| + if (imageIt == m_imageForContainerMap.end()) {
|
| + RefPtr<SVGImageForContainer> image = SVGImageForContainer::create(m_svgImage, containerSizeWithoutZoom, 1, containerZoom);
|
| + m_imageForContainerMap.set(client, image);
|
| + } else {
|
| + imageIt->value->setSize(containerSizeWithoutZoom);
|
| + imageIt->value->setZoom(containerZoom);
|
| + }
|
| }
|
|
|
| IntSize SVGImageCache::imageSizeForRenderer(const RenderObject* renderer) const
|
| {
|
| IntSize imageSize = m_svgImage->size();
|
| -
|
| if (!renderer)
|
| return imageSize;
|
| - SizeAndScalesMap::const_iterator it = m_sizeAndScalesMap.find(renderer);
|
| - if (it == m_sizeAndScalesMap.end())
|
| +
|
| + ImageForContainerMap::const_iterator it = m_imageForContainerMap.find(renderer);
|
| + if (it == m_imageForContainerMap.end())
|
| return imageSize;
|
|
|
| - SizeAndScales sizeAndScales = it->value;
|
| - if (!sizeAndScales.size.isEmpty()) {
|
| - float scale = sizeAndScales.scale;
|
| - if (!scale) {
|
| - Page* page = renderer->document()->page();
|
| - scale = page->deviceScaleFactor() * page->pageScaleFactor();
|
| - }
|
| -
|
| - imageSize.setWidth(scale * sizeAndScales.size.width());
|
| - imageSize.setHeight(scale * sizeAndScales.size.height());
|
| + RefPtr<SVGImageForContainer> image = it->value;
|
| + FloatSize size = image->containerSize();
|
| + if (!size.isEmpty()) {
|
| + size.scale(image->zoom());
|
| + imageSize.setWidth(size.width());
|
| + imageSize.setHeight(size.height());
|
| }
|
| +
|
| return imageSize;
|
| }
|
|
|
| -void SVGImageCache::imageContentChanged()
|
| +// FIXME: This doesn't take into account the animation timeline so animations will not
|
| +// restart on page load, nor will two animations in different pages have different timelines.
|
| +Image* SVGImageCache::imageForRenderer(const RenderObject* renderer)
|
| {
|
| - ImageDataMap::iterator end = m_imageDataMap.end();
|
| - for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it)
|
| - it->value.imageNeedsUpdate = true;
|
| -
|
| - // Always redraw on a timer because this method may be invoked from destructors of things we are intending to draw.
|
| - if (!m_redrawTimer.isActive())
|
| - m_redrawTimer.startOneShot(0);
|
| -}
|
| -
|
| -void SVGImageCache::redraw()
|
| -{
|
| - ImageDataMap::iterator end = m_imageDataMap.end();
|
| - for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it) {
|
| - ImageData& data = it->value;
|
| - if (!data.imageNeedsUpdate)
|
| - continue;
|
| - // If the content changed we redraw using our existing ImageBuffer.
|
| - ASSERT(data.buffer);
|
| - ASSERT(data.image);
|
| - m_svgImage->drawSVGToImageBuffer(data.buffer, data.sizeAndScales.size, data.sizeAndScales.zoom * data.sizeAndScales.scale, SVGImage::ClearImageBuffer);
|
| - data.image = data.buffer->copyImage(CopyBackingStore);
|
| - data.imageNeedsUpdate = false;
|
| - }
|
| - ASSERT(m_svgImage->imageObserver());
|
| - m_svgImage->imageObserver()->animationAdvanced(m_svgImage);
|
| -}
|
| -
|
| -void SVGImageCache::redrawTimerFired(Timer<SVGImageCache>*)
|
| -{
|
| - // We have no guarantee that the frame does not require layout when the timer fired.
|
| - // So be sure to check again in case it is still not safe to run redraw.
|
| - FrameView* frameView = m_svgImage->frameView();
|
| - if (frameView && (frameView->needsLayout() || frameView->isInLayout())) {
|
| - if (!m_redrawTimer.isActive())
|
| - m_redrawTimer.startOneShot(0);
|
| - } else
|
| - redraw();
|
| -}
|
| -
|
| -void SVGImageCache::cacheClearTimerFired(DeferrableOneShotTimer<SVGImageCache>*)
|
| -{
|
| - clearBitmapCache();
|
| -}
|
| -
|
| -Image* SVGImageCache::lookupOrCreateBitmapImageForRenderer(const RenderObject* renderer)
|
| -{
|
| if (!renderer)
|
| return Image::nullImage();
|
|
|
| - const CachedImageClient* client = renderer;
|
| -
|
| // The cache needs to know the size of the renderer before querying an image for it.
|
| - SizeAndScalesMap::iterator sizeIt = m_sizeAndScalesMap.find(renderer);
|
| - if (sizeIt == m_sizeAndScalesMap.end())
|
| + ImageForContainerMap::iterator it = m_imageForContainerMap.find(renderer);
|
| + if (it == m_imageForContainerMap.end())
|
| return Image::nullImage();
|
|
|
| - FloatSize size = sizeIt->value.size;
|
| - float zoom = sizeIt->value.zoom;
|
| - float scale = sizeIt->value.scale;
|
| + RefPtr<SVGImageForContainer> image = it->value;
|
| + ASSERT(!image->containerSize().isEmpty());
|
|
|
| - // FIXME (85335): This needs to take CSS transform scale into account as well.
|
| + // FIXME: Set the page scale in setContainerSizeForRenderer instead of looking it up here.
|
| Page* page = renderer->document()->page();
|
| - if (!scale)
|
| - scale = page->deviceScaleFactor() * page->pageScaleFactor();
|
| + image->setPageScale(page->deviceScaleFactor() * page->pageScaleFactor());
|
|
|
| - ASSERT(!size.isEmpty());
|
| -
|
| - // (Re)schedule the oneshot timer to throw out all the cached ImageBuffers if they remain unused for too long.
|
| - m_cacheClearTimer.restart();
|
| -
|
| - // Lookup image for client in cache and eventually update it.
|
| - ImageDataMap::iterator it = m_imageDataMap.find(client);
|
| - if (it != m_imageDataMap.end()) {
|
| - ImageData& data = it->value;
|
| -
|
| - // Common case: image size & zoom remained the same.
|
| - if (data.sizeAndScales.size == size && data.sizeAndScales.zoom == zoom && data.sizeAndScales.scale == scale)
|
| - return data.image.get();
|
| -
|
| - // If the image size for the client changed, we have to delete the buffer, remove the item from the cache and recreate it.
|
| - delete data.buffer;
|
| - m_imageDataMap.remove(it);
|
| - }
|
| -
|
| - FloatSize scaledSize(size);
|
| - scaledSize.scale(scale * zoom);
|
| -
|
| - // Create and cache new image and image buffer at requested size.
|
| - OwnPtr<ImageBuffer> newBuffer = ImageBuffer::create(expandedIntSize(scaledSize), 1);
|
| - if (!newBuffer)
|
| - return Image::nullImage();
|
| -
|
| - m_svgImage->drawSVGToImageBuffer(newBuffer.get(), size, scale * zoom, SVGImage::DontClearImageBuffer);
|
| -
|
| - RefPtr<Image> newImage = newBuffer->copyImage(CopyBackingStore);
|
| - Image* newImagePtr = newImage.get();
|
| - ASSERT(newImagePtr);
|
| -
|
| - m_imageDataMap.add(client, ImageData(newBuffer.leakPtr(), newImage.release(), SizeAndScales(size, zoom, scale)));
|
| - return newImagePtr;
|
| + return image.get();
|
| }
|
|
|
| } // namespace WebCore
|
|
|