Title: [201424] trunk/Source/WebCore
Revision
201424
Author
commit-qu...@webkit.org
Date
2016-05-26 11:46:02 -0700 (Thu, 26 May 2016)

Log Message

BitmapImage::checkForSolidColor() cleanup
https://bugs.webkit.org/show_bug.cgi?id=157750

Patch by Said Abou-Hallawa <sabouhallawa@apple,com> on 2016-05-26
Reviewed by Darin Adler.

Have a single implementation for BitmapImage::checkForSolidColor(). Create
a new function named NativeImage::solidColor() and call it from the former
one. The goal is to have the platform files contain only the platform dependent
code rather than repeating the platform independent code multiple times.

* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::destroyMetadataAndNotify): Invalidate m_solidColor.
(WebCore::BitmapImage::singlePixelSolidColor): Combine mayFillWithSolidColor(),
checkForSolidColor() and solidColor() in one function to guarantee the validity
of the returned value. Before, if solidColor() is called without calling
mayFillWithSolidColor() or checkForSolidColor(), the returned value would be
incorrect.

(WebCore::BitmapImage::dump): Use the m_solidColor Optional and Color states.
(WebCore::BitmapImage::mayFillWithSolidColor): Deleted.
(WebCore::BitmapImage::solidColor): Deleted.

* platform/graphics/BitmapImage.h: Delete m_checkedForSolidColor and
m_isSolidColor and change m_solidColor to be Optional<Color>.

* platform/graphics/Image.cpp:
(WebCore::Image::drawTiled): Use singlePixelSolidColor() and check the returned
value to know whether the singe pixel solid color optimization applies or not.

* platform/graphics/Image.h:
(WebCore::Image::singlePixelSolidColor):
(WebCore::Image::mayFillWithSolidColor): Deleted.
(WebCore::Image::solidColor): Deleted.
Replace mayFillWithSolidColor() and solidColor() with a single function named
singlePixelSolidColor(). isValid() of the returned Color can be used to tell
whether the singe pixel solid color optimization applies or not.

* platform/graphics/cairo/BitmapImageCairo.cpp:
(WebCore::NativeImage::singlePixelSolidColor):
(WebCore::BitmapImage::draw):
(WebCore::BitmapImage::checkForSolidColor): Deleted.
Delete the platform dependent BitmapImage::checkForSolidColor() and add
the new platform dependent function NativeImage::singlePixelSolidColor() and
use to know whether the singe pixel solid color optimization applies or not.

* platform/graphics/cg/BitmapImageCG.cpp:
(WebCore::NativeImage::singlePixelSolidColor):
(WebCore::BitmapImage::draw):
(WebCore::BitmapImage::checkForSolidColor): Deleted.
Ditto.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (201423 => 201424)


--- trunk/Source/WebCore/ChangeLog	2016-05-26 18:19:30 UTC (rev 201423)
+++ trunk/Source/WebCore/ChangeLog	2016-05-26 18:46:02 UTC (rev 201424)
@@ -1,3 +1,56 @@
+2016-05-26  Said Abou-Hallawa  <sabouhallawa@apple,com>
+
+        BitmapImage::checkForSolidColor() cleanup
+        https://bugs.webkit.org/show_bug.cgi?id=157750
+
+        Reviewed by Darin Adler.
+
+        Have a single implementation for BitmapImage::checkForSolidColor(). Create
+        a new function named NativeImage::solidColor() and call it from the former
+        one. The goal is to have the platform files contain only the platform dependent
+        code rather than repeating the platform independent code multiple times.
+
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::destroyMetadataAndNotify): Invalidate m_solidColor.
+        (WebCore::BitmapImage::singlePixelSolidColor): Combine mayFillWithSolidColor(),
+        checkForSolidColor() and solidColor() in one function to guarantee the validity
+        of the returned value. Before, if solidColor() is called without calling
+        mayFillWithSolidColor() or checkForSolidColor(), the returned value would be
+        incorrect.
+        
+        (WebCore::BitmapImage::dump): Use the m_solidColor Optional and Color states.
+        (WebCore::BitmapImage::mayFillWithSolidColor): Deleted.
+        (WebCore::BitmapImage::solidColor): Deleted.
+        
+        * platform/graphics/BitmapImage.h: Delete m_checkedForSolidColor and
+        m_isSolidColor and change m_solidColor to be Optional<Color>.
+        
+        * platform/graphics/Image.cpp:
+        (WebCore::Image::drawTiled): Use singlePixelSolidColor() and check the returned
+        value to know whether the singe pixel solid color optimization applies or not.
+        
+        * platform/graphics/Image.h:
+        (WebCore::Image::singlePixelSolidColor):
+        (WebCore::Image::mayFillWithSolidColor): Deleted.
+        (WebCore::Image::solidColor): Deleted.
+        Replace mayFillWithSolidColor() and solidColor() with a single function named
+        singlePixelSolidColor(). isValid() of the returned Color can be used to tell
+        whether the singe pixel solid color optimization applies or not.
+        
+        * platform/graphics/cairo/BitmapImageCairo.cpp:
+        (WebCore::NativeImage::singlePixelSolidColor):
+        (WebCore::BitmapImage::draw):
+        (WebCore::BitmapImage::checkForSolidColor): Deleted.
+        Delete the platform dependent BitmapImage::checkForSolidColor() and add
+        the new platform dependent function NativeImage::singlePixelSolidColor() and
+        use to know whether the singe pixel solid color optimization applies or not.
+        
+        * platform/graphics/cg/BitmapImageCG.cpp:
+        (WebCore::NativeImage::singlePixelSolidColor):
+        (WebCore::BitmapImage::draw):
+        (WebCore::BitmapImage::checkForSolidColor): Deleted.
+        Ditto.
+
 2016-05-26  Pranjal Jumde  <pju...@apple.com>
 
         Sites served over insecure connections should not be allowed to use geolocation.

Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (201423 => 201424)


--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp	2016-05-26 18:19:30 UTC (rev 201423)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp	2016-05-26 18:46:02 UTC (rev 201424)
@@ -48,8 +48,6 @@
 
 BitmapImage::BitmapImage(ImageObserver* observer)
     : Image(observer)
-    , m_isSolidColor(false)
-    , m_checkedForSolidColor(false)
     , m_animationFinished(false)
     , m_allDataReceived(false)
     , m_haveSize(false)
@@ -63,8 +61,6 @@
     : Image(observer)
     , m_source(image)
     , m_frameCount(1)
-    , m_isSolidColor(false)
-    , m_checkedForSolidColor(false)
     , m_animationFinished(true)
     , m_allDataReceived(true)
     , m_haveSize(true)
@@ -81,8 +77,6 @@
     m_frames[0].m_hasAlpha = NativeImage::hasAlpha(image);
     m_frames[0].m_haveMetadata = true;
     m_frames[0].m_image = WTFMove(image);
-    
-    checkForSolidColor();
 }
 
 BitmapImage::~BitmapImage()
@@ -167,8 +161,7 @@
 
 void BitmapImage::destroyMetadataAndNotify(unsigned frameBytesCleared, ClearedSource clearedSource)
 {
-    m_isSolidColor = false;
-    m_checkedForSolidColor = false;
+    m_solidColor = Nullopt;
     invalidatePlatformData();
 
     ASSERT(m_decodedSize >= frameBytesCleared);
@@ -195,8 +188,6 @@
     if (frameCaching == CacheMetadataAndFrame) {
         m_frames[index].m_image = m_source.createFrameImageAtIndex(index, subsamplingLevel);
         m_frames[index].m_subsamplingLevel = subsamplingLevel;
-        if (numFrames == 1 && m_frames[index].m_image)
-            checkForSolidColor();
     }
 
     m_frames[index].m_orientation = m_source.orientationAtIndex(index);
@@ -689,18 +680,30 @@
     return advancedAnimation;
 }
 
-bool BitmapImage::mayFillWithSolidColor()
+Color BitmapImage::singlePixelSolidColor()
 {
-    if (!m_checkedForSolidColor && frameCount() > 0) {
-        checkForSolidColor();
-        ASSERT(m_checkedForSolidColor);
+    // If the image size is not available yet or if the image will be animating don't use the solid color optimization.
+    if (frameCount() != 1)
+        return Color();
+    
+    if (m_solidColor)
+        return m_solidColor.value();
+
+    // If the frame image is not loaded, first use the decoder to get the size of the image.
+    if (!haveFrameImageAtIndex(0) && m_source.frameSizeAtIndex(0, 0) != IntSize(1, 1)) {
+        m_solidColor = Color();
+        return m_solidColor.value();
     }
-    return m_isSolidColor && !m_currentFrame;
-}
 
-Color BitmapImage::solidColor() const
-{
-    return m_solidColor;
+    // Cache the frame image. The size will be calculated from the NativeImagePtr.
+    if (!ensureFrameIsCached(0))
+        return Color();
+    
+    ASSERT(m_frames.size());
+    m_solidColor = NativeImage::singlePixelSolidColor(m_frames[0].m_image.get());
+    
+    ASSERT(m_solidColor);
+    return m_solidColor.value();
 }
     
 bool BitmapImage::canAnimate()
@@ -720,8 +723,8 @@
         ts.dumpProperty("current-frame", m_currentFrame);
     }
     
-    if (m_isSolidColor)
-        ts.dumpProperty("solid-color", m_isSolidColor);
+    if (m_solidColor)
+        ts.dumpProperty("solid-color", m_solidColor.value());
     
     m_source.dump(ts);
 }

Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.h (201423 => 201424)


--- trunk/Source/WebCore/platform/graphics/BitmapImage.h	2016-05-26 18:19:30 UTC (rev 201423)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.h	2016-05-26 18:46:02 UTC (rev 201424)
@@ -63,6 +63,7 @@
 namespace NativeImage {
     IntSize size(const NativeImagePtr&);
     bool hasAlpha(const NativeImagePtr&);
+    Color singlePixelSolidColor(const NativeImagePtr&);
 }
 
 // ================================================
@@ -274,14 +275,8 @@
     // Handle platform-specific data
     void invalidatePlatformData();
 
-    // Checks to see if the image is a 1x1 solid color. We optimize these images and just do a fill rect instead.
-    // This check should happen regardless whether m_checkedForSolidColor is already set, as the frame may have
-    // changed.
-    void checkForSolidColor();
+    Color singlePixelSolidColor() override;
 
-    bool mayFillWithSolidColor() override;
-    Color solidColor() const override;
-
 #if !ASSERT_DISABLED
     bool notSolidColor() override;
 #endif
@@ -312,7 +307,10 @@
     mutable RetainPtr<CFDataRef> m_tiffRep; // Cached TIFF rep for frame 0. Only built lazily if someone queries for one.
 #endif
 
-    Color m_solidColor;  // If we're a 1x1 solid color, this is the color to use to fill.
+    // The value of this data member is a missing value if we haven’t analyzed to check for a solid color or not, but an invalid
+    // color if we have analyzed and decided it’s not a solid color, and a valid color if we have analyzed and decide that the
+    // solid color optimization applies. The analysis, we do, handles only the case of 1x1 solid color images.
+    Optional<Color> m_solidColor;
 
     unsigned m_decodedSize { 0 }; // The current size of all decoded frames.
     mutable unsigned m_decodedPropertiesSize { 0 }; // The size of data decoded by the source to determine image properties (e.g. size, frame count, etc).
@@ -323,9 +321,6 @@
     double m_progressiveLoadChunkTime { 0 };
     uint16_t m_progressiveLoadChunkCount { 0 };
 #endif
-    bool m_isSolidColor : 1; // Whether or not we are a 1x1 solid image.
-    bool m_checkedForSolidColor : 1; // Whether we've checked the frame for solid color.
-
     bool m_animationFinished : 1; // Whether or not we've completed the entire animation.
 
     bool m_allDataReceived : 1; // Whether or not we've received all our data.

Modified: trunk/Source/WebCore/platform/graphics/Image.cpp (201423 => 201424)


--- trunk/Source/WebCore/platform/graphics/Image.cpp	2016-05-26 18:19:30 UTC (rev 201423)
+++ trunk/Source/WebCore/platform/graphics/Image.cpp	2016-05-26 18:46:02 UTC (rev 201424)
@@ -91,9 +91,10 @@
 }
 
 void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& destRect, const FloatPoint& srcPoint, const FloatSize& scaledTileSize, const FloatSize& spacing, CompositeOperator op, BlendMode blendMode)
-{    
-    if (mayFillWithSolidColor()) {
-        fillWithSolidColor(ctxt, destRect, solidColor(), op);
+{
+    Color color = singlePixelSolidColor();
+    if (color.isValid()) {
+        fillWithSolidColor(ctxt, destRect, color, op);
         return;
     }
 
@@ -204,8 +205,9 @@
 void Image::drawTiled(GraphicsContext& ctxt, const FloatRect& dstRect, const FloatRect& srcRect,
     const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator op)
 {    
-    if (mayFillWithSolidColor()) {
-        fillWithSolidColor(ctxt, dstRect, solidColor(), op);
+    Color color = singlePixelSolidColor();
+    if (color.isValid()) {
+        fillWithSolidColor(ctxt, dstRect, color, op);
         return;
     }
     

Modified: trunk/Source/WebCore/platform/graphics/Image.h (201423 => 201424)


--- trunk/Source/WebCore/platform/graphics/Image.h	2016-05-26 18:19:30 UTC (rev 201423)
+++ trunk/Source/WebCore/platform/graphics/Image.h	2016-05-26 18:46:02 UTC (rev 201424)
@@ -194,8 +194,7 @@
     void drawTiled(GraphicsContext&, const FloatRect& dstRect, const FloatRect& srcRect, const FloatSize& tileScaleFactor, TileRule hRule, TileRule vRule, CompositeOperator);
 
     // Supporting tiled drawing
-    virtual bool mayFillWithSolidColor() { return false; }
-    virtual Color solidColor() const { return Color(); }
+    virtual Color singlePixelSolidColor() { return Color(); }
     
 private:
     RefPtr<SharedBuffer> m_encodedImageData;

Modified: trunk/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp (201423 => 201424)


--- trunk/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp	2016-05-26 18:19:30 UTC (rev 201423)
+++ trunk/Source/WebCore/platform/graphics/cairo/BitmapImageCairo.cpp	2016-05-26 18:46:02 UTC (rev 201424)
@@ -50,8 +50,22 @@
     return cairo_surface_get_content(image.get()) != CAIRO_CONTENT_COLOR;
 }
 
+Color singlePixelSolidColor(const RefPtr<cairo_surface_t>& image)
+{
+    ASSERT(image);
+    
+    if (NativeImage::size(image) != IntSize(1, 1))
+        return Color();
+
+    if (cairo_surface_get_type(image.get()) != CAIRO_SURFACE_TYPE_IMAGE)
+        return Color();
+
+    RGBA32* pixel = reinterpret_cast_ptr<RGBA32*>(cairo_image_surface_get_data(image.get()));
+    return colorFromPremultipliedARGB(*pixel);
 }
 
+}
+
 void BitmapImage::draw(GraphicsContext& context, const FloatRect& dst, const FloatRect& src, CompositeOperator op,
     BlendMode blendMode, ImageOrientationDescription description)
 {
@@ -64,8 +78,9 @@
     if (!surface) // If it's too early we won't have an image yet.
         return;
 
-    if (mayFillWithSolidColor()) {
-        fillWithSolidColor(context, dst, solidColor(), op);
+    Color color = singlePixelSolidColor();
+    if (color.isValid()) {
+        fillWithSolidColor(context, dst, color, op);
         return;
     }
 
@@ -110,32 +125,6 @@
         imageObserver()->didDraw(this);
 }
 
-void BitmapImage::checkForSolidColor()
-{
-    m_isSolidColor = false;
-    m_checkedForSolidColor = true;
-
-    if (frameCount() > 1)
-        return;
-
-    auto surface = frameImageAtIndex(m_currentFrame);
-    if (!surface) // If it's too early we won't have an image yet.
-        return;
-
-    if (cairo_surface_get_type(surface.get()) != CAIRO_SURFACE_TYPE_IMAGE)
-        return;
-
-    IntSize size = cairoSurfaceSize(surface.get());
-
-    if (size.width() != 1 || size.height() != 1)
-        return;
-
-    unsigned* pixelColor = reinterpret_cast_ptr<unsigned*>(cairo_image_surface_get_data(surface.get()));
-    m_solidColor = colorFromPremultipliedARGB(*pixelColor);
-
-    m_isSolidColor = true;
-}
-
 bool FrameData::clear(bool clearMetadata)
 {
     if (clearMetadata)

Modified: trunk/Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp (201423 => 201424)


--- trunk/Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp	2016-05-26 18:19:30 UTC (rev 201423)
+++ trunk/Source/WebCore/platform/graphics/cg/BitmapImageCG.cpp	2016-05-26 18:46:02 UTC (rev 201424)
@@ -54,6 +54,7 @@
 
 IntSize size(const RetainPtr<CGImageRef>& image)
 {
+    ASSERT(image);
     return IntSize(CGImageGetWidth(image.get()), CGImageGetHeight(image.get()));
 }
 
@@ -62,9 +63,32 @@
     // FIXME: Answer correctly the question: does the CGImageRef have alpha channnel?
     return true;
 }
+    
+Color singlePixelSolidColor(const RetainPtr<CGImageRef>& image)
+{
+    ASSERT(image);
+    
+    if (NativeImage::size(image) != IntSize(1, 1))
+        return Color();
+    
+    unsigned char pixel[4]; // RGBA
+    auto bitmapContext = adoptCF(CGBitmapContextCreate(pixel, 1, 1, 8, sizeof(pixel), sRGBColorSpaceRef(),
+        kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big));
 
+    if (!bitmapContext)
+        return Color();
+    
+    CGContextSetBlendMode(bitmapContext.get(), kCGBlendModeCopy);
+    CGContextDrawImage(bitmapContext.get(), CGRectMake(0, 0, 1, 1), image.get());
+    
+    if (!pixel[3])
+        return Color(0, 0, 0, 0);
+
+    return Color(pixel[0] * 255 / pixel[3], pixel[1] * 255 / pixel[3], pixel[2] * 255 / pixel[3], pixel[3]);
 }
 
+}
+
 bool FrameData::clear(bool clearMetadata)
 {
     if (clearMetadata)
@@ -82,49 +106,6 @@
     return false;
 }
 
-void BitmapImage::checkForSolidColor()
-{
-    m_checkedForSolidColor = true;
-    m_isSolidColor = false;
-
-    if (frameCount() > 1)
-        return;
-
-    if (!haveFrameImageAtIndex(0)) {
-        IntSize size = m_source.frameSizeAtIndex(0, 0);
-        if (size.width() != 1 || size.height() != 1)
-            return;
-
-        if (!ensureFrameIsCached(0))
-            return;
-    }
-
-    CGImageRef image = nullptr;
-    if (m_frames.size())
-        image = m_frames[0].m_image.get();
-
-    if (!image)
-        return;
-
-    // Currently we only check for solid color in the important special case of a 1x1 image.
-    if (CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
-        unsigned char pixel[4]; // RGBA
-        RetainPtr<CGContextRef> bitmapContext = adoptCF(CGBitmapContextCreate(pixel, 1, 1, 8, sizeof(pixel), sRGBColorSpaceRef(),
-            kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big));
-        if (!bitmapContext)
-            return;
-        GraphicsContext(bitmapContext.get()).setCompositeOperation(CompositeCopy);
-        CGRect destinationRect = CGRectMake(0, 0, 1, 1);
-        CGContextDrawImage(bitmapContext.get(), destinationRect, image);
-        if (!pixel[3])
-            m_solidColor = Color(0, 0, 0, 0);
-        else
-            m_solidColor = Color(pixel[0] * 255 / pixel[3], pixel[1] * 255 / pixel[3], pixel[2] * 255 / pixel[3], pixel[3]);
-
-        m_isSolidColor = true;
-    }
-}
-
 CGImageRef BitmapImage::getCGImageRef()
 {
     return frameImageAtIndex(0).get();
@@ -179,8 +160,9 @@
     if (!image) // If it's too early we won't have an image yet.
         return;
     
-    if (mayFillWithSolidColor()) {
-        fillWithSolidColor(ctxt, destRect, solidColor(), compositeOp);
+    Color color = singlePixelSolidColor();
+    if (color.isValid()) {
+        fillWithSolidColor(ctxt, destRect, color, compositeOp);
         return;
     }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to