WebCore:
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Oct 2007 21:03:41 +0000 (21:03 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 25 Oct 2007 21:03:41 +0000 (21:03 +0000)
        Fix for bug 15672, background images don't tile properly inside transforms.  This patch fixes background
        tiling to work in the presence of transforms and fixes bugs in both SVG and CSS transforms.

        Reviewed by aroben and mitz

        * WebCore.base.exp:
        * platform/graphics/Image.cpp:
        (WebCore::Image::setData):
        * platform/graphics/cg/ImageCG.cpp:
        (WebCore::ImageInfo::ImageInfo):
        (WebCore::Image::drawPatternCallback):
        (WebCore::Image::drawPattern):
        * platform/graphics/mac/GraphicsContextMac.mm:
        (WebCore::GraphicsContext::drawLineForMisspellingOrBadGrammar):
        * platform/mac/WebCoreSystemInterface.h:
        * platform/mac/WebCoreSystemInterface.mm:

WebKit:

        Fix for bug 15672, backgrounds don't tile properly inside transforms.  This patch fixes tiling
        of backgrounds inside CSS transforms and also of HTML content with background images inside SVG
        transforms.

        Reviewed by aroben and mmitz

        * WebCoreSupport/WebSystemInterface.m:
        (InitWebCoreSystemInterface):
        * WebKit.xcodeproj/project.pbxproj:

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

WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/platform/graphics/Image.cpp
WebCore/platform/graphics/cg/ImageCG.cpp
WebCore/platform/graphics/mac/GraphicsContextMac.mm
WebCore/platform/mac/WebCoreSystemInterface.h
WebCore/platform/mac/WebCoreSystemInterface.mm
WebKit/ChangeLog
WebKit/WebCoreSupport/WebSystemInterface.m

index 70254ea3af96ecf834dcc65165b5853451ea10bd..6c9e56866eb39fd64b6c61b8d6f79e809ed0f8a8 100644 (file)
@@ -1,3 +1,22 @@
+2007-10-25  David Hyatt  <hyatt@apple.com>
+
+        Fix for bug 15672, background images don't tile properly inside transforms.  This patch fixes background
+        tiling to work in the presence of transforms and fixes bugs in both SVG and CSS transforms.
+
+        Reviewed by aroben and mitz
+
+        * WebCore.base.exp:
+        * platform/graphics/Image.cpp:
+        (WebCore::Image::setData):
+        * platform/graphics/cg/ImageCG.cpp:
+        (WebCore::ImageInfo::ImageInfo):
+        (WebCore::Image::drawPatternCallback):
+        (WebCore::Image::drawPattern):
+        * platform/graphics/mac/GraphicsContextMac.mm:
+        (WebCore::GraphicsContext::drawLineForMisspellingOrBadGrammar):
+        * platform/mac/WebCoreSystemInterface.h:
+        * platform/mac/WebCoreSystemInterface.mm:
+
 2007-10-25  Brady Eidson  <beidson@apple.com>
 
         Blind build fix attempt
index 9115d881301a98d3573136215e44edb383a31b1b..9855d4dd251fee36344980789a86a989823b1064 100644 (file)
@@ -738,6 +738,7 @@ _wkSetCGFontRenderingMode
 _wkSetDragImage
 _wkSetNSURLConnectionDefersCallbacks
 _wkSetNSURLRequestShouldContentSniff
+_wkSetPatternBaseCTM
 _wkSetPatternPhaseInUserSpace
 _wkSetUpFontCache
 _wkSignalCFReadStreamEnd
index 6933aaf9a3e42bdd9506ee84a0dcd94a81f9a700..9eeff51934b2c6d10b60cd98078de9a4f8d7b7c8 100644 (file)
@@ -68,16 +68,6 @@ bool Image::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
     int length = m_data->size();
     if (!length)
         return true;
-
-#ifdef kImageBytesCutoff
-    // This is a hack to help with testing display of partially-loaded images.
-    // To enable it, define kImageBytesCutoff to be a size smaller than that of the image files
-    // being loaded. They'll never finish loading.
-    if (length > kImageBytesCutoff) {
-        length = kImageBytesCutoff;
-        allDataReceived = false;
-    }
-#endif
     
     return dataChanged(allDataReceived);
 }
index 81add6dde3b8bbfeda0ae164db7ef3ba35338975..848adfec98822b56a8d78b2245c0e4e444b3e058 100644 (file)
 #include <ApplicationServices/ApplicationServices.h>
 #include "WebCoreSystemInterface.h"
 
+#if PLATFORM(WIN)
+#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#endif
+
 namespace WebCore {
 
 void FrameData::clear()
@@ -167,49 +171,56 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dstRect, const Fl
         imageObserver()->didDraw(this);
 }
 
+struct ImageInfo {
+    ImageInfo(const FloatPoint& point, Image* i)
+    : tilePoint(point)
+    , image(i)
+    {}
+    
+    FloatPoint tilePoint;
+    Image* image;
+};
+
 void Image::drawPatternCallback(void* info, CGContextRef context)
 {
-    Image* data = (Image*)info;
-    CGImageRef image = data->nativeImageForCurrentFrame();
-    float w = CGImageGetWidth(image);
-    float h = CGImageGetHeight(image);
-    CGContextDrawImage(context, GraphicsContext(context).roundToDevicePixels(FloatRect(0, -h, w, h)), image);
+    ImageInfo* data = (ImageInfo*)info;
+    CGImageRef image = data->image->nativeImageForCurrentFrame();
+    CGContextDrawImage(context, GraphicsContext(context).roundToDevicePixels(FloatRect(data->tilePoint.x(), data->tilePoint.y(), CGImageGetWidth(image), CGImageGetHeight(image))), image);
 }
 
 void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
                         const FloatPoint& phase, CompositeOperator op, const FloatRect& destRect)
 {
     CGContextRef context = ctxt->platformContext();
+    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 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() + tileRect.x() * patternTransform.a(); // We translated the context so that destRect.x() is the origin, so subtract it out.
+    float adjustedY = destRect.height() - (phase.y() - destRect.y() + tileRect.y() * patternTransform.d() + scaledTileHeight);
 
+    CGImageRef tileImage = nativeImageForCurrentFrame();
+    float h = CGImageGetHeight(tileImage);
+    
 #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 scaledTileWidth = tileRect.width() * narrowPrecisionToCGFloat(patternTransform.a());
     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);
-
+    if (w == size().width() && h == size().height() && tileRect.size() == size())
         CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), tileImage);
-        ctxt->restore();
-    } else {
+    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
@@ -218,31 +229,38 @@ void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const
     // 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(), 
+    CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY);
+    matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
+    
+    // If we're painting a subimage, store the offset to the image.
+    ImageInfo info(FloatPoint(-tileRect.x(), tileRect.y() + tileRect.height() - h), this);
+    CGPatternRef pattern = CGPatternCreate(&info, CGRectMake(0, 0, tileRect.width(), tileRect.height()),
+                                           matrix, tileRect.width(), tileRect.height(), 
                                            kCGPatternTilingConstantSpacing, true, &patternCallbacks);
-    if (!pattern)
+    if (pattern == NULL) {
+        ctxt->restore();
         return;
-    
-    ctxt->save();
-    
-    // FIXME: Really want a public API for this.
-    wkSetPatternPhaseInUserSpace(context, phase);
-    
+    }
+
     CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
+    
+    CGFloat alpha = 1;
+    CGColorRef color = CGColorCreateWithPattern(patternSpace, pattern, &alpha);
     CGContextSetFillColorSpace(context, patternSpace);
     CGColorSpaceRelease(patternSpace);
+    CGPatternRelease(pattern);
+
+    // FIXME: Really want a public API for this.  It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
+    wkSetPatternBaseCTM(context, CGAffineTransformIdentity);
+    CGContextSetPatternPhase(context, CGSizeZero);
+
+    CGContextSetFillColorWithColor(context, color);
+    CGContextFillRect(context, CGContextGetClipBoundingBox(context));
     
-    CGFloat patternAlpha = 1;
-    CGContextSetFillPattern(context, pattern, &patternAlpha);
-    
-    ctxt->setCompositeOperation(op);
-    
-    CGContextFillRect(context, destRect);
+    CGColorRelease(color);
     
     ctxt->restore();
-    CGPatternRelease(pattern);
-
+    
 #ifndef BUILDING_ON_TIGER
     }
 #endif
index b47f96a8832725a61742e02c6b5e3194bbbd691b..da834162e58619bf860cc56d2efde8175e21e964 100644 (file)
@@ -163,7 +163,9 @@ void GraphicsContext::drawLineForMisspellingOrBadGrammar(const IntPoint& point,
     
     // FIXME: This code should not use NSGraphicsContext currentContext
     // In order to remove this requirement we will need to use CGPattern instead of NSColor
-    
+    // FIXME: This code should not be using wkSetPatternPhaseInUserSpace, as this approach is wrong
+    // for transforms.
+
     // Draw underline
     NSGraphicsContext *currentContext = [NSGraphicsContext currentContext];
     CGContextRef context = (CGContextRef)[currentContext graphicsPort];
index 8ee92ed0ff0b4a7dfa32c86d5f37158d9a811e5c..bde14f065ec1c6072272c8623012f61273868289 100644 (file)
@@ -112,6 +112,7 @@ extern void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*);
 extern void (*wkSetDragImage)(NSImage*, NSPoint offset);
 extern void (*wkSetNSURLConnectionDefersCallbacks)(NSURLConnection *, BOOL);
 extern void (*wkSetNSURLRequestShouldContentSniff)(NSMutableURLRequest *, BOOL);
+extern void (*wkSetPatternBaseCTM)(CGContextRef, CGAffineTransform);
 extern void (*wkSetPatternPhaseInUserSpace)(CGContextRef, CGPoint);
 extern void (*wkSetUpFontCache)(size_t);
 extern void (*wkSignalCFReadStreamEnd)(CFReadStreamRef stream);
index 3d33e532af0029eb6a2e37d9c317eaa2c054a6e3..81b2a42e195d3e63e213a705c08ddf0ff142123f 100644 (file)
@@ -59,6 +59,7 @@ void (*wkPopupMenu)(NSMenu*, NSPoint location, float width, NSView*, int selecte
 void (*wkReleaseStyleGroup)(void* group);
 void (*wkSetCGFontRenderingMode)(CGContextRef, NSFont*);
 void (*wkSetDragImage)(NSImage*, NSPoint offset);
+void (*wkSetPatternBaseCTM)(CGContextRef, CGAffineTransform);
 void (*wkSetPatternPhaseInUserSpace)(CGContextRef, CGPoint point);
 void (*wkSetUpFontCache)(size_t);
 void (*wkSignalCFReadStreamEnd)(CFReadStreamRef stream);
index a958b389b21e205d2e3bd7eebe1db54107668e42..b06456c2a08ed6cf3560a1d32ed869bc0bc024c2 100644 (file)
@@ -1,3 +1,15 @@
+2007-10-25  David Hyatt  <hyatt@apple.com>
+
+        Fix for bug 15672, backgrounds don't tile properly inside transforms.  This patch fixes tiling
+        of backgrounds inside CSS transforms and also of HTML content with background images inside SVG
+        transforms.
+
+        Reviewed by aroben and mmitz
+
+        * WebCoreSupport/WebSystemInterface.m:
+        (InitWebCoreSystemInterface):
+        * WebKit.xcodeproj/project.pbxproj:
+
 2007-10-25  John Sullivan  <sullivan@apple.com>
 
         Reviewed by Tim Hatcher
index 9dc71444bd807d3454fa8a90762176aa76774f0d..66e22ebf983207e1c96c7afbddbd48fc55a57760 100644 (file)
@@ -76,6 +76,7 @@ void InitWebCoreSystemInterface(void)
     INIT(SetDragImage);
     INIT(SetNSURLConnectionDefersCallbacks);
     INIT(SetNSURLRequestShouldContentSniff);
+    INIT(SetPatternBaseCTM);
     INIT(SetPatternPhaseInUserSpace);
     INIT(SetUpFontCache);
     INIT(SignalCFReadStreamEnd);