Changeset 198782 in webkit


Ignore:
Timestamp:
Mar 29, 2016 9:18:25 AM (8 years ago)
Author:
commit-queue@webkit.org
Message:

Create a CG ImageDecoder class instead of defining it as CGImageSourceRef
https://bugs.webkit.org/show_bug.cgi?id=155422

Patch by Said Abou-Hallawa <sabouhallawa@apple,com> on 2016-03-29
Reviewed by Simon Fraser.

Move the image CG decoding code from the class ImageSource out to a new
class named ImageDecoder. The purpose of this split is to unify the code
of the ImageSource for all platforms. This class should be a container
for the ImageDecoder. All the direct frame manipulation like querying the
frame metadata or creating a frame image should be the responsibility of
the ImageDecoder. The ImageSource will be responsible of the image frame
caching. When responding to a frame metadata query, for example. the
ImageSource checks its cache first. If an entry does not exist for the
requested frame, the ImageSource will cache the image and the metadata
of this frame. The ImageSource will respond at the end from the image
frame cache.

The plan after this patch is is the following:

-- Move the new class to separate files
-- Merge the ImageSource.cpp and ImageSourceCG.cpp. in one file
-- Move caching the FrameData from BitmapImage to ImageSource.

  • loader/cache/CachedImage.cpp:

(WebCore::CachedImage::imageSizeForRenderer):
BitmapImage::sizeRespectingOrientation() does not take any argument now.
Fix the call to this function and delete the conditionally compiled code
since the code is the same for the two cases.

  • platform/graphics/BitmapImage.cpp:

(WebCore::BitmapImage::updateSize):
(WebCore::BitmapImage::sizeRespectingOrientation):
(WebCore::BitmapImage::frameImageAtIndex):
(WebCore::BitmapImage::BitmapImage):
An image can have two sizes: size() and sizeRespectingOrientation(). The
sizeRespectingOrientation() is the transpose of size() iff the image
orientation has usesWidthAsHeight() is true. So there is no need for the
ImageOrientationDescription argument. So there is no need for the members
m_imageOrientation or m_shouldRespectImageOrientation. Also move
m_allowSubsampling and m_minimumSubsamplingLevel (which should be named
m_maximumSubsamplingLevel) to ImageSource instead.

(WebCore::BitmapImage::frameOrientationAtIndex): Replace DefaultImageOrientation
by ImageOrientation().

(WebCore::BitmapImage::dump): Move dumping the image metadata to the
ImageSource.

  • platform/graphics/BitmapImage.h:
  • platform/graphics/GraphicsContext.h:
  • platform/graphics/ImageOrientation.h:

(WebCore::ImageOrientation::ImageOrientation):
(WebCore::ImageOrientation::fromEXIFValue):
(WebCore::ImageOrientation::operator ImageOrientationEnum):
Add a casting operator to ImageOrientation so it can be dumped as enum
value. Also add a default constructor and make the other constructor be
explicit. All the rvalues DefaultImageOrientation should be replaced by
ImageOrientation().

  • platform/graphics/ImageSource.cpp:

(WebCore::ImageSource::ImageSource):
(WebCore::ImageSource::clear):
m_decoder is now a unique_ptr. To release it, assign it to nullptr.

(WebCore::ImageSource::ensureDecoderIsCreated): Ensure m_decoder is created.

(WebCore::ImageSource::setData): Call ensureDecoderIsCreated() before
actually setting the data.

(WebCore::ImageSource::isSizeAvailable): Use initialized();

(WebCore::ImageSource::size):
(WebCore::ImageSource::sizeRespectingOrientation):
(WebCore::ImageSource::frameSizeAtIndex):
These functions return the size of the image.

(WebCore::ImageSource::getHotSpot):
(WebCore::ImageSource::repetitionCount):
(WebCore::ImageSource::frameCount):
(WebCore::ImageSource::createFrameImageAtIndex):
(WebCore::ImageSource::frameDurationAtIndex):
(WebCore::ImageSource::orientationAtIndex):
(WebCore::ImageSource::frameHasAlphaAtIndex):
(WebCore::ImageSource::frameIsCompleteAtIndex):
(WebCore::ImageSource::frameBytesAtIndex):
Check for initialized() instead of checking m_decoder.

(WebCore::ImageSource::dump): Dump the image metadata.

(WebCore::ImageSource::initialized): Deleted.

  • platform/graphics/ImageSource.h: The image decoder is now named

ImageDecoder for all platforms.

(WebCore::ImageSource::initialized): Moved to the header file.

(WebCore::ImageSource::setAllowSubsampling): Moved from BitmapImage.

  • platform/graphics/cairo/BitmapImageCairo.cpp:

(WebCore::BitmapImage::BitmapImage):
(WebCore::BitmapImage::determineMinimumSubsamplingLevel): Deleted.
Delete initializing m_minimumSubsamplingLevel and determineMinimumSubsamplingLevel()
since they are moved to ImageSource.

  • platform/graphics/cg/BitmapImageCG.cpp:

(WebCore::BitmapImage::BitmapImage):
(WebCore::BitmapImage::determineMinimumSubsamplingLevel): Deleted.
Delete members and methods which are now owned and calculated by ImageSource.

  • platform/graphics/cg/ImageSourceCG.cpp:

(WebCore::ImageDecoder::create): Returns a CG ImageDecoder object.

(WebCore::orientationFromProperties): Replace DefaultImageOrientation
by ImageOrientation().

(WebCore::ImageDecoder::ImageDecoder): Creates a native CG image decoder.

(WebCore::ImageDecoder::~ImageDecoder): Releases the native CG image decoder.

(WebCore::ImageDecoder::subsamplingLevelForScale): Moved from ImageSource.
A new argument named 'maximumSubsamplingLevel' is added to low filter the
return value.

(WebCore::ImageDecoder::bytesDecodedToDetermineProperties):
(WebCore::ImageDecoder::filenameExtension):
(WebCore::ImageDecoder::isSizeAvailable):
(WebCore::ImageDecoder::size):
(WebCore::ImageDecoder::frameCount):
(WebCore::ImageDecoder::repetitionCount):
(WebCore::ImageDecoder::hotSpot):
(WebCore::ImageDecoder::frameSizeAtIndex):
(WebCore::ImageDecoder::frameIsCompleteAtIndex):
(WebCore::ImageDecoder::orientationAtIndex):
(WebCore::ImageDecoder::frameDurationAtIndex):
(WebCore::ImageDecoder::allowSubsamplingOfFrameAtIndex):
(WebCore::ImageDecoder::frameHasAlphaAtIndex):
(WebCore::ImageDecoder::frameBytesAtIndex):
(WebCore::ImageDecoder::createFrameImageAtIndex):
(WebCore::ImageDecoder::setData):
The code of these function was moved from the functions of ImageSource.

(WebCore::ImageSource::ImageSource):
(WebCore::ImageSource::~ImageSource):
(WebCore::ImageSource::clear):
(WebCore::ImageSource::ensureDecoderIsCreated):
(WebCore::ImageSource::setData):
(WebCore::ImageSource::filenameExtension):
(WebCore::ImageSource::calculateMaximumSubsamplingLevel):
(WebCore::ImageSource::maximumSubsamplingLevel):
(WebCore::ImageSource::subsamplingLevelForScale):
(WebCore::ImageSource::isSizeAvailable):
(WebCore::ImageSource::allowSubsamplingOfFrameAtIndex):
(WebCore::ImageSource::frameSizeAtIndex):
(WebCore::ImageSource::orientationAtIndex):
(WebCore::ImageSource::size):
(WebCore::ImageSource::sizeRespectingOrientation):
(WebCore::ImageSource::getHotSpot):
(WebCore::ImageSource::bytesDecodedToDetermineProperties):
(WebCore::ImageSource::repetitionCount):
(WebCore::ImageSource::frameCount):
(WebCore::ImageSource::createFrameImageAtIndex):
(WebCore::ImageSource::frameIsCompleteAtIndex):
(WebCore::ImageSource::frameDurationAtIndex):
(WebCore::ImageSource::frameHasAlphaAtIndex):
(WebCore::ImageSource::frameBytesAtIndex):
Call m_decoder's function to do the real work.

(WebCore::ImageSource::dump): Dump the image metadata.

(WebCore::ImageSource::initialized): Deleted.

  • platform/image-decoders/ImageDecoder.cpp:

(WebCore::ImageDecoder::create):

  • platform/image-decoders/ImageDecoder.h:

Change the return of ImageDecoder::create() to be unique_ptr.

  • platform/mac/DragImageMac.mm:

(WebCore::createDragImageFromImage): Delete unneeded argument.

Location:
trunk/Source/WebCore
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r198780 r198782  
     12016-03-29  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 Simon Fraser.
     7
     8        Move the image CG decoding code from the class ImageSource out to a new
     9        class named ImageDecoder. The purpose of this split is to unify the code
     10        of the ImageSource for all platforms. This class should be a container
     11        for the ImageDecoder. All the direct frame manipulation like querying the
     12        frame metadata or creating a frame image should be the responsibility of
     13        the ImageDecoder. The ImageSource will be responsible of the image frame
     14        caching. When responding to a frame metadata query, for example. the
     15        ImageSource checks its cache first. If an entry does not exist for the
     16        requested frame, the ImageSource will cache the image and the metadata
     17        of this frame. The ImageSource will respond at the end from the image
     18        frame cache.
     19 
     20        The plan after this patch is is the following:
     21            -- Move the new class to separate files
     22            -- Merge the ImageSource.cpp and ImageSourceCG.cpp. in one file
     23            -- Move caching the FrameData from BitmapImage to ImageSource.
     24 
     25        * loader/cache/CachedImage.cpp:
     26        (WebCore::CachedImage::imageSizeForRenderer):
     27        BitmapImage::sizeRespectingOrientation() does not take any argument now.
     28        Fix the call to this function and delete the conditionally compiled code
     29        since the code is the same for the two cases.
     30 
     31        * platform/graphics/BitmapImage.cpp:
     32        (WebCore::BitmapImage::updateSize):
     33        (WebCore::BitmapImage::sizeRespectingOrientation):
     34        (WebCore::BitmapImage::frameImageAtIndex):
     35        (WebCore::BitmapImage::BitmapImage):
     36        An image can have two sizes: size() and sizeRespectingOrientation(). The
     37        sizeRespectingOrientation() is the transpose of size() iff the image
     38        orientation has usesWidthAsHeight() is true. So there is no need for the
     39        ImageOrientationDescription argument. So there is no need for the members
     40        m_imageOrientation or m_shouldRespectImageOrientation. Also move
     41        m_allowSubsampling and m_minimumSubsamplingLevel (which should be named
     42        m_maximumSubsamplingLevel) to ImageSource instead.
     43
     44        (WebCore::BitmapImage::frameOrientationAtIndex): Replace DefaultImageOrientation
     45        by ImageOrientation().
     46       
     47        (WebCore::BitmapImage::dump): Move dumping the image metadata to the
     48        ImageSource.
     49       
     50        * platform/graphics/BitmapImage.h:
     51       
     52        * platform/graphics/GraphicsContext.h:
     53        * platform/graphics/ImageOrientation.h:
     54        (WebCore::ImageOrientation::ImageOrientation):
     55        (WebCore::ImageOrientation::fromEXIFValue):
     56        (WebCore::ImageOrientation::operator ImageOrientationEnum):
     57        Add a casting operator to ImageOrientation so it can be dumped as enum
     58        value. Also add a default constructor and make the other constructor be
     59        explicit. All the rvalues DefaultImageOrientation should be replaced by
     60        ImageOrientation().
     61
     62        * platform/graphics/ImageSource.cpp:
     63        (WebCore::ImageSource::ImageSource):
     64        (WebCore::ImageSource::clear):
     65        m_decoder is now a unique_ptr. To release it, assign it to nullptr.
     66
     67        (WebCore::ImageSource::ensureDecoderIsCreated): Ensure m_decoder is created.
     68       
     69        (WebCore::ImageSource::setData): Call ensureDecoderIsCreated() before
     70        actually setting the data.
     71       
     72        (WebCore::ImageSource::isSizeAvailable): Use initialized();
     73       
     74        (WebCore::ImageSource::size):
     75        (WebCore::ImageSource::sizeRespectingOrientation):
     76        (WebCore::ImageSource::frameSizeAtIndex):
     77        These functions return the size of the image.
     78   
     79        (WebCore::ImageSource::getHotSpot):
     80        (WebCore::ImageSource::repetitionCount):
     81        (WebCore::ImageSource::frameCount):
     82        (WebCore::ImageSource::createFrameImageAtIndex):
     83        (WebCore::ImageSource::frameDurationAtIndex):
     84        (WebCore::ImageSource::orientationAtIndex):
     85        (WebCore::ImageSource::frameHasAlphaAtIndex):
     86        (WebCore::ImageSource::frameIsCompleteAtIndex):
     87        (WebCore::ImageSource::frameBytesAtIndex):
     88        Check for initialized() instead of checking m_decoder.
     89       
     90        (WebCore::ImageSource::dump): Dump the image metadata.
     91       
     92        (WebCore::ImageSource::initialized): Deleted.
     93       
     94        * platform/graphics/ImageSource.h: The image decoder is now named
     95        ImageDecoder for all platforms.
     96       
     97        (WebCore::ImageSource::initialized): Moved to the header file.
     98
     99        (WebCore::ImageSource::setAllowSubsampling): Moved from BitmapImage.
     100       
     101        * platform/graphics/cairo/BitmapImageCairo.cpp:
     102        (WebCore::BitmapImage::BitmapImage):
     103        (WebCore::BitmapImage::determineMinimumSubsamplingLevel): Deleted.
     104        Delete initializing m_minimumSubsamplingLevel and determineMinimumSubsamplingLevel()
     105        since they are moved to ImageSource.
     106       
     107        * platform/graphics/cg/BitmapImageCG.cpp:
     108        (WebCore::BitmapImage::BitmapImage):
     109        (WebCore::BitmapImage::determineMinimumSubsamplingLevel): Deleted.
     110        Delete members and methods which are now owned and calculated by ImageSource.
     111       
     112        * platform/graphics/cg/ImageSourceCG.cpp:
     113        (WebCore::ImageDecoder::create): Returns a CG ImageDecoder object.
     114       
     115        (WebCore::orientationFromProperties):  Replace DefaultImageOrientation
     116        by ImageOrientation().
     117       
     118        (WebCore::ImageDecoder::ImageDecoder): Creates a native CG image decoder.
     119       
     120        (WebCore::ImageDecoder::~ImageDecoder): Releases the native CG image decoder.
     121       
     122        (WebCore::ImageDecoder::subsamplingLevelForScale): Moved from ImageSource.
     123        A new argument named 'maximumSubsamplingLevel' is added to low filter the
     124        return value.
     125       
     126        (WebCore::ImageDecoder::bytesDecodedToDetermineProperties):
     127        (WebCore::ImageDecoder::filenameExtension):
     128        (WebCore::ImageDecoder::isSizeAvailable):
     129        (WebCore::ImageDecoder::size):
     130        (WebCore::ImageDecoder::frameCount):
     131        (WebCore::ImageDecoder::repetitionCount):
     132        (WebCore::ImageDecoder::hotSpot):
     133        (WebCore::ImageDecoder::frameSizeAtIndex):
     134        (WebCore::ImageDecoder::frameIsCompleteAtIndex):
     135        (WebCore::ImageDecoder::orientationAtIndex):
     136        (WebCore::ImageDecoder::frameDurationAtIndex):
     137        (WebCore::ImageDecoder::allowSubsamplingOfFrameAtIndex):
     138        (WebCore::ImageDecoder::frameHasAlphaAtIndex):
     139        (WebCore::ImageDecoder::frameBytesAtIndex):
     140        (WebCore::ImageDecoder::createFrameImageAtIndex):
     141        (WebCore::ImageDecoder::setData):
     142        The code of these function was moved from the functions of ImageSource.
     143       
     144        (WebCore::ImageSource::ImageSource):
     145        (WebCore::ImageSource::~ImageSource):
     146        (WebCore::ImageSource::clear):
     147        (WebCore::ImageSource::ensureDecoderIsCreated):
     148        (WebCore::ImageSource::setData):
     149        (WebCore::ImageSource::filenameExtension):
     150        (WebCore::ImageSource::calculateMaximumSubsamplingLevel):
     151        (WebCore::ImageSource::maximumSubsamplingLevel):
     152        (WebCore::ImageSource::subsamplingLevelForScale):
     153        (WebCore::ImageSource::isSizeAvailable):
     154        (WebCore::ImageSource::allowSubsamplingOfFrameAtIndex):
     155        (WebCore::ImageSource::frameSizeAtIndex):
     156        (WebCore::ImageSource::orientationAtIndex):
     157        (WebCore::ImageSource::size):
     158        (WebCore::ImageSource::sizeRespectingOrientation):
     159        (WebCore::ImageSource::getHotSpot):
     160        (WebCore::ImageSource::bytesDecodedToDetermineProperties):
     161        (WebCore::ImageSource::repetitionCount):
     162        (WebCore::ImageSource::frameCount):
     163        (WebCore::ImageSource::createFrameImageAtIndex):
     164        (WebCore::ImageSource::frameIsCompleteAtIndex):
     165        (WebCore::ImageSource::frameDurationAtIndex):
     166        (WebCore::ImageSource::frameHasAlphaAtIndex):
     167        (WebCore::ImageSource::frameBytesAtIndex):
     168        Call m_decoder's function to do the real work.
     169       
     170        (WebCore::ImageSource::dump): Dump the image metadata.
     171       
     172        (WebCore::ImageSource::initialized): Deleted.
     173       
     174        * platform/image-decoders/ImageDecoder.cpp:
     175        (WebCore::ImageDecoder::create):
     176        * platform/image-decoders/ImageDecoder.h:
     177        Change the return of ImageDecoder::create() to be unique_ptr.
     178       
     179        * platform/mac/DragImageMac.mm:
     180        (WebCore::createDragImageFromImage): Delete unneeded argument.
     181
    11822016-03-29  Eric Carlson  <eric.carlson@apple.com>
    2183
  • trunk/Source/WebCore/loader/cache/CachedImage.cpp

    r198177 r198782  
    273273        return LayoutSize();
    274274
    275     LayoutSize imageSize(m_image->size());
    276 
    277 #if ENABLE(CSS_IMAGE_ORIENTATION)
    278     if (renderer && is<BitmapImage>(*m_image)) {
    279         ImageOrientationDescription orientationDescription(renderer->shouldRespectImageOrientation(), renderer->style().imageOrientation());
    280         if (orientationDescription.respectImageOrientation() == RespectImageOrientation)
    281             imageSize = LayoutSize(downcast<BitmapImage>(*m_image).sizeRespectingOrientation(orientationDescription));
    282     }
    283 #else
    284     if (is<BitmapImage>(*m_image) && (renderer && renderer->shouldRespectImageOrientation() == RespectImageOrientation))
     275    LayoutSize imageSize;
     276
     277    if (is<BitmapImage>(*m_image) && renderer && renderer->shouldRespectImageOrientation() == RespectImageOrientation)
    285278        imageSize = LayoutSize(downcast<BitmapImage>(*m_image).sizeRespectingOrientation());
    286 #endif // ENABLE(CSS_IMAGE_ORIENTATION)
    287 
    288     else if (is<SVGImage>(*m_image) && sizeType == UsedSize) {
     279    else if (is<SVGImage>(*m_image) && sizeType == UsedSize)
    289280        imageSize = LayoutSize(m_svgImageCache->imageSizeForRenderer(renderer));
    290     }
     281    else
     282        imageSize = LayoutSize(m_image->size());
    291283
    292284    if (multiplier == 1.0f)
  • trunk/Source/WebCore/platform/graphics/BitmapImage.cpp

    r198655 r198782  
    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)
     
    6360    , m_progressiveLoadChunkTime(0)
    6461    , m_progressiveLoadChunkCount(0)
    65     , m_allowSubsampling(true)
    66 #else
    67     , m_allowSubsampling(false)
    6862#endif
    6963    , m_isSolidColor(false)
     
    237231}
    238232
    239 void BitmapImage::updateSize(ImageOrientationDescription description) const
     233void BitmapImage::updateSize() const
    240234{
    241235    if (!m_sizeAvailable || m_haveSize)
    242236        return;
    243237
    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());
     238    m_size = m_source.size();
     239    m_sizeRespectingOrientation = m_source.sizeRespectingOrientation();
    249240
    250241    m_haveSize = true;
    251 
    252     determineMinimumSubsamplingLevel();
    253242    didDecodeProperties();
    254243}
     
    260249}
    261250
    262 IntSize BitmapImage::sizeRespectingOrientation(ImageOrientationDescription description) const
    263 {
    264     updateSize(description);
     251IntSize BitmapImage::sizeRespectingOrientation() const
     252{
     253    updateSize();
    265254    return m_sizeRespectingOrientation;
    266255}
     
    392381        return nullptr;
    393382
    394     SubsamplingLevel subsamplingLevel = std::min(m_source.subsamplingLevelForScale(presentationScaleHint), m_minimumSubsamplingLevel);
     383    SubsamplingLevel subsamplingLevel = m_source.subsamplingLevelForScale(presentationScaleHint);
    395384
    396385    // We may have cached a frame with a higher subsampling level, in which case we need to
     
    453442{
    454443    if (!ensureFrameIsCached(index, CacheMetadataOnly))
    455         return DefaultImageOrientation;
     444        return ImageOrientation();
    456445
    457446    if (m_frames[index].m_haveMetadata)
     
    711700    }
    712701   
    713     if (allowSubsampling())
    714         ts.dumpProperty("allow-subsampling", allowSubsampling());
    715702    if (m_isSolidColor)
    716703        ts.dumpProperty("solid-color", m_isSolidColor);
    717704   
    718     if (m_imageOrientation != OriginTopLeft)
    719         ts.dumpProperty("orientation", m_imageOrientation);
    720 }
    721 
    722 }
     705    m_source.dump(ts);
     706}
     707
     708}
  • trunk/Source/WebCore/platform/graphics/BitmapImage.h

    r198655 r198782  
    124124    // FloatSize due to override.
    125125    FloatSize size() const override;
    126     IntSize sizeRespectingOrientation(ImageOrientationDescription = ImageOrientationDescription()) const;
     126    IntSize sizeRespectingOrientation() const;
    127127
    128128    bool getHotSpot(IntPoint&) const override;
     
    180180    bool canAnimate();
    181181
    182     bool allowSubsampling() const { return m_allowSubsampling; }
    183     void setAllowSubsampling(bool allowSubsampling) { m_allowSubsampling = allowSubsampling; }
     182    void setAllowSubsampling(bool allowSubsampling) { m_source.setAllowSubsampling(allowSubsampling); }
    184183
    185184    size_t currentFrame() const { return m_currentFrame; }
     
    188187    bool isBitmapImage() const override { return true; }
    189188
    190     void updateSize(ImageOrientationDescription = ImageOrientationDescription()) const;
    191     void determineMinimumSubsamplingLevel() const;
     189    void updateSize() const;
    192190
    193191protected:
     
    296294    mutable IntSize m_sizeRespectingOrientation;
    297295
    298     mutable SubsamplingLevel m_minimumSubsamplingLevel;
    299 
    300     mutable unsigned m_imageOrientation : 4; // ImageOrientationEnum
    301     mutable unsigned m_shouldRespectImageOrientation : 1; // RespectImageOrientationEnum
    302 
    303296    size_t m_currentFrame; // The index of the current frame of animation.
    304297    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.
     
    328321    uint16_t m_progressiveLoadChunkCount;
    329322#endif
    330 
    331     bool m_allowSubsampling : 1; // Whether we should attempt subsampling if this image is very large.
    332323    bool m_isSolidColor : 1; // Whether or not we are a 1x1 solid image.
    333324    bool m_checkedForSolidColor : 1; // Whether we've checked the frame for solid color.
  • trunk/Source/WebCore/platform/graphics/GraphicsContext.h

    r198655 r198782  
    303303
    304304#if USE(CG) || USE(CAIRO)
    305     WEBCORE_EXPORT void drawNativeImage(const NativeImagePtr&, const FloatSize& selfSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, BlendMode = BlendModeNormal, ImageOrientation = DefaultImageOrientation);
     305    WEBCORE_EXPORT void drawNativeImage(const NativeImagePtr&, const FloatSize& selfSize, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver, BlendMode = BlendModeNormal, ImageOrientation = ImageOrientation());
    306306#endif
    307307
  • trunk/Source/WebCore/platform/graphics/ImageOrientation.h

    r154375 r198782  
    8585class ImageOrientation {
    8686public:
    87     ImageOrientation(ImageOrientationEnum orientation = DefaultImageOrientation)
     87    ImageOrientation()
     88        : m_orientation(DefaultImageOrientation)
     89    {
     90    }
     91
     92    explicit ImageOrientation(ImageOrientationEnum orientation)
    8893        : m_orientation(orientation)
    8994    {
     
    102107        // Values direct from images may be invalid, in which case we use the default.
    103108        if (exifValue < OriginTopLeft || exifValue > OriginLeftBottom)
    104             return DefaultImageOrientation;
    105         return static_cast<ImageOrientationEnum>(exifValue);
     109            return ImageOrientation();
     110        return ImageOrientation(static_cast<ImageOrientationEnum>(exifValue));
    106111    }
    107112
     
    110115    AffineTransform transformFromDefault(const FloatSize& drawnSize) const;
    111116
     117    inline operator ImageOrientationEnum() const { return m_orientation; }
     118   
    112119    inline bool operator==(const ImageOrientation& other) const { return other.m_orientation == m_orientation; }
    113120    inline bool operator!=(const ImageOrientation& other) const { return !(*this == other); }
  • trunk/Source/WebCore/platform/graphics/ImageSource.cpp

    r198655 r198782  
    4444
    4545ImageSource::ImageSource(ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
    46     : m_decoder(0)
    47     , m_alphaOption(alphaOption)
     46    : m_alphaOption(alphaOption)
    4847    , m_gammaAndColorProfileOption(gammaAndColorProfileOption)
    4948{
     
    6362    }
    6463
    65     delete m_decoder;
    66     m_decoder = 0;
     64    m_decoder = nullptr;
     65
    6766    if (data)
    6867        setData(data, allDataReceived);
    6968}
    7069
    71 bool ImageSource::initialized() const
    72 {
    73     return m_decoder;
    74 }
    75 
    76 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
    77 {
     70void ImageSource::ensureDecoderIsCreated(SharedBuffer* data)
     71{
     72    if (initialized())
     73        return;
     74   
    7875    // Make the decoder by sniffing the bytes.
    7976    // This method will examine the data and instantiate an instance of the appropriate decoder plugin.
    8077    // If insufficient bytes are available to determine the image type, no decoder plugin will be
    8178    // made.
    82     if (!m_decoder) {
    83         m_decoder = static_cast<NativeImageDecoderPtr>(NativeImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption));
     79    m_decoder = ImageDecoder::create(*data, m_alphaOption, m_gammaAndColorProfileOption);
    8480#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
    85         if (m_decoder && s_maxPixelsPerDecodedImage)
    86             m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage);
     81    if (m_decoder && s_maxPixelsPerDecodedImage)
     82        m_decoder->setMaxNumPixels(s_maxPixelsPerDecodedImage);
    8783#endif
     84}
     85
     86void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
     87{
     88    if (!data)
     89        return;
     90   
     91    ensureDecoderIsCreated(data);
     92   
     93    if (!initialized()) {
     94        ASSERT_NOT_REACHED();
     95        return;
    8896    }
    8997
     
    109117bool ImageSource::isSizeAvailable()
    110118{
    111     return m_decoder && m_decoder->isSizeAvailable();
    112 }
    113 
    114 IntSize ImageSource::size(ImageOrientationDescription description) const
    115 {
    116     return frameSizeAtIndex(0, 0, description);
    117 }
    118 
    119 IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel, ImageOrientationDescription description) const
    120 {
    121     if (!m_decoder)
    122         return IntSize();
     119    return initialized() && m_decoder->isSizeAvailable();
     120}
     121
     122IntSize ImageSource::size() const
     123{
     124    return frameSizeAtIndex(0, 0);
     125}
     126
     127IntSize ImageSource::sizeRespectingOrientation() const
     128{
     129    return frameSizeAtIndex(0, 0, RespectImageOrientation);
     130}
     131
     132IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel, RespectImageOrientationEnum shouldRespectImageOrientation) const
     133{
     134    if (!initialized())
     135        return { };
    123136
    124137    IntSize size = m_decoder->frameSizeAtIndex(index);
    125     if ((description.respectImageOrientation() == RespectImageOrientation) && m_decoder->orientation().usesWidthAsHeight())
    126         return IntSize(size.height(), size.width());
    127 
    128     return size;
     138    ImageOrientation orientation = m_decoder->orientation();
     139   
     140    return shouldRespectImageOrientation == RespectImageOrientation && orientation.usesWidthAsHeight() ? size.transposedSize() : size;
    129141}
    130142
    131143bool ImageSource::getHotSpot(IntPoint& hotSpot) const
    132144{
    133     return m_decoder ? m_decoder->hotSpot(hotSpot) : false;
     145    return initialized() && m_decoder->hotSpot(hotSpot);
    134146}
    135147
     
    141153int ImageSource::repetitionCount()
    142154{
    143     return m_decoder ? m_decoder->repetitionCount() : cAnimationNone;
     155    return initialized() ? m_decoder->repetitionCount() : cAnimationNone;
    144156}
    145157
    146158size_t ImageSource::frameCount() const
    147159{
    148     return m_decoder ? m_decoder->frameCount() : 0;
     160    return initialized() ? m_decoder->frameCount() : 0;
    149161}
    150162
    151163NativeImagePtr ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLevel)
    152164{
    153     if (!m_decoder)
    154         return nullptr;
    155 
    156     ImageFrame* buffer = m_decoder->frameBufferAtIndex(index);
    157     if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
     165    if (!initialized())
    158166        return nullptr;
    159167
     
    163171        return nullptr;
    164172
     173    ImageFrame* buffer = m_decoder->frameBufferAtIndex(index);
     174    if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
     175        return nullptr;
     176
    165177    // Return the buffer contents as a native image.  For some ports, the data
    166178    // is already in a native container, and this just increments its refcount.
     
    170182float ImageSource::frameDurationAtIndex(size_t index)
    171183{
    172     if (!m_decoder)
     184    if (!initialized())
    173185        return 0;
    174186
     
    189201ImageOrientation ImageSource::orientationAtIndex(size_t) const
    190202{
    191     return m_decoder ? m_decoder->orientation() : DefaultImageOrientation;
     203    return initialized() ? m_decoder->orientation() : ImageOrientation();
    192204}
    193205
    194206bool ImageSource::frameHasAlphaAtIndex(size_t index)
    195207{
    196     if (!m_decoder)
    197         return true;
    198     return m_decoder->frameHasAlphaAtIndex(index);
     208    return !initialized() || m_decoder->frameHasAlphaAtIndex(index);
    199209}
    200210
    201211bool ImageSource::frameIsCompleteAtIndex(size_t index)
    202212{
    203     if (!m_decoder)
     213    if (!initialized())
    204214        return false;
    205215
     
    210220unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel) const
    211221{
    212     if (!m_decoder)
    213         return 0;
    214     return m_decoder->frameBytesAtIndex(index);
    215 }
    216 
     222    return initialized() ? m_decoder->frameBytesAtIndex(index) : 0;
     223}
     224
     225void ImageSource::dump(TextStream& ts) const
     226{
     227    if (m_allowSubsampling)
     228        ts.dumpProperty("allow-subsampling", m_allowSubsampling);
     229   
     230    ImageOrientation orientation = orientationAtIndex(0);
     231    if (orientation != OriginTopLeft)
     232        ts.dumpProperty("orientation", orientation);
     233}
     234   
    217235}
    218236
  • trunk/Source/WebCore/platform/graphics/ImageSource.h

    r198655 r198782  
    3030#include "ImageOrientation.h"
    3131#include "NativeImagePtr.h"
     32#include "TextStream.h"
    3233
    3334#include <wtf/Forward.h>
     
    4647class IntSize;
    4748class SharedBuffer;
    48 
    49 #if USE(CG)
    50 typedef CGImageSourceRef NativeImageDecoderPtr;
    51 #else
    5249class ImageDecoder;
    53 typedef ImageDecoder* NativeImageDecoderPtr;
    54 #endif
    55 
    56 #if USE(CG)
    57 #define NativeImageDecoder ImageDecoder
    58 #else
    59 typedef ImageDecoder NativeImageDecoder;
    60 #endif
    6150
    6251// Right now GIFs are the only recognized image format that supports animation.
     
    8372class ImageSource {
    8473    WTF_MAKE_NONCOPYABLE(ImageSource);
     74    friend class BitmapImage;
    8575public:
    8676    enum AlphaOption {
     
    123113               bool allDataReceived = false);
    124114
    125     bool initialized() const;
     115    bool initialized() const { return m_decoder.get(); }
    126116
    127117    void setData(SharedBuffer* data, bool allDataReceived);
     
    130120    SubsamplingLevel subsamplingLevelForScale(float) const;
    131121    bool allowSubsamplingOfFrameAtIndex(size_t) const;
     122    void setAllowSubsampling(bool allowSubsampling) { m_allowSubsampling = allowSubsampling; }
     123    SubsamplingLevel maximumSubsamplingLevel() const;
    132124
    133125    bool isSizeAvailable();
     126   
    134127    // Always original size, without subsampling.
    135     IntSize size(ImageOrientationDescription = ImageOrientationDescription()) const;
     128    IntSize size() const;
     129    IntSize sizeRespectingOrientation() const;
     130   
    136131    // Size of optionally subsampled frame.
    137     IntSize frameSizeAtIndex(size_t, SubsamplingLevel = 0, ImageOrientationDescription = ImageOrientationDescription()) const;
     132    IntSize frameSizeAtIndex(size_t, SubsamplingLevel = 0, RespectImageOrientationEnum = DoNotRespectImageOrientation) const;
    138133
    139134    bool getHotSpot(IntPoint&) const;
     
    164159
    165160private:
    166     NativeImageDecoderPtr m_decoder;
     161    void ensureDecoderIsCreated(SharedBuffer*);
     162    SubsamplingLevel calculateMaximumSubsamplingLevel() const;
     163    void dump(TextStream&) const;
     164   
     165    std::unique_ptr<ImageDecoder> m_decoder;
     166   
     167#if PLATFORM(IOS)
     168    bool m_allowSubsampling { true };
     169#else
     170    bool m_allowSubsampling { false };
     171#endif
    167172
    168173#if !USE(CG)
  • trunk/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp

    r198655 r198782  
    4242    : Image(observer)
    4343    , m_size(cairoSurfaceSize(nativeImage.get()))
    44     , m_minimumSubsamplingLevel(0)
    4544    , m_currentFrame(0)
    4645    , m_repetitionCount(cAnimationNone)
     
    123122}
    124123
    125 void BitmapImage::determineMinimumSubsamplingLevel() const
    126 {
    127     m_minimumSubsamplingLevel = 0;
    128 }
    129 
    130124void BitmapImage::checkForSolidColor()
    131125{
  • trunk/Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp

    r198655 r198782  
    5656        m_haveMetadata = false;
    5757
    58     m_orientation = DefaultImageOrientation;
    5958    m_subsamplingLevel = 0;
    6059
     
    7170BitmapImage::BitmapImage(RetainPtr<CGImageRef>&& image, ImageObserver* observer)
    7271    : Image(observer)
    73     , m_minimumSubsamplingLevel(0)
    74     , m_imageOrientation(OriginTopLeft)
    75     , m_shouldRespectImageOrientation(false)
    7672    , m_currentFrame(0)
    7773    , m_repetitionCount(cAnimationNone)
     
    106102}
    107103
    108 void BitmapImage::determineMinimumSubsamplingLevel() const
    109 {
    110     if (!m_allowSubsampling)
    111         return;
    112 
    113     if (!m_source.allowSubsamplingOfFrameAtIndex(0))
    114         return;
    115 
    116     // Values chosen to be appropriate for iOS.
    117     const int cMaximumImageAreaBeforeSubsampling = 5 * 1024 * 1024;
    118     const SubsamplingLevel maxSubsamplingLevel = 3;
    119 
    120     SubsamplingLevel currentLevel = 0;
    121     for ( ; currentLevel <= maxSubsamplingLevel; ++currentLevel) {
    122         IntSize frameSize = m_source.frameSizeAtIndex(0, currentLevel);
    123         if (frameSize.area() < cMaximumImageAreaBeforeSubsampling)
    124             break;
    125     }
    126 
    127     m_minimumSubsamplingLevel = currentLevel;
    128 }
    129 
    130104void BitmapImage::checkForSolidColor()
    131105{
  • trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp

    r198655 r198782  
    5252
    5353namespace WebCore {
     54   
     55class ImageDecoder {
     56public:
     57    ImageDecoder();
     58   
     59    static std::unique_ptr<ImageDecoder> create()
     60    {
     61        return std::make_unique<ImageDecoder>();
     62    }
     63
     64    static size_t bytesDecodedToDetermineProperties();
     65    static SubsamplingLevel subsamplingLevelForScale(float scale, SubsamplingLevel maximumSubsamplingLevel);
     66
     67    String filenameExtension() const;
     68    bool isSizeAvailable() const;
     69   
     70    // Always original size, without subsampling.
     71    IntSize size() const;
     72    size_t frameCount() const;
     73    int repetitionCount() const;
     74    bool hotSpot(IntPoint& hotSpot) const;
     75
     76    IntSize frameSizeAtIndex(size_t, SubsamplingLevel) const;
     77    bool frameIsCompleteAtIndex(size_t) const;
     78    ImageOrientation orientationAtIndex(size_t) const;
     79
     80    float frameDurationAtIndex(size_t) const;
     81    bool frameHasAlphaAtIndex(size_t) const;
     82    bool allowSubsamplingOfFrameAtIndex(size_t) const;
     83    unsigned frameBytesAtIndex(size_t, SubsamplingLevel = 0) const;
     84
     85    NativeImagePtr createFrameImageAtIndex(size_t, SubsamplingLevel) const;
     86
     87    void setData(CFDataRef, bool allDataReceived);
     88    void setData(SharedBuffer*, bool allDataReceived);
     89
     90protected:
     91    mutable IntSize m_size;
     92    RetainPtr<CGImageSourceRef> m_nativeDecoder;
     93};
    5494
    5595const CFStringRef WebCoreCGImagePropertyAPNGUnclampedDelayTime = CFSTR("UnclampedDelayTime");
     
    5999const CFStringRef kCGImageSourceShouldPreferRGB32 = CFSTR("kCGImageSourceShouldPreferRGB32");
    60100const 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 
    83 ImageSource::ImageSource(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption)
    84     : m_decoder(0)
    85 {
    86     // FIXME: AlphaOption and GammaAndColorProfileOption are ignored.
    87 }
    88 
    89 ImageSource::~ImageSource()
    90 {
    91     clear(true);
    92 }
    93 
    94 void ImageSource::clear(bool destroyAllFrames, size_t, SharedBuffer* data, bool allDataReceived)
    95 {
    96     // Recent versions of ImageIO discard previously decoded image frames if the client
    97     // application no longer holds references to them, so there's no need to throw away
    98     // the decoder unless we're explicitly asked to destroy all of the frames.
    99     if (!destroyAllFrames)
    100         return;
    101 
    102     if (m_decoder) {
    103         CFRelease(m_decoder);
    104         m_decoder = 0;
    105     }
    106     if (data)
    107         setData(data, allDataReceived);
    108 }
    109101
    110102static RetainPtr<CFDictionaryRef> createImageSourceOptions(SubsamplingLevel subsamplingLevel)
     
    136128}
    137129
    138 bool ImageSource::initialized() const
    139 {
    140     return m_decoder;
    141 }
    142 
    143 void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
    144 {
    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
    163 }
    164 
    165 String ImageSource::filenameExtension() const
    166 {
    167     if (!m_decoder)
    168         return String();
    169     CFStringRef imageSourceType = CGImageSourceGetType(m_decoder);
    170     return WebCore::preferredExtensionForImageSourceType(imageSourceType);
    171 }
    172 
    173 SubsamplingLevel ImageSource::subsamplingLevelForScale(float scale) const
    174 {
    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;
    180 }
    181 
    182 bool ImageSource::isSizeAvailable()
    183 {
    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);
    194 }
    195 
    196130static ImageOrientation orientationFromProperties(CFDictionaryRef imageProperties)
    197131{
     
    199133    CFNumberRef orientationProperty = (CFNumberRef)CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation);
    200134    if (!orientationProperty)
    201         return DefaultImageOrientation;
     135        return ImageOrientation();
    202136
    203137    int exifValue;
     
    206140}
    207141
    208 bool ImageSource::allowSubsamplingOfFrameAtIndex(size_t) const
    209 {
    210     RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions().get()));
     142#if !PLATFORM(COCOA)
     143size_t sharedBufferGetBytesAtPosition(void* info, void* buffer, off_t position, size_t count)
     144{
     145    SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
     146    size_t sourceSize = sharedBuffer->size();
     147    if (position >= sourceSize)
     148        return 0;
     149
     150    const char* source = sharedBuffer->data() + position;
     151    size_t amount = std::min<size_t>(count, sourceSize - position);
     152    memcpy(buffer, source, amount);
     153    return amount;
     154}
     155
     156void sharedBufferRelease(void* info)
     157{
     158    SharedBuffer* sharedBuffer = static_cast<SharedBuffer*>(info);
     159    sharedBuffer->deref();
     160}
     161#endif
     162   
     163ImageDecoder::ImageDecoder()
     164{
     165    m_nativeDecoder = adoptCF(CGImageSourceCreateIncremental(nullptr));
     166}
     167   
     168SubsamplingLevel ImageDecoder::subsamplingLevelForScale(float scale, SubsamplingLevel maximumSubsamplingLevel)
     169{
     170    // There are four subsampling levels: 0 = 1x, 1 = 0.5x, 2 = 0.25x, 3 = 0.125x.
     171    float clampedScale = std::max<float>(0.125, std::min<float>(1, scale));
     172    SubsamplingLevel result = ceilf(log2f(1 / clampedScale));
     173    ASSERT(result >=0 && result <= 3);
     174    return std::min(result, maximumSubsamplingLevel);
     175}
     176
     177size_t ImageDecoder::bytesDecodedToDetermineProperties()
     178{
     179    // Measured by tracing malloc/calloc calls on Mac OS 10.6.6, x86_64.
     180    // A non-zero value ensures cached images with no decoded frames still enter
     181    // the live decoded resources list when the CGImageSource decodes image
     182    // properties, allowing the cache to prune the partially decoded image.
     183    // This value is likely to be inaccurate on other platforms, but the overall
     184    // behavior is unchanged.
     185    return 13088;
     186}
     187   
     188String ImageDecoder::filenameExtension() const
     189{
     190    CFStringRef imageSourceType = CGImageSourceGetType(m_nativeDecoder.get());
     191    return WebCore::preferredExtensionForImageSourceType(imageSourceType);
     192}
     193
     194bool ImageDecoder::isSizeAvailable() const
     195{
     196    // Ragnaros yells: TOO SOON! You have awakened me TOO SOON, Executus!
     197    if (CGImageSourceGetStatus(m_nativeDecoder.get()) < kCGImageStatusIncomplete)
     198        return false;
     199
     200    RetainPtr<CFDictionaryRef> image0Properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder.get(), 0, imageSourceOptions().get()));
     201    if (!image0Properties)
     202        return false;
     203
     204    return CFDictionaryContainsKey(image0Properties.get(), kCGImagePropertyPixelWidth)
     205        && CFDictionaryContainsKey(image0Properties.get(), kCGImagePropertyPixelHeight);
     206}
     207
     208IntSize ImageDecoder::size() const
     209{
     210    if (m_size.isEmpty())
     211        m_size = frameSizeAtIndex(0, 0);
     212    return m_size;
     213}
     214
     215size_t ImageDecoder::frameCount() const
     216{
     217    return CGImageSourceGetCount(m_nativeDecoder.get());
     218}
     219
     220int ImageDecoder::repetitionCount() const
     221{
     222    RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyProperties(m_nativeDecoder.get(), imageSourceOptions().get()));
     223    if (!properties)
     224        return cAnimationLoopOnce;
     225
     226    CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
     227    if (gifProperties) {
     228        CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFLoopCount);
     229
     230        // No property means loop once.
     231        if (!num)
     232            return cAnimationLoopOnce;
     233
     234        int loopCount;
     235        CFNumberGetValue(num, kCFNumberIntType, &loopCount);
     236
     237        // A property with value 0 means loop forever.
     238        return loopCount ? loopCount : cAnimationLoopInfinite;
     239    }
     240
     241    CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary);
     242    if (pngProperties) {
     243        CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGLoopCount);
     244        if (!num)
     245            return cAnimationLoopOnce;
     246
     247        int loopCount;
     248        CFNumberGetValue(num, kCFNumberIntType, &loopCount);
     249        return loopCount ? loopCount : cAnimationLoopInfinite;
     250    }
     251
     252    // Turns out we're not an animated image after all, so we don't animate.
     253    return cAnimationNone;
     254}
     255
     256bool ImageDecoder::hotSpot(IntPoint& hotSpot) const
     257{
     258    RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder.get(), 0, imageSourceOptions().get()));
     259    if (!properties)
     260        return false;
     261
     262    int x = -1, y = -1;
     263    CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotX"));
     264    if (!num || !CFNumberGetValue(num, kCFNumberIntType, &x))
     265        return false;
     266
     267    num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotY"));
     268    if (!num || !CFNumberGetValue(num, kCFNumberIntType, &y))
     269        return false;
     270
     271    if (x < 0 || y < 0)
     272        return false;
     273
     274    hotSpot = IntPoint(x, y);
     275    return true;
     276}
     277
     278IntSize ImageDecoder::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
     279{
     280    RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder.get(), index, imageSourceOptions(subsamplingLevel).get()));
     281
     282    if (!properties)
     283        return { };
     284
     285    int width = 0;
     286    int height = 0;
     287    CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth);
     288    if (num)
     289        CFNumberGetValue(num, kCFNumberIntType, &width);
     290
     291    num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight);
     292    if (num)
     293        CFNumberGetValue(num, kCFNumberIntType, &height);
     294
     295    return IntSize(width, height);
     296}
     297
     298bool ImageDecoder::frameIsCompleteAtIndex(size_t index) const
     299{
     300    ASSERT(frameCount());
     301    return CGImageSourceGetStatusAtIndex(m_nativeDecoder.get(), index) == kCGImageStatusComplete;
     302}
     303
     304ImageOrientation ImageDecoder::orientationAtIndex(size_t index) const
     305{
     306    RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder.get(), index, imageSourceOptions().get()));
     307    if (!properties)
     308        return ImageOrientation();
     309
     310    return orientationFromProperties(properties.get());
     311}
     312
     313float ImageDecoder::frameDurationAtIndex(size_t index) const
     314{
     315    float duration = 0;
     316    RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder.get(), index, imageSourceOptions().get()));
     317    if (properties) {
     318        CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
     319        if (gifProperties) {
     320            if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFUnclampedDelayTime)) {
     321                // Use the unclamped frame delay if it exists.
     322                CFNumberGetValue(num, kCFNumberFloatType, &duration);
     323            } else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime)) {
     324                // Fall back to the clamped frame delay if the unclamped frame delay does not exist.
     325                CFNumberGetValue(num, kCFNumberFloatType, &duration);
     326            }
     327        }
     328
     329        CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary);
     330        if (pngProperties) {
     331            if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGUnclampedDelayTime))
     332                CFNumberGetValue(num, kCFNumberFloatType, &duration);
     333            else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGDelayTime))
     334                CFNumberGetValue(num, kCFNumberFloatType, &duration);
     335        }
     336    }
     337
     338    // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
     339    // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
     340    // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
     341    // for more information.
     342    if (duration < 0.011f)
     343        return 0.1f;
     344    return duration;
     345}
     346
     347bool ImageDecoder::allowSubsamplingOfFrameAtIndex(size_t) const
     348{
     349    RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_nativeDecoder.get(), 0, imageSourceOptions().get()));
    211350    if (!properties)
    212351        return false;
     
    228367}
    229368
    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)
    235         return IntSize();
    236 
    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);
    248 
    249     return IntSize(width, height);
    250 }
    251 
    252 ImageOrientation ImageSource::orientationAtIndex(size_t index) const
    253 {
    254     RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions().get()));
    255     if (!properties)
    256         return DefaultImageOrientation;
    257 
    258     return orientationFromProperties(properties.get());
    259 }
    260 
    261 IntSize ImageSource::size(ImageOrientationDescription description) const
    262 {
    263     return frameSizeAtIndex(0, 0, description);
    264 }
    265 
    266 bool ImageSource::getHotSpot(IntPoint& hotSpot) const
    267 {
    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);
     369bool ImageDecoder::frameHasAlphaAtIndex(size_t index) const
     370{
     371    if (!frameIsCompleteAtIndex(index))
     372        return true;
     373
     374    CFStringRef imageType = CGImageSourceGetType(m_nativeDecoder.get());
     375
     376    // Return false if there is no image type or the image type is JPEG, because
     377    // JPEG does not support alpha transparency.
     378    if (!imageType || CFEqual(imageType, CFSTR("public.jpeg")))
     379        return false;
     380
     381    // FIXME: Could return false for other non-transparent image formats.
     382    // FIXME: Could maybe return false for a GIF Frame if we have enough info in the GIF properties dictionary
     383    // to determine whether or not a transparent color was defined.
    285384    return true;
    286385}
    287386
    288 size_t ImageSource::bytesDecodedToDetermineProperties() const
    289 {
    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;
    297 }
    298    
    299 int ImageSource::repetitionCount()
    300 {
    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;
    336 }
    337 
    338 size_t ImageSource::frameCount() const
    339 {
    340     return m_decoder ? CGImageSourceGetCount(m_decoder) : 0;
    341 }
    342 
    343 RetainPtr<CGImageRef> ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
    344 {
    345     if (!initialized())
    346         return nullptr;
    347 
    348     RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_decoder, index, imageSourceOptions(subsamplingLevel).get()));
     387unsigned ImageDecoder::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
     388{
     389    IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel);
     390    return frameSize.area() * 4;
     391}
     392
     393NativeImagePtr ImageDecoder::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
     394{
     395    RetainPtr<CGImageRef> image = adoptCF(CGImageSourceCreateImageAtIndex(m_nativeDecoder.get(), index, imageSourceOptions(subsamplingLevel).get()));
    349396
    350397#if PLATFORM(IOS)
     
    357404#pragma clang diagnostic ignored "-Wdeprecated-declarations"
    358405#endif
    359     CGImageSetCachingFlags(image.get(), kCGImageCachingTemporary);
     406        CGImageSetCachingFlags(image.get(), kCGImageCachingTemporary);
    360407#if COMPILER(CLANG)
    361408#pragma clang diagnostic pop
     
    363410#endif // PLATFORM(IOS)
    364411
    365     CFStringRef imageUTI = CGImageSourceGetType(m_decoder);
     412    CFStringRef imageUTI = CGImageSourceGetType(m_nativeDecoder.get());
    366413    static const CFStringRef xbmUTI = CFSTR("public.xbitmap-image");
    367414
     
    371418    if (!CFEqual(imageUTI, xbmUTI))
    372419        return image;
    373    
     420
    374421    // If it is an xbm image, mask out all the white areas to render them transparent.
    375422    const CGFloat maskingColors[6] = {255, 255,  255, 255, 255, 255};
     
    378425}
    379426
     427void ImageDecoder::setData(CFDataRef data, bool allDataReceived)
     428{
     429    CGImageSourceUpdateData(m_nativeDecoder.get(), data, allDataReceived);
     430}
     431
     432void ImageDecoder::setData(SharedBuffer* data, bool allDataReceived)
     433{
     434#if PLATFORM(COCOA)
     435    // On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge.
     436    // We use SharedBuffer's ability to wrap itself inside CFData to get around this, ensuring that ImageIO is
     437    // really looking at the SharedBuffer.
     438    setData(data->createCFData().get(), allDataReceived);
     439    CGImageSourceUpdateData(m_nativeDecoder.get(), data->createCFData().get(), allDataReceived);
     440#else
     441    // Create a CGDataProvider to wrap the SharedBuffer.
     442    data->ref();
     443    // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer
     444    // does not provide a way to lock down the byte pointer and guarantee that it won't move, which
     445    // is a requirement for using the GetBytePointer callback.
     446    CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, sharedBufferRelease };
     447    RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateDirect(data, data->size(), &providerCallbacks));
     448    CGImageSourceUpdateDataProvider(m_nativeDecoder.get(), dataProvider.get(), allDataReceived);
     449#endif
     450}
     451
     452ImageSource::ImageSource(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption)
     453{
     454    // FIXME: AlphaOption and GammaAndColorProfileOption are ignored.
     455}
     456
     457ImageSource::~ImageSource()
     458{
     459    clear(true);
     460}
     461
     462void ImageSource::clear(bool destroyAllFrames, size_t, SharedBuffer* data, bool allDataReceived)
     463{
     464    // Recent versions of ImageIO discard previously decoded image frames if the client
     465    // application no longer holds references to them, so there's no need to throw away
     466    // the decoder unless we're explicitly asked to destroy all of the frames.
     467    if (!destroyAllFrames)
     468        return;
     469
     470    m_decoder = nullptr;
     471   
     472    if (data)
     473        setData(data, allDataReceived);
     474}
     475   
     476void ImageSource::ensureDecoderIsCreated(SharedBuffer*)
     477{
     478    if (initialized())
     479        return;
     480    m_decoder = ImageDecoder::create();
     481}
     482
     483void ImageSource::setData(SharedBuffer* data, bool allDataReceived)
     484{
     485    if (!data)
     486        return;
     487   
     488    ensureDecoderIsCreated(data);
     489   
     490    if (!initialized()) {
     491        ASSERT_NOT_REACHED();
     492        return;
     493    }
     494   
     495    m_decoder->setData(data, allDataReceived);
     496}
     497
     498String ImageSource::filenameExtension() const
     499{
     500    return initialized() ? m_decoder->filenameExtension() : String();
     501}
     502   
     503SubsamplingLevel ImageSource::calculateMaximumSubsamplingLevel() const
     504{
     505    if (!m_allowSubsampling || !allowSubsamplingOfFrameAtIndex(0))
     506        return 0;
     507
     508    // Values chosen to be appropriate for iOS.
     509    const int cMaximumImageAreaBeforeSubsampling = 5 * 1024 * 1024;
     510    const SubsamplingLevel maxSubsamplingLevel = 3;
     511
     512    SubsamplingLevel currentLevel = 0;
     513    for ( ; currentLevel <= maxSubsamplingLevel; ++currentLevel) {
     514        IntSize frameSize = frameSizeAtIndex(0, currentLevel);
     515        if (frameSize.area() < cMaximumImageAreaBeforeSubsampling)
     516            break;
     517    }
     518
     519    return currentLevel;
     520}
     521   
     522SubsamplingLevel ImageSource::maximumSubsamplingLevel() const
     523{
     524#if PLATFORM(IOS)
     525    return calculateMaximumSubsamplingLevel();
     526#endif
     527    return 0;
     528}
     529
     530SubsamplingLevel ImageSource::subsamplingLevelForScale(float scale) const
     531{
     532    return ImageDecoder::subsamplingLevelForScale(scale, maximumSubsamplingLevel());
     533}
     534
     535bool ImageSource::isSizeAvailable()
     536{
     537    return initialized() && m_decoder->isSizeAvailable();
     538}
     539
     540bool ImageSource::allowSubsamplingOfFrameAtIndex(size_t index) const
     541{
     542    return initialized() && m_decoder->allowSubsamplingOfFrameAtIndex(index);
     543}
     544
     545IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel, RespectImageOrientationEnum shouldRespectImageOrientation) const
     546{
     547    if (!initialized())
     548        return { };
     549   
     550    IntSize size = m_decoder->frameSizeAtIndex(index, subsamplingLevel);
     551    ImageOrientation orientation = m_decoder->orientationAtIndex(index);
     552   
     553    return shouldRespectImageOrientation == RespectImageOrientation && orientation.usesWidthAsHeight() ? size.transposedSize() : size;
     554}
     555
     556ImageOrientation ImageSource::orientationAtIndex(size_t index) const
     557{
     558    return initialized() ? m_decoder->orientationAtIndex(index) : ImageOrientation();
     559}
     560
     561IntSize ImageSource::size() const
     562{
     563    return frameSizeAtIndex(0, 0);
     564}
     565   
     566IntSize ImageSource::sizeRespectingOrientation() const
     567{
     568    return frameSizeAtIndex(0, 0, RespectImageOrientation);
     569}
     570
     571bool ImageSource::getHotSpot(IntPoint& hotSpot) const
     572{
     573    return initialized() && m_decoder->hotSpot(hotSpot);
     574}
     575
     576size_t ImageSource::bytesDecodedToDetermineProperties() const
     577{
     578    return ImageDecoder::bytesDecodedToDetermineProperties();
     579}
     580   
     581int ImageSource::repetitionCount()
     582{
     583    return initialized() ? m_decoder->repetitionCount() : cAnimationLoopOnce;
     584}
     585
     586size_t ImageSource::frameCount() const
     587{
     588    return initialized() ? m_decoder->frameCount() : 0;
     589}
     590
     591RetainPtr<CGImageRef> ImageSource::createFrameImageAtIndex(size_t index, SubsamplingLevel subsamplingLevel)
     592{
     593    return initialized() ? m_decoder->createFrameImageAtIndex(index, subsamplingLevel) : nullptr;
     594}
     595
    380596bool ImageSource::frameIsCompleteAtIndex(size_t index)
    381597{
    382     ASSERT(frameCount());
    383     return CGImageSourceGetStatusAtIndex(m_decoder, index) == kCGImageStatusComplete;
     598    return initialized() && m_decoder->frameIsCompleteAtIndex(index);
    384599}
    385600
    386601float ImageSource::frameDurationAtIndex(size_t index)
    387602{
    388     if (!initialized())
    389         return 0;
    390 
    391     float duration = 0;
    392     RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions().get()));
    393     if (properties) {
    394         CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary);
    395         if (gifProperties) {
    396             if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFUnclampedDelayTime)) {
    397                 // Use the unclamped frame delay if it exists.
    398                 CFNumberGetValue(num, kCFNumberFloatType, &duration);
    399             } else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime)) {
    400                 // Fall back to the clamped frame delay if the unclamped frame delay does not exist.
    401                 CFNumberGetValue(num, kCFNumberFloatType, &duration);
    402             }
    403         }
    404 
    405         CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary);
    406         if (pngProperties) {
    407             if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGUnclampedDelayTime))
    408                 CFNumberGetValue(num, kCFNumberFloatType, &duration);
    409             else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGDelayTime))
    410                 CFNumberGetValue(num, kCFNumberFloatType, &duration);
    411         }
    412     }
    413 
    414     // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
    415     // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
    416     // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
    417     // for more information.
    418     if (duration < 0.011f)
    419         return 0.1f;
    420     return duration;
     603    return initialized() ? m_decoder->frameDurationAtIndex(index) : 0;
    421604}
    422605
    423606bool ImageSource::frameHasAlphaAtIndex(size_t index)
    424607{
    425     if (!m_decoder)
    426         return false; // FIXME: why doesn't this return true?
    427 
    428     if (!frameIsCompleteAtIndex(index))
    429         return true;
    430 
    431     CFStringRef imageType = CGImageSourceGetType(m_decoder);
    432 
    433     // Return false if there is no image type or the image type is JPEG, because
    434     // JPEG does not support alpha transparency.
    435     if (!imageType || CFEqual(imageType, CFSTR("public.jpeg")))
    436         return false;
    437 
    438     // FIXME: Could return false for other non-transparent image formats.
    439     // FIXME: Could maybe return false for a GIF Frame if we have enough info in the GIF properties dictionary
    440     // to determine whether or not a transparent color was defined.
    441     return true;
     608    return !initialized() || m_decoder->frameHasAlphaAtIndex(index);
    442609}
    443610
    444611unsigned ImageSource::frameBytesAtIndex(size_t index, SubsamplingLevel subsamplingLevel) const
    445612{
    446     IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel, ImageOrientationDescription(RespectImageOrientation));
    447     return frameSize.width() * frameSize.height() * 4;
     613    IntSize frameSize = frameSizeAtIndex(index, subsamplingLevel);
     614    return frameSize.area() * 4;
     615}
     616   
     617void ImageSource::dump(TextStream& ts) const
     618{
     619    if (m_allowSubsampling)
     620        ts.dumpProperty("allow-subsampling", m_allowSubsampling);
     621   
     622    ImageOrientation orientation = orientationAtIndex(0);
     623    if (orientation != OriginTopLeft)
     624        ts.dumpProperty("orientation", orientation);
    448625}
    449626
  • trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp

    r156795 r198782  
    9696}
    9797
    98 ImageDecoder* ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
     98std::unique_ptr<ImageDecoder> ImageDecoder::create(const SharedBuffer& data, ImageSource::AlphaOption alphaOption, ImageSource::GammaAndColorProfileOption gammaAndColorProfileOption)
    9999{
    100100    static const unsigned lengthOfLongestSignature = 14; // To wit: "RIFF????WEBPVP"
     
    102102    unsigned length = copyFromSharedBuffer(contents, lengthOfLongestSignature, data, 0);
    103103    if (length < lengthOfLongestSignature)
    104         return 0;
     104        return nullptr;
    105105
    106106    if (matchesGIFSignature(contents))
    107         return new GIFImageDecoder(alphaOption, gammaAndColorProfileOption);
     107        return std::unique_ptr<ImageDecoder> { std::make_unique<GIFImageDecoder>(alphaOption, gammaAndColorProfileOption) };
    108108
    109109    if (matchesPNGSignature(contents))
    110         return new PNGImageDecoder(alphaOption, gammaAndColorProfileOption);
     110        return std::unique_ptr<ImageDecoder> { std::make_unique<PNGImageDecoder>(alphaOption, gammaAndColorProfileOption) };
    111111
    112112    if (matchesICOSignature(contents) || matchesCURSignature(contents))
    113         return new ICOImageDecoder(alphaOption, gammaAndColorProfileOption);
     113        return std::unique_ptr<ImageDecoder> { std::make_unique<ICOImageDecoder>(alphaOption, gammaAndColorProfileOption) };
    114114
    115115    if (matchesJPEGSignature(contents))
    116         return new JPEGImageDecoder(alphaOption, gammaAndColorProfileOption);
     116        return std::unique_ptr<ImageDecoder> { std::make_unique<JPEGImageDecoder>(alphaOption, gammaAndColorProfileOption) };
    117117
    118118#if USE(WEBP)
    119119    if (matchesWebPSignature(contents))
    120         return new WEBPImageDecoder(alphaOption, gammaAndColorProfileOption);
     120        return std::unique_ptr<ImageDecoder> { std::make_unique<WEBPImageDecoder>(alphaOption, gammaAndColorProfileOption) };
    121121#endif
    122122
    123123    if (matchesBMPSignature(contents))
    124         return new BMPImageDecoder(alphaOption, gammaAndColorProfileOption);
    125 
    126     return 0;
     124        return std::unique_ptr<ImageDecoder> { std::make_unique<BMPImageDecoder>(alphaOption, gammaAndColorProfileOption) };
     125
     126    return nullptr;
    127127}
    128128
  • trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h

    r198655 r198782  
    249249        // we can't sniff a supported type from the provided data (possibly
    250250        // because there isn't enough data yet).
    251         static ImageDecoder* create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
     251        static std::unique_ptr<ImageDecoder> create(const SharedBuffer& data, ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
    252252
    253253        virtual String filenameExtension() const = 0;
  • trunk/Source/WebCore/platform/mac/DragImageMac.mm

    r197789 r198782  
    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)
Note: See TracChangeset for help on using the changeset viewer.