Changeset 214635 in webkit
- Timestamp:
- Mar 30, 2017 3:41:14 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 15 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r214634 r214635 1 2017-03-30 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 REGRESSION (r213764): Background image from sprite sheet incorrectly scaled 4 https://bugs.webkit.org/show_bug.cgi?id=169547 5 6 Reviewed by Simon Fraser. 7 8 * fast/images/async-image-background-image.html: 9 * fast/images/resources/sprite-sheet-red-green-blue.png: Added. 10 * fast/images/sprite-sheet-image-draw-expected.html: Added. 11 * fast/images/sprite-sheet-image-draw.html: Added. 12 1 13 2017-03-30 Matt Baker <mattbaker@apple.com> 2 14 -
trunk/LayoutTests/fast/images/async-image-background-image-expected.html
r214450 r214635 1 <!DOCTYPE html> 2 <html> 1 3 <style> 2 div{4 .box { 3 5 width: 300px; 4 6 height: 300px; 7 } 8 .rgb-background { 5 9 background-color: green; 10 } 11 @media (-webkit-min-device-pixel-ratio: 2) { 12 .box { 13 width: 150px; 14 height: 150px; 15 } 6 16 } 7 17 </style> 8 18 <body> 9 <div ></div>19 <div class="box rgb-background"></div> 10 20 </body> 21 </html> -
trunk/LayoutTests/fast/images/async-image-background-image.html
r214450 r214635 2 2 <html> 3 3 <style> 4 div{4 .box { 5 5 width: 300px; 6 6 height: 300px; 7 } 8 .image-background { 7 9 background-image: url(resources/red-green-blue-900-300.png); 8 10 background-position: -300px 0px; 9 11 } 12 @media (-webkit-min-device-pixel-ratio: 2) { 13 .box { 14 width: 150px; 15 height: 150px; 16 } 17 .image-background { 18 background-position: -150px 0px; 19 background-size: 450px, 150px; 20 } 21 } 10 22 </style> 11 <script>12 if (window.internals)13 internals.settings.setLargeImageAsyncDecodingEnabled(true);14 </script>15 23 <body> 16 <div></div> 24 <div class="box image-background"></div> 25 <script> 26 function forceRedraw(element) { 27 var disp = element.style.display; 28 element.style.display = 'none'; 29 var trick = element.offsetHeight; 30 element.style.display = disp; 31 } 32 33 (function() { 34 var divElement = document.getElementsByClassName("image-background")[0]; 35 36 if (window.internals) { 37 internals.clearMemoryCache(); 38 internals.settings.setLargeImageAsyncDecodingEnabled(true); 39 } 40 41 if (window.testRunner) { 42 testRunner.waitUntilDone(); 43 forceRedraw(divElement); 44 setTimeout(function() { 45 forceRedraw(divElement); 46 testRunner.notifyDone(); 47 }, 50); 48 } 49 } 50 </script> 17 51 </body> 18 52 </html> -
trunk/Source/WebCore/ChangeLog
r214634 r214635 1 2017-03-30 Said Abou-Hallawa <sabouhallawa@apple.com> 2 3 REGRESSION (r213764): Background image from sprite sheet incorrectly scaled 4 https://bugs.webkit.org/show_bug.cgi?id=169547 5 6 Reviewed by Simon Fraser. 7 8 The bug happens when drawing only a rectangle of an image not the whole 9 image. In BitmapImage::draw(), sizeForDrawing was calculated as the destRect 10 scaled by the transformation which is applied to the GraphicsContext. Two 11 problems with this approach. The first one is destRect can be only part of 12 the image. The second problem is, the ratio destRect / srcRect is another 13 scaling that needs to be considered. 14 15 To fix this issue, first the base size has to be size of the image and not 16 destRect.size(). Secondly, we need to scale this base size with the context 17 transformation multiplied by the ratio destRect / srcRect. This scaling is 18 exactly the same scaling which is calculated in subsamplingScale(). Finally 19 we use this scaled size as the sizeForDrawing to send to the ImageDecoder. 20 21 Test: fast/images/sprite-sheet-image-draw.html 22 23 * platform/graphics/BitmapImage.cpp: 24 (WebCore::BitmapImage::draw): Fix the bug. 25 (WebCore::BitmapImage::stopAnimation): Stops the async image decoding for animated images only. 26 The decoding for large images will be stopped when BitmapImage::newFrameNativeImageAvailableAtIndex() 27 is called and the decoding queue is idle. 28 (WebCore::BitmapImage::newFrameNativeImageAvailableAtIndex): Add image logging. 29 * platform/graphics/BitmapImage.h: Move sourceURL() to the Image class. 30 * platform/graphics/GraphicsContext.cpp: Pass imagePaintingOptions.m_decodingMode to Image::drawTiled(). 31 (WebCore::GraphicsContext::drawTiledImage): Pass imagePaintingOptions.m_decodingMode) to Image::drawTiled(). 32 * platform/graphics/Image.cpp: 33 (WebCore::Image::sourceURL): Moved from BitmapImage. 34 (WebCore::Image::drawTiled): Add a DecodingMode argument instead of calling always with DecodingMode::Synchronous. 35 * platform/graphics/Image.h: 36 * platform/graphics/ImageFrameCache.cpp: 37 (WebCore::ImageFrameCache::cacheAsyncFrameNativeImageAtIndex): Add image logging. 38 (WebCore::ImageFrameCache::startAsyncDecodingQueue): Ditto, 39 (WebCore::ImageFrameCache::requestFrameAsyncDecodingAtIndex): Ditto. 40 (WebCore::ImageFrameCache::stopAsyncDecodingQueue): Ditto. 41 (WebCore::ImageFrameCache::sourceURL): A helper function to avoid checking the value of m_image. 42 * platform/graphics/ImageFrameCache.h: 43 * platform/graphics/NativeImage.h: Rename subsamplingScale() to nativeImageDrawingScale() and return image scaling instead. 44 * platform/graphics/cairo/NativeImageCairo.cpp: 45 (WebCore::nativeImageDrawingScale): Ditto. 46 (WebCore::subsamplingScale): Deleted. 47 * platform/graphics/cg/NativeImageCG.cpp: 48 (WebCore::nativeImageDrawingScale): Ditto. 49 (WebCore::subsamplingScale): Deleted. 50 * platform/graphics/win/NativeImageDirect2D.cpp: 51 (WebCore::nativeImageDrawingScale): Ditto. 52 (WebCore::subsamplingScale): Deleted. 53 1 54 2017-03-30 Matt Baker <mattbaker@apple.com> 2 55 -
trunk/Source/WebCore/platform/graphics/BitmapImage.cpp
r214503 r214635 164 164 return; 165 165 166 float scale = subsamplingScale(context, destRect, srcRect); 167 m_currentSubsamplingLevel = allowSubsampling() ? m_source.subsamplingLevelForScale(scale) : SubsamplingLevel::Default; 168 IntSize sizeForDrawing = enclosingIntRect(context.getCTM().mapRect(destRect)).size(); 169 170 LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel = %d scale = %.4f]", __FUNCTION__, this, sourceURL().utf8().data(), static_cast<int>(m_currentSubsamplingLevel), scale); 166 FloatSize scale = nativeImageDrawingScale(context, destRect, srcRect); 167 float subsamplingScale = std::min(float(1), std::max(scale.width(), scale.height())); 168 m_currentSubsamplingLevel = allowSubsampling() ? m_source.subsamplingLevelForScale(subsamplingScale) : SubsamplingLevel::Default; 169 IntSize sizeForDrawing = expandedIntSize(size() * scale); 170 171 LOG(Images, "BitmapImage::%s - %p - url: %s [subsamplingLevel = %d scale = %.4f]", __FUNCTION__, this, sourceURL().utf8().data(), static_cast<int>(m_currentSubsamplingLevel), subsamplingScale); 171 172 172 173 NativeImagePtr image; … … 176 177 if (!frameHasDecodedNativeImageCompatibleWithOptionsAtIndex(m_currentFrame, m_currentSubsamplingLevel, DecodingOptions(sizeForDrawing)) 177 178 && !frameIsBeingDecodedAndIsCompatibleWithOptionsAtIndex(m_currentFrame, DecodingOptions(sizeForDrawing))) { 179 LOG(Images, "BitmapImage::%s - %p - url: %s [requesting large async decoding]", __FUNCTION__, this, sourceURL().utf8().data()); 178 180 m_source.requestFrameAsyncDecodingAtIndex(0, m_currentSubsamplingLevel, sizeForDrawing); 179 LOG(Images, "BitmapImage::%s - %p - url: %s [requesting large async decoding]", __FUNCTION__, this, sourceURL().utf8().data());180 181 } 181 182 … … 187 188 188 189 image = frameImageAtIndex(m_currentFrame); 190 LOG(Images, "BitmapImage::%s - %p - url: %s [a decoded image frame is available for drawing]", __FUNCTION__, this, sourceURL().utf8().data()); 189 191 } else { 190 192 StartAnimationStatus status = internalStartAnimation(); … … 417 419 // the timer unless all renderers have stopped drawing. 418 420 clearTimer(); 419 m_source.stopAsyncDecodingQueue(); 421 if (canAnimate()) 422 m_source.stopAsyncDecodingQueue(); 420 423 } 421 424 … … 435 438 { 436 439 UNUSED_PARAM(index); 440 LOG(Images, "BitmapImage::%s - %p - url: %s [requested frame %ld is now available]", __FUNCTION__, this, sourceURL().utf8().data(), index); 441 437 442 if (canAnimate()) { 438 443 ASSERT(index == (m_currentFrame + 1) % frameCount()); -
trunk/Source/WebCore/platform/graphics/BitmapImage.h
r214503 r214635 137 137 NativeImagePtr frameImageAtIndexCacheIfNeeded(size_t, SubsamplingLevel = SubsamplingLevel::Default, const GraphicsContext* = nullptr); 138 138 139 String sourceURL() const { return imageObserver() ? imageObserver()->sourceUrl().string() : emptyString(); }140 139 bool allowSubsampling() const { return imageObserver() && imageObserver()->allowSubsampling(); } 141 140 bool allowLargeImageAsyncDecoding() const { return imageObserver() && imageObserver()->allowLargeImageAsyncDecoding(); } -
trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp
r214450 r214635 743 743 744 744 InterpolationQualityMaintainer interpolationQualityForThisScope(*this, imagePaintingOptions.m_interpolationQuality); 745 image.drawTiled(*this, destination, source, tileSize, spacing, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode );745 image.drawTiled(*this, destination, source, tileSize, spacing, imagePaintingOptions.m_compositeOperator, imagePaintingOptions.m_blendMode, imagePaintingOptions.m_decodingMode); 746 746 } 747 747 -
trunk/Source/WebCore/platform/graphics/Image.cpp
r214450 r214635 80 80 } 81 81 82 String Image::sourceURL() const 83 { 84 return imageObserver() ? imageObserver()->sourceUrl().string() : emptyString(); 85 } 86 82 87 void Image::fillWithSolidColor(GraphicsContext& ctxt, const FloatRect& dstRect, const Color& color, CompositeOperator op) 83 88 { … … 91 96 } 92 97 93 void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode )98 void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode, DecodingMode decodingMode) 94 99 { 95 100 Color color = singlePixelSolidColor(); … … 127 132 visibleSrcRect.setWidth(destRect.width() / scale.width()); 128 133 visibleSrcRect.setHeight(destRect.height() / scale.height()); 129 draw(ctxt, destRect, visibleSrcRect, op, blendMode, DecodingMode::Synchronous, ImageOrientationDescription());134 draw(ctxt, destRect, visibleSrcRect, op, blendMode, decodingMode, ImageOrientationDescription()); 130 135 return; 131 136 } … … 140 145 visibleSrcRect.setWidth(1); 141 146 visibleSrcRect.setHeight(destRect.height() / scale.height()); 142 draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, DecodingMode::Synchronous, ImageOrientationDescription());147 draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription()); 143 148 return; 144 149 } … … 149 154 visibleSrcRect.setWidth(destRect.width() / scale.width()); 150 155 visibleSrcRect.setHeight(1); 151 draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, DecodingMode::Synchronous, ImageOrientationDescription());156 draw(ctxt, destRect, visibleSrcRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription()); 152 157 return; 153 158 } … … 181 186 fromRect.scale(1 / scale.width(), 1 / scale.height()); 182 187 183 draw(ctxt, toRect, fromRect, op, BlendModeNormal, DecodingMode::Synchronous, ImageOrientationDescription());188 draw(ctxt, toRect, fromRect, op, BlendModeNormal, decodingMode, ImageOrientationDescription()); 184 189 toX += currentTileRect.width(); 185 190 currentTileRect.shiftXEdgeTo(oneTileRect.x()); -
trunk/Source/WebCore/platform/graphics/Image.h
r214503 r214635 137 137 ImageObserver* imageObserver() const { return m_imageObserver; } 138 138 void setImageObserver(ImageObserver* observer) { m_imageObserver = observer; } 139 String sourceURL() const; 139 140 140 141 enum TileRule { StretchTile, RoundTile, SpaceTile, RepeatTile }; … … 188 189 #endif 189 190 virtual void draw(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, CompositeOperator, BlendMode, DecodingMode, ImageOrientationDescription) = 0; 190 void drawTiled(GraphicsContext&, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, const FloatSize& spacing, CompositeOperator, BlendMode );191 void drawTiled(GraphicsContext&, const FloatRect& dstRect, const FloatPoint& srcPoint, const FloatSize& tileSize, const FloatSize& spacing, CompositeOperator, BlendMode, DecodingMode); 191 192 void drawTiled(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator); 192 193 -
trunk/Source/WebCore/platform/graphics/ImageFrameCache.cpp
r214450 r214635 29 29 #include "Image.h" 30 30 #include "ImageObserver.h" 31 #include "Logging.h" 31 32 #include <wtf/SystemTracing.h> 32 33 … … 250 251 // Clean the old native image and set a new one 251 252 cacheFrameNativeImageAtIndex(WTFMove(nativeImage), index, subsamplingLevel, decodingOptions); 253 LOG(Images, "ImageFrameCache::%s - %p - url: %s [frame %ld has been cached]", __FUNCTION__, this, sourceURL().utf8().data(), index); 252 254 253 255 // Notify the image with the readiness of the new frame NativeImage. … … 284 286 // Get the frame NativeImage on the decoding thread. 285 287 NativeImagePtr nativeImage = protectedDecoder->createFrameImageAtIndex(frameRequest.index, frameRequest.subsamplingLevel, frameRequest.decodingOptions); 288 if (nativeImage) 289 LOG(Images, "ImageFrameCache::%s - %p - url: %s [frame %ld has been decoded]", __FUNCTION__, this, sourceURL().utf8().data(), frameRequest.index); 290 else 291 LOG(Images, "ImageFrameCache::%s - %p - url: %s [decoding for frame %ld has failed]", __FUNCTION__, this, sourceURL().utf8().data(), frameRequest.index); 286 292 287 293 // Update the cached frames on the main thread to avoid updating the MemoryCache from a different thread. … … 292 298 m_frameCommitQueue.removeFirst(); 293 299 cacheAsyncFrameNativeImageAtIndex(WTFMove(nativeImage), frameRequest.index, frameRequest.subsamplingLevel, frameRequest.decodingOptions); 294 } 300 } else 301 LOG(Images, "ImageFrameCache::%s - %p - url: %s [frame %ld will not cached]", __FUNCTION__, this, sourceURL().utf8().data(), frameRequest.index); 295 302 }); 296 303 } … … 317 324 startAsyncDecodingQueue(); 318 325 326 LOG(Images, "ImageFrameCache::%s - %p - url: %s [enqueuing frame %ld for decoding]", __FUNCTION__, this, sourceURL().utf8().data(), index); 319 327 m_frameRequestQueue.enqueue({ index, subsamplingLevel, sizeForDrawing }); 320 328 m_frameCommitQueue.append({ index, subsamplingLevel, sizeForDrawing }); … … 334 342 std::for_each(m_frameCommitQueue.begin(), m_frameCommitQueue.end(), [this](const ImageFrameRequest& frameRequest) { 335 343 ImageFrame& frame = m_frames[frameRequest.index]; 336 if (!frame.isEmpty()) 344 if (!frame.isEmpty()) { 345 LOG(Images, "ImageFrameCache::%s - %p - url: %s [decoding has been cancelled for frame %ld]", __FUNCTION__, this, sourceURL().utf8().data(), frameRequest.index); 337 346 frame.clear(); 347 } 338 348 }); 339 349 … … 341 351 m_frameCommitQueue.clear(); 342 352 m_decodingQueue = nullptr; 353 LOG(Images, "ImageFrameCache::%s - %p - url: %s [decoding has been stopped]", __FUNCTION__, this, sourceURL().utf8().data()); 343 354 } 344 355 … … 380 391 } 381 392 393 String ImageFrameCache::sourceURL() const 394 { 395 return m_image ? m_image->sourceURL() : emptyString(); 396 } 397 382 398 template<typename T, T (ImageDecoder::*functor)() const> 383 399 T ImageFrameCache::metadata(const T& defaultValue, std::optional<T>* cachedValue) -
trunk/Source/WebCore/platform/graphics/ImageFrameCache.h
r214450 r214635 67 67 void growFrames(); 68 68 void clearMetadata(); 69 String sourceURL() const; 69 70 70 71 // Asynchronous image decoding -
trunk/Source/WebCore/platform/graphics/NativeImage.h
r206742 r214635 66 66 Color nativeImageSinglePixelSolidColor(const NativeImagePtr&); 67 67 68 float subsamplingScale(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect);68 FloatSize nativeImageDrawingScale(GraphicsContext&, const FloatRect& destRect, const FloatRect& srcRect); 69 69 70 70 void drawNativeImage(const NativeImagePtr&, GraphicsContext&, const FloatRect&, const FloatRect&, const IntSize&, CompositeOperator, BlendMode, const ImageOrientation&); -
trunk/Source/WebCore/platform/graphics/cairo/NativeImageCairo.cpp
r206156 r214635 57 57 } 58 58 59 float subsamplingScale(GraphicsContext&, const FloatRect&, const FloatRect&)59 FloatSize nativeImageDrawingScale(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect) 60 60 { 61 return 1; 61 auto transformedDestinationRect = context.getCTM().mapRect(destRect); 62 return { static_cast<float>(transformedDestinationRect.width() / srcRect.width()), static_cast<float>(transformedDestinationRect.height() / srcRect.height()) }; 62 63 } 63 64 -
trunk/Source/WebCore/platform/graphics/cg/NativeImageCG.cpp
r206156 r214635 74 74 } 75 75 76 float subsamplingScale(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect)76 FloatSize nativeImageDrawingScale(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect) 77 77 { 78 78 // Never use subsampled images for drawing into PDF contexts. 79 79 if (wkCGContextIsPDFContext(context.platformContext())) 80 return 1;80 return { 1, 1 }; 81 81 82 82 CGRect transformedDestinationRect = CGRectApplyAffineTransform(destRect, CGContextGetCTM(context.platformContext())); 83 return std::min<float>(1, std::max(transformedDestinationRect.size.width / srcRect.width(), transformedDestinationRect.size.height / srcRect.height()));83 return { static_cast<float>(transformedDestinationRect.size.width / srcRect.width()), static_cast<float>(transformedDestinationRect.size.height / srcRect.height()) }; 84 84 } 85 85 -
trunk/Source/WebCore/platform/graphics/win/NativeImageDirect2D.cpp
r208131 r214635 61 61 } 62 62 63 float subsamplingScale(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect)63 FloatSize nativeImageDrawingScale(GraphicsContext& context, const FloatRect& destRect, const FloatRect& srcRect) 64 64 { 65 65 D2D1_MATRIX_3X2_F ctm; … … 69 69 70 70 auto transformedDestinationRect = transform.mapRect(destRect); 71 return std::min<float>(1, std::max(transformedDestinationRect.width() / srcRect.width(), transformedDestinationRect.height() / srcRect.height()));71 return { static_cast<float>(transformedDestinationRect.width() / srcRect.width()), static_cast<float>(transformedDestinationRect.height() / srcRect.height()) }; 72 72 } 73 73
Note: See TracChangeset
for help on using the changeset viewer.