Changeset 142765 in webkit
- Timestamp:
- Feb 13, 2013, 11:44:19 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r142759 r142765 1 2013-02-13 Philip Rogers <pdr@google.com> 2 3 Replace SVG bitmap cache with directly-rendered SVG 4 https://bugs.webkit.org/show_bug.cgi?id=106159 5 6 Reviewed by Tim Horton. 7 8 This patch fixes two existing bugs (WK99481 and WK104189) that were due to caching bitmaps 9 at a fixed size. A test has been added for each of these bugs. 10 11 * platform/chromium/TestExpectations: 12 * svg/as-image/svg-image-scaled-expected.html: Added. 13 * svg/as-image/svg-image-scaled.html: Added. 14 * svg/as-image/svg-image-viewbox-expected.html: Added. 15 * svg/as-image/svg-image-viewbox.html: Added. 16 1 17 2013-02-13 Florin Malita <fmalita@chromium.org> 2 18 -
trunk/LayoutTests/platform/chromium/TestExpectations
r142739 r142765 4137 4137 webkit.org/b/103308 [ SnowLeopard Lion ] css3/filters/custom/custom-filter-transforms-animation.html [ Pass Timeout ] 4138 4138 4139 # Rebaseline after https://bugs.webkit.org/show_bug.cgi?id=106159 4140 webkit.org/b/106159 svg/as-background-image/animated-svg-as-background.html [ ImageOnlyFailure Pass ] 4141 webkit.org/b/106159 svg/as-background-image/svg-as-background-1.html [ ImageOnlyFailure Pass ] 4142 webkit.org/b/106159 svg/as-background-image/svg-as-background-2.html [ ImageOnlyFailure Pass ] 4143 webkit.org/b/106159 svg/as-background-image/svg-as-background-3.html [ ImageOnlyFailure Pass ] 4144 webkit.org/b/106159 svg/as-background-image/svg-as-background-4.html [ ImageOnlyFailure Pass ] 4145 webkit.org/b/106159 svg/as-background-image/svg-as-background-5.html [ ImageOnlyFailure Pass ] 4146 webkit.org/b/106159 svg/as-background-image/svg-as-background-6.html [ ImageOnlyFailure Pass ] 4147 webkit.org/b/106159 svg/as-background-image/svg-as-background-with-relative-size.html [ ImageOnlyFailure Pass ] 4148 webkit.org/b/106159 svg/as-background-image/svg-background-partial-redraw.html [ ImageOnlyFailure Pass ] 4149 webkit.org/b/106159 svg/as-border-image/svg-as-border-image.html [ ImageOnlyFailure Pass ] 4150 webkit.org/b/106159 svg/as-image/animated-svg-as-image-no-fixed-intrinsic-size.html [ ImageOnlyFailure Pass ] 4151 webkit.org/b/106159 svg/as-image/img-preserveAspectRatio-support-2.html [ ImageOnlyFailure Pass ] 4152 webkit.org/b/106159 svg/as-image/svg-image-change-content-size.xhtml [ ImageOnlyFailure Pass ] 4153 webkit.org/b/106159 svg/as-image/svg-non-integer-scaled-image.html [ ImageOnlyFailure Pass ] 4154 webkit.org/b/106159 svg/carto.net/combobox.svg [ ImageOnlyFailure Pass ] 4155 webkit.org/b/106159 svg/wicd/test-scalable-background-image1.xhtml [ ImageOnlyFailure Pass ] 4156 webkit.org/b/106159 svg/wicd/test-scalable-background-image2.xhtml [ ImageOnlyFailure Pass ] 4157 webkit.org/b/106159 svg/zoom/page/zoom-background-images.html [ ImageOnlyFailure Pass ] 4158 webkit.org/b/106159 svg/zoom/page/zoom-svg-as-background-with-relative-size-and-viewBox.html [ ImageOnlyFailure Pass ] 4159 webkit.org/b/106159 svg/zoom/page/zoom-svg-as-background-with-relative-size.html [ ImageOnlyFailure Pass ] 4160 webkit.org/b/106159 css2.1/20110323/background-intrinsic-005.htm [ ImageOnlyFailure Pass ] 4161 webkit.org/b/106159 svg/as-image/same-image-two-instances.html [ ImageOnlyFailure Pass ] 4162 webkit.org/b/106159 css2.1/20110323/background-intrinsic-004.htm [ ImageOnlyFailure Pass ] 4163 webkit.org/b/106159 fast/backgrounds/size/contain-and-cover.html [ ImageOnlyFailure Pass ] 4164 webkit.org/b/106159 fast/writing-mode/block-level-images.html [ ImageOnlyFailure Pass ] 4165 4139 4166 webkit.org/b/103363 [ Mac ] touchadjustment/touch-links-longpress.html [ Failure ] 4140 4167 webkit.org/b/103446 [ Mac ] http/tests/canvas/canvas-slow-font-loading.html [ ImageOnlyFailure ] -
trunk/Source/WebCore/CMakeLists.txt
r142739 r142765 2495 2495 svg/graphics/SVGImage.cpp 2496 2496 svg/graphics/SVGImageCache.cpp 2497 svg/graphics/SVGImageForContainer.cpp 2497 2498 2498 2499 svg/graphics/filters/SVGFEImage.cpp -
trunk/Source/WebCore/ChangeLog
r142764 r142765 1 2013-02-13 Philip Rogers <pdr@google.com> 2 3 Replace SVG bitmap cache with directly-rendered SVG 4 https://bugs.webkit.org/show_bug.cgi?id=106159 5 6 Reviewed by Tim Horton. 7 8 This patch removes the caching of SVG bitmaps so SVG images are rendered directly. This 9 enables WebKit to pass the IE Chalkboard demo in 10s on a Z620: 10 http://ie.microsoft.com/testdrive/Performance/Chalkboard/ 11 12 On a simple scaled SVG benchmark similar to the IE10 Chalkboard demo 13 (http://philbit.com/SvgImagePerformance/viewport.html): 14 without patch: ~20FPS 15 with patch: ~55FPS 16 17 The bitmap SVG image cache had several shortcomings: 18 - The bitmap cache prevented viewport rendering. (WK104693) 19 - Bitmap memory usage was high. (WK106484) 20 - Caching animating images was expensive. 21 22 This change removes almost all of the SVGImageCache implementation, replacing it with 23 directly-rendered SVG. Instead of caching bitmaps, an SVGImageForContainer is cached which 24 is a thin wrapper around an SVG image with the associated container size and scale. 25 When rendering patterns (e.g., tiled backgrounds), a temporary bitmap is used for 26 performance. This change also removes the redraw timer of the old cache, instead relying 27 on the SVG image to notify clients if the image changes (e.g., during animations). 28 29 This patch fixes two existing bugs (WK99481 and WK104189) that were due to caching bitmaps 30 at a fixed size. A test has been added for each of these bugs. 31 32 Tests: svg/as-image/svg-image-scaled.html 33 svg/as-image/svg-image-viewbox.html 34 35 * CMakeLists.txt: 36 * GNUmakefile.list.am: 37 * Target.pri: 38 * WebCore.gypi: 39 * WebCore.vcproj/WebCore.vcproj: 40 * WebCore.xcodeproj/project.pbxproj: 41 * loader/cache/CachedImage.cpp: 42 (WebCore::CachedImage::lookupOrCreateImageForRenderer): 43 (WebCore::CachedImage::setContainerSizeForRenderer): 44 (WebCore::CachedImage::clear): 45 (WebCore::CachedImage::changedInRect): 46 47 SVG images are no longer special-cased here. When the SVG image changes, users are 48 notified through this function, and users can then request their content to be redrawn. 49 50 * svg/graphics/SVGImage.cpp: 51 (WebCore::SVGImage::setContainerSize): 52 (WebCore::SVGImage::drawForContainer): 53 54 drawForContainer lays out the SVG content for a specific container size and renders it. 55 The logic is fairly straightforward but a note about the scales and zooms here: 56 the destination rect parameter is zoomed but not scaled 57 the source rect parameter is zoomed but not scaled 58 the context is scaled but not zoomed 59 SVGImage::draw(...) only accepts a source and destination rect but does not consider 60 scale or zoom. Therefore, drawForContainer removes the zoom component from the source 61 so SVGImage::draw(...) will draw from the pre-zoom source to the post-zoom destination. 62 63 (WebCore::SVGImage::drawPatternForContainer): 64 65 For performance, drawPatternForContainer renders the SVG content onto a bitmap, then 66 has the bitmap image draw the pattern. This is necessary because drawPattern is used 67 for tiling. 68 69 (WebCore): 70 (WebCore::SVGImage::startAnimation): 71 (WebCore::SVGImage::stopAnimation): 72 (WebCore::SVGImage::resetAnimation): 73 (WebCore::SVGImage::reportMemoryUsage): 74 * svg/graphics/SVGImage.h: 75 (WebCore): 76 (SVGImage): 77 * svg/graphics/SVGImageCache.cpp: 78 79 Instead of storing a SizeAndScales values for each renderer, a SVGImageForContainer 80 is stored which is just a thin wrapper around an SVG image that contains container 81 sizing information. By combining the image and size information, the two maps of 82 SVGImageCache have been merged into one. 83 84 To make this patch easier to review, SVGImageCache still exists and works similar to 85 how it did before the patch. Now, SVGImageCache simply stores the SVGImageForContainers. 86 In a followup patch it will be removed. 87 88 Note: the redraw timer of SVGImageCache has been removed because animation 89 invalidation is now properly propagated back to the image clients. 90 91 (WebCore): 92 (WebCore::SVGImageCache::SVGImageCache): 93 (WebCore::SVGImageCache::~SVGImageCache): 94 (WebCore::SVGImageCache::removeClientFromCache): 95 (WebCore::SVGImageCache::setContainerSizeForRenderer): 96 (WebCore::SVGImageCache::imageSizeForRenderer): 97 98 Previously, this function returned the scaled image size which was incorrect. The image 99 size is used by clients such as GraphicsContext2D to determine the source size 100 for drawing the image. draw() accepts zoomed but not scaled values, so this has been 101 changed. 102 103 (WebCore::SVGImageCache::imageForRenderer): 104 105 A FIXME has been added here to not set the scale on every lookup. This can be improved 106 by setting the page scale factor in setContainerSizeForRenderer() in a future patch. 107 108 * svg/graphics/SVGImageCache.h: 109 (WebCore): 110 (SVGImageCache): 111 * svg/graphics/SVGImageForContainer.cpp: Added. 112 (WebCore): 113 114 SVGImageForContainer is a thin wrapper around an SVG image. The lifetime of the 115 SVGImage will be longer than the image cache. 116 117 (WebCore::SVGImageForContainer::size): 118 119 This is the only logic in SVGImageForContainer. The size returned needs to be zoomed 120 but not scaled because it is used (e.g., by RenderImage) to pass back into draw() which 121 takes zoomed but not scaled values. 122 123 (WebCore::SVGImageForContainer::draw): 124 (WebCore::SVGImageForContainer::drawPattern): 125 * svg/graphics/SVGImageForContainer.h: Added. 126 (WebCore): 127 (SVGImageForContainer): 128 129 In a future patch SVGImageForContainer can be made immutable but without a refactoring 130 for not setting the page scale factor in SVGImageCache::lookupOrCreateImageForRenderer, 131 setters are needed. 132 133 (WebCore::SVGImageForContainer::create): 134 (WebCore::SVGImageForContainer::containerSize): 135 (WebCore::SVGImageForContainer::pageScale): 136 (WebCore::SVGImageForContainer::zoom): 137 (WebCore::SVGImageForContainer::setSize): 138 (WebCore::SVGImageForContainer::setZoom): 139 (WebCore::SVGImageForContainer::setPageScale): 140 (WebCore::SVGImageForContainer::SVGImageForContainer): 141 (WebCore::SVGImageForContainer::destroyDecodedData): 142 (WebCore::SVGImageForContainer::decodedSize): 143 1 144 2013-02-12 Antti Koivisto <antti@apple.com> 2 145 -
trunk/Source/WebCore/GNUmakefile.list.am
r142739 r142765 4926 4926 Source/WebCore/svg/graphics/SVGImageCache.h \ 4927 4927 Source/WebCore/svg/graphics/SVGImageChromeClient.h \ 4928 Source/WebCore/svg/graphics/SVGImageForContainer.cpp \ 4929 Source/WebCore/svg/graphics/SVGImageForContainer.h \ 4928 4930 Source/WebCore/svg/graphics/SVGImage.cpp \ 4929 4931 Source/WebCore/svg/graphics/SVGImage.h \ -
trunk/Source/WebCore/Target.pri
r142739 r142765 2654 2654 svg/graphics/SVGImage.h \ 2655 2655 svg/graphics/SVGImageCache.h \ 2656 svg/graphics/SVGImageForContainer.h \ 2656 2657 svg/properties/SVGAttributeToPropertyMap.h \ 2657 2658 svg/properties/SVGAnimatedEnumerationPropertyTearOff.h \ … … 3775 3776 svg/graphics/SVGImage.cpp \ 3776 3777 svg/graphics/SVGImageCache.cpp \ 3778 svg/graphics/SVGImageForContainer.cpp \ 3777 3779 svg/properties/SVGAttributeToPropertyMap.cpp \ 3778 3780 svg/properties/SVGPathSegListPropertyTearOff.cpp \ -
trunk/Source/WebCore/WebCore.gypi
r142739 r142765 5116 5116 'svg/graphics/SVGImage.cpp', 5117 5117 'svg/graphics/SVGImage.h', 5118 'svg/graphics/SVGImageForContainer.h', 5119 'svg/graphics/SVGImageForContainer.cpp', 5118 5120 'svg/graphics/filters/SVGFEImage.cpp', 5119 5121 'svg/graphics/filters/SVGFEImage.h', -
trunk/Source/WebCore/WebCore.vcproj/WebCore.vcproj
r142739 r142765 74626 74626 > 74627 74627 </File> 74628 <File 74629 RelativePath="..\svg\graphics\SVGImageForContainer.cpp" 74630 > 74631 </File> 74632 <File 74633 RelativePath="..\svg\graphics\SVGImageForContainer.h" 74634 > 74635 </File> 74628 74636 <Filter 74629 74637 Name="filters" -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r142739 r142765 220 220 08F859D41463F9CD0067D933 /* SVGImageCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08F859D21463F9CD0067D933 /* SVGImageCache.cpp */; }; 221 221 08F859D51463F9CD0067D933 /* SVGImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 08F859D31463F9CD0067D933 /* SVGImageCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; 222 08F859D41463F9CD0067D934 /* SVGImageForContainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08F859D21463F9CD0067D934 /* SVGImageForContainer.cpp */; }; 223 08F859D51463F9CD0067D934 /* SVGImageForContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 08F859D31463F9CD0067D934 /* SVGImageForContainer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 222 224 08FB17C113BC7E9100040086 /* SVGAttributeToPropertyMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 08FB17C013BC7E9100040086 /* SVGAttributeToPropertyMap.cpp */; }; 223 225 08FB3F8413BC754C0099FC18 /* SVGAttributeToPropertyMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 08FB3F8313BC754C0099FC18 /* SVGAttributeToPropertyMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 7494 7496 08F859D21463F9CD0067D933 /* SVGImageCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGImageCache.cpp; sourceTree = "<group>"; }; 7495 7497 08F859D31463F9CD0067D933 /* SVGImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGImageCache.h; sourceTree = "<group>"; }; 7498 08F859D21463F9CD0067D934 /* SVGImageForContainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGImageForContainer.cpp; sourceTree = "<group>"; }; 7499 08F859D31463F9CD0067D934 /* SVGImageForContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGImageForContainer.h; sourceTree = "<group>"; }; 7496 7500 08FB17C013BC7E9100040086 /* SVGAttributeToPropertyMap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SVGAttributeToPropertyMap.cpp; sourceTree = "<group>"; }; 7497 7501 08FB3F8313BC754C0099FC18 /* SVGAttributeToPropertyMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGAttributeToPropertyMap.h; sourceTree = "<group>"; }; … … 20429 20433 08F859D21463F9CD0067D933 /* SVGImageCache.cpp */, 20430 20434 08F859D31463F9CD0067D933 /* SVGImageCache.h */, 20435 08F859D21463F9CD0067D934 /* SVGImageForContainer.cpp */, 20436 08F859D31463F9CD0067D934 /* SVGImageForContainer.h */, 20431 20437 AAC08CED15F933D600F1E188 /* SVGImageChromeClient.h */, 20432 20438 ); … … 26100 26106 B25599A40D00D8BA00BB825C /* SVGImage.h in Headers */, 26101 26107 08F859D51463F9CD0067D933 /* SVGImageCache.h in Headers */, 26108 08F859D51463F9CD0067D934 /* SVGImageForContainer.h in Headers */, 26102 26109 AAC08CEF15F933D600F1E188 /* SVGImageChromeClient.h in Headers */, 26103 26110 B2227A2D0D00BF220071B782 /* SVGImageElement.h in Headers */, … … 29376 29383 B25599A30D00D8BA00BB825C /* SVGImage.cpp in Sources */, 29377 29384 08F859D41463F9CD0067D933 /* SVGImageCache.cpp in Sources */, 29385 08F859D41463F9CD0067D934 /* SVGImageForContainer.cpp in Sources */, 29378 29386 B2227A2C0D00BF220071B782 /* SVGImageElement.cpp in Sources */, 29379 29387 B28C6A290D00C44800334AA4 /* SVGImageLoader.cpp in Sources */, -
trunk/Source/WebCore/loader/cache/CachedImage.cpp
r141637 r142765 165 165 if (!m_image->isSVGImage()) 166 166 return m_image.get(); 167 Image* useImage = m_svgImageCache-> lookupOrCreateBitmapImageForRenderer(renderer);167 Image* useImage = m_svgImageCache->imageForRenderer(renderer); 168 168 if (useImage == Image::nullImage()) 169 169 return m_image.get(); … … 216 216 return; 217 217 ASSERT(renderer); 218 ASSERT(containerZoom); 218 219 if (!m_image) { 219 220 m_pendingContainerSizeRequests.set(renderer, SizeAndZoom(containerSize, containerZoom)); … … 313 314 { 314 315 destroyDecodedData(); 315 #if ENABLE(SVG)316 m_svgImageCache.clear();317 #endif318 316 clearImage(); 319 317 m_pendingContainerSizeRequests.clear(); … … 485 483 if (!image || image != m_image) 486 484 return; 487 #if ENABLE(SVG)488 // We have to update the cached ImageBuffers if the underlying content changed.489 if (image->isSVGImage()) {490 m_svgImageCache->imageContentChanged();491 return;492 }493 #endif494 485 notifyObservers(&rect); 495 486 } -
trunk/Source/WebCore/svg/graphics/SVGImage.cpp
r141570 r142765 35 35 #include "ImageBuffer.h" 36 36 #include "ImageObserver.h" 37 #include "IntRect.h" 37 38 #include "RenderSVGRoot.h" 38 39 #include "SVGDocument.h" … … 60 61 } 61 62 62 void SVGImage::setContainerSize(const IntSize&) 63 { 64 // SVGImageCache already intercepted this call, as it stores & caches the desired container sizes & zoom levels. 65 ASSERT_NOT_REACHED(); 63 void SVGImage::setContainerSize(const IntSize& size) 64 { 65 if (!m_page || !usesContainerSize()) 66 return; 67 68 Frame* frame = m_page->mainFrame(); 69 SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); 70 if (!rootElement) 71 return; 72 RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()); 73 if (!renderer) 74 return; 75 76 FrameView* view = frameView(); 77 view->resize(this->size()); 78 79 renderer->setContainerSize(size); 66 80 } 67 81 … … 100 114 } 101 115 102 void SVGImage::drawSVGToImageBuffer(ImageBuffer* buffer, const FloatSize& size, float zoomAndScale, ShouldClearBuffer shouldClear) 103 { 104 // FIXME: This doesn't work correctly with animations. If an image contains animations, that say run for 2 seconds, 105 // and we currently have one <img> that displays us. If we open another document referencing the same SVGImage it 106 // will display the document at a time where animations already ran - even though it has its own ImageBuffer. 107 // We currently don't implement SVGSVGElement::setCurrentTime, and can NOT go back in time, once animations started. 108 // There's no way to fix this besides avoiding style/attribute mutations from SVGAnimationElement. 109 ASSERT(buffer); 110 ASSERT(!size.isEmpty()); 111 112 if (!m_page) 113 return; 114 115 Frame* frame = m_page->mainFrame(); 116 SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); 117 if (!rootElement) 118 return; 119 RenderSVGRoot* renderer = toRenderSVGRoot(rootElement->renderer()); 120 if (!renderer) 121 return; 122 123 // Draw image at requested size. 116 void SVGImage::drawForContainer(GraphicsContext* context, const FloatSize containerSize, float zoom, const FloatRect& dstRect, 117 const FloatRect& srcRect, ColorSpace colorSpace, CompositeOperator compositeOp, BlendMode blendMode) 118 { 119 if (!m_page) 120 return; 121 124 122 ImageObserver* observer = imageObserver(); 125 123 ASSERT(observer); … … 128 126 setImageObserver(0); 129 127 130 // Disable repainting; we don't want deferred repaints to schedule any timers due to this relayout. 131 frame->view()->beginDisableRepaints(); 132 133 IntSize containerSize = roundedIntSize(size); 134 renderer->setContainerSize(containerSize); 135 frame->view()->resize(this->size()); 136 137 FloatSize scaledContainerSize(size); 138 scaledContainerSize.scale(zoomAndScale); 139 IntRect destRect = IntRect(IntPoint(), expandedIntSize(scaledContainerSize)); 140 if (shouldClear == ClearImageBuffer) 141 buffer->context()->clearRect(destRect); 142 143 // Draw SVG on top of ImageBuffer. 144 draw(buffer->context(), destRect, IntRect(IntPoint(), containerSize), ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal); 145 146 if (frame->view()->needsLayout()) 147 frame->view()->layout(); 128 IntSize roundedContainerSize = roundedIntSize(containerSize); 129 setContainerSize(roundedContainerSize); 130 131 FloatRect scaledSrc = srcRect; 132 scaledSrc.scale(1 / zoom); 133 134 // Compensate for the container size rounding by adjusting the source rect. 135 FloatSize adjustedSrcSize = scaledSrc.size(); 136 adjustedSrcSize.scale(roundedContainerSize.width() / containerSize.width(), roundedContainerSize.height() / containerSize.height()); 137 scaledSrc.setSize(adjustedSrcSize); 138 139 draw(context, dstRect, scaledSrc, colorSpace, compositeOp, blendMode); 148 140 149 141 setImageObserver(observer); 150 151 frame->view()->endDisableRepaints(); 142 } 143 144 void SVGImage::drawPatternForContainer(GraphicsContext* context, const FloatSize containerSize, float pageScale, float zoom, const FloatRect& srcRect, 145 const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace colorSpace, CompositeOperator compositeOp, const FloatRect& dstRect) 146 { 147 FloatSize zoomedContainerSize(containerSize); 148 zoomedContainerSize.scale(zoom); 149 FloatRect zoomedContainerRect = FloatRect(FloatPoint(), zoomedContainerSize); 150 151 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(expandedIntSize(zoomedContainerSize), pageScale); 152 drawForContainer(buffer->context(), containerSize, zoom, zoomedContainerRect, zoomedContainerRect, ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal); 153 154 RefPtr<Image> image = buffer->copyImage(CopyBackingStore); 155 image->drawPattern(context, srcRect, patternTransform, phase, colorSpace, compositeOp, dstRect); 152 156 } 153 157 … … 251 255 } 252 256 253 NativeImagePtr SVGImage::nativeImageForCurrentFrame() 254 { 255 // FIXME: In order to support dynamic SVGs we need to have a way to invalidate this 256 // frame cache, or better yet, not use a cache for tiled drawing at all, instead 257 // having a tiled drawing callback (hopefully non-virtual). 258 if (!m_frameCache) { 259 if (!m_page) 260 return 0; 261 OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size(), 1); 262 if (!buffer) // failed to allocate image 263 return 0; 264 draw(buffer->context(), rect(), rect(), ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal); 265 m_frameCache = buffer->copyImage(CopyBackingStore); 266 } 267 return m_frameCache->nativeImageForCurrentFrame(); 257 // FIXME: support catchUpIfNecessary. 258 void SVGImage::startAnimation(bool /* catchUpIfNecessary */) 259 { 260 if (!m_page) 261 return; 262 Frame* frame = m_page->mainFrame(); 263 SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); 264 if (!rootElement) 265 return; 266 rootElement->unpauseAnimations(); 267 rootElement->setCurrentTime(0); 268 } 269 270 void SVGImage::stopAnimation() 271 { 272 if (!m_page) 273 return; 274 Frame* frame = m_page->mainFrame(); 275 SVGSVGElement* rootElement = static_cast<SVGDocument*>(frame->document())->rootElement(); 276 if (!rootElement) 277 return; 278 rootElement->pauseAnimations(); 279 } 280 281 void SVGImage::resetAnimation() 282 { 283 stopAnimation(); 284 startAnimation(); 268 285 } 269 286 … … 323 340 info.addMember(m_chromeClient, "chromeClient"); 324 341 info.addMember(m_page, "page"); 325 info.addMember(m_frameCache, "frameCache");326 342 } 327 343 -
trunk/Source/WebCore/svg/graphics/SVGImage.h
r141637 r142765 39 39 class RenderBox; 40 40 class SVGImageChromeClient; 41 class SVGImageForContainer; 41 42 42 43 class SVGImage : public Image { … … 47 48 } 48 49 49 enum ShouldClearBuffer {50 ClearImageBuffer,51 DontClearImageBuffer52 };53 54 void drawSVGToImageBuffer(ImageBuffer*, const FloatSize&, float, ShouldClearBuffer);55 50 RenderBox* embeddedContentBox() const; 56 51 FrameView* frameView() const; … … 62 57 virtual bool hasRelativeHeight() const; 63 58 59 virtual void startAnimation(bool /*catchUpIfNecessary*/ = true) OVERRIDE; 60 virtual void stopAnimation() OVERRIDE; 61 virtual void resetAnimation() OVERRIDE; 62 64 63 virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE; 65 64 66 65 private: 67 66 friend class SVGImageChromeClient; 67 friend class SVGImageForContainer; 68 68 69 virtual ~SVGImage(); 69 70 … … 88 89 SVGImage(ImageObserver*); 89 90 virtual void draw(GraphicsContext*, const FloatRect& fromRect, const FloatRect& toRect, ColorSpace styleColorSpace, CompositeOperator, BlendMode); 90 91 virtual NativeImagePtr nativeImageForCurrentFrame(); 91 void drawForContainer(GraphicsContext*, const FloatSize, float, const FloatRect&, const FloatRect&, ColorSpace, CompositeOperator, BlendMode); 92 void drawPatternForContainer(GraphicsContext*, const FloatSize, float, float, const FloatRect&, const AffineTransform&, 93 const FloatPoint&, ColorSpace, CompositeOperator, const FloatRect&); 92 94 93 95 OwnPtr<SVGImageChromeClient> m_chromeClient; 94 96 OwnPtr<Page> m_page; 95 RefPtr<Image> m_frameCache;96 97 }; 97 98 } -
trunk/Source/WebCore/svg/graphics/SVGImageCache.cpp
r141303 r142765 30 30 #include "RenderSVGRoot.h" 31 31 #include "SVGImage.h" 32 #include "SVGImageForContainer.h" 32 33 33 34 namespace WebCore { 34 35 35 static const int timeToKeepCachedBitmapsAfterLastUseInSeconds = 30;36 37 36 SVGImageCache::SVGImageCache(SVGImage* svgImage) 38 37 : m_svgImage(svgImage) 39 , m_redrawTimer(this, &SVGImageCache::redrawTimerFired)40 , m_cacheClearTimer(this, &SVGImageCache::cacheClearTimerFired, timeToKeepCachedBitmapsAfterLastUseInSeconds)41 38 { 42 39 ASSERT(m_svgImage); … … 45 42 SVGImageCache::~SVGImageCache() 46 43 { 47 m_sizeAndScalesMap.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 remove itself from this 56 // cache before its end of life, otherwise the following ASSERT will crash 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(); 44 m_imageForContainerMap.clear(); 63 45 } 64 46 … … 66 48 { 67 49 ASSERT(client); 68 m_sizeAndScalesMap.remove(client);69 50 70 ImageDataMap::iterator it = m_imageDataMap.find(client); 71 if (it == m_imageDataMap.end()) 72 return; 73 74 delete it->value.buffer; 75 m_imageDataMap.remove(it); 51 if (m_imageForContainerMap.contains(client)) 52 m_imageForContainerMap.remove(client); 76 53 } 77 54 … … 83 60 FloatSize containerSizeWithoutZoom(containerSize); 84 61 containerSizeWithoutZoom.scale(1 / containerZoom); 85 m_sizeAndScalesMap.set(client, SizeAndScales(containerSizeWithoutZoom, containerZoom)); 62 63 ImageForContainerMap::iterator imageIt = m_imageForContainerMap.find(client); 64 if (imageIt == m_imageForContainerMap.end()) { 65 RefPtr<SVGImageForContainer> image = SVGImageForContainer::create(m_svgImage, 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 … … 89 74 { 90 75 IntSize imageSize = m_svgImage->size(); 91 92 76 if (!renderer) 93 77 return imageSize; 94 SizeAndScalesMap::const_iterator it = m_sizeAndScalesMap.find(renderer); 95 if (it == m_sizeAndScalesMap.end()) 78 79 ImageForContainerMap::const_iterator it = m_imageForContainerMap.find(renderer); 80 if (it == m_imageForContainerMap.end()) 96 81 return imageSize; 97 82 98 SizeAndScales sizeAndScales= it->value;99 if (!sizeAndScales.size.isEmpty()) {100 float scale = sizeAndScales.scale;101 if (!scale) {102 Page* page = renderer->document()->page();103 scale = page->deviceScaleFactor() * page->pageScaleFactor();104 83 RefPtr<SVGImageForContainer> image = it->value; 84 FloatSize size = image->containerSize(); 85 if (!size.isEmpty()) { 86 size.scale(image->zoom()); 87 imageSize.setWidth(size.width()); 88 imageSize.setHeight(size.height()); 89 } 105 90 106 imageSize.setWidth(scale * sizeAndScales.size.width());107 imageSize.setHeight(scale * sizeAndScales.size.height());108 }109 91 return imageSize; 110 92 } 111 93 112 void SVGImageCache::imageContentChanged() 113 { 114 ImageDataMap::iterator end = m_imageDataMap.end(); 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 destructors 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, data.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 timer 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* renderer) 94 // FIXME: This doesn't take into account the animation timeline so animations will not 95 // restart on page load, nor will two animations in different pages have different timelines. 96 Image* SVGImageCache::imageForRenderer(const RenderObject* renderer) 159 97 { 160 98 if (!renderer) 161 99 return Image::nullImage(); 162 100 163 const CachedImageClient* client = renderer;164 165 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);167 if ( sizeIt == m_sizeAndScalesMap.end())102 ImageForContainerMap::iterator it = m_imageForContainerMap.find(renderer); 103 if (it == m_imageForContainerMap.end()) 168 104 return Image::nullImage(); 169 105 170 FloatSize size = sizeIt->value.size; 171 float zoom = sizeIt->value.zoom; 172 float scale = sizeIt->value.scale; 106 RefPtr<SVGImageForContainer> image = it->value; 107 ASSERT(!image->containerSize().isEmpty()); 173 108 174 // FIXME (85335): This needs to take CSS transform scale into account as well.109 // FIXME: Set the page scale in setContainerSizeForRenderer instead of looking it up here. 175 110 Page* page = renderer->document()->page(); 176 if (!scale) 177 scale = page->deviceScaleFactor() * page->pageScaleFactor(); 111 image->setPageScale(page->deviceScaleFactor() * page->pageScaleFactor()); 178 112 179 ASSERT(!size.isEmpty()); 180 181 // (Re)schedule the oneshot timer to throw out all the cached ImageBuffers if 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 buffer, 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(scaledSize), 1); 203 if (!newBuffer) 204 return Image::nullImage(); 205 206 m_svgImage->drawSVGToImageBuffer(newBuffer.get(), size, scale * zoom, SVGImage::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; 113 return image.get(); 214 114 } 215 115 -
trunk/Source/WebCore/svg/graphics/SVGImageCache.h
r141303 r142765 25 25 #include "Image.h" 26 26 #include "IntSize.h" 27 #include "Timer.h"28 27 #include <wtf/HashMap.h> 29 28 #include <wtf/PassOwnPtr.h> … … 36 35 class ImageBuffer; 37 36 class SVGImage; 37 class SVGImageForContainer; 38 38 class RenderObject; 39 39 … … 48 48 } 49 49 50 struct SizeAndScales {51 SizeAndScales()52 : zoom(1)53 , scale(0)54 {55 }56 57 SizeAndScales(const FloatSize& newSize, float newZoom, float newScale)58 : size(newSize)59 , zoom(newZoom)60 , scale(newScale)61 {62 }63 64 SizeAndScales(const FloatSize& newSize, float newZoom)65 : size(newSize)66 , zoom(newZoom)67 , scale(0)68 {69 }70 71 FloatSize size; // This is the container size without zoom.72 float zoom;73 float scale; // A scale of 0 indicates that the default scale should be used.74 };75 76 50 void removeClientFromCache(const CachedImageClient*); 77 51 … … 79 53 IntSize imageSizeForRenderer(const RenderObject*) const; 80 54 81 Image* lookupOrCreateBitmapImageForRenderer(const RenderObject*); 82 void imageContentChanged(); 55 Image* imageForRenderer(const RenderObject*); 83 56 84 57 private: 85 58 SVGImageCache(SVGImage*); 86 void redraw();87 void redrawTimerFired(Timer<SVGImageCache>*);88 void cacheClearTimerFired(DeferrableOneShotTimer<SVGImageCache>*);89 void clearBitmapCache();90 59 91 struct ImageData { 92 ImageData() 93 : imageNeedsUpdate(false) 94 , buffer(0) 95 { 96 } 97 98 ImageData(ImageBuffer* newBuffer, PassRefPtr<Image> newImage, const SizeAndScales& newSizeAndScales) 99 : imageNeedsUpdate(false) 100 , sizeAndScales(newSizeAndScales) 101 , buffer(newBuffer) 102 , image(newImage) 103 { 104 } 105 106 bool imageNeedsUpdate; 107 SizeAndScales sizeAndScales; 108 109 ImageBuffer* buffer; 110 RefPtr<Image> image; 111 }; 112 113 typedef HashMap<const CachedImageClient*, SizeAndScales> SizeAndScalesMap; 114 typedef HashMap<const CachedImageClient*, ImageData> ImageDataMap; 60 typedef HashMap<const CachedImageClient*, RefPtr<SVGImageForContainer> > ImageForContainerMap; 115 61 116 62 SVGImage* m_svgImage; 117 SizeAndScalesMap m_sizeAndScalesMap; 118 ImageDataMap m_imageDataMap; 119 Timer<SVGImageCache> m_redrawTimer; 120 DeferrableOneShotTimer<SVGImageCache> m_cacheClearTimer; 63 ImageForContainerMap m_imageForContainerMap; 121 64 }; 122 65
Note:
See TracChangeset
for help on using the changeset viewer.