Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(319)

Side by Side Diff: Source/WebCore/svg/graphics/SVGImageCache.cpp

Issue 12319101: Merge 142765 (Closed) Base URL: http://svn.webkit.org/repository/webkit/branches/chromium/1410/
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2011 Research In Motion Limited. All rights reserved. 2 * Copyright (C) 2011 Research In Motion Limited. All rights reserved.
3 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
(...skipping 11 matching lines...) Expand all
22 #include "SVGImageCache.h" 22 #include "SVGImageCache.h"
23 23
24 #if ENABLE(SVG) 24 #if ENABLE(SVG)
25 #include "CachedImage.h" 25 #include "CachedImage.h"
26 #include "FrameView.h" 26 #include "FrameView.h"
27 #include "GraphicsContext.h" 27 #include "GraphicsContext.h"
28 #include "ImageBuffer.h" 28 #include "ImageBuffer.h"
29 #include "Page.h" 29 #include "Page.h"
30 #include "RenderSVGRoot.h" 30 #include "RenderSVGRoot.h"
31 #include "SVGImage.h" 31 #include "SVGImage.h"
32 #include "SVGImageForContainer.h"
32 33
33 namespace WebCore { 34 namespace WebCore {
34 35
35 static const int timeToKeepCachedBitmapsAfterLastUseInSeconds = 30;
36
37 SVGImageCache::SVGImageCache(SVGImage* svgImage) 36 SVGImageCache::SVGImageCache(SVGImage* svgImage)
38 : m_svgImage(svgImage) 37 : m_svgImage(svgImage)
39 , m_redrawTimer(this, &SVGImageCache::redrawTimerFired)
40 , m_cacheClearTimer(this, &SVGImageCache::cacheClearTimerFired, timeToKeepCa chedBitmapsAfterLastUseInSeconds)
41 { 38 {
42 ASSERT(m_svgImage); 39 ASSERT(m_svgImage);
43 } 40 }
44 41
45 SVGImageCache::~SVGImageCache() 42 SVGImageCache::~SVGImageCache()
46 { 43 {
47 m_sizeAndScalesMap.clear(); 44 m_imageForContainerMap.clear();
48 clearBitmapCache();
49 }
50
51 void SVGImageCache::clearBitmapCache()
52 {
53 ImageDataMap::iterator end = m_imageDataMap.end();
54 for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it) {
55 // Checks if the client (it->key) is still valid. The client should remo ve itself from this
56 // cache before its end of life, otherwise the following ASSERT will cra sh on pure virtual
57 // function call or a general crash.
58 ASSERT(it->key->resourceClientType() == CachedImageClient::expectedType( ));
59 delete it->value.buffer;
60 }
61
62 m_imageDataMap.clear();
63 } 45 }
64 46
65 void SVGImageCache::removeClientFromCache(const CachedImageClient* client) 47 void SVGImageCache::removeClientFromCache(const CachedImageClient* client)
66 { 48 {
67 ASSERT(client); 49 ASSERT(client);
68 m_sizeAndScalesMap.remove(client);
69 50
70 ImageDataMap::iterator it = m_imageDataMap.find(client); 51 if (m_imageForContainerMap.contains(client))
71 if (it == m_imageDataMap.end()) 52 m_imageForContainerMap.remove(client);
72 return;
73
74 delete it->value.buffer;
75 m_imageDataMap.remove(it);
76 } 53 }
77 54
78 void SVGImageCache::setContainerSizeForRenderer(const CachedImageClient* client, const IntSize& containerSize, float containerZoom) 55 void SVGImageCache::setContainerSizeForRenderer(const CachedImageClient* client, const IntSize& containerSize, float containerZoom)
79 { 56 {
80 ASSERT(client); 57 ASSERT(client);
81 ASSERT(!containerSize.isEmpty()); 58 ASSERT(!containerSize.isEmpty());
82 59
83 FloatSize containerSizeWithoutZoom(containerSize); 60 FloatSize containerSizeWithoutZoom(containerSize);
84 containerSizeWithoutZoom.scale(1 / containerZoom); 61 containerSizeWithoutZoom.scale(1 / containerZoom);
85 m_sizeAndScalesMap.set(client, SizeAndScales(containerSizeWithoutZoom, conta inerZoom)); 62
63 ImageForContainerMap::iterator imageIt = m_imageForContainerMap.find(client) ;
64 if (imageIt == m_imageForContainerMap.end()) {
65 RefPtr<SVGImageForContainer> image = SVGImageForContainer::create(m_svgI mage, containerSizeWithoutZoom, 1, containerZoom);
66 m_imageForContainerMap.set(client, image);
67 } else {
68 imageIt->value->setSize(containerSizeWithoutZoom);
69 imageIt->value->setZoom(containerZoom);
70 }
86 } 71 }
87 72
88 IntSize SVGImageCache::imageSizeForRenderer(const RenderObject* renderer) const 73 IntSize SVGImageCache::imageSizeForRenderer(const RenderObject* renderer) const
89 { 74 {
90 IntSize imageSize = m_svgImage->size(); 75 IntSize imageSize = m_svgImage->size();
91
92 if (!renderer) 76 if (!renderer)
93 return imageSize; 77 return imageSize;
94 SizeAndScalesMap::const_iterator it = m_sizeAndScalesMap.find(renderer); 78
95 if (it == m_sizeAndScalesMap.end()) 79 ImageForContainerMap::const_iterator it = m_imageForContainerMap.find(render er);
80 if (it == m_imageForContainerMap.end())
96 return imageSize; 81 return imageSize;
97 82
98 SizeAndScales sizeAndScales = it->value; 83 RefPtr<SVGImageForContainer> image = it->value;
99 if (!sizeAndScales.size.isEmpty()) { 84 FloatSize size = image->containerSize();
100 float scale = sizeAndScales.scale; 85 if (!size.isEmpty()) {
101 if (!scale) { 86 size.scale(image->zoom());
102 Page* page = renderer->document()->page(); 87 imageSize.setWidth(size.width());
103 scale = page->deviceScaleFactor() * page->pageScaleFactor(); 88 imageSize.setHeight(size.height());
104 } 89 }
105 90
106 imageSize.setWidth(scale * sizeAndScales.size.width());
107 imageSize.setHeight(scale * sizeAndScales.size.height());
108 }
109 return imageSize; 91 return imageSize;
110 } 92 }
111 93
112 void SVGImageCache::imageContentChanged() 94 // FIXME: This doesn't take into account the animation timeline so animations wi ll not
113 { 95 // restart on page load, nor will two animations in different pages have differe nt timelines.
114 ImageDataMap::iterator end = m_imageDataMap.end(); 96 Image* SVGImageCache::imageForRenderer(const RenderObject* renderer)
115 for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it)
116 it->value.imageNeedsUpdate = true;
117
118 // Always redraw on a timer because this method may be invoked from destruct ors of things we are intending to draw.
119 if (!m_redrawTimer.isActive())
120 m_redrawTimer.startOneShot(0);
121 }
122
123 void SVGImageCache::redraw()
124 {
125 ImageDataMap::iterator end = m_imageDataMap.end();
126 for (ImageDataMap::iterator it = m_imageDataMap.begin(); it != end; ++it) {
127 ImageData& data = it->value;
128 if (!data.imageNeedsUpdate)
129 continue;
130 // If the content changed we redraw using our existing ImageBuffer.
131 ASSERT(data.buffer);
132 ASSERT(data.image);
133 m_svgImage->drawSVGToImageBuffer(data.buffer, data.sizeAndScales.size, d ata.sizeAndScales.zoom * data.sizeAndScales.scale, SVGImage::ClearImageBuffer);
134 data.image = data.buffer->copyImage(CopyBackingStore);
135 data.imageNeedsUpdate = false;
136 }
137 ASSERT(m_svgImage->imageObserver());
138 m_svgImage->imageObserver()->animationAdvanced(m_svgImage);
139 }
140
141 void SVGImageCache::redrawTimerFired(Timer<SVGImageCache>*)
142 {
143 // We have no guarantee that the frame does not require layout when the time r fired.
144 // So be sure to check again in case it is still not safe to run redraw.
145 FrameView* frameView = m_svgImage->frameView();
146 if (frameView && (frameView->needsLayout() || frameView->isInLayout())) {
147 if (!m_redrawTimer.isActive())
148 m_redrawTimer.startOneShot(0);
149 } else
150 redraw();
151 }
152
153 void SVGImageCache::cacheClearTimerFired(DeferrableOneShotTimer<SVGImageCache>*)
154 {
155 clearBitmapCache();
156 }
157
158 Image* SVGImageCache::lookupOrCreateBitmapImageForRenderer(const RenderObject* r enderer)
159 { 97 {
160 if (!renderer) 98 if (!renderer)
161 return Image::nullImage(); 99 return Image::nullImage();
162 100
163 const CachedImageClient* client = renderer;
164
165 // The cache needs to know the size of the renderer before querying an image for it. 101 // The cache needs to know the size of the renderer before querying an image for it.
166 SizeAndScalesMap::iterator sizeIt = m_sizeAndScalesMap.find(renderer); 102 ImageForContainerMap::iterator it = m_imageForContainerMap.find(renderer);
167 if (sizeIt == m_sizeAndScalesMap.end()) 103 if (it == m_imageForContainerMap.end())
168 return Image::nullImage(); 104 return Image::nullImage();
169 105
170 FloatSize size = sizeIt->value.size; 106 RefPtr<SVGImageForContainer> image = it->value;
171 float zoom = sizeIt->value.zoom; 107 ASSERT(!image->containerSize().isEmpty());
172 float scale = sizeIt->value.scale;
173 108
174 // FIXME (85335): This needs to take CSS transform scale into account as wel l. 109 // FIXME: Set the page scale in setContainerSizeForRenderer instead of looki ng it up here.
175 Page* page = renderer->document()->page(); 110 Page* page = renderer->document()->page();
176 if (!scale) 111 image->setPageScale(page->deviceScaleFactor() * page->pageScaleFactor());
177 scale = page->deviceScaleFactor() * page->pageScaleFactor();
178 112
179 ASSERT(!size.isEmpty()); 113 return image.get();
180
181 // (Re)schedule the oneshot timer to throw out all the cached ImageBuffers i f they remain unused for too long.
182 m_cacheClearTimer.restart();
183
184 // Lookup image for client in cache and eventually update it.
185 ImageDataMap::iterator it = m_imageDataMap.find(client);
186 if (it != m_imageDataMap.end()) {
187 ImageData& data = it->value;
188
189 // Common case: image size & zoom remained the same.
190 if (data.sizeAndScales.size == size && data.sizeAndScales.zoom == zoom & & data.sizeAndScales.scale == scale)
191 return data.image.get();
192
193 // If the image size for the client changed, we have to delete the buffe r, remove the item from the cache and recreate it.
194 delete data.buffer;
195 m_imageDataMap.remove(it);
196 }
197
198 FloatSize scaledSize(size);
199 scaledSize.scale(scale * zoom);
200
201 // Create and cache new image and image buffer at requested size.
202 OwnPtr<ImageBuffer> newBuffer = ImageBuffer::create(expandedIntSize(scaledSi ze), 1);
203 if (!newBuffer)
204 return Image::nullImage();
205
206 m_svgImage->drawSVGToImageBuffer(newBuffer.get(), size, scale * zoom, SVGIma ge::DontClearImageBuffer);
207
208 RefPtr<Image> newImage = newBuffer->copyImage(CopyBackingStore);
209 Image* newImagePtr = newImage.get();
210 ASSERT(newImagePtr);
211
212 m_imageDataMap.add(client, ImageData(newBuffer.leakPtr(), newImage.release() , SizeAndScales(size, zoom, scale)));
213 return newImagePtr;
214 } 114 }
215 115
216 } // namespace WebCore 116 } // namespace WebCore
217 117
218 #endif // ENABLE(SVG) 118 #endif // ENABLE(SVG)
OLDNEW
« no previous file with comments | « Source/WebCore/svg/graphics/SVGImageCache.h ('k') | Source/WebCore/svg/graphics/SVGImageForContainer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698