Source/WebCore/ChangeLog

 12016-03-13 Said Abou-Hallawa <sabouhallawa@apple,com>
 2
 3 Create a CG ImageDecoder class instead of defining it as CGImageSourceRef
 4 https://bugs.webkit.org/show_bug.cgi?id=155422
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Move the image decoding code from ImageSourceCG.cpp out to a new class named
 9 ImageDecoder. The purpose of this split is to have the CG ImageSource similar
 10 to the none CG ImageSource where there is a separate class for decoding. The
 11 plan is to merge the ImageSource.cpp and ImageSourceCG.cpp in one file so
 12 deciding whether the decoding should happen synchronously or asynchronously
 13 can happen in one place and the caching of the frames can be handled by the
 14 ImageSource as well.
 15
 16 * PlatformAppleWin.cmake:
 17 * PlatformMac.cmake:
 18 * WebCore.xcodeproj/project.pbxproj:
 19 * loader/cache/CachedImage.cpp:
 20 (WebCore::CachedImage::imageSizeForRenderer):
 21 * platform/graphics/BitmapImage.cpp:
 22 (WebCore::BitmapImage::updateSize):
 23 (WebCore::BitmapImage::sizeRespectingOrientation):
 24 (WebCore::BitmapImage::frameImageAtIndex):
 25 (WebCore::BitmapImage::dump): Deleted.
 26 * platform/graphics/BitmapImage.h:
 27 * platform/graphics/ImageSource.cpp:
 28 (WebCore::ImageSource::size):
 29 (WebCore::ImageSource::sizeRespectingOrientation):
 30 (WebCore::ImageSource::frameSizeAtIndex):
 31 * platform/graphics/ImageSource.h:
 32 (WebCore::ImageSource::initialized):
 33 * platform/graphics/cg/BitmapImageCG.cpp:
 34 (WebCore::BitmapImage::BitmapImage):
 35 * platform/graphics/cg/ImageDecoder.cpp: Copied from Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp.
 36 (WebCore::createImageSourceOptions):
 37 (WebCore::imageSourceOptions):
 38 (WebCore::sharedBufferGetBytesAtPosition);
 39 (WebCore::sharedBufferRelease);
 40 (WebCore::orientationFromProperties):
 41 (WebCore::ImageDecoder::ImageDecoder):
 42 (WebCore::ImageDecoder::subsamplingLevelForScale):
 43 (WebCore::ImageDecoder::bytesDecodedToDetermineProperties):
 44 (WebCore::ImageDecoder::filenameExtension):
 45 (WebCore::ImageDecoder::isSizeAvailable):
 46 (WebCore::ImageDecoder::size):
 47 (WebCore::ImageDecoder::frameCount):
 48 (WebCore::ImageDecoder::repetitionCount):
 49 (WebCore::ImageDecoder::getHotSpot):
 50 (WebCore::ImageDecoder::frameSizeAtIndex):
 51 (WebCore::ImageDecoder::frameIsCompleteAtIndex):
 52 (WebCore::ImageDecoder::orientationAtIndex):
 53 (WebCore::ImageDecoder::frameDurationAtIndex):
 54 (WebCore::ImageDecoder::allowSubsamplingOfFrameAtIndex):
 55 (WebCore::ImageDecoder::frameHasAlphaAtIndex):
 56 (WebCore::ImageDecoder::frameBytesAtIndex):
 57 (WebCore::ImageDecoder::createFrameImageAtIndex):
 58 (WebCore::ImageDecoder::setData):
 59 * platform/graphics/cg/ImageDecoder.h: Added.
 60 (WebCore::ImageDecoder::~ImageDecoder):
 61 * platform/graphics/cg/ImageSourceCG.cpp:
 62 (WebCore::ImageSource::clear):
 63 (WebCore::ImageSource::ensureDecoderIsCreated):
 64 (WebCore::ImageSource::setData):
 65 (WebCore::ImageSource::filenameExtension):
 66 (WebCore::ImageSource::subsamplingLevelForScale):
 67 (WebCore::ImageSource::bytesDecodedToDetermineProperties):
 68 (WebCore::ImageSource::isSizeAvailable):
 69 (WebCore::ImageSource::allowSubsamplingOfFrameAtIndex):
 70 (WebCore::ImageSource::frameSizeAtIndex):
 71 (WebCore::ImageSource::orientationAtIndex):
 72 (WebCore::ImageSource::size):
 73 (WebCore::ImageSource::sizeRespectingOrientation):
 74 (WebCore::ImageSource::getHotSpot):
 75 (WebCore::ImageSource::repetitionCount):
 76 (WebCore::ImageSource::frameCount):
 77 (WebCore::ImageSource::createFrameImageAtIndex):
 78 (WebCore::ImageSource::frameIsCompleteAtIndex):
 79 (WebCore::ImageSource::frameDurationAtIndex):
 80 (WebCore::ImageSource::frameHasAlphaAtIndex):
 81 (WebCore::ImageSource::frameBytesAtIndex):
 82 (WebCore::sharedBufferGetBytesAtPosition): Deleted.
 83 (WebCore::sharedBufferRelease): Deleted.
 84 (WebCore::ImageSource::ImageSource): Deleted.
 85 (WebCore::createImageSourceOptions): Deleted.
 86 (WebCore::imageSourceOptions): Deleted.
 87 (WebCore::ImageSource::initialized): Deleted.
 88 (WebCore::orientationFromProperties): Deleted.
 89 (WebCore::ImageSource::createFrameAtIndex): Deleted.
 90 * platform/mac/DragImageMac.mm:
 91 (WebCore::createDragImageFromImage):
 92 * platform/graphics/cairo/BitmapImageCairo.cpp:
 93 (WebCore::BitmapImage::determineMinimumSubsamplingLevel):
 94
 952016-03-13 Said Abou-Hallawa <sabouhallawa@apple,com>
 96
 97 Change NativeImagePtr for CG to be RetainPtr<CGImageRef>
 98 https://bugs.webkit.org/show_bug.cgi?id=155412
 99
 100 Reviewed by NOBODY (OOPS!).
 101
 102 Having NativeImagePtr as a raw pointer makes managing the life cycle of
 103 the CGImageRef hard. A lot of works was done to make sure the CG pointer
 104 is maintained correctly. It was also not possible to move a FrameData since
 105 calling the destructor was releasing the CGImageRef.
 106
 107 I am going to follow this naming convention:
 108 1. An Image object can have one or more FrameData. A FrameData can be named
 109 for shortness as "frame", "m_frames", etc.
 110 2. A FrameData can have zero or one NativeImagePtr. A NativeImagePtr can
 111 be named as "image", "m_image", etc.
 112
 113 * loader/cache/MemoryCache.cpp:
 114 (WebCore::MemoryCache::addImageToCache):
 115 * platform/graphics/BitmapImage.cpp:
 116 (WebCore::BitmapImage::haveFrameImageAtIndex):
 117 (WebCore::BitmapImage::cacheFrame):
 118 (WebCore::BitmapImage::ensureFrameIsCached):
 119 (WebCore::BitmapImage::frameImageAtIndex):
 120 (WebCore::BitmapImage::nativeImageForCurrentFrame):
 121 (WebCore::BitmapImage::haveFrameAtIndex): Deleted.
 122 (WebCore::BitmapImage::frameAtIndex): Deleted.
 123 * platform/graphics/BitmapImage.h:
 124 (WebCore::FrameData::FrameData): Deleted.
 125 * platform/graphics/Icon.h:
 126 * platform/graphics/ImageSource.cpp:
 127 (WebCore::ImageSource::createFrameImageAtIndex):
 128 (WebCore::ImageSource::createFrameAtIndex): Deleted.
 129 * platform/graphics/ImageSource.h:
 130 * platform/graphics/NativeImagePtr.h:
 131 * platform/graphics/ca/GraphicsLayerCA.cpp:
 132 (WebCore::GraphicsLayerCA::setContentsToImage):
 133 * platform/graphics/cairo/BitmapImageCairo.cpp:
 134 (WebCore::BitmapImage::BitmapImage):
 135 (WebCore::BitmapImage::draw):
 136 (WebCore::BitmapImage::checkForSolidColor):
 137 (WebCore::FrameData::clear):
 138 * platform/graphics/cairo/GraphicsContext3DCairo.cpp:
 139 (WebCore::GraphicsContext3D::ImageExtractor::extractImage):
 140 * platform/graphics/cg/BitmapImageCG.cpp:
 141 (WebCore::FrameData::clear):
 142 (WebCore::BitmapImage::BitmapImage):
 143 (WebCore::BitmapImage::checkForSolidColor):
 144 (WebCore::BitmapImage::getCGImageRef):
 145 (WebCore::BitmapImage::getFirstCGImageRefOfSize):
 146 (WebCore::BitmapImage::getCGImageArray):
 147 (WebCore::BitmapImage::draw):
 148 (WebCore::BitmapImage::copyUnscaledFrameImageAtIndex):
 149 (WebCore::BitmapImage::copyUnscaledFrameAtIndex): Deleted.
 150 * platform/graphics/cg/GraphicsContext3DCG.cpp:
 151 (WebCore::GraphicsContext3D::ImageExtractor::extractImage):
 152 (WebCore::GraphicsContext3D::paintToCanvas):
 153 * platform/graphics/cg/GraphicsContextCG.cpp:
 154 (WebCore::GraphicsContext::drawPattern):
 155 * platform/graphics/cg/ImageSourceCG.cpp:
 156 (WebCore::ImageSource::createFrameImageAtIndex):
 157 (WebCore::ImageSource::createFrameAtIndex): Deleted.
 158 * platform/graphics/efl/GraphicsContext3DEfl.cpp:
 159 (WebCore::GraphicsContext3D::ImageExtractor::extractImage):
 160 * platform/graphics/ios/IconIOS.mm:
 161 (WebCore::Icon::Icon):
 162 * platform/graphics/mac/ImageMac.mm:
 163 (WebCore::BitmapImage::getTIFFRepresentation):
 164 * platform/graphics/win/ImageCGWin.cpp:
 165 (WebCore::BitmapImage::drawFrameMatchingSourceSize):
 166 * platform/graphics/win/ImageCairoWin.cpp:
 167 (WebCore::BitmapImage::drawFrameMatchingSourceSize):
 168
11692016-03-12 Zalan Bujtas <zalan@apple.com>
2170
3171 [Forms: focus] focus rings around text fields do not follow contour (border-radius)

Source/WebCore/PlatformAppleWin.cmake

@@list(APPEND WebCore_SOURCES
7171 platform/graphics/cg/ImageBufferCG.cpp
7272 platform/graphics/cg/ImageBufferDataCG.cpp
7373 platform/graphics/cg/ImageCG.cpp
 74 platform/graphics/cg/ImageDecoder.cpp
7475 platform/graphics/cg/ImageSourceCG.cpp
7576 platform/graphics/cg/ImageSourceCGWin.cpp
7677 platform/graphics/cg/IntPointCG.cpp

Source/WebCore/PlatformMac.cmake

@@list(APPEND WebCore_SOURCES
400400 platform/graphics/cg/ImageBufferCG.cpp
401401 platform/graphics/cg/ImageBufferDataCG.cpp
402402 platform/graphics/cg/ImageCG.cpp
 403 platform/graphics/cg/ImageDecoder.cpp
403404 platform/graphics/cg/ImageSourceCG.cpp
404405 platform/graphics/cg/ImageSourceCGMac.mm
405406 platform/graphics/cg/IntPointCG.cpp

Source/WebCore/WebCore.xcodeproj/project.pbxproj

22912291 53EF766C16531994004CBE49 /* SettingsMacros.h in Copy Generated Headers */ = {isa = PBXBuildFile; fileRef = 53EF766A16530A61004CBE49 /* SettingsMacros.h */; };
22922292 550A0BC9085F6039007353D6 /* QualifiedName.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 550A0BC7085F6039007353D6 /* QualifiedName.cpp */; };
22932293 550A0BCA085F6039007353D6 /* QualifiedName.h in Headers */ = {isa = PBXBuildFile; fileRef = 550A0BC8085F6039007353D6 /* QualifiedName.h */; settings = {ATTRIBUTES = (Private, ); }; };
 2294 559BB8791C964658002413CD /* ImageDecoder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 559BB8771C964658002413CD /* ImageDecoder.cpp */; };
 2295 559BB87A1C964658002413CD /* ImageDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 559BB8781C964658002413CD /* ImageDecoder.h */; };
22942296 572A7F211C6E5719009C6149 /* SimulatedClick.h in Headers */ = {isa = PBXBuildFile; fileRef = 572A7F201C6E5719009C6149 /* SimulatedClick.h */; };
22952297 572A7F231C6E5A66009C6149 /* SimulatedClick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 572A7F221C6E5A66009C6149 /* SimulatedClick.cpp */; };
22962298 580371611A66F00A00BAF519 /* ClipRect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5803715F1A66F00A00BAF519 /* ClipRect.cpp */; };

98759877 53EF766A16530A61004CBE49 /* SettingsMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsMacros.h; sourceTree = "<group>"; };
98769878 550A0BC7085F6039007353D6 /* QualifiedName.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = QualifiedName.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
98779879 550A0BC8085F6039007353D6 /* QualifiedName.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = QualifiedName.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
 9880 559BB8771C964658002413CD /* ImageDecoder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageDecoder.cpp; sourceTree = "<group>"; };
 9881 559BB8781C964658002413CD /* ImageDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageDecoder.h; sourceTree = "<group>"; };
98789882 55D408F71A7C631800C78450 /* SVGImageClients.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGImageClients.h; sourceTree = "<group>"; };
98799883 572A7F201C6E5719009C6149 /* SimulatedClick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimulatedClick.h; sourceTree = "<group>"; };
98809884 572A7F221C6E5A66009C6149 /* SimulatedClick.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SimulatedClick.cpp; sourceTree = "<group>"; };

2183321837 2292B27B1356669400CF11EF /* ImageBufferDataCG.cpp */,
2183421838 22BD9F80135364FE009BD102 /* ImageBufferDataCG.h */,
2183521839 B27535300B053814002CE64F /* ImageCG.cpp */,
 21840 559BB8771C964658002413CD /* ImageDecoder.cpp */,
 21841 559BB8781C964658002413CD /* ImageDecoder.h */,
2183621842 B27535310B053814002CE64F /* ImageSourceCG.cpp */,
2183721843 4B3480920EEF50D400AC1B41 /* ImageSourceCG.h */,
2183821844 4B3480910EEF50D400AC1B41 /* ImageSourceCGMac.mm */,

2681226818 FDA15ECE12B03F61003A583A /* JSScriptProcessorNode.h in Headers */,
2681326819 9FA37EFB1172FDA600C4CD55 /* JSScriptProfile.h in Headers */,
2681426820 9FA37EFD1172FDA600C4CD55 /* JSScriptProfileNode.h in Headers */,
 26821 559BB87A1C964658002413CD /* ImageDecoder.h in Headers */,
2681526822 CED06AD11C77754800FDFAF1 /* JSSecurityPolicyViolationEvent.h in Headers */,
2681626823 9BDA64D81B975CF2009C4387 /* JSShadowRoot.h in Headers */,
2681726824 CD9DE17B17AAC75B00EA386D /* JSSourceBuffer.h in Headers */,

2920329210 B27535660B053814002CE64F /* Color.cpp in Sources */,
2920429211 0FCF33240F2B9715004B6795 /* ColorCG.cpp in Sources */,
2920529212 1ABA76C911D20E47004C201C /* ColorData.cpp in Sources */,
 29213 559BB8791C964658002413CD /* ImageDecoder.cpp in Sources */,
2920629214 BC29935D17A1DD5800BCE880 /* ColorInputType.cpp in Sources */,
2920729215 B27535770B053814002CE64F /* ColorMac.mm in Sources */,
2920829216 43EDD67E1B485DBF00640E75 /* CombinedFiltersAlphabet.cpp in Sources */,

Source/WebCore/loader/cache/CachedImage.cpp

@@LayoutSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float
278278 if (renderer && is<BitmapImage>(*m_image)) {
279279 ImageOrientationDescription orientationDescription(renderer->shouldRespectImageOrientation(), renderer->style().imageOrientation());
280280 if (orientationDescription.respectImageOrientation() == RespectImageOrientation)
281  imageSize = LayoutSize(downcast<BitmapImage>(*m_image).sizeRespectingOrientation(orientationDescription));
 281 imageSize = LayoutSize(downcast<BitmapImage>(*m_image).sizeRespectingOrientation());
282282 }
283283#else
284284 if (is<BitmapImage>(*m_image) && (renderer && renderer->shouldRespectImageOrientation() == RespectImageOrientation))

Source/WebCore/loader/cache/MemoryCache.cpp

@@bool MemoryCache::addImageToCache(NativeImagePtr image, const URL& url, const St
225225
226226 std::unique_ptr<CachedImage> cachedImage = std::make_unique<CachedImage>(url, bitmapImage.get(), CachedImage::ManuallyCached, sessionID);
227227
228  // Actual release of the CGImageRef is done in BitmapImage.
229  CFRetain(image);
230228 cachedImage->addClient(&dummyCachedImageClient());
231229 cachedImage->setDecodedSize(bitmapImage->decodedSize());
232230#if ENABLE(CACHE_PARTITIONING)

Source/WebCore/platform/graphics/BitmapImage.cpp

@@namespace WebCore {
4747
4848BitmapImage::BitmapImage(ImageObserver* observer)
4949 : Image(observer)
50  , m_minimumSubsamplingLevel(0)
51  , m_imageOrientation(OriginTopLeft)
52  , m_shouldRespectImageOrientation(false)
5350 , m_currentFrame(0)
5451 , m_repetitionCount(cAnimationNone)
5552 , m_repetitionCountStatus(Unknown)

@@void BitmapImage::startTimer(double delay)
9693 m_frameTimer->startOneShot(delay);
9794}
9895
99 bool BitmapImage::haveFrameAtIndex(size_t index)
 96bool BitmapImage::haveFrameImageAtIndex(size_t index)
10097{
10198 if (index >= frameCount())
10299 return false;

@@bool BitmapImage::haveFrameAtIndex(size_t index)
104101 if (index >= m_frames.size())
105102 return false;
106103
107  return m_frames[index].m_frame;
 104 return m_frames[index].m_image;
108105}
109106
110107bool BitmapImage::hasSingleSecurityOrigin() const

@@void BitmapImage::cacheFrame(size_t index, SubsamplingLevel subsamplingLevel, Im
184181 m_frames.grow(numFrames);
185182
186183 if (frameCaching == CacheMetadataAndFrame) {
187  m_frames[index].m_frame = m_source.createFrameAtIndex(index, subsamplingLevel);
 184 m_frames[index].m_image = m_source.createFrameImageAtIndex(index, subsamplingLevel);
188185 m_frames[index].m_subsamplingLevel = subsamplingLevel;
189  if (numFrames == 1 && m_frames[index].m_frame)
 186 if (numFrames == 1 && m_frames[index].m_image)
190187 checkForSolidColor();
191188 }
192189

@@void BitmapImage::cacheFrame(size_t index, SubsamplingLevel subsamplingLevel, Im
204201 if (!subsamplingLevel && frameSize != m_size)
205202 m_hasUniformFrameSize = false;
206203
207  if (m_frames[index].m_frame) {
 204 if (m_frames[index].m_image) {
208205 int deltaBytes = safeCast<int>(m_frames[index].m_frameBytes);
209206 m_decodedSize += deltaBytes;
210207 // The fully-decoded frame will subsume the partially decoded data used

@@void BitmapImage::didDecodeProperties() const
236233 imageObserver()->decodedSizeChanged(this, deltaBytes);
237234}
238235
239 void BitmapImage::updateSize(ImageOrientationDescription description) const
 236void BitmapImage::updateSize() const
240237{
241238 if (!m_sizeAvailable || m_haveSize)
242239 return;
243240
244  m_size = m_source.size(description);
245  m_sizeRespectingOrientation = m_source.size(ImageOrientationDescription(RespectImageOrientation, description.imageOrientation()));
246 
247  m_imageOrientation = static_cast<unsigned>(description.imageOrientation());
248  m_shouldRespectImageOrientation = static_cast<unsigned>(description.respectImageOrientation());
 241 m_size = m_source.size();
 242 m_sizeRespectingOrientation = m_source.sizeRespectingOrientation();
249243
250244 m_haveSize = true;
251245

@@FloatSize BitmapImage::size() const
259253 return m_size;
260254}
261255
262 IntSize BitmapImage::sizeRespectingOrientation(ImageOrientationDescription description) const
 256IntSize BitmapImage::sizeRespectingOrientation() const
263257{
264  updateSize(description);
 258 updateSize();
265259 return m_sizeRespectingOrientation;
266260}
267261

@@bool BitmapImage::ensureFrameIsCached(size_t index, ImageFrameCaching frameCachi
379373 return false;
380374
381375 if (index >= m_frames.size()
382  || (frameCaching == CacheMetadataAndFrame && !m_frames[index].m_frame)
 376 || (frameCaching == CacheMetadataAndFrame && !m_frames[index].m_image)
383377 || (frameCaching == CacheMetadataOnly && !m_frames[index].m_haveMetadata))
384378 cacheFrame(index, 0, frameCaching);
385379
386380 return true;
387381}
388382
389 PassNativeImagePtr BitmapImage::frameAtIndex(size_t index, float presentationScaleHint)
 383PassNativeImagePtr BitmapImage::frameImageAtIndex(size_t index, float presentationScaleHint)
390384{
391385 if (index >= frameCount())
392386 return nullptr;
393387
394  SubsamplingLevel subsamplingLevel = std::min(m_source.subsamplingLevelForScale(presentationScaleHint), m_minimumSubsamplingLevel);
 388 SubsamplingLevel subsamplingLevel = m_source.subsamplingLevelForScale(presentationScaleHint, m_maximumSubsamplingLevel);
395389
396390 // We may have cached a frame with a higher subsampling level, in which case we need to
397391 // re-decode with a lower level.
398  if (index < m_frames.size() && m_frames[index].m_frame && subsamplingLevel < m_frames[index].m_subsamplingLevel) {
 392 if (index < m_frames.size() && m_frames[index].m_image && subsamplingLevel < m_frames[index].m_subsamplingLevel) {
399393 // If the image is already cached, but at too small a size, re-decode a larger version.
400394 int sizeChange = -m_frames[index].m_frameBytes;
401395 m_frames[index].clear(true);

@@PassNativeImagePtr BitmapImage::frameAtIndex(size_t index, float presentationSca
406400 }
407401
408402 // If we haven't fetched a frame yet, do so.
409  if (index >= m_frames.size() || !m_frames[index].m_frame)
 403 if (index >= m_frames.size() || !m_frames[index].m_image)
410404 cacheFrame(index, subsamplingLevel, CacheMetadataAndFrame);
411405
412  return m_frames[index].m_frame;
 406 return m_frames[index].m_image;
413407}
414408
415409bool BitmapImage::frameIsCompleteAtIndex(size_t index)

@@float BitmapImage::frameDurationAtIndex(size_t index)
430424
431425PassNativeImagePtr BitmapImage::nativeImageForCurrentFrame()
432426{
433  return frameAtIndex(currentFrame());
 427 return frameImageAtIndex(currentFrame());
434428}
435429
436430bool BitmapImage::frameHasAlphaAtIndex(size_t index)

@@void BitmapImage::dump(TextStream& ts) const
714708 ts.dumpProperty("allow-subsampling", allowSubsampling());
715709 if (m_isSolidColor)
716710 ts.dumpProperty("solid-color", m_isSolidColor);
717 
718  if (m_imageOrientation != OriginTopLeft)
719  ts.dumpProperty("orientation", m_imageOrientation);
720711}
721712
722713}

Source/WebCore/platform/graphics/BitmapImage.h

@@typedef struct HBITMAP__ *HBITMAP;
4747#endif
4848
4949namespace WebCore {
50  struct FrameData;
51 }
52 
53 namespace WTF {
54  template<> struct VectorTraits<WebCore::FrameData> : public SimpleClassVectorTraits {
55  static const bool canInitializeWithMemset = false; // Not all FrameData members initialize to 0.
56  };
57 }
58 
59 namespace WebCore {
6050
6151class Timer;
6252

@@class Timer;
6555// ================================================
6656
6757struct FrameData {
68  WTF_MAKE_NONCOPYABLE(FrameData);
6958public:
7059 FrameData()
71  : m_frame(0)
72  , m_orientation(DefaultImageOrientation)
73  , m_subsamplingLevel(0)
74  , m_duration(0)
75  , m_haveMetadata(false)
76  , m_isComplete(false)
77  , m_hasAlpha(true)
78  , m_frameBytes(0)
7960 {
8061 }
8162

@@public:
8465 clear(true);
8566 }
8667
87  // Clear the cached image data on the frame, and (optionally) the metadata.
88  // Returns whether there was cached image data to clear.
8968 bool clear(bool clearMetadata);
90 
91  NativeImagePtr m_frame;
92  ImageOrientation m_orientation;
93  SubsamplingLevel m_subsamplingLevel;
94  float m_duration;
95  bool m_haveMetadata : 1;
96  bool m_isComplete : 1;
97  bool m_hasAlpha : 1;
98  unsigned m_frameBytes;
 69 Optional<Color> solidColor() const;
 70
 71 NativeImagePtr m_image;
 72 ImageOrientation m_orientation { DefaultImageOrientation };
 73 SubsamplingLevel m_subsamplingLevel { 0 };
 74 float m_duration { 0 };
 75 union {
 76 struct {
 77 bool m_haveMetadata : 1;
 78 bool m_isComplete : 1;
 79 bool m_hasAlpha : 1;
 80 };
 81 uint8_t m_flags[sizeof(bool)] { 0 };
 82 };
 83 unsigned m_frameBytes { 0 };
9984};
10085
10186// =================================================

@@public:
125110
126111 // FloatSize due to override.
127112 FloatSize size() const override;
128  IntSize sizeRespectingOrientation(ImageOrientationDescription = ImageOrientationDescription()) const;
 113 IntSize sizeRespectingOrientation() const;
129114
130115 bool getHotSpot(IntPoint&) const override;
131116

@@public:
189174private:
190175 bool isBitmapImage() const override { return true; }
191176
192  void updateSize(ImageOrientationDescription = ImageOrientationDescription()) const;
 177 void updateSize() const;
193178 void determineMinimumSubsamplingLevel() const;
194179
195180protected:

@@protected:
214199
215200 size_t frameCount();
216201
217  PassNativeImagePtr frameAtIndex(size_t, float presentationScaleHint = 1);
218  PassNativeImagePtr copyUnscaledFrameAtIndex(size_t);
 202 PassNativeImagePtr frameImageAtIndex(size_t, float presentationScaleHint = 1);
 203 PassNativeImagePtr copyUnscaledFrameImageAtIndex(size_t);
219204
220  bool haveFrameAtIndex(size_t);
 205 bool haveFrameImageAtIndex(size_t);
221206
222207 bool frameIsCompleteAtIndex(size_t);
223208 float frameDurationAtIndex(size_t);

@@private:
297282 mutable IntSize m_size; // The size to use for the overall image (will just be the size of the first image).
298283 mutable IntSize m_sizeRespectingOrientation;
299284
300  mutable SubsamplingLevel m_minimumSubsamplingLevel;
301 
302  mutable unsigned m_imageOrientation : 4; // ImageOrientationEnum
303  mutable unsigned m_shouldRespectImageOrientation : 1; // RespectImageOrientationEnum
 285 mutable SubsamplingLevel m_maximumSubsamplingLevel { 0 };
304286
305287 size_t m_currentFrame; // The index of the current frame of animation.
306288 Vector<FrameData, 1> m_frames; // An array of the cached frames of the animation. We have to ref frames to pin them in the cache.

Source/WebCore/platform/graphics/Icon.h

@@public:
6868
6969private:
7070#if PLATFORM(IOS)
71  Icon(CGImageRef);
72  RetainPtr<CGImageRef> m_cgImage;
 71 Icon(NativeImagePtr);
 72 NativeImagePtr m_cgImage;
7373#elif PLATFORM(MAC)
7474 Icon(NSImage*);
7575 RetainPtr<NSImage> m_nsImage;

Source/WebCore/platform/graphics/ImageSource.cpp

@@void ImageSource::clear(bool destroyAll, size_t clearBeforeFrame, SharedBuffer*
6868 setData(data, allDataReceived);
6969}
7070
71 bool ImageSource::initialized() const
72 {
73  return m_decoder;
74 }
75 
7671void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
7772{
7873 // Make the decoder by sniffing the bytes.

@@String ImageSource::filenameExtension() const
9691 return m_decoder ? m_decoder->filenameExtension() : String();
9792}
9893
99 SubsamplingLevel ImageSource::subsamplingLevelForScale(float) const
 94SubsamplingLevel ImageSource::subsamplingLevelForScale(float, SubsamplingLevel) const
10095{
10196 return 0;
10297}

@@bool ImageSource::isSizeAvailable()
111106 return m_decoder && m_decoder->isSizeAvailable();
112107}
113108
114 IntSize ImageSource::size(ImageOrientationDescription description) const
 109IntSize ImageSource::size() const
115110{
116  return frameSizeAtIndex(0, 0, description);
 111 return frameSizeAtIndex(0, 0);
 112}
 113
 114IntSize ImageSource::sizeRespectingOrientation() const
 115{
 116 return frameSizeAtIndex(0, 0, RespectImageOrientation);
117117}
118118
119 IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel, ImageOrientationDescription description) const
 119IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel, RespectImageOrientationEnum shouldRespectImageOrientation) const
120120{
121  if (!m_decoder)
 121 if (!initialized())
122122 return IntSize();
123123
124124 IntSize size = m_decoder->frameSizeAtIndex(index);
125  if ((description.respectImageOrientation() == RespectImageOrientation) && m_decoder->orientation().usesWidthAsHeight())
126  return IntSize(size.height(), size.width());
 125 ImageOrientation orientation = m_decoder->orientation();
127126
128  return size;
 127 return shouldRespectImageOrientation == RespectImageOrientation && orientation.usesWidthAsHeight() ? size.transposedSize() : size;
129128}
130129
131130bool ImageSource::getHotSpot(IntPoint& hotSpot) const

@@size_t ImageSource::frameCount() const
148147 return m_decoder ? m_decoder->frameCount() : 0;
149148}
150149
151 PassNativeImagePtr ImageSource::createFrameAtIndex(size_t index, SubsamplingLevel)
 150PassNativeImagePtr ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLevel)
152151{
153152 if (!m_decoder)
154153 return 0;

Source/WebCore/platform/graphics/ImageSource.h

@@class IntPoint;
4646class IntSize;
4747class SharedBuffer;
4848
49 #if USE(CG)
50 typedef CGImageSourceRef NativeImageDecoderPtr;
51 #else
5249class ImageDecoder;
5350typedef ImageDecoder* NativeImageDecoderPtr;
54 #endif
55 
56 #if USE(CG)
57 #define NativeImageDecoder ImageDecoder
58 #else
5951typedef ImageDecoder NativeImageDecoder;
60 #endif
6152
6253// Right now GIFs are the only recognized image format that supports animation.
6354// The animation system and the constants below are designed with this in mind.

@@public:
110101 // decoded frames.
111102 //
112103 // Callers should not call clear(false, n) and subsequently call
113  // createFrameAtIndex(m) with m < n, unless they first call clear(true).
 104 // createFrameImageAtIndex(m) with m < n, unless they first call clear(true).
114105 // This ensures that stateful ImageSources/decoders will work properly.
115106 //
116107 // The |data| and |allDataReceived| parameters should be supplied by callers

@@public:
122113 SharedBuffer* data = NULL,
123114 bool allDataReceived = false);
124115
125  bool initialized() const;
 116 bool initialized() const { return m_decoder; }
126117
127118 void setData(SharedBuffer* data, bool allDataReceived);
128119 String filenameExtension() const;
129120
130  SubsamplingLevel subsamplingLevelForScale(float) const;
 121 SubsamplingLevel subsamplingLevelForScale(float, SubsamplingLevel) const;
131122 bool allowSubsamplingOfFrameAtIndex(size_t) const;
132123
133124 bool isSizeAvailable();
134125 // Always original size, without subsampling.
135  IntSize size(ImageOrientationDescription = ImageOrientationDescription()) const;
 126 IntSize size() const;
 127 IntSize sizeRespectingOrientation() const;
136128 // Size of optionally subsampled frame.
137  IntSize frameSizeAtIndex(size_t, SubsamplingLevel = 0, ImageOrientationDescription = ImageOrientationDescription()) const;
 129 IntSize frameSizeAtIndex(size_t, SubsamplingLevel = 0, RespectImageOrientationEnum = DoNotRespectImageOrientation) const;
138130
139131 bool getHotSpot(IntPoint&) const;
140132

@@public:
146138
147139 // Callers should not call this after calling clear() with a higher index;
148140 // see comments on clear() above.
149  PassNativeImagePtr createFrameAtIndex(size_t, SubsamplingLevel = 0);
 141 PassNativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel = 0);
150142
151143 float frameDurationAtIndex(size_t);
152144 bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.

@@public:
163155#endif
164156
165157private:
166  NativeImageDecoderPtr m_decoder;
 158 void ensureDecoderIsCreated(SharedBuffer*);
 159
 160 NativeImageDecoderPtr m_decoder { nullptr };
167161
168162#if !USE(CG)
169163 AlphaOption m_alphaOption;

Source/WebCore/platform/graphics/NativeImagePtr.h

2929#define NativeImagePtr_h
3030
3131#if USE(CG)
 32#include <wtf/RetainPtr.h>
3233typedef struct CGImage* CGImageRef;
3334#elif USE(CAIRO)
3435#include "RefPtrCairo.h"

@@namespace WebCore {
4142// FIXME: NativeImagePtr and PassNativeImagePtr should be smart
4243// pointers (see SVGImage::nativeImageForCurrentFrame()).
4344#if USE(CG)
44 typedef CGImageRef NativeImagePtr;
 45typedef RetainPtr<CGImageRef> NativeImagePtr;
4546#elif USE(CAIRO)
4647typedef RefPtr<cairo_surface_t> NativeImagePtr;
4748typedef PassRefPtr<cairo_surface_t> PassNativeImagePtr;

Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

@@void GraphicsLayerCA::setContentsToSolidColor(const Color& color)
10371037void GraphicsLayerCA::setContentsToImage(Image* image)
10381038{
10391039 if (image) {
1040  CGImageRef newImage = image->nativeImageForCurrentFrame();
 1040 CGImageRef newImage = image->nativeImageForCurrentFrame().get();
10411041 if (!newImage)
10421042 return;
10431043

Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp

@@namespace WebCore {
4141BitmapImage::BitmapImage(PassRefPtr<cairo_surface_t> nativeImage, ImageObserver* observer)
4242 : Image(observer)
4343 , m_size(cairoSurfaceSize(nativeImage.get()))
44  , m_minimumSubsamplingLevel(0)
4544 , m_currentFrame(0)
4645 , m_repetitionCount(cAnimationNone)
4746 , m_repetitionCountStatus(Unknown)

@@BitmapImage::BitmapImage(PassRefPtr<cairo_surface_t> nativeImage, ImageObserver*
5857{
5958 m_frames.grow(1);
6059 m_frames[0].m_hasAlpha = cairo_surface_get_content(nativeImage.get()) != CAIRO_CONTENT_COLOR;
61  m_frames[0].m_frame = nativeImage;
 60 m_frames[0].m_image = nativeImage;
6261 m_frames[0].m_haveMetadata = true;
6362
6463 checkForSolidColor();

@@void BitmapImage::draw(GraphicsContext& context, const FloatRect& dst, const Flo
7271
7372 startAnimation();
7473
75  RefPtr<cairo_surface_t> surface = frameAtIndex(m_currentFrame);
 74 RefPtr<cairo_surface_t> surface = frameImageAtIndex(m_currentFrame);
7675 if (!surface) // If it's too early we won't have an image yet.
7776 return;
7877

@@void BitmapImage::draw(GraphicsContext& context, const FloatRect& dst, const Flo
124123
125124void BitmapImage::determineMinimumSubsamplingLevel() const
126125{
127  m_minimumSubsamplingLevel = 0;
 126 m_maximumSubsamplingLevel = 0;
128127}
129128
130129void BitmapImage::checkForSolidColor()

@@void BitmapImage::checkForSolidColor()
135134 if (frameCount() > 1)
136135 return;
137136
138  RefPtr<cairo_surface_t> surface = frameAtIndex(m_currentFrame);
 137 RefPtr<cairo_surface_t> surface = frameImageAtIndex(m_currentFrame);
139138 if (!surface) // If it's too early we won't have an image yet.
140139 return;
141140

@@bool FrameData::clear(bool clearMetadata)
158157 if (clearMetadata)
159158 m_haveMetadata = false;
160159
161  if (m_frame) {
162  m_frame = nullptr;
 160 if (m_image) {
 161 m_image = nullptr;
163162 return true;
164163 }
165164 return false;

Source/WebCore/platform/graphics/cairo/GraphicsContext3DCairo.cpp

@@bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool
215215 decoder.setData(m_image->data(), true);
216216 if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
217217 return false;
218  m_imageSurface = decoder.createFrameAtIndex(0);
 218 m_imageSurface = decoder.createFrameImageAtIndex(0);
219219 } else {
220220 m_imageSurface = m_image->nativeImageForCurrentFrame();
221221 // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel,

Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp

@@bool FrameData::clear(bool clearMetadata)
5858 m_orientation = DefaultImageOrientation;
5959 m_subsamplingLevel = 0;
6060
61  if (m_frame) {
 61 if (m_image) {
6262#if CACHE_SUBIMAGES
63  subimageCache().clearImage(m_frame);
 63 subimageCache().clearImage(m_image.get());
6464#endif
65  CGImageRelease(m_frame);
66  m_frame = 0;
 65 m_image = nullptr;
6766 return true;
6867 }
6968 return false;
7069}
7170
72 BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer)
 71BitmapImage::BitmapImage(NativeImagePtr image, ImageObserver* observer)
7372 : Image(observer)
74  , m_minimumSubsamplingLevel(0)
75  , m_imageOrientation(OriginTopLeft)
76  , m_shouldRespectImageOrientation(false)
7773 , m_currentFrame(0)
7874 , m_repetitionCount(cAnimationNone)
7975 , m_repetitionCountStatus(Unknown)

@@BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer)
8985 , m_sizeAvailable(true)
9086 , m_haveFrameCount(true)
9187{
92  CGFloat width = CGImageGetWidth(cgImage);
93  CGFloat height = CGImageGetHeight(cgImage);
 88 CGFloat width = CGImageGetWidth(image.get());
 89 CGFloat height = CGImageGetHeight(image.get());
9490 m_decodedSize = width * height * 4;
9591 m_size = IntSize(width, height);
9692

@@BitmapImage::BitmapImage(CGImageRef cgImage, ImageObserver* observer)
9995 m_sizeRespectingOrientation = m_size;
10096
10197 m_frames.grow(1);
102  m_frames[0].m_frame = CGImageRetain(cgImage);
 98 m_frames[0].m_image = image;
10399 m_frames[0].m_hasAlpha = true;
104100 m_frames[0].m_haveMetadata = true;
105101

@@void BitmapImage::determineMinimumSubsamplingLevel() const
125121 break;
126122 }
127123
128  m_minimumSubsamplingLevel = currentLevel;
 124 m_maximumSubsamplingLevel = currentLevel;
129125}
130126
131127void BitmapImage::checkForSolidColor()

@@void BitmapImage::checkForSolidColor()
136132 if (frameCount() > 1)
137133 return;
138134
139  if (!haveFrameAtIndex(0)) {
 135 if (!haveFrameImageAtIndex(0)) {
140136 IntSize size = m_source.frameSizeAtIndex(0, 0);
141137 if (size.width() != 1 || size.height() != 1)
142138 return;

@@void BitmapImage::checkForSolidColor()
147143
148144 CGImageRef image = nullptr;
149145 if (m_frames.size())
150  image = m_frames[0].m_frame;
 146 image = m_frames[0].m_image.get();
151147
152148 if (!image)
153149 return;

@@void BitmapImage::checkForSolidColor()
173169
174170CGImageRef BitmapImage::getCGImageRef()
175171{
176  return frameAtIndex(0);
 172 return frameImageAtIndex(0).get();
177173}
178174
179175CGImageRef BitmapImage::getFirstCGImageRefOfSize(const IntSize& size)
180176{
181177 size_t count = frameCount();
182178 for (size_t i = 0; i < count; ++i) {
183  CGImageRef cgImage = frameAtIndex(i);
184  if (cgImage && IntSize(CGImageGetWidth(cgImage), CGImageGetHeight(cgImage)) == size)
185  return cgImage;
 179 PassNativeImagePtr image = frameImageAtIndex(i);
 180 if (image && IntSize(CGImageGetWidth(image.get()), CGImageGetHeight(image.get())) == size)
 181 return image.get();
186182 }
187183
188184 // Fallback to the default CGImageRef if we can't find the right size

@@RetainPtr<CFArrayRef> BitmapImage::getCGImageArray()
197193
198194 CFMutableArrayRef array = CFArrayCreateMutable(NULL, count, &kCFTypeArrayCallBacks);
199195 for (size_t i = 0; i < count; ++i) {
200  if (CGImageRef currFrame = frameAtIndex(i))
201  CFArrayAppendValue(array, currFrame);
 196 if (NativeImagePtr currFrame = frameImageAtIndex(i))
 197 CFArrayAppendValue(array, currFrame.get());
202198 }
203199 return adoptCF(array);
204200}

@@void BitmapImage::draw(GraphicsContext& ctxt, const FloatRect& destRect, const F
211207 startAnimation();
212208#endif
213209
214  RetainPtr<CGImageRef> image;
 210 NativeImagePtr image;
215211 // Never use subsampled images for drawing into PDF contexts.
216212 if (wkCGContextIsPDFContext(ctxt.platformContext()))
217  image = adoptCF(copyUnscaledFrameAtIndex(m_currentFrame));
 213 image = copyUnscaledFrameImageAtIndex(m_currentFrame);
218214 else {
219215 CGRect transformedDestinationRect = CGRectApplyAffineTransform(destRect, CGContextGetCTM(ctxt.platformContext()));
220216 float subsamplingScale = std::min<float>(1, std::max(transformedDestinationRect.size.width / srcRect.width(), transformedDestinationRect.size.height / srcRect.height()));
221217
222  image = frameAtIndex(m_currentFrame, subsamplingScale);
 218 image = frameImageAtIndex(m_currentFrame, subsamplingScale);
223219 }
224220
225221 if (!image) // If it's too early we won't have an image yet.

@@void BitmapImage::draw(GraphicsContext& ctxt, const FloatRect& destRect, const F
251247 imageObserver()->didDraw(this);
252248}
253249
254 PassNativeImagePtr BitmapImage::copyUnscaledFrameAtIndex(size_t index)
 250PassNativeImagePtr BitmapImage::copyUnscaledFrameImageAtIndex(size_t index)
255251{
256252 if (index >= frameCount())
257253 return nullptr;
258254
259  if (index >= m_frames.size() || !m_frames[index].m_frame)
 255 if (index >= m_frames.size() || !m_frames[index].m_image)
260256 cacheFrame(index, 0);
261257
262258 if (!m_frames[index].m_subsamplingLevel)
263  return CGImageRetain(m_frames[index].m_frame);
 259 return m_frames[index].m_image;
264260
265  return m_source.createFrameAtIndex(index);
 261 return m_source.createFrameImageAtIndex(index);
266262}
267263
268264}

Source/WebCore/platform/graphics/cg/GraphicsContext3DCG.cpp

@@bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool
333333 if (!decoder.frameCount())
334334 return false;
335335
336  m_decodedImage = adoptCF(decoder.createFrameAtIndex(0));
 336 m_decodedImage = decoder.createFrameImageAtIndex(0);
337337 m_cgImage = m_decodedImage.get();
338338 } else
339  m_cgImage = m_image->nativeImageForCurrentFrame();
 339 m_cgImage = m_image->nativeImageForCurrentFrame().get();
340340 if (!m_cgImage)
341341 return false;
342342

@@void GraphicsContext3D::paintToCanvas(const unsigned char* imagePixels, int imag
536536 context.scale(FloatSize(1, -1));
537537 context.translate(0, -imageHeight);
538538 context.setImageInterpolationQuality(InterpolationNone);
539  context.drawNativeImage(cgImage.get(), imageSize, canvasRect, FloatRect(FloatPoint(), imageSize), CompositeCopy);
 539 context.drawNativeImage(cgImage, imageSize, canvasRect, FloatRect(FloatPoint(), imageSize), CompositeCopy);
540540}
541541
542542} // namespace WebCore

Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp

@@void GraphicsContext::drawPattern(Image& image, const FloatRect& tileRect, const
311311 float adjustedX = phase.x() - destRect.x() + tileRect.x() * narrowPrecisionToFloat(patternTransform.a()); // We translated the context so that destRect.x() is the origin, so subtract it out.
312312 float adjustedY = destRect.height() - (phase.y() - destRect.y() + tileRect.y() * narrowPrecisionToFloat(patternTransform.d()) + scaledTileHeight);
313313
314  CGImageRef tileImage = image.nativeImageForCurrentFrame();
315  float h = CGImageGetHeight(tileImage);
 314 RetainPtr<CGImageRef> tileImage = image.nativeImageForCurrentFrame();
 315 float h = CGImageGetHeight(tileImage.get());
316316
317317 RetainPtr<CGImageRef> subImage;
318318#if PLATFORM(IOS)

@@void GraphicsContext::drawPattern(Image& image, const FloatRect& tileRect, const
326326 // Copying a sub-image out of a partially-decoded image stops the decoding of the original image. It should never happen
327327 // because sub-images are only used for border-image, which only renders when the image is fully decoded.
328328 ASSERT(h == image.height());
329  subImage = adoptCF(CGImageCreateWithImageInRect(tileImage, tileRect));
 329 subImage = adoptCF(CGImageCreateWithImageInRect(tileImage.get(), tileRect));
330330 }
331331
332332 // If we need to paint gaps between tiles because we have a partially loaded image or non-zero spacing,
333333 // fall back to the less efficient CGPattern-based mechanism.
334334 float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a());
335  float w = CGImageGetWidth(tileImage);
 335 float w = CGImageGetWidth(tileImage.get());
336336 if (w == image.size().width() && h == image.size().height() && !spacing.width() && !spacing.height()) {
337337 // FIXME: CG seems to snap the images to integral sizes. When we care (e.g. with border-image-repeat: round),
338338 // we should tile all but the last, and stetch the last image to fit.

Source/WebCore/platform/graphics/cg/ImageDecoder.cpp

 1/*
 2 * Copyright (C) 2016 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#include "config.h"
 27#include "ImageDecoder.h"
 28
 29#if USE(CG)
 30
 31#include "CoreGraphicsSPI.h"
 32#include "ImageOrientation.h"
 33#include "IntPoint.h"
 34#include "IntSize.h"
 35#include "MIMETypeRegistry.h"
 36#include "SharedBuffer.h"
 37#include <wtf/NeverDestroyed.h>
 38
 39#if !PLATFORM(IOS)
 40#include <ApplicationServices/ApplicationServices.h>
 41#else
 42#include <ImageIO/ImageIO.h>
 43#include <wtf/RetainPtr.h>
 44#endif
 45
 46#if USE(APPLE_INTERNAL_SDK)
 47#import <ImageIO/CGImageSourcePrivate.h>
 48#else
 49const CFStringRef kCGImageSourceSubsampleFactor = CFSTR("kCGImageSourceSubsampleFactor");
 50const CFStringRef kCGImageSourceShouldCacheImmediately = CFSTR("kCGImageSourceShouldCacheImmediately");
 51#endif
 52
 53namespace WebCore {
 54
 55const CFStringRef WebCoreCGImagePropertyAPNGUnclampedDelayTime = CFSTR("UnclampedDelayTime");
 56const CFStringRef WebCoreCGImagePropertyAPNGDelayTime = CFSTR("DelayTime");
 57const CFStringRef WebCoreCGImagePropertyAPNGLoopCount = CFSTR("LoopCount");
 58
 59const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
 60const CFStringRef kCGImageSourceSkipMetadata = CFSTR("kCGImageSourceSkipMetadata");
 61
 62static RetainPtr<CFDictionaryRef> createImageSourceOptions(SubsamplingLevel subsamplingLevel, DecodeMode decodeMode)
 63{
 64 const CFIndex basicOptions = 3;
 65 const void* keys[basicOptions + 2] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata };
 66 const void* values[basicOptions + 2] = { kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue };
 67 CFIndex numOptions = basicOptions;
 68
 69 if (subsamplingLevel > 0) {
 70 short constrainedSubsamplingLevel = std::min<short>(3, std::max<short>(0, subsamplingLevel));
 71 int subsampleInt = 1 << constrainedSubsamplingLevel; // [0..3] => [1, 2, 4, 8]
 72 RetainPtr<CFNumberRef> subsampleNumber = adoptCF(CFNumberCreate(nullptr, kCFNumberIntType, &subsampleInt));
 73
 74 keys[numOptions] = kCGImageSourceSubsampleFactor;
 75 values[numOptions++] = kCGImageSourceSubsampleFactor;
 76 }
 77
 78 if (decodeMode == DecodeMode::Immediate) {
 79 keys[numOptions] = kCGImageSourceShouldCacheImmediately;
 80 values[numOptions++] = kCFBooleanTrue;
 81 }
 82
 83 return adoptCF(CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
 84}
 85
 86static RetainPtr<CFDictionaryRef> imageSourceOptions(SubsamplingLevel subsamplingLevel = 0, DecodeMode decodeMode = DecodeMode::Lazy)
 87{
 88 if (subsamplingLevel || decodeMode == DecodeMode::Immediate)
 89 return createImageSourceOptions(subsamplingLevel, decodeMode);
 90
 91 static NeverDestroyed<RetainPtr<CFDictionaryRef>> options = createImageSourceOptions(0, DecodeMode::Lazy);
 92 return options;
 93}
 94
 95static ImageOrientation orientationFromProperties(CFDictionaryRef imageProperties)
 96{
 97 ASSERT(imageProperties);
 98 CFNumberRef orientationProperty = (CFNumberRef)CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation);
 99 if (!orientationProperty)
 100 return DefaultImageOrientation;
 101
 102 int exifValue;
 103 CFNumberGetValue(orientationProperty, kCFNumberIntType, &exifValue);
 104 return ImageOrientation::fromEXIFValue(exifValue);
 105}
 106
 107#if !PLATFORM(COCOA)
 108size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count)
 109{
 110 SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
 111 size_t sourceSize = sharedBuffer->size();
 112 if (position >= sourceSize)
 113 return 0;
 114
 115 const char* source = sharedBuffer->data() + position;
 116 size_t amount = std::min<size_t>(count, sourceSize - position);
 117 memcpy(buffer, source, amount);
 118 return amount;
 119}
 120
 121void sharedBufferRelease(void* info)
 122{
 123 SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
 124 sharedBuffer->deref();
 125}
 126#endif
 127
 128ImageDecoder::ImageDecoder()
 129{
 130 m_nativeDecoder = CGImageSourceCreateIncremental(0);
 131}
 132
 133SubsamplingLevel ImageDecoder::subsamplingLevelForScale(float scale, SubsamplingLevel maximumSubsamplingLevel)
 134{
 135 // There are four subsampling levels: 0 = 1x, 1 = 0.5x, 2 = 0.25x, 3 = 0.125x.
 136 float clampedScale = std::max<float>(0.125, std::min<float>(1, scale));
 137 SubsamplingLevel result = ceilf(log2f(1 / clampedScale));
 138 ASSERT(result >=0 && result <= 3);
 139 return std::min(result, maximumSubsamplingLevel);
 140}
 141
 142size_t ImageDecoder::bytesDecodedToDetermineProperties()
 143{
 144 // Measured by tracing malloc/calloc calls on Mac OS 10.6.6, x86_64.
 145 // A non-zero value ensures cached images with no decoded frames still enter
 146 // the live decoded resources list when the CGImageSource decodes image
 147 // properties, allowing the cache to prune the partially decoded image.
 148 // This value is likely to be inaccurate on other platforms, but the overall
 149 // behavior is unchanged.
 150 return 13088;
 151}
 152
 153String ImageDecoder::filenameExtension() const
 154{
 155 CFStringRef imageSourceType = CGImageSourceGetType(m_nativeDecoder);
 156 return WebCore::preferredExtensionForImageSourceType(imageSourceType);
 157}
 158
 159bool ImageDecoder::isSizeAvailable() const
 160{
 161 // Ragnaros yells: TOO SOON! You have awakened me TOO SOON, Executus!
 162 if (CGImageSourceGetStatus(m_nativeDecoder) < kCGImageStatusIncomplete)
 163 return false;
 164
 165 RetainPtr<CFDictionaryRef> image0Properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder, 0, imageSourceOptions().get()));
 166 if (!image0Properties)
 167 return false;
 168
 169 return CFDictionaryContainsKey(image0Properties.get(), kCGImagePropertyPixelWidth)
 170 && CFDictionaryContainsKey(image0Properties.get(), kCGImagePropertyPixelHeight);
 171}
 172
 173IntSize ImageDecoder::size() const
 174{
 175 if (m_size.isEmpty())
 176 m_size = frameSizeAtIndex(0, 0);
 177 return m_size;
 178}
 179
 180size_t ImageDecoder::frameCount() const
 181{
 182 return CGImageSourceGetCount(m_nativeDecoder);
 183}
 184
 185int ImageDecoder::repetitionCount() const
 186{
 187 RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyProperties(m_nativeDecoder, imageSourceOptions().get()));
 188 if (!properties)
 189 return cAnimationLoopOnce;
 190
 191 CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
 192 if (gifProperties) {
 193 CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFLoopCount);
 194
 195 // No property means loop once.
 196 if (!num)
 197 return cAnimationLoopOnce;
 198
 199 int loopCount;
 200 CFNumberGetValue(num, kCFNumberIntType, &loopCount);
 201
 202 // A property with value 0 means loop forever.
 203 return loopCount ? loopCount : cAnimationLoopInfinite;
 204 }
 205
 206 CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary);
 207 if (pngProperties) {
 208 CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGLoopCount);
 209 if (!num)
 210 return cAnimationLoopOnce;
 211
 212 int loopCount;
 213 CFNumberGetValue(num, kCFNumberIntType, &loopCount);
 214 return loopCount ? loopCount : cAnimationLoopInfinite;
 215 }
 216
 217 // Turns out we're not an animated image after all, so we don't animate.
 218 return cAnimationNone;
 219}
 220
 221bool ImageDecoder::getHotSpot(IntPoint& hotSpot) const
 222{
 223 RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder, 0, imageSourceOptions().get()));
 224 if (!properties)
 225 return false;
 226
 227 int x = -1, y = -1;
 228 CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotX"));
 229 if (!num || !CFNumberGetValue(num, kCFNumberIntType, &x))
 230 return false;
 231
 232 num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotY"));
 233 if (!num || !CFNumberGetValue(num, kCFNumberIntType, &y))
 234 return false;
 235
 236 if (x < 0 || y < 0)
 237 return false;
 238
 239 hotSpot = IntPoint(x, y);
 240 return true;
 241}
 242
 243IntSize ImageDecoder::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
 244{
 245 RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder, index, imageSourceOptions(subsamplingLevel).get()));
 246
 247 if (!properties)
 248 return { };
 249
 250 int width = 0;
 251 int height = 0;
 252 CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
 253 if (num)
 254 CFNumberGetValue(num, kCFNumberIntType, &width);
 255
 256 num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
 257 if (num)
 258 CFNumberGetValue(num, kCFNumberIntType, &height);
 259
 260 return IntSize(width, height);
 261}
 262
 263bool ImageDecoder::frameIsCompleteAtIndex(size_t index) const
 264{
 265 ASSERT(frameCount());
 266 return CGImageSourceGetStatusAtIndex(m_nativeDecoder, index) == kCGImageStatusComplete;
 267}
 268
 269ImageOrientation ImageDecoder::orientationAtIndex(size_t index) const
 270{
 271 RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder, index, imageSourceOptions().get()));
 272 if (!properties)
 273 return DefaultImageOrientation;
 274
 275 return orientationFromProperties(properties.get());
 276}
 277
 278float ImageDecoder::frameDurationAtIndex(size_t index) const
 279{
 280 float duration = 0;
 281 RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder, index, imageSourceOptions().get()));
 282 if (properties) {
 283 CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
 284 if (gifProperties) {
 285 if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFUnclampedDelayTime)) {
 286 // Use the unclamped frame delay if it exists.
 287 CFNumberGetValue(num, kCFNumberFloatType, &duration);
 288 } else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime)) {
 289 // Fall back to the clamped frame delay if the unclamped frame delay does not exist.
 290 CFNumberGetValue(num, kCFNumberFloatType, &duration);
 291 }
 292 }
 293
 294 CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary);
 295 if (pngProperties) {
 296 if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGUnclampedDelayTime))
 297 CFNumberGetValue(num, kCFNumberFloatType, &duration);
 298 else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGDelayTime))
 299 CFNumberGetValue(num, kCFNumberFloatType, &duration);
 300 }
 301 }
 302
 303 // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
 304 // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
 305 // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
 306 // for more information.
 307 if (duration < 0.011f)
 308 return 0.1f;
 309 return duration;
 310}
 311
 312bool ImageDecoder::allowSubsamplingOfFrameAtIndex(size_t) const
 313{
 314 RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder, 0, imageSourceOptions().get()));
 315 if (!properties)
 316 return false;
 317
 318 CFDictionaryRef jfifProperties = static_cast<CFDictionaryRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyJFIFDictionary));
 319 if (jfifProperties) {
 320 CFBooleanRef isProgCFBool = static_cast<CFBooleanRef>(CFDictionaryGetValue(jfifProperties, kCGImagePropertyJFIFIsProgressive));
 321 if (isProgCFBool) {
 322 bool isProgressive = CFBooleanGetValue(isProgCFBool);
 323 // Workaround for <rdar://problem/5184655> - Hang rendering very large progressive JPEG. Decoding progressive
 324 // images hangs for a very long time right now. Until this is fixed, don't sub-sample progressive images. This
 325 // will cause them to fail our large image check and they won't be decoded.
 326 // FIXME: Remove once underlying issue is fixed (<rdar://problem/5191418>)
 327 return !isProgressive;
 328 }
 329 }
 330
 331 return true;
 332}
 333
 334bool ImageDecoder::frameHasAlphaAtIndex(size_t index) const
 335{
 336 if (!frameIsCompleteAtIndex(index))
 337 return true;
 338
 339 CFStringRef imageType = CGImageSourceGetType(m_nativeDecoder);
 340
 341 // Return false if there is no image type or the image type is JPEG, because
 342 // JPEG does not support alpha transparency.
 343 if (!imageType || CFEqual(imageType, CFSTR("public.jpeg")))
 344 return false;
 345
 346 // FIXME: Could return false for other non-transparent image formats.
 347 // FIXME: Could maybe return false for a GIF Frame if we have enough info in the GIF properties dictionary
 348 // to determine whether or not a transparent color was defined.
 349 return true;
 350}
 351
 352unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
 353{
 354 IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel);
 355 return frameSize.width() * frameSize.height() * 4;
 356}
 357
 358PassNativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel, DecodeMode decodeMode) const
 359{
 360 RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_nativeDecoder, index, imageSourceOptions(subsamplingLevel, decodeMode).get()));
 361
 362#if PLATFORM(IOS)
 363 // <rdar://problem/7371198> - CoreGraphics changed the default caching behaviour in iOS 4.0 to kCGImageCachingTransient
 364 // which caused a performance regression for us since the images had to be resampled/recreated every time we called
 365 // CGContextDrawImage. We now tell CG to cache the drawn images. See also <rdar://problem/14366755> -
 366 // CoreGraphics needs to un-deprecate kCGImageCachingTemporary since it's still not the default.
 367#if COMPILER(CLANG)
 368#pragma clang diagnostic push
 369#pragma clang diagnostic ignored "-Wdeprecated-declarations"
 370#endif
 371 CGImageSetCachingFlags(image.get(), kCGImageCachingTemporary);
 372#if COMPILER(CLANG)
 373#pragma clang diagnostic pop
 374#endif
 375#endif // PLATFORM(IOS)
 376
 377 CFStringRef imageUTI = CGImageSourceGetType(m_nativeDecoder);
 378 static const CFStringRef xbmUTI = CFSTR("public.xbitmap-image");
 379
 380 if (!imageUTI)
 381 return image;
 382
 383 if (!CFEqual(imageUTI, xbmUTI))
 384 return image;
 385
 386 // If it is an xbm image, mask out all the white areas to render them transparent.
 387 const CGFloat maskingColors[6] = {255, 255, 255, 255, 255, 255};
 388 RetainPtr<CGImageRef> maskedImage = adoptCF(CGImageCreateWithMaskingColors(image.get(), maskingColors));
 389 return maskedImage ? maskedImage : image;
 390}
 391
 392void ImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
 393{
 394#if PLATFORM(COCOA)
 395 // On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge.
 396 // We use SharedBuffer's ability to wrap itself inside CFData to get around this, ensuring that ImageIO is
 397 // really looking at the SharedBuffer.
 398 CGImageSourceUpdateData(m_nativeDecoder, data->createCFData().get(), allDataReceived);
 399#else
 400 // Create a CGDataProvider to wrap the SharedBuffer.
 401 data->ref();
 402 // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
 403 // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
 404 // is a requirement for using the GetBytePointer callback.
 405 CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, sharedBufferRelease };
 406 RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateDirect(data, data->size(), &providerCallbacks));
 407 CGImageSourceUpdateDataProvider(m_nativeDecoder, dataProvider.get(), allDataReceived);
 408#endif
 409}
 410
 411}
 412
 413#endif // USE(CG)

Source/WebCore/platform/graphics/cg/ImageDecoder.h

 1/*
 2 * Copyright (C) 2016 Apple Inc. All Rights Reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26#ifndef ImageDecoder_h
 27#define ImageDecoder_h
 28
 29#include "ImageSource.h"
 30#include "IntSize.h"
 31
 32namespace WebCore {
 33
 34String preferredExtensionForImageSourceType(const String& type);
 35
 36enum class DecodeMode { Immediate, Lazy };
 37
 38class SharedBuffer;
 39
 40class ImageDecoder {
 41public:
 42 ImageDecoder();
 43 virtual ~ImageDecoder() { }
 44
 45 static size_t bytesDecodedToDetermineProperties();
 46 static SubsamplingLevel subsamplingLevelForScale(float scale, SubsamplingLevel maximumSubsamplingLevel);
 47
 48 String filenameExtension() const;
 49 bool isSizeAvailable() const;
 50 IntSize size() const;
 51 size_t frameCount() const;
 52 int repetitionCount() const;
 53 bool getHotSpot(IntPoint& hotSpot) const;
 54
 55 IntSize frameSizeAtIndex(size_t, SubsamplingLevel) const;
 56 bool frameIsCompleteAtIndex(size_t) const;
 57 ImageOrientation orientationAtIndex(size_t) const;
 58
 59 float frameDurationAtIndex(size_t) const;
 60 bool frameHasAlphaAtIndex(size_t) const;
 61 bool allowSubsamplingOfFrameAtIndex(size_t) const;
 62 unsigned frameBytesAtIndex(size_t, SubsamplingLevel = 0) const;
 63
 64 PassNativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel, DecodeMode = DecodeMode::Lazy) const;
 65
 66 void setData(SharedBuffer*, bool allDataReceived);
 67
 68protected:
 69 mutable IntSize m_size;
 70 CGImageSourceRef m_nativeDecoder;
 71};
 72
 73}
 74
 75#endif // ImageDecoder_h

Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp

3030#include "ImageSourceCG.h"
3131
3232#include "CoreGraphicsSPI.h"
 33#include "ImageDecoder.h"
3334#include "ImageOrientation.h"
3435#include "IntPoint.h"
3536#include "IntSize.h"

4445#include <wtf/RetainPtr.h>
4546#endif
4647
47 #if USE(APPLE_INTERNAL_SDK)
48 #import <ImageIO/CGImageSourcePrivate.h>
49 #else
50 const CFStringRef kCGImageSourceSubsampleFactor = CFSTR("kCGImageSourceSubsampleFactor");
51 #endif
52 
5348namespace WebCore {
5449
55 const CFStringRef WebCoreCGImagePropertyAPNGUnclampedDelayTime = CFSTR("UnclampedDelayTime");
56 const CFStringRef WebCoreCGImagePropertyAPNGDelayTime = CFSTR("DelayTime");
57 const CFStringRef WebCoreCGImagePropertyAPNGLoopCount = CFSTR("LoopCount");
58 
59 const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
60 const CFStringRef kCGImageSourceSkipMetadata = CFSTR("kCGImageSourceSkipMetadata");
61 
62 #if !PLATFORM(COCOA)
63 size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count)
64 {
65  SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
66  size_t sourceSize = sharedBuffer->size();
67  if (position >= sourceSize)
68  return 0;
69 
70  const char* source = sharedBuffer->data() + position;
71  size_t amount = std::min<size_t>(count, sourceSize - position);
72  memcpy(buffer, source, amount);
73  return amount;
74 }
75 
76 void sharedBufferRelease(void* info)
77 {
78  SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
79  sharedBuffer->deref();
80 }
81 #endif
82 
8350ImageSource::ImageSource(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption)
84  : m_decoder(0)
8551{
8652 // FIXME: AlphaOption and GammaAndColorProfileOption are ignored.
8753}

@@void ImageSource::clear(bool destroyAllFrames, size_t, SharedBuffer* data, bool
10066 return;
10167
10268 if (m_decoder) {
103  CFRelease(m_decoder);
 69 delete m_decoder;
10470 m_decoder = 0;
10571 }
 72
10673 if (data)
10774 setData(data, allDataReceived);
10875}
109 
110 static RetainPtr<CFDictionaryRef> createImageSourceOptions(SubsamplingLevel subsamplingLevel)
 76
 77void ImageSource::ensureDecoderIsCreated(SharedBuffer* data)
11178{
112  if (!subsamplingLevel) {
113  const unsigned numOptions = 3;
114  const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata };
115  const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue };
116  return CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
117  }
118 
119  short constrainedSubsamplingLevel = std::min<short>(3, std::max<short>(0, subsamplingLevel));
120  int subsampleInt = 1 << constrainedSubsamplingLevel; // [0..3] => [1, 2, 4, 8]
121 
122  RetainPtr<CFNumberRef> subsampleNumber = adoptCF(CFNumberCreate(nullptr, kCFNumberIntType, &subsampleInt));
123  const CFIndex numOptions = 4;
124  const void* keys[numOptions] = { kCGImageSourceShouldCache, kCGImageSourceShouldPreferRGB32, kCGImageSourceSkipMetadata, kCGImageSourceSubsampleFactor };
125  const void* values[numOptions] = { kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue, subsampleNumber.get() };
126  return adoptCF(CFDictionaryCreate(nullptr, keys, values, numOptions, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
 79 UNUSED_PARAM(data);
 80
 81 if (m_decoder)
 82 return;
 83
 84 m_decoder = new ImageDecoder();
12785}
128 
129 static RetainPtr<CFDictionaryRef> imageSourceOptions(SubsamplingLevel subsamplingLevel = 0)
 86
 87void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
13088{
131  if (subsamplingLevel)
132  return createImageSourceOptions(subsamplingLevel);
 89 if (!data)
 90 return;
13391
134  static NeverDestroyed<RetainPtr<CFDictionaryRef>> options = createImageSourceOptions(0);
135  return options;
136 }
 92 ensureDecoderIsCreated(data);
 93 if (!m_decoder) {
 94 ASSERT_NOT_REACHED();
 95 return;
 96 }
13797
138 bool ImageSource::initialized() const
139 {
140  return m_decoder;
 98 m_decoder->setData(data, allDataReceived);
14199}
142100
143 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
 101String ImageSource::filenameExtension() const
144102{
145 #if PLATFORM(COCOA)
146  if (!m_decoder)
147  m_decoder = CGImageSourceCreateIncremental(0);
148  // On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability
149  // to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer.
150  CGImageSourceUpdateData(m_decoder, data->createCFData().get(), allDataReceived);
151 #else
152  if (!m_decoder)
153  m_decoder = CGImageSourceCreateIncremental(0);
154  // Create a CGDataProvider to wrap the SharedBuffer.
155  data->ref();
156  // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
157  // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
158  // is a requirement for using the GetBytePointer callback.
159  CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, sharedBufferRelease };
160  RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateDirect(data, data->size(), &providerCallbacks));
161  CGImageSourceUpdateDataProvider(m_decoder, dataProvider.get(), allDataReceived);
162 #endif
 103 return initialized() ? m_decoder->filenameExtension() : String();
163104}
164105
165 String ImageSource::filenameExtension() const
 106SubsamplingLevel ImageSource::subsamplingLevelForScale(float scale, SubsamplingLevel maximumSubsamplingLevel) const
166107{
167  if (!m_decoder)
168  return String();
169  CFStringRef imageSourceType = CGImageSourceGetType(m_decoder);
170  return WebCore::preferredExtensionForImageSourceType(imageSourceType);
 108 return ImageDecoder::subsamplingLevelForScale(scale, maximumSubsamplingLevel);
171109}
 110
172111
173 SubsamplingLevel ImageSource::subsamplingLevelForScale(float scale) const
 112size_t ImageSource::bytesDecodedToDetermineProperties() const
174113{
175  // There are four subsampling levels: 0 = 1x, 1 = 0.5x, 2 = 0.25x, 3 = 0.125x.
176  float clampedScale = std::max<float>(0.125, std::min<float>(1, scale));
177  int result = ceilf(log2f(1 / clampedScale));
178  ASSERT(result >=0 && result <= 3);
179  return result;
 114 return ImageDecoder::bytesDecodedToDetermineProperties();
180115}
181 
 116
182117bool ImageSource::isSizeAvailable()
183118{
184  // Ragnaros yells: TOO SOON! You have awakened me TOO SOON, Executus!
185  if (CGImageSourceGetStatus(m_decoder) < kCGImageStatusIncomplete)
186  return false;
187 
188  RetainPtr<CFDictionaryRef> image0Properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions().get()));
189  if (!image0Properties)
190  return false;
191 
192  return CFDictionaryContainsKey(image0Properties.get(), kCGImagePropertyPixelWidth)
193  && CFDictionaryContainsKey(image0Properties.get(), kCGImagePropertyPixelHeight);
 119 return m_decoder && m_decoder->isSizeAvailable();
194120}
195121
196 static ImageOrientation orientationFromProperties(CFDictionaryRef imageProperties)
 122bool ImageSource::allowSubsamplingOfFrameAtIndex(size_t index) const
197123{
198  ASSERT(imageProperties);
199  CFNumberRef orientationProperty = (CFNumberRef)CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation);
200  if (!orientationProperty)
201  return DefaultImageOrientation;
202 
203  int exifValue;
204  CFNumberGetValue(orientationProperty, kCFNumberIntType, &exifValue);
205  return ImageOrientation::fromEXIFValue(exifValue);
 124 return initialized() && m_decoder->allowSubsamplingOfFrameAtIndex(index);
206125}
207126
208 bool ImageSource::allowSubsamplingOfFrameAtIndex(size_t) const
 127IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel, RespectImageOrientationEnum shouldRespectImageOrientation) const
209128{
210  RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions().get()));
211  if (!properties)
212  return false;
213 
214  CFDictionaryRef jfifProperties = static_cast<CFDictionaryRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyJFIFDictionary));
215  if (jfifProperties) {
216  CFBooleanRef isProgCFBool = static_cast<CFBooleanRef>(CFDictionaryGetValue(jfifProperties, kCGImagePropertyJFIFIsProgressive));
217  if (isProgCFBool) {
218  bool isProgressive = CFBooleanGetValue(isProgCFBool);
219  // Workaround for <rdar://problem/5184655> - Hang rendering very large progressive JPEG. Decoding progressive
220  // images hangs for a very long time right now. Until this is fixed, don't sub-sample progressive images. This
221  // will cause them to fail our large image check and they won't be decoded.
222  // FIXME: Remove once underlying issue is fixed (<rdar://problem/5191418>)
223  return !isProgressive;
224  }
225  }
226 
227  return true;
228 }
229 
230 IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageOrientationDescription description) const
231 {
232  RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(subsamplingLevel).get()));
233 
234  if (!properties)
 129 if (!initialized())
235130 return IntSize();
236131
237  int width = 0;
238  int height = 0;
239  CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
240  if (num)
241  CFNumberGetValue(num, kCFNumberIntType, &width);
242  num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
243  if (num)
244  CFNumberGetValue(num, kCFNumberIntType, &height);
245 
246  if ((description.respectImageOrientation() == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight())
247  return IntSize(height, width);
 132 IntSize size = m_decoder->frameSizeAtIndex(index, subsamplingLevel);
 133 ImageOrientation orientation = m_decoder->orientationAtIndex(index);
248134
249  return IntSize(width, height);
 135 return shouldRespectImageOrientation == RespectImageOrientation && orientation.usesWidthAsHeight() ? size.transposedSize() : size;
250136}
251137
252138ImageOrientation ImageSource::orientationAtIndex(size_t index) const
253139{
254  RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions().get()));
255  if (!properties)
256  return DefaultImageOrientation;
257 
258  return orientationFromProperties(properties.get());
 140 return initialized() ? m_decoder->orientationAtIndex(index) : DefaultImageOrientation;
259141}
260142
261 IntSize ImageSource::size(ImageOrientationDescription description) const
 143IntSize ImageSource::size() const
262144{
263  return frameSizeAtIndex(0, 0, description);
 145 return frameSizeAtIndex(0, 0);
264146}
265147
266 bool ImageSource::getHotSpot(IntPoint& hotSpot) const
 148IntSize ImageSource::sizeRespectingOrientation() const
267149{
268  RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions().get()));
269  if (!properties)
270  return false;
271 
272  int x = -1, y = -1;
273  CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotX"));
274  if (!num || !CFNumberGetValue(num, kCFNumberIntType, &x))
275  return false;
276 
277  num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotY"));
278  if (!num || !CFNumberGetValue(num, kCFNumberIntType, &y))
279  return false;
280 
281  if (x < 0 || y < 0)
282  return false;
283 
284  hotSpot = IntPoint(x, y);
285  return true;
 150 return frameSizeAtIndex(0, 0, RespectImageOrientation);
286151}
287152
288 size_t ImageSource::bytesDecodedToDetermineProperties() const
 153bool ImageSource::getHotSpot(IntPoint& hotSpot) const
289154{
290  // Measured by tracing malloc/calloc calls on Mac OS 10.6.6, x86_64.
291  // A non-zero value ensures cached images with no decoded frames still enter
292  // the live decoded resources list when the CGImageSource decodes image
293  // properties, allowing the cache to prune the partially decoded image.
294  // This value is likely to be inaccurate on other platforms, but the overall
295  // behavior is unchanged.
296  return 13088;
 155 return m_decoder && m_decoder->getHotSpot(hotSpot);
297156}
298 
 157
299158int ImageSource::repetitionCount()
300159{
301  if (!initialized())
302  return cAnimationLoopOnce;
303 
304  RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyProperties(m_decoder, imageSourceOptions().get()));
305  if (!properties)
306  return cAnimationLoopOnce;
307 
308  CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
309  if (gifProperties) {
310  CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFLoopCount);
311 
312  // No property means loop once.
313  if (!num)
314  return cAnimationLoopOnce;
315 
316  int loopCount;
317  CFNumberGetValue(num, kCFNumberIntType, &loopCount);
318 
319  // A property with value 0 means loop forever.
320  return loopCount ? loopCount : cAnimationLoopInfinite;
321  }
322 
323  CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary);
324  if (pngProperties) {
325  CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGLoopCount);
326  if (!num)
327  return cAnimationLoopOnce;
328 
329  int loopCount;
330  CFNumberGetValue(num, kCFNumberIntType, &loopCount);
331  return loopCount ? loopCount : cAnimationLoopInfinite;
332  }
333 
334  // Turns out we're not an animated image after all, so we don't animate.
335  return cAnimationNone;
 160 return initialized() ? m_decoder->repetitionCount() : cAnimationLoopOnce;
336161}
337162
338163size_t ImageSource::frameCount() const
339164{
340  return m_decoder ? CGImageSourceGetCount(m_decoder) : 0;
 165 return m_decoder ? m_decoder->frameCount() : 0;
341166}
342167
343 CGImageRef ImageSource::createFrameAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
 168PassNativeImagePtr ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
344169{
345  if (!initialized())
346  return nullptr;
347 
348  RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions(subsamplingLevel).get()));
349 
350 #if PLATFORM(IOS)
351  // <rdar://problem/7371198> - CoreGraphics changed the default caching behaviour in iOS 4.0 to kCGImageCachingTransient
352  // which caused a performance regression for us since the images had to be resampled/recreated every time we called
353  // CGContextDrawImage. We now tell CG to cache the drawn images. See also <rdar://problem/14366755> -
354  // CoreGraphics needs to un-deprecate kCGImageCachingTemporary since it's still not the default.
355 #if COMPILER(CLANG)
356 #pragma clang diagnostic push
357 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
358 #endif
359  CGImageSetCachingFlags(image.get(), kCGImageCachingTemporary);
360 #if COMPILER(CLANG)
361 #pragma clang diagnostic pop
362 #endif
363 #endif // PLATFORM(IOS)
364 
365  CFStringRef imageUTI = CGImageSourceGetType(m_decoder);
366  static const CFStringRef xbmUTI = CFSTR("public.xbitmap-image");
367 
368  if (!imageUTI)
369  return image.leakRef();
370 
371  if (!CFEqual(imageUTI, xbmUTI))
372  return image.leakRef();
373 
374  // If it is an xbm image, mask out all the white areas to render them transparent.
375  const CGFloat maskingColors[6] = {255, 255, 255, 255, 255, 255};
376  RetainPtr<CGImageRef> maskedImage = adoptCF(CGImageCreateWithMaskingColors(image.get(), maskingColors));
377  if (!maskedImage)
378  return image.leakRef();
379 
380  return maskedImage.leakRef();
 170 return initialized() ? m_decoder->createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
381171}
382172
383173bool ImageSource::frameIsCompleteAtIndex(size_t index)
384174{
385175 ASSERT(frameCount());
386  return CGImageSourceGetStatusAtIndex(m_decoder, index) == kCGImageStatusComplete;
 176 return initialized() && m_decoder->frameIsCompleteAtIndex(index);
387177}
388178
389179float ImageSource::frameDurationAtIndex(size_t index)
390180{
391  if (!initialized())
392  return 0;
393 
394  float duration = 0;
395  RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions().get()));
396  if (properties) {
397  CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
398  if (gifProperties) {
399  if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFUnclampedDelayTime)) {
400  // Use the unclamped frame delay if it exists.
401  CFNumberGetValue(num, kCFNumberFloatType, &duration);
402  } else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime)) {
403  // Fall back to the clamped frame delay if the unclamped frame delay does not exist.
404  CFNumberGetValue(num, kCFNumberFloatType, &duration);
405  }
406  }
407 
408  CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary);
409  if (pngProperties) {
410  if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGUnclampedDelayTime))
411  CFNumberGetValue(num, kCFNumberFloatType, &duration);
412  else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGDelayTime))
413  CFNumberGetValue(num, kCFNumberFloatType, &duration);
414  }
415  }
416 
417  // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
418  // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
419  // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
420  // for more information.
421  if (duration < 0.011f)
422  return 0.1f;
423  return duration;
 181 return initialized() ? m_decoder->frameDurationAtIndex(index) : 0;
424182}
425183
426184bool ImageSource::frameHasAlphaAtIndex(size_t index)
427185{
428  if (!m_decoder)
429  return false; // FIXME: why doesn't this return true?
430 
431  if (!frameIsCompleteAtIndex(index))
432  return true;
433 
434  CFStringRef imageType = CGImageSourceGetType(m_decoder);
435 
436  // Return false if there is no image type or the image type is JPEG, because
437  // JPEG does not support alpha transparency.
438  if (!imageType || CFEqual(imageType, CFSTR("public.jpeg")))
439  return false;
440 
441  // FIXME: Could return false for other non-transparent image formats.
442  // FIXME: Could maybe return false for a GIF Frame if we have enough info in the GIF properties dictionary
443  // to determine whether or not a transparent color was defined.
444  return true;
 186 return initialized() && m_decoder->frameHasAlphaAtIndex(index);
445187}
446188
447189unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
448190{
449  IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel, ImageOrientationDescription(RespectImageOrientation));
450  return frameSize.width() * frameSize.height() * 4;
 191 return initialized() ? m_decoder->frameBytesAtIndex(index, subsamplingLevel) : 0;
451192}
452193
453194}

Source/WebCore/platform/graphics/efl/GraphicsContext3DEfl.cpp

@@bool GraphicsContext3D::ImageExtractor::extractImage(bool premultiplyAlpha, bool
263263 if (!decoder.frameCount() || !decoder.frameIsCompleteAtIndex(0))
264264 return false;
265265
266  m_imageSurface = decoder.createFrameAtIndex(0);
 266 m_imageSurface = decoder.createFrameImageAtIndex(0);
267267 } else {
268268 m_imageSurface = m_image->nativeImageForCurrentFrame();
269269 // 1. For texImage2D with HTMLVideoElment input, assume no PremultiplyAlpha had been applied and the alpha value is 0xFF for each pixel,

Source/WebCore/platform/graphics/ios/IconIOS.mm

3333
3434namespace WebCore {
3535
36 Icon::Icon(CGImageRef image)
 36Icon::Icon(NativeImagePtr image)
3737 : m_cgImage(image)
3838{
3939}

Source/WebCore/platform/graphics/mac/ImageMac.mm

@@CFDataRef BitmapImage::getTIFFRepresentation()
9595
9696 Vector<CGImageRef> images;
9797 for (unsigned i = 0; i < numFrames; ++i ) {
98  CGImageRef cgImage = frameAtIndex(i);
 98 CGImageRef cgImage = frameImageAtIndex(i).get();
9999 if (cgImage)
100100 images.append(cgImage);
101101 }

Source/WebCore/platform/graphics/win/ImageCGWin.cpp

@@void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext& ctxt, const Float
9090{
9191 size_t frames = frameCount();
9292 for (size_t i = 0; i < frames; ++i) {
93  CGImageRef image = frameAtIndex(i);
 93 CGImageRef image = frameImageAtIndex(i).get();
9494 if (image && CGImageGetHeight(image) == static_cast<size_t>(srcSize.height()) && CGImageGetWidth(image) == static_cast<size_t>(srcSize.width())) {
9595 size_t currentFrame = m_currentFrame;
9696 m_currentFrame = i;

Source/WebCore/platform/graphics/win/ImageCairoWin.cpp

@@void BitmapImage::drawFrameMatchingSourceSize(GraphicsContext& ctxt, const Float
9393{
9494 size_t frames = frameCount();
9595 for (size_t i = 0; i < frames; ++i) {
96  RefPtr<cairo_surface_t> surface = frameAtIndex(i);
 96 RefPtr<cairo_surface_t> surface = frameImageAtIndex(i);
9797 if (!surface)
9898 continue;
9999

Source/WebCore/platform/mac/DragImageMac.mm

@@RetainPtr<NSImage> createDragImageFromImage(Image* image, ImageOrientationDescri
9191 if (is<BitmapImage>(*image)) {
9292 ImageOrientation orientation;
9393 BitmapImage& bitmapImage = downcast<BitmapImage>(*image);
94  IntSize sizeRespectingOrientation = bitmapImage.sizeRespectingOrientation(description);
 94 IntSize sizeRespectingOrientation = bitmapImage.sizeRespectingOrientation();
9595
9696 if (description.respectImageOrientation() == RespectImageOrientation)
9797 orientation = bitmapImage.orientationForCurrentFrame();