Changeset 208511 in webkit
- Timestamp:
- Nov 9, 2016 5:13:05 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r208509 r208511 1 2016-11-09 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 Change the decoding for some animated images to be asynchronous 4 https://bugs.webkit.org/show_bug.cgi?id=161566 5 6 Reviewed by Simon Fraser. 7 8 * fast/images/slower-animation-than-decoding-image-expected.txt: Added. 9 * fast/images/slower-animation-than-decoding-image.html: Added. 10 * fast/images/slower-decoding-than-animation-image-expected.txt: Added. 11 * fast/images/slower-decoding-than-animation-image.html: Added. 12 In these tests, CanvasRenderingContext2D.drawImage() is used to better 13 control advancing the animation of an animated image. A setTimeout() is 14 used instead of the frame duration to schedule when the drawing happens. 15 The first test ensures that faster decoding does not overrule the frame 16 duration; the setTimeout interval in this case. The second test ensures 17 the animation is not advanced unless decoding the next frame has finished. 18 19 * fast/images/stopped-animation-deleted-image-expected.txt: Added. 20 * fast/images/stopped-animation-deleted-image.html: Added. 21 This test ensures that if an animated image is removed from the document, 22 its draw() method won't be called even if the animation timer fires or the 23 decoding new frame availability notification is received. 24 1 25 2016-11-04 Brent Fulgham <bfulgham@apple.com> 2 26 -
trunk/Source/WebCore/ChangeLog
r208509 r208511 1 2016-11-09 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 Change the decoding for some animated images to be asynchronous 4 https://bugs.webkit.org/show_bug.cgi?id=161566 5 6 Reviewed by Simon Fraser. 7 8 Tests: fast/images/slower-animation-than-decoding-image.html 9 fast/images/slower-decoding-than-animation-image.html 10 fast/images/stopped-animation-deleted-image.html 11 12 Request the next frame before firing the animation timer. The asynchronous 13 image decoding work queue notifies the BitmapImage when the frame finishes 14 decoding. If the timer fires before the frame is decoded, no repaint will 15 be requested. Only when the image frame is ready, the animation will be 16 advanced and the image will be repainted. 17 18 * loader/cache/CachedImage.cpp: 19 (WebCore::CachedImage::load): Cache the image settings in CachedImage. 20 (WebCore::CachedImage::createImage): No need to pass allowSubsampling to BitmapImage. It can be retrieved through Image::imageObserver(). 21 (WebCore::CachedImage::changedInRect): Change the parameter to notifyObservers() to be a pointer. 22 * loader/cache/CachedImage.h: Cache the settings: allowSubsampling, allowAsyncImageDecoding and showDebugBackground through m_loader. 23 * platform/graphics/BitmapImage.cpp: 24 (WebCore::BitmapImage::dataChanged): Fix a logging message. 25 (WebCore::BitmapImage::draw): Store the current SubsamplingLevel to be used when requesting decoding the image of the next frame. 26 Draw a debug rectangle if the next frame is missed because it is being decoded and the setting showDebugBackground is on. 27 (WebCore::BitmapImage::startAnimation): Deleted. Moved to the header file. 28 (WebCore::BitmapImage::internalStartAnimation): Added. Request asynchronous image decoding for the next frame if required. Return the 29 result of starting the animation. 30 (WebCore::BitmapImage::advanceAnimation): Call internalAdvanceAnimation() if the frame image is not being decoded. If it is being decoded 31 and the setting showDebugBackground is on, force repaint so the debug rectangle is drawn. 32 (WebCore::BitmapImage::internalAdvanceAnimation): This is the old body of advanceAnimation(). 33 (WebCore::BitmapImage::stopAnimation): Stop the asynchronous image decoding if it is started. 34 (WebCore::BitmapImage::newFrameNativeImageAvailableAtIndex): This function is called from the async image decoding work queue when finishing decoding a native image frame. 35 * platform/graphics/BitmapImage.h: 36 (WebCore::BitmapImage::startAnimation): Added. It is now calls internalStartAnimation(). 37 * platform/graphics/Color.h: Define a constant for the yellow color. 38 * platform/graphics/ImageFrameCache.cpp: 39 (WebCore::ImageFrameCache::clearMetadata): Delete unreferenced member. 40 (WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): Return true if the frame is requested for async decoding. 41 * platform/graphics/ImageFrameCache.h: 42 * platform/graphics/ImageObserver.h: Add virtual functions for allowSubsampling, allowAsyncImageDecoding and showDebugBackground. 43 * platform/graphics/ImageSource.cpp: 44 (WebCore::ImageSource::maximumSubsamplingLevel): Move checking allowSubsampling() to the caller BitmapImage::draw(). 45 * platform/graphics/ImageSource.h: Remove the setting allowSubsampling(); it can be retrieved from imageObserver(). 46 (WebCore::ImageSource::setAllowSubsampling): Deleted. 47 * rendering/RenderImageResource.cpp: 48 (WebCore::RenderImageResource::shutdown): Stop the animation of an image when shutting down the resource. 49 * rendering/RenderImageResourceStyleImage.cpp: 50 (WebCore::RenderImageResourceStyleImage::shutdown): Ditto. 51 svg/graphics/SVGImageClients.h: Change the parameter to ImageObserver::changedInRect() to be a pointer. 52 (WebCore::SVGImageChromeClient::invalidateContentsAndRootView): 53 * testing/Internals.cpp: 54 (WebCore::Internals::setImageFrameDecodingDuration): Sets a fixed frame decoding duration for testing. 55 * testing/Internals.h: 56 * testing/Internals.idl: Adds an internal option for ImageFrameDecodingDuration. 57 1 58 2016-11-04 Brent Fulgham <bfulgham@apple.com> 2 59 -
trunk/Source/WebCore/loader/cache/CachedImage.cpp
r208102 r208511 90 90 else 91 91 setLoading(false); 92 93 if (m_loader) { 94 m_allowSubsampling = m_loader->frameLoader()->frame().settings().imageSubsamplingEnabled(); 95 m_allowAsyncImageDecoding = m_loader->frameLoader()->frame().settings().asyncImageDecodingEnabled(); 96 m_showDebugBackground = m_loader->frameLoader()->frame().settings().showDebugBorders(); 97 } 92 98 } 93 99 … … 326 332 m_svgImageCache = std::make_unique<SVGImageCache>(svgImage.ptr()); 327 333 m_image = WTFMove(svgImage); 328 } else {334 } else 329 335 m_image = BitmapImage::create(this); 330 downcast<BitmapImage>(*m_image).setAllowSubsampling(m_loader && m_loader->frameLoader()->frame().settings().imageSubsamplingEnabled());331 }332 336 333 337 if (m_image) { … … 482 486 } 483 487 484 void CachedImage::changedInRect(const Image* image, const IntRect &rect)488 void CachedImage::changedInRect(const Image* image, const IntRect* rect) 485 489 { 486 490 if (!image || image != m_image) 487 491 return; 488 notifyObservers( &rect);492 notifyObservers(rect); 489 493 } 490 494 -
trunk/Source/WebCore/loader/cache/CachedImage.h
r206867 r208511 119 119 120 120 // ImageObserver 121 bool allowSubsampling() const override { return m_allowSubsampling; } 122 bool allowAsyncImageDecoding() const override { return m_allowAsyncImageDecoding; } 123 bool showDebugBackground() const override { return m_showDebugBackground; } 121 124 void decodedSizeChanged(const Image*, long long delta) override; 122 125 void didDraw(const Image*) override; 123 126 124 127 void animationAdvanced(const Image*) override; 125 void changedInRect(const Image*, const IntRect &) override;128 void changedInRect(const Image*, const IntRect* changeRect = nullptr) override; 126 129 127 130 void addIncrementalDataBuffer(SharedBuffer&); … … 137 140 bool m_isManuallyCached { false }; 138 141 bool m_shouldPaintBrokenImage { true }; 142 143 // The default value of m_allowSubsampling should be the same as defaultImageSubsamplingEnabled in Settings.cpp 144 #if PLATFORM(IOS) 145 bool m_allowSubsampling { true }; 146 #else 147 bool m_allowSubsampling { false }; 148 #endif 149 bool m_allowAsyncImageDecoding { true }; 150 bool m_showDebugBackground { false }; 139 151 }; 140 152 -
trunk/Source/WebCore/platform/graphics/BitmapImage.cpp
r208365 r208511 84 84 { 85 85 if (!frameHasValidNativeImageAtIndex(index, subsamplingLevel)) { 86 LOG(Images, "BitmapImage %p frameImageAtIndex - subsamplingLevel was %d, resampling", this, static_cast<int>(frameSubsamplingLevelAtIndex(index)));86 LOG(Images, "BitmapImage %p %s - subsamplingLevel was %d, resampling", this, __FUNCTION__, static_cast<int>(frameSubsamplingLevelAtIndex(index))); 87 87 invalidatePlatformData(); 88 88 } … … 142 142 return; 143 143 144 startAnimation(); 145 146 Color color = singlePixelSolidColor(); 144 StartAnimationResult result = internalStartAnimation(); 145 146 Color color; 147 if (result == StartAnimationResult::DecodingActive && showDebugBackground()) 148 color = Color::yellow; 149 else 150 color = singlePixelSolidColor(); 151 147 152 if (color.isValid()) { 148 153 fillWithSolidColor(context, destRect, color, op); … … 151 156 152 157 float scale = subsamplingScale(context, destRect, srcRect); 153 SubsamplingLevel subsamplingLevel = m_source.subsamplingLevelForScale(scale);154 LOG(Images, "BitmapImage %p draw - subsamplingLevel %d at scale %.4f", this, static_cast<int>( subsamplingLevel), scale);155 156 auto image = frameImageAtIndex(m_currentFrame, subsamplingLevel, &context);158 m_currentSubsamplingLevel = allowSubsampling() ? m_source.subsamplingLevelForScale(scale) : SubsamplingLevel::Default; 159 LOG(Images, "BitmapImage %p draw - subsamplingLevel %d at scale %.4f", this, static_cast<int>(m_currentSubsamplingLevel), scale); 160 161 auto image = frameImageAtIndex(m_currentFrame, m_currentSubsamplingLevel, &context); 157 162 if (!image) // If it's too early we won't have an image yet. 158 163 return; … … 224 229 } 225 230 226 void BitmapImage::startAnimation() 227 { 228 if (m_frameTimer || !shouldAnimate() || frameCount() <= 1) 229 return; 231 BitmapImage::StartAnimationResult BitmapImage::internalStartAnimation() 232 { 233 if (!canAnimate()) 234 return StartAnimationResult::CannotStart; 235 236 if (m_frameTimer) 237 return StartAnimationResult::TimerActive; 238 239 // Don't start a new animation until we draw the frame that is currently being decoded. 240 size_t nextFrame = (m_currentFrame + 1) % frameCount(); 241 if (frameIsBeingDecodedAtIndex(nextFrame)) 242 return StartAnimationResult::DecodingActive; 230 243 231 244 if (m_currentFrame >= frameCount() - 1) { … … 235 248 // wait on it. 236 249 if (!m_source.isAllDataReceived() && repetitionCount() == RepetitionCountOnce) 237 return ;250 return StartAnimationResult::IncompleteData; 238 251 239 252 ++m_repetitionsComplete; … … 243 256 m_animationFinished = true; 244 257 destroyDecodedDataIfNecessary(false); 245 return ;258 return StartAnimationResult::CannotStart; 246 259 } 247 260 … … 250 263 251 264 // Don't advance the animation to an incomplete frame. 252 size_t nextFrame = (m_currentFrame + 1) % frameCount();253 265 if (!m_source.isAllDataReceived() && !frameIsCompleteAtIndex(nextFrame)) 254 return ;266 return StartAnimationResult::IncompleteData; 255 267 256 268 double time = monotonicallyIncreasingTime(); … … 263 275 m_desiredFrameStartTime = std::max(time, m_desiredFrameStartTime + frameDurationAtIndex(m_currentFrame)); 264 276 277 // Request async decoding for nextFrame only if this is required. If nextFrame is not in the frameCache, 278 // it will be decoded on a separate work queue. When decoding nextFrame finishes, we will be notified 279 // through the callback newFrameNativeImageAvailableAtIndex(). Otherwise, advanceAnimation() will be called 280 // when the timer fires and m_currentFrame will be advanced to nextFrame since it is not being decoded. 281 if ((allowAsyncImageDecoding() && m_source.isAsyncDecodingRequired()) || isAsyncDecodingForcedForTesting()) { 282 if (!m_source.requestFrameAsyncDecodingAtIndex(nextFrame, m_currentSubsamplingLevel)) 283 LOG(Images, "BitmapImage %p %s - cachedFrameCount %ld nextFrame %ld", this, __FUNCTION__, ++m_cachedFrameCount, nextFrame); 284 m_desiredFrameDecodeTimeForTesting = time + std::max(m_frameDecodingDurationForTesting, 0.0f); 285 } 286 265 287 ASSERT(!m_frameTimer); 266 288 startTimer(m_desiredFrameStartTime - time); 289 return StartAnimationResult::Started; 267 290 } 268 291 … … 271 294 clearTimer(); 272 295 296 // Pretend as if decoding nextFrame has taken m_frameDecodingDurationForTesting from 297 // the time this decoding was requested. 298 if (isAsyncDecodingForcedForTesting()) { 299 double time = monotonicallyIncreasingTime(); 300 // Start a timer with the remaining time from now till the m_desiredFrameDecodeTime. 301 if (m_desiredFrameDecodeTimeForTesting > std::max(time, m_desiredFrameStartTime)) { 302 startTimer(m_desiredFrameDecodeTimeForTesting - time); 303 return; 304 } 305 } 306 307 // Don't advance to nextFrame unless its decoding has finished or was not required. 308 size_t nextFrame = (m_currentFrame + 1) % frameCount(); 309 if (!frameIsBeingDecodedAtIndex(nextFrame)) 310 internalAdvanceAnimation(); 311 else { 312 // Force repaint if showDebugBackground() is on. 313 if (showDebugBackground()) 314 imageObserver()->changedInRect(this); 315 LOG(Images, "BitmapImage %p %s - lateFrameCount %ld nextFrame %ld", this, __FUNCTION__, ++m_lateFrameCount, nextFrame); 316 } 317 } 318 319 void BitmapImage::internalAdvanceAnimation() 320 { 273 321 m_currentFrame = (m_currentFrame + 1) % frameCount(); 322 ASSERT(!frameIsBeingDecodedAtIndex(m_currentFrame)); 323 274 324 destroyDecodedDataIfNecessary(false); 275 325 … … 283 333 // the timer unless all renderers have stopped drawing. 284 334 clearTimer(); 335 m_source.stopAsyncDecodingQueue(); 285 336 } 286 337 … … 295 346 // For extremely large animations, when the animation is reset, we just throw everything away. 296 347 destroyDecodedDataIfNecessary(true); 348 } 349 350 void BitmapImage::newFrameNativeImageAvailableAtIndex(size_t index) 351 { 352 UNUSED_PARAM(index); 353 ASSERT(index == (m_currentFrame + 1) % frameCount()); 354 355 // Don't advance to nextFrame unless the timer was fired before its decoding finishes. 356 if (canAnimate() && !m_frameTimer) 357 internalAdvanceAnimation(); 358 else 359 LOG(Images, "BitmapImage %p %s - earlyFrameCount %ld nextFrame %ld", this, __FUNCTION__, ++m_earlyFrameCount, index); 297 360 } 298 361 -
trunk/Source/WebCore/platform/graphics/BitmapImage.h
r208365 r208511 30 30 #include "Image.h" 31 31 #include "Color.h" 32 #include "ImageObserver.h" 32 33 #include "ImageOrientation.h" 33 34 #include "ImageSource.h" … … 81 82 Color singlePixelSolidColor() const override { return m_source.singlePixelSolidColor(); } 82 83 83 void setAllowSubsampling(bool allowSubsampling) { m_source.setAllowSubsampling(allowSubsampling); }84 85 84 bool frameIsBeingDecodedAtIndex(size_t index) const { return m_source.frameIsBeingDecodedAtIndex(index); } 86 85 bool frameIsCompleteAtIndex(size_t index) const { return m_source.frameIsCompleteAtIndex(index); } … … 96 95 ImageOrientation orientationForCurrentFrame() const override { return frameOrientationAtIndex(currentFrame()); } 97 96 97 bool isAsyncDecodingForcedForTesting() const { return m_frameDecodingDurationForTesting > 0; } 98 void setFrameDecodingDurationForTesting(float duration) { m_frameDecodingDurationForTesting = duration; } 99 98 100 // Accessors for native image formats. 99 101 #if USE(APPKIT) … … 131 133 132 134 NativeImagePtr frameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default, const GraphicsContext* = nullptr); 135 136 bool allowSubsampling() const { return imageObserver() && imageObserver()->allowSubsampling(); } 137 bool allowAsyncImageDecoding() const { return imageObserver() && imageObserver()->allowAsyncImageDecoding(); } 138 bool showDebugBackground() const { return imageObserver() && imageObserver()->showDebugBackground(); } 133 139 134 140 // Called to invalidate cached data. When |destroyAll| is true, we wipe out … … 151 157 152 158 // Animation. 159 enum class StartAnimationResult { CannotStart, IncompleteData, TimerActive, DecodingActive, Started }; 153 160 bool isAnimated() const override { return m_source.frameCount() > 1; } 154 161 bool shouldAnimate(); 155 162 bool canAnimate(); 156 void startAnimation() override; 163 void startAnimation() override { internalStartAnimation(); } 164 StartAnimationResult internalStartAnimation(); 157 165 void advanceAnimation(); 166 void internalAdvanceAnimation(); 158 167 159 168 // It may look unusual that there is no start animation call as public API. This is because … … 162 171 void stopAnimation() override; 163 172 void resetAnimation() override; 173 void newFrameNativeImageAvailableAtIndex(size_t) override; 164 174 165 175 // Handle platform-specific data … … 183 193 184 194 size_t m_currentFrame { 0 }; // The index of the current frame of animation. 195 SubsamplingLevel m_currentSubsamplingLevel { SubsamplingLevel::Default }; 185 196 std::unique_ptr<Timer> m_frameTimer; 186 197 RepetitionCount m_repetitionsComplete { RepetitionCountNone }; // How many repetitions we've finished. … … 188 199 bool m_animationFinished { false }; 189 200 201 float m_frameDecodingDurationForTesting { 0 }; 202 double m_desiredFrameDecodeTimeForTesting { 0 }; 203 #if !LOG_DISABLED 204 size_t m_lateFrameCount { 0 }; 205 size_t m_earlyFrameCount { 0 }; 206 size_t m_cachedFrameCount { 0 }; 207 #endif 208 190 209 #if USE(APPKIT) 191 210 mutable RetainPtr<NSImage> m_nsImage; // A cached NSImage of all the frames. Only built lazily if someone actually queries for one. -
trunk/Source/WebCore/platform/graphics/Color.h
r208460 r208511 265 265 WEBCORE_EXPORT static const RGBA32 transparent = 0x00000000; 266 266 static const RGBA32 cyan = 0xFF00FFFF; 267 static const RGBA32 yellow = 0xFFFFFF00; 267 268 268 269 #if PLATFORM(IOS) -
trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp
r208365 r208511 285 285 } 286 286 287 voidImageFrameCache::requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel)287 bool ImageFrameCache::requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel) 288 288 { 289 289 if (!isDecoderAvailable()) 290 return ;290 return false; 291 291 292 292 if (!hasDecodingQueue()) … … 300 300 301 301 if (frame.hasValidNativeImage(subsamplingLevel)) 302 return ;302 return false; 303 303 304 304 frame.setDecoding(ImageFrame::Decoding::BeingDecoded); 305 305 m_frameRequestQueue.enqueue({ index, subsamplingLevel }); 306 return true; 306 307 } 307 308 … … 337 338 m_frameCount = Nullopt; 338 339 m_singlePixelSolidColor = Nullopt; 339 m_maximumSubsamplingLevel = Nullopt;340 340 } 341 341 -
trunk/Source/WebCore/platform/graphics/ImageFrameCache.h
r208365 r208511 69 69 // Asynchronous image decoding 70 70 void startAsyncDecodingQueue(); 71 voidrequestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel);71 bool requestFrameAsyncDecodingAtIndex(size_t, SubsamplingLevel); 72 72 void stopAsyncDecodingQueue(); 73 73 bool hasDecodingQueue() { return m_decodingQueue; } … … 163 163 Optional<IntSize> m_size; 164 164 Optional<IntSize> m_sizeRespectingOrientation; 165 Optional<SubsamplingLevel> m_maximumSubsamplingLevel;166 165 Optional<Color> m_singlePixelSolidColor; 167 166 }; -
trunk/Source/WebCore/platform/graphics/ImageObserver.h
r206635 r208511 38 38 virtual ~ImageObserver() {} 39 39 public: 40 virtual bool allowSubsampling() const = 0; 41 virtual bool allowAsyncImageDecoding() const = 0; 42 virtual bool showDebugBackground() const = 0; 40 43 virtual void decodedSizeChanged(const Image*, long long delta) = 0; 44 41 45 virtual void didDraw(const Image*) = 0; 42 46 43 47 virtual void animationAdvanced(const Image*) = 0; 44 48 45 virtual void changedInRect(const Image*, const IntRect &) = 0;49 virtual void changedInRect(const Image*, const IntRect* changeRect = nullptr) = 0; 46 50 }; 47 51 -
trunk/Source/WebCore/platform/graphics/ImageSource.cpp
r208365 r208511 187 187 return m_maximumSubsamplingLevel.value(); 188 188 189 if (! m_allowSubsampling || !isDecoderAvailable() || !m_decoder->frameAllowSubsamplingAtIndex(0))189 if (!isDecoderAvailable() || !m_decoder->frameAllowSubsamplingAtIndex(0)) 190 190 return SubsamplingLevel::Default; 191 191 -
trunk/Source/WebCore/platform/graphics/ImageSource.h
r208365 r208511 67 67 68 68 bool isAsyncDecodingRequired(); 69 void requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel) {m_frameCache->requestFrameAsyncDecodingAtIndex(index, subsamplingLevel); }69 bool requestFrameAsyncDecodingAtIndex(size_t index, SubsamplingLevel subsamplingLevel) { return m_frameCache->requestFrameAsyncDecodingAtIndex(index, subsamplingLevel); } 70 70 void stopAsyncDecodingQueue() { m_frameCache->stopAsyncDecodingQueue(); } 71 71 … … 99 99 SubsamplingLevel maximumSubsamplingLevel(); 100 100 SubsamplingLevel subsamplingLevelForScale(float); 101 void setAllowSubsampling(bool allowSubsampling) { m_allowSubsampling = allowSubsampling; }102 101 NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = SubsamplingLevel::Default); 103 102 … … 114 113 Optional<SubsamplingLevel> m_maximumSubsamplingLevel; 115 114 116 // The default value of m_allowSubsampling should be the same as defaultImageSubsamplingEnabled in Settings.cpp117 #if PLATFORM(IOS)118 bool m_allowSubsampling { true };119 #else120 bool m_allowSubsampling { false };121 #endif122 123 115 #if PLATFORM(IOS) 124 116 // FIXME: We should expose a setting to enable/disable progressive loading so that we can remove the PLATFORM(IOS)-guard. -
trunk/Source/WebCore/rendering/RenderImageResource.cpp
r206867 r208511 57 57 ASSERT(m_renderer); 58 58 59 if (m_cachedImage) 59 if (m_cachedImage) { 60 image()->stopAnimation(); 60 61 m_cachedImage->removeClient(*m_renderer); 62 } 61 63 } 62 64 -
trunk/Source/WebCore/rendering/RenderImageResourceStyleImage.cpp
r205181 r208511 58 58 ASSERT(m_renderer); 59 59 m_styleImage->removeClient(m_renderer); 60 m_cachedImage = nullptr; 60 if (m_cachedImage) { 61 image()->stopAnimation(); 62 m_cachedImage = nullptr; 63 } 61 64 } 62 65 -
trunk/Source/WebCore/svg/graphics/SVGImageClients.h
r203469 r208511 55 55 // If m_image->m_page is null, we're being destructed, don't fire changedInRect() in that case. 56 56 if (m_image && m_image->imageObserver() && m_image->m_page) 57 m_image->imageObserver()->changedInRect(m_image, r);57 m_image->imageObserver()->changedInRect(m_image, &r); 58 58 } 59 59 -
trunk/Source/WebCore/testing/Internals.cpp
r208475 r208511 650 650 } 651 651 652 void Internals::setImageFrameDecodingDuration(HTMLImageElement& element, float duration) 653 { 654 auto* cachedImage = element.cachedImage(); 655 if (!cachedImage) 656 return; 657 658 auto* image = cachedImage->image(); 659 if (!is<BitmapImage>(image)) 660 return; 661 662 downcast<BitmapImage>(*image).setFrameDecodingDurationForTesting(duration); 663 } 664 652 665 void Internals::clearPageCache() 653 666 { -
trunk/Source/WebCore/testing/Internals.h
r208475 r208511 104 104 105 105 unsigned imageFrameIndex(HTMLImageElement&); 106 void setImageFrameDecodingDuration(HTMLImageElement&, float duration); 106 107 107 108 void clearPageCache(); -
trunk/Source/WebCore/testing/Internals.idl
r208475 r208511 222 222 223 223 unsigned long imageFrameIndex(HTMLImageElement element); 224 void setImageFrameDecodingDuration(HTMLImageElement element, unrestricted float duration); 224 225 225 226 readonly attribute InternalSettings settings;
Note: See TracChangeset
for help on using the changeset viewer.