Branch: refs/heads/main
  Home:   https://github.com/WebKit/WebKit
  Commit: 9814e35d8f3dcda43ab13de8b3a3f9f875164ec5
      
https://github.com/WebKit/WebKit/commit/9814e35d8f3dcda43ab13de8b3a3f9f875164ec5
  Author: Brent Fulgham <[email protected]>
  Date:   2026-09-29 (Tue, 29 Sep 2026)

  Changed paths:
    A 
LayoutTests/fast/images/image-natural-size-after-encoded-data-replaced-expected.txt
    A 
LayoutTests/fast/images/image-natural-size-after-encoded-data-replaced.html
    M Source/WebCore/platform/graphics/BitmapImage.cpp
    M Source/WebCore/platform/graphics/BitmapImage.h
    M Source/WebCore/platform/graphics/BitmapImageDescriptor.cpp
    M Source/WebCore/platform/graphics/BitmapImageDescriptor.h
    M Source/WebCore/platform/graphics/ImageDecoder.cpp
    M Source/WebCore/platform/graphics/ImageFrame.cpp
    M Source/WebCore/platform/graphics/ImageFrame.h
    M Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp
    M Source/WebCore/testing/Internals.cpp
    M Source/WebCore/testing/Internals.h
    M Source/WebCore/testing/Internals.idl

  Log Message:
  -----------
  [Cocoa] <img> size may be computed based on a decoded thumbnail rather than 
the true size
https://bugs.webkit.org/show_bug.cgi?id=325301
rdar://172477431

Reviewed by Said Abou-Hallawa.

When a site displays a large image at thumbnail size, WebKit may record the
thumbnail's decode size as the image's natural size, and every other use of the
same image URL then lays out at that size.

Sites often reuse one image URL at several display sizes and scale it with CSS.
To save memory, WebKit decodes a large image drawn at a small size 
asynchronously
at roughly its displayed size, and records the size of that decode on the 
image's
primary frame.

On zillow.com, the same 750x750 floor plan is shown as an 80x80 thumbnail and 
as a
large image on the unit detail view. The sequence is:

1. The image loads from the network and the 80x80 thumbnail is drawn. The image 
is
   decoded asynchronously at a size for drawing (160x160 on a 2x display), and
   fetchFrameMetaDataAtIndex() records 160x160 as the primary frame's size.
2. Shortly after the load, the memory cache replaces the image's encoded data 
with
   the file-backed copy from the disk cache. BitmapImageSource::dataReplaced()
   clears the image's cached metadata, including its size. It keeps the primary
   frame, because the thumbnail is still visible.
3. The next time the image's size is needed, BitmapImageDescriptor::sourceSize()
   reads it from that primary frame and caches 160x160 as the image's intrinsic 
size.
4. The large floor plan uses the same cached image, so it now reports a
   naturalWidth of 160 and is laid out at 160px instead of 750px.

Because the wrong size stays in the memory cache, reloading does not fix it. 
Only
network loads replace their data with a disk cache copy, which is why it happens
on first load.

Fix this by recording the image's natural size on ImageFrame separately from the
size it was decoded at, and taking the intrinsic size from it. This matches 
Blink,
which takes the intrinsic size from a metadata-only decoder and keeps scaled
decodes out of the image's metadata.

Test: fast/images/image-natural-size-after-encoded-data-replaced.html

* 
LayoutTests/fast/images/image-natural-size-after-encoded-data-replaced-expected.txt:
 Added.
* LayoutTests/fast/images/image-natural-size-after-encoded-data-replaced.html: 
Added.
* Source/WebCore/platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::simulateDataReplacedForTesting):
* Source/WebCore/platform/graphics/BitmapImage.h:
* Source/WebCore/platform/graphics/BitmapImageDescriptor.cpp:
(WebCore::BitmapImageDescriptor::sourceSize const): Read the primary frame's 
natural
size instead of its decoded size.
* Source/WebCore/platform/graphics/BitmapImageDescriptor.h: Rename 
CachedFlag::Size
to CachedFlag::NaturalSize, since it now caches the natural size.
* Source/WebCore/platform/graphics/ImageDecoder.cpp:
(WebCore::ImageDecoder::fetchFrameMetaDataAtIndex const):
* Source/WebCore/platform/graphics/ImageFrame.cpp:
(WebCore::ImageFrame::ImageFrame):
* Source/WebCore/platform/graphics/ImageFrame.h:
(WebCore::ImageFrame::naturalSize const):
* Source/WebCore/platform/graphics/cg/ImageDecoderCG.cpp:
(WebCore::ImageDecoderCG::fetchFrameMetaDataAtIndex const): Record the natural 
size
even when the frame is decoded at a size for drawing.
* Source/WebCore/testing/Internals.cpp:
(WebCore::Internals::simulateImageDataReplacedForTesting): Notify an image that 
its
encoded data was replaced with an identical copy, as the disk cache does with a
file-backed one.
* Source/WebCore/testing/Internals.h:
* Source/WebCore/testing/Internals.idl:

Canonical link: https://commits.webkit.org/322220@main



To unsubscribe from these emails, change your notification settings at 
https://github.com/WebKit/WebKit/settings/notifications

Reply via email to