Fix for <rdar://problem/5249757> Painting of JPGs in WebKit is too slow.
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Aug 2007 19:58:44 +0000 (19:58 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Aug 2007 19:58:44 +0000 (19:58 +0000)
        Use a new Leopard API for fast tiling of images.  We only use this API
        when the whole image is being tiled and when the current CGImageRef to tile
        has a size that matches the size of the whole image.

        We can optimize border-image in the future by adding a cache of the 9
        sub-images.

        Reviewed by darin

        * platform/graphics/cg/ImageCG.cpp:
        (WebCore::Image::drawPattern):

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

WebCore/ChangeLog
WebCore/platform/graphics/cg/ImageCG.cpp

index 4f9877c00ace651222af1d57fa4f83dda56af1fd..a49e6aac72cab84eb6febc135f0bd6283263eb65 100644 (file)
@@ -1,3 +1,19 @@
+2007-08-21  David Hyatt  <hyatt@apple.com>
+
+        Fix for <rdar://problem/5249757> Painting of JPGs in WebKit is too slow.
+
+        Use a new Leopard API for fast tiling of images.  We only use this API
+        when the whole image is being tiled and when the current CGImageRef to tile
+        has a size that matches the size of the whole image.
+
+        We can optimize border-image in the future by adding a cache of the 9
+        sub-images.
+
+        Reviewed by darin
+
+        * platform/graphics/cg/ImageCG.cpp:
+        (WebCore::Image::drawPattern):
+
 2007-08-22  Kevin McCullough  <kmccullough@apple.com>
 
         - Rolling back since I need to update some layouttests this change breaks.
index eb0e88039bb7dd45aabd516579fb126457e7b864..81add6dde3b8bbfeda0ae164db7ef3ba35338975 100644 (file)
@@ -29,6 +29,7 @@
 #if PLATFORM(CG)
 
 #include "AffineTransform.h"
+#include "FloatConversion.h"
 #include "FloatRect.h"
 #include "GraphicsContext.h"
 #include "ImageObserver.h"
@@ -176,8 +177,46 @@ void Image::drawPatternCallback(void* info, CGContextRef context)
 }
 
 void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
-                                const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
+                        const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
 {
+    CGContextRef context = ctxt->platformContext();
+
+#ifndef BUILDING_ON_TIGER
+    // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
+    // its buffer is the same size as the overall image.  Because a partially decoded CGImageRef with a smaller width or height than the
+    // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case.  We also avoid this optimization
+    // when tiling portions of an image, since until we can actually cache the subimage we want to tile, this code won't be any faster.
+    // FIXME: Could create WebKitSystemInterface SPI for CGCreatePatternWithImage2 and probably make Tiger tile faster as well.
+    CGImageRef tileImage = nativeImageForCurrentFrame();
+    float w = CGImageGetWidth(tileImage);
+    float h = CGImageGetHeight(tileImage);
+    if (w == size().width() && h == size().height() && tileRect.size() == size()) {
+        ctxt->save();
+        CGContextClipToRect(context, destRect);
+        ctxt->setCompositeOperation(op);
+        CGContextTranslateCTM(context, destRect.x(), destRect.y());
+        CGContextScaleCTM(context, 1, -1);
+        CGContextTranslateCTM(context, 0, -destRect.height());
+        
+        // Compute the scaled tile size.
+        float scaledTileWidth = tileRect.width() * narrowPrecisionToCGFloat(patternTransform.a());
+        float scaledTileHeight = tileRect.height() * narrowPrecisionToCGFloat(patternTransform.d());
+    
+        // We have to adjust the phase to deal with the fact we're in Cartesian space now (with the bottom left corner of destRect being
+        // the origin).
+        float adjustedX = phase.x() - destRect.x(); // We translated the context so that destRect.x() is the origin, so subtract it out.
+        float adjustedY = destRect.height() - (phase.y() - destRect.y() + scaledTileHeight);
+
+        CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), tileImage);
+        ctxt->restore();
+    } else {
+#endif
+
+    // On Leopard, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image or for
+    // tiling a portion of an image (i.e., a subimage like the ones used by CSS border-image).
+    // On Tiger this code runs all the time.  This code is suboptimal because the pattern does not reference the image directly, and the
+    // pattern is destroyed before exiting the function.  This means any decoding the pattern does doesn't end up cached anywhere, so we
+    // redecode every time we paint.
     static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, NULL };
     CGPatternRef pattern = CGPatternCreate(this, FloatRect(tileRect.x(), -tileRect.y() - tileRect.height(), tileRect.width(), tileRect.height()),
                                            CGAffineTransform(patternTransform), tileRect.width(), tileRect.height(), 
@@ -185,7 +224,6 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
     if (!pattern)
         return;
     
-    CGContextRef context = ctxt->platformContext();
     ctxt->save();
     
     // FIXME: Really want a public API for this.
@@ -205,6 +243,10 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
     ctxt->restore();
     CGPatternRelease(pattern);
 
+#ifndef BUILDING_ON_TIGER
+    }
+#endif
+
     if (imageObserver())
         imageObserver()->didDraw(this);
 }