Fix for 4638376. The 1x1 solid color image optimization was broken when
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Jul 2006 21:49:25 +0000 (21:49 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 19 Jul 2006 21:49:25 +0000 (21:49 +0000)
        I re-architected image.  This patch restores the optimization for CG.  Cairo
        will still need the optimization.

        Reviewed by darin

        WARNING: NO TEST CASES ADDED OR CHANGED (need test cases still)

        * platform/Image.cpp:
        (WebCore::Image::Image):
        (WebCore::Image::invalidateData):
        (WebCore::Image::cacheFrame):
        * platform/Image.h:
        (WebCore::Image::setIsPDF):
        * platform/cairo/ImageCairo.cpp:
        (WebCore::Image::checkForSolidColor):
        * platform/mac/ImageMac.mm:
        (WebCore::Image::initNativeData):
        (WebCore::Image::invalidateNativeData):
        (WebCore::Image::checkForSolidColor):
        (WebCore::Image::draw):
        (WebCore::Image::drawTiled):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@15529 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/platform/Image.cpp
WebCore/platform/Image.h
WebCore/platform/cairo/ImageCairo.cpp
WebCore/platform/mac/ImageMac.mm

index 46882af92d17470d525495813915af67956feca8..b08a4e20f9e5f1e191d81ab2404b3f409495a179 100644 (file)
@@ -1,3 +1,28 @@
+2006-07-19  David Hyatt  <hyatt@apple.com>
+
+        Fix for 4638376.  The 1x1 solid color image optimization was broken when
+        I re-architected image.  This patch restores the optimization for CG.  Cairo
+        will still need the optimization.
+
+        Reviewed by darin
+
+        WARNING: NO TEST CASES ADDED OR CHANGED (need test cases still)
+
+        * platform/Image.cpp:
+        (WebCore::Image::Image):
+        (WebCore::Image::invalidateData):
+        (WebCore::Image::cacheFrame):
+        * platform/Image.h:
+        (WebCore::Image::setIsPDF):
+        * platform/cairo/ImageCairo.cpp:
+        (WebCore::Image::checkForSolidColor):
+        * platform/mac/ImageMac.mm:
+        (WebCore::Image::initNativeData):
+        (WebCore::Image::invalidateNativeData):
+        (WebCore::Image::checkForSolidColor):
+        (WebCore::Image::draw):
+        (WebCore::Image::drawTiled):
+
 2006-07-19  Justin Garcia  <justin.garcia@apple.com>
 
         Reviewed by levi
index 1a847905173b001700d0ccb29725dabcac949b3e..ea7dcb0a03a8b1cb84dd056166ea5815670eb5af 100644 (file)
@@ -49,7 +49,7 @@ namespace WebCore {
 Image::Image()
 : m_currentFrame(0), m_frames(0), m_animationObserver(0),
   m_frameTimer(0), m_repetitionCount(0), m_repetitionsComplete(0),
-  m_animatingImageType(true), m_animationFinished(0),
+  m_isSolidColor(false), m_animatingImageType(true), m_animationFinished(false),
   m_haveSize(false), m_sizeAvailable(false)
 {
     initNativeData();
@@ -58,7 +58,7 @@ Image::Image()
 Image::Image(ImageAnimationObserver* observer, bool isPDF)
  : m_currentFrame(0), m_frames(0), m_animationObserver(0),
   m_frameTimer(0), m_repetitionCount(0), m_repetitionsComplete(0),
-  m_animatingImageType(true), m_animationFinished(0),
+  m_isSolidColor(false), m_animatingImageType(true), m_animationFinished(false),
   m_haveSize(false), m_sizeAvailable(false)
 {
     initNativeData();
@@ -81,6 +81,7 @@ void Image::invalidateData()
     // Destroy the cached images and release them.
     if (m_frames.size()) {
         m_frames.last().clear();
+        m_isSolidColor = false;
         invalidateNativeData();
     }
 }
@@ -99,6 +100,8 @@ void Image::cacheFrame(size_t index)
         m_frames.resize(numFrames);
 
     m_frames[index].m_frame = m_source.createFrameAtIndex(index);
+    checkForSolidColor();
+
     if (shouldAnimate())
         m_frames[index].m_duration = m_source.frameDurationAtIndex(index);
     m_frames[index].m_hasAlpha = m_source.frameHasAlphaAtIndex(index);
index c49af1ad61984301dcc42d119f61d664ce87b2b3..4b071da0aed99548d1ab2900d43ff7ee32091e83 100644 (file)
@@ -27,6 +27,7 @@
 #ifndef IMAGE_H_
 #define IMAGE_H_
 
+#include "Color.h"
 #include "GraphicsTypes.h"
 #include "ImageSource.h"
 #include "IntSize.h"
@@ -130,7 +131,7 @@ public:
     ImageAnimationObserver* animationObserver() const { return m_animationObserver; }
 
     enum TileRule { StretchTile, RoundTile, RepeatTile };
-
+    
 #if __APPLE__
     // Accessors for native image formats.
     CGImageRef getCGImageRef();
@@ -139,9 +140,6 @@ public:
 
     // PDF
     void setIsPDF() { m_isPDF = true; }
-
-private:
-    void checkForSolidColor(CGImageRef);
 #endif
 
 private:
@@ -174,6 +172,9 @@ private:
     // Invalidation of native data.
     void invalidateNativeData();
 
+    // Checks to see if the image is a 1x1 solid color.  We optimize these images and just do a fill rect instead.
+    void checkForSolidColor();
+
     // Members
     Vector<char> m_data; // The encoded raw data for the image.
     ImageSource m_source;
@@ -192,16 +193,17 @@ private:
     mutable NSImage* m_nsImage; // A cached NSImage of frame 0. Only built lazily if someone actually queries for one.
     mutable CFDataRef m_tiffRep; // Cached TIFF rep for frame 0.  Only built lazily if someone queries for one.
     PDFDocumentImage* m_PDFDoc;
-    CGColorRef m_solidColor; // Will be 0 if transparent.
-    bool m_isSolidColor : 1; // If the image is 1x1 with no alpha, we can just do a rect fill when painting/tiling.
-    bool m_isPDF : 1;
+    bool m_isPDF;
 #endif
 
-    bool m_animatingImageType : 1;  // Whether or not we're an image type that is capable of animating (GIF).
-    bool m_animationFinished : 1;  // Whether or not we've completed the entire animation.
+    Color m_solidColor;  // If we're a 1x1 solid color, this is the color to use to fill.
+    bool m_isSolidColor;  // Whether or not we are a 1x1 solid image.
+
+    bool m_animatingImageType;  // Whether or not we're an image type that is capable of animating (GIF).
+    bool m_animationFinished;  // Whether or not we've completed the entire animation.
 
-    mutable bool m_haveSize : 1; // Whether or not our |m_size| member variable has the final overall image size yet.
-    bool m_sizeAvailable : 1; // Whether or not we can obtain the size of the first image frame yet from ImageIO.
+    mutable bool m_haveSize; // Whether or not our |m_size| member variable has the final overall image size yet.
+    bool m_sizeAvailable; // Whether or not we can obtain the size of the first image frame yet from ImageIO.
 };
 
 }
index 93ff7108c73ca592bb6eba51c5f42a326e8b51b2..2d0aaed0981fdf2128ceab8fdad817902b5e7365 100644 (file)
@@ -92,6 +92,12 @@ static void setCompositingOperation(cairo_t* context, CompositeOperator op, bool
         cairo_set_operator(context, CAIRO_OPERATOR_OVER);
 }
 
+void Image::checkForSolidColor()
+{
+    // FIXME: It's easy to implement this optimization. Just need to check the RGBA32 buffer to see if it is 1x1.
+    m_isSolidColor = false;
+}
+
 void Image::draw(GraphicsContext* ctxt, const FloatRect& dst, const FloatRect& src, CompositeOperator op)
 {
     cairo_t* context = ctxt->platformContext();
index ec5fbc9fa30e754e513ba36b93d731e415041656..c081c663e16aa65d47427086bf8578058a8c766d 100644 (file)
@@ -54,8 +54,6 @@ void Image::initNativeData()
 {
     m_nsImage = 0;
     m_tiffRep = 0;
-    m_solidColor = 0;
-    m_isSolidColor = 0;
     m_isPDF = false;
     m_PDFDoc = 0;
 }
@@ -79,12 +77,6 @@ void Image::invalidateNativeData()
         CFRelease(m_tiffRep);
         m_tiffRep = 0;
     }
-
-    m_isSolidColor = false;
-    if (m_solidColor) {
-        CFRelease(m_solidColor);
-        m_solidColor = 0;
-    }
 }
 
 Image* Image::loadResource(const char *name)
@@ -109,47 +101,29 @@ bool Image::supportsType(const String& type)
 
 // Drawing Routines
 
-static void fillSolidColorInRect(GraphicsContext* context, CGColorRef color, CGRect rect, CompositeOperator op)
-{
-    if (color) {
-        context->save();
-        CGContextSetFillColorWithColor(context->platformContext(), color);
-        context->setCompositeOperation(op);
-        CGContextFillRect(context->platformContext(), rect);
-        context->restore();
-    }
-}
-
-void Image::checkForSolidColor(CGImageRef image)
+void Image::checkForSolidColor()
 {
-    m_isSolidColor = false;
-    if (m_solidColor) {
-        CFRelease(m_solidColor);
-        m_solidColor = 0;
-    }
-    
-    // Currently we only check for solid color in the important special case of a 1x1 image.
-    if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
-        CGFloat pixel[4]; // RGBA
-        CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
-// This #if won't be needed once the CG header that includes kCGBitmapByteOrder32Host is included in the OS.
-#if __ppc__
-        CGContextRef bmap = CGBitmapContextCreate(&pixel, 1, 1, 8*sizeof(float), sizeof(pixel), space,
-            kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents);
-#else
-        CGContextRef bmap = CGBitmapContextCreate(&pixel, 1, 1, 8*sizeof(float), sizeof(pixel), space,
-            kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents | kCGBitmapByteOrder32Host);
-#endif
-        if (bmap) {
-            GraphicsContext(bmap).setCompositeOperation(CompositeCopy);
-            CGRect dst = { {0, 0}, {1, 1} };
-            CGContextDrawImage(bmap, dst, image);
-            if (pixel[3] > 0)
-                m_solidColor = CGColorCreate(space,pixel);
-            m_isSolidColor = true;
-            CFRelease(bmap);
-        } 
-        CFRelease(space);
+    if (frameCount() > 1)
+        m_isSolidColor = false;
+    else {
+        CGImageRef image = frameAtIndex(0);
+        
+        // Currently we only check for solid color in the important special case of a 1x1 image.
+        if (image && CGImageGetWidth(image) == 1 && CGImageGetHeight(image) == 1) {
+            CGFloat pixel[4]; // RGBA
+            CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
+            CGContextRef bmap = CGBitmapContextCreate(&pixel, 1, 1, 8*sizeof(float), sizeof(pixel), space,
+                kCGImageAlphaPremultipliedLast | kCGBitmapFloatComponents | kCGBitmapByteOrder32Host);
+            if (bmap) {
+                GraphicsContext(bmap).setCompositeOperation(CompositeCopy);
+                CGRect dst = { {0, 0}, {1, 1} };
+                CGContextDrawImage(bmap, dst, image);
+                m_solidColor = Color(int(pixel[0] * 255), int(pixel[1] * 255), int(pixel[2] * 255), int(pixel[3] * 255));
+                m_isSolidColor = true;
+                CFRelease(bmap);
+            } 
+            CFRelease(space);
+        }
     }
 }
 
@@ -216,13 +190,17 @@ void Image::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRec
     if (!image) // If it's too early we won't have an image yet.
         return;
 
-    if (m_isSolidColor && m_currentFrame == 0)
-        return fillSolidColorInRect(ctxt, m_solidColor, ir, compositeOp);
+    if (m_isSolidColor && m_currentFrame == 0) {
+        if (m_solidColor.alpha() > 0) {
+            ctxt->setCompositeOperation(!m_solidColor.hasAlpha() && compositeOp == CompositeSourceOver ? CompositeCopy : compositeOp);
+            ctxt->fillRect(ir, m_solidColor);
+        }
+        return;
+    }
 
     CGContextRef context = ctxt->platformContext();
-
     ctxt->save();
-        
+
     // Get the height (in adjusted, i.e. scaled, coords) of the portion of the image
     // that is currently decoded.  This could be less that the actual height.
     CGSize selfSize = size();                          // full image size, in pixels
@@ -291,14 +269,17 @@ static void drawPattern(void* info, CGContextRef context)
 static const CGPatternCallbacks patternCallbacks = { 0, drawPattern, NULL };
 
 void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const FloatPoint& srcPoint,
-    const FloatSize& tileSize, CompositeOperator op)
+                      const FloatSize& tileSize, CompositeOperator op)
 {    
     CGImageRef image = frameAtIndex(m_currentFrame);
     if (!image)
         return;
 
-    if (m_currentFrame == 0 && m_isSolidColor) {
-        fillSolidColorInRect(ctxt, m_solidColor, destRect, op);
+    if (m_isSolidColor && m_currentFrame == 0) {
+        if (m_solidColor.alpha() > 0) {
+            ctxt->setCompositeOperation(!m_solidColor.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
+            ctxt->fillRect(destRect, m_solidColor);
+        }
         return;
     }
 
@@ -372,14 +353,19 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& destRect, const Fl
 
 // FIXME: Merge with the other drawTiled eventually, since we need a combination of both for some things.
 void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const FloatRect& srcRect, TileRule hRule,
-    TileRule vRule, CompositeOperator op)
+                      TileRule vRule, CompositeOperator op)
 {    
     CGImageRef image = frameAtIndex(m_currentFrame);
     if (!image)
         return;
 
-    if (m_currentFrame == 0 && m_isSolidColor)
-        return fillSolidColorInRect(ctxt, m_solidColor, dstRect, op);
+    if (m_isSolidColor && m_currentFrame == 0) {
+        if (m_solidColor.alpha() > 0) {
+            ctxt->setCompositeOperation(!m_solidColor.hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
+            ctxt->fillRect(dstRect, m_solidColor);
+        }
+        return;
+    }
 
     ctxt->save();