Changeset 91332 in webkit


Ignore:
Timestamp:
Jul 19, 2011 9:24:40 PM (13 years ago)
Author:
mdelaney@apple.com
Message:

Add fast path for ImageBuffer::draw
https://bugs.webkit.org/show_bug.cgi?id=64535

Reviewed by Simon Fraser.

No new tests. This patch doesn't change behavior; current tests are sufficient.

  • platform/graphics/GraphicsContext.cpp:

(WebCore::GraphicsContext::drawImage): Moved the main method version next to wrapper versions.

  • platform/graphics/ImageBuffer.h:

1) Added BackingStoreCopy enum for choosing to copy backing store or not in copyImage().
2) Added copyNativeImage() behind USE(CG) - same as copyImage() but gives NativeImagePtr.

  • platform/graphics/cg/ImageBufferCG.cpp: Added new methods described above.
  • platform/graphics/GraphicsContext.h: Adding drawNativeImage() for fast draw path.
  • platform/graphics/cg/GraphicsContextCG.cpp:

(WebCore::GraphicsContext::drawNativeImage): Added. Draws a nativeImagePtr into context.

  • platform/graphics/Image.h: Added imageWithColorSpace behind CG platform ifdef
  • platform/graphics/cg/ImageCG.cpp:

(WebCore::BitmapImage::draw): Refactored out actual image drawing code into GraphicsContext,
so that it can be used by more than just BitmapImage without having to copy code.
(WebCore::Image::imageWithColorSpace): Made into an Image class function.

Updated copyImage() to for BackingStoreCopy:

  • platform/graphics/qt/ImageBufferQt.cpp
  • platform/graphics/filters/FETile.cpp
  • platform/graphics/cairo/ImageBufferCairo.cpp
  • platform/graphics/skia/ImageBufferSkia.cpp
  • platform/graphics/wx/ImageBufferWx.cpp
  • platform/graphics/wince/ImageBufferWinCE.cpp
  • svg/SVGFEImageElement.cpp
  • svg/graphics/SVGImage.cpp
  • html/HTMLCanvasElement.cpp
  • html/canvas/WebGLRenderingContext.cpp
  • rendering/svg/RenderSVGResourcePattern.cpp
Location:
trunk/Source/WebCore
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r91331 r91332  
     12011-07-19  Matthew Delaney  <mdelaney@apple.com>
     2
     3        Add fast path for ImageBuffer::draw
     4        https://bugs.webkit.org/show_bug.cgi?id=64535
     5
     6        Reviewed by Simon Fraser.
     7
     8        No new tests. This patch doesn't change behavior; current tests are sufficient.
     9
     10        * platform/graphics/GraphicsContext.cpp:
     11        (WebCore::GraphicsContext::drawImage): Moved the main method version next to wrapper versions.
     12
     13        * platform/graphics/ImageBuffer.h:
     14        1) Added BackingStoreCopy enum for choosing to copy backing store or not in copyImage().
     15        2) Added copyNativeImage() behind USE(CG) - same as copyImage() but gives NativeImagePtr.
     16        * platform/graphics/cg/ImageBufferCG.cpp: Added new methods described above.
     17
     18        * platform/graphics/GraphicsContext.h: Adding drawNativeImage() for fast draw path.
     19        * platform/graphics/cg/GraphicsContextCG.cpp:
     20        (WebCore::GraphicsContext::drawNativeImage): Added. Draws a nativeImagePtr into context.
     21
     22        * platform/graphics/Image.h: Added imageWithColorSpace behind CG platform ifdef
     23        * platform/graphics/cg/ImageCG.cpp:
     24        (WebCore::BitmapImage::draw): Refactored out actual image drawing code into GraphicsContext,
     25        so that it can be used by more than just BitmapImage without having to copy code.
     26        (WebCore::Image::imageWithColorSpace): Made into an Image class function.
     27
     28        Updated copyImage() to for BackingStoreCopy:
     29        * platform/graphics/qt/ImageBufferQt.cpp
     30        * platform/graphics/filters/FETile.cpp
     31        * platform/graphics/cairo/ImageBufferCairo.cpp
     32        * platform/graphics/skia/ImageBufferSkia.cpp
     33        * platform/graphics/wx/ImageBufferWx.cpp
     34        * platform/graphics/wince/ImageBufferWinCE.cpp
     35        * svg/SVGFEImageElement.cpp
     36        * svg/graphics/SVGImage.cpp
     37        * html/HTMLCanvasElement.cpp
     38        * html/canvas/WebGLRenderingContext.cpp
     39        * rendering/svg/RenderSVGResourcePattern.cpp
     40
    1412011-07-19  Leo Yang  <leoyang.webkit@gmail.com>
    242
  • trunk/Source/WebCore/html/HTMLCanvasElement.cpp

    r91228 r91332  
    310310    if (!m_presentedImage) {
    311311        // The buffer contains the last presented data, so save a copy of it.
    312         m_presentedImage = buffer()->copyImage();
     312        m_presentedImage = buffer()->copyImage(CopyBackingStore);
    313313    }
    314314}
     
    473473        if (m_context)
    474474            m_context->paintRenderingResultsToCanvas();
    475         m_copiedImage = buffer()->copyImage();
     475        m_copiedImage = buffer()->copyImage(CopyBackingStore);
    476476    }
    477477    return m_copiedImage.get();
  • trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp

    r91112 r91332  
    32233223    // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
    32243224    video->paintCurrentFrameInContext(buf->context(), destRect);
    3225     return buf->copyImage();
     3225    return buf->copyImage(CopyBackingStore);
    32263226}
    32273227
  • trunk/Source/WebCore/platform/graphics/GraphicsContext.cpp

    r90872 r91332  
    352352}
    353353
    354 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
    355 {
    356     drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
    357 }
    358 
    359 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
    360 {
    361     drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
    362 }
    363 
    364 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
    365 {
    366     drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
    367 }
    368 
    369 void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
    370 {
    371     drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
    372 }
    373 
    374354#if !OS(WINCE) || (PLATFORM(QT) && !HAVE(QRAWFONT))
    375355void GraphicsContext::drawText(const Font& font, const TextRun& run, const FloatPoint& point, int from, int to)
     
    432412
    433413    fillRect(font.selectionRectForText(run, point, h, from, to), backgroundColor, colorSpace);
     414}
     415
     416void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
     417{
     418    drawImage(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
     419}
     420
     421void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
     422{
     423    drawImage(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
     424}
     425
     426void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
     427{
     428    drawImage(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
     429}
     430
     431void GraphicsContext::drawImage(Image* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
     432{
     433    drawImage(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
    434434}
    435435
  • trunk/Source/WebCore/platform/graphics/GraphicsContext.h

    r91133 r91332  
    266266        void drawPath(const Path&);
    267267       
     268        void drawNativeImage(NativeImagePtr, const FloatSize& selfSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator = CompositeSourceOver);
     269
    268270        // Allow font smoothing (LCD antialiasing). Not part of the graphics state.
    269271        void setAllowsFontSmoothing(bool);
  • trunk/Source/WebCore/platform/graphics/Image.h

    r85697 r91332  
    142142    virtual CGImageRef getFirstCGImageRefOfSize(const IntSize&) { return 0; }
    143143    virtual RetainPtr<CFArrayRef> getCGImageArray() { return 0; }
     144    static RetainPtr<CGImageRef> imageWithColorSpace(CGImageRef originalImage, ColorSpace);
    144145#endif
    145146
  • trunk/Source/WebCore/platform/graphics/ImageBuffer.h

    r91228 r91332  
    5959        Accelerated
    6060    };
     61   
     62    enum BackingStoreCopy {
     63        CopyBackingStore, // Guarantee subsequent draws don't affect the copy.
     64        DontCopyBackingStore // Subsequent draws may affect the copy.
     65    };
    6166
    6267    class ImageBuffer {
     
    8489
    8590        bool isAccelerated() const { return m_accelerateRendering; }
    86         PassRefPtr<Image> copyImage() const; // Return a new image that is a copy of the buffer.
     91        PassRefPtr<Image> copyImage(BackingStoreCopy copyPreference = CopyBackingStore) const;
    8792
    8893        PassRefPtr<ByteArray> getUnmultipliedImageData(const IntRect&) const;
     
    104109
    105110    private:
     111#if USE(CG)
     112        NativeImagePtr copyNativeImage(BackingStoreCopy copyPreference = CopyBackingStore) const;
     113#endif
     114
    106115        void clip(GraphicsContext*, const FloatRect&) const;
    107116
    108         // The draw method draws the contents of the buffer without copying it.
    109         void draw(GraphicsContext*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
    110                              CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
    111         void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
    112                          const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
    113        
     117        void draw(GraphicsContext*, ColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1), CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
     118        void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
     119
    114120        inline void genericConvertToLuminanceMask();
    115121
  • trunk/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp

    r91228 r91332  
    8787}
    8888
    89 PassRefPtr<Image> ImageBuffer::copyImage() const
    90 {
     89PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyPreference) const
     90{
     91    ASSERT(copyPreference == CopyBackingStore);
    9192    // BitmapImage will release the passed in surface on destruction
    9293    return BitmapImage::create(copyCairoImageSurface(m_data.m_surface).leakRef());
  • trunk/Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp

    r90832 r91332  
    153153}
    154154
     155void GraphicsContext::drawNativeImage(NativeImagePtr imagePtr, const FloatSize& imageSize, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op)
     156{
     157    RetainPtr<CGImageRef> image(imagePtr);
     158
     159    float currHeight = CGImageGetHeight(image.get());
     160    if (currHeight <= srcRect.y())
     161        return;
     162
     163    CGContextRef context = platformContext();
     164    CGContextSaveGState(context);
     165
     166    bool shouldUseSubimage = false;
     167
     168    // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image
     169    // and then set a clip to the portion that we want to display.
     170    FloatRect adjustedDestRect = destRect;
     171
     172    if (srcRect.size() != imageSize) {
     173        CGInterpolationQuality interpolationQuality = CGContextGetInterpolationQuality(context);
     174        // When the image is scaled using high-quality interpolation, we create a temporary CGImage
     175        // containing only the portion we want to display. We need to do this because high-quality
     176        // interpolation smoothes sharp edges, causing pixels from outside the source rect to bleed
     177        // into the destination rect. See <rdar://problem/6112909>.
     178        shouldUseSubimage = (interpolationQuality != kCGInterpolationNone) && (srcRect.size() != destRect.size() || !getCTM().isIdentityOrTranslationOrFlipped());
     179        float xScale = srcRect.width() / destRect.width();
     180        float yScale = srcRect.height() / destRect.height();
     181        if (shouldUseSubimage) {
     182            FloatRect subimageRect = srcRect;
     183            float leftPadding = srcRect.x() - floorf(srcRect.x());
     184            float topPadding = srcRect.y() - floorf(srcRect.y());
     185
     186            subimageRect.move(-leftPadding, -topPadding);
     187            adjustedDestRect.move(-leftPadding / xScale, -topPadding / yScale);
     188
     189            subimageRect.setWidth(ceilf(subimageRect.width() + leftPadding));
     190            adjustedDestRect.setWidth(subimageRect.width() / xScale);
     191
     192            subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
     193            adjustedDestRect.setHeight(subimageRect.height() / yScale);
     194
     195            image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
     196            if (currHeight < srcRect.maxY()) {
     197                ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
     198                adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
     199            }
     200        } else {
     201            adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
     202            adjustedDestRect.setSize(FloatSize(imageSize.width() / xScale, imageSize.height() / yScale));
     203        }
     204
     205        if (!destRect.contains(adjustedDestRect))
     206            CGContextClipToRect(context, destRect);
     207    }
     208
     209    // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
     210    if (!shouldUseSubimage && currHeight < imageSize.height())
     211        adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / imageSize.height());
     212
     213    setPlatformCompositeOperation(op);
     214
     215    // Flip the coords.
     216    CGContextScaleCTM(context, 1, -1);
     217    adjustedDestRect.setY(-adjustedDestRect.maxY());
     218   
     219    // Adjust the color space.
     220    image = Image::imageWithColorSpace(image.get(), styleColorSpace);
     221
     222    // Draw the image.
     223    CGContextDrawImage(context, adjustedDestRect, image.get());
     224
     225    CGContextRestoreGState(context);
     226}
     227
    155228// Draws a filled rectangle with a stroked border.
    156229void GraphicsContext::drawRect(const IntRect& rect)
  • trunk/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp

    r91228 r91332  
    178178}
    179179
    180 PassRefPtr<Image> ImageBuffer::copyImage() const
    181 {
    182     // BitmapImage will release the passed in CGImage on destruction
    183     CGImageRef ctxImage = 0;
    184     if (!m_accelerateRendering)
    185         ctxImage = CGBitmapContextCreateImage(context()->platformContext());
     180PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyPreference) const
     181{
     182    RetainPtr<CGImageRef> image = copyNativeImage(copyPreference);
     183
     184    if (!image)
     185        return 0;
     186
     187    return BitmapImage::create(image.get());
     188}
     189
     190NativeImagePtr ImageBuffer::copyNativeImage(BackingStoreCopy copyPreference) const
     191{
     192    CGImageRef image = 0;
     193    if (!m_accelerateRendering) {
     194        switch (copyPreference) {
     195        case DontCopyBackingStore:
     196            image = CGImageCreate(m_size.width(), m_size.height(), 8, 32, m_data.m_bytesPerRow, m_data.m_colorSpace, m_data.m_bitmapInfo, m_data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
     197            break;
     198        case CopyBackingStore:
     199            image = CGBitmapContextCreateImage(context()->platformContext());
     200            break;
     201        default:
     202            ASSERT_NOT_REACHED();
     203            break;
     204        }
     205    }
    186206#if USE(IOSURFACE_CANVAS_BACKING_STORE)
    187207    else
    188         ctxImage = wkIOSurfaceContextCreateImage(context()->platformContext());
    189 #endif
    190     return BitmapImage::create(ctxImage);
    191 }
    192 
    193 static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data)
    194 {
    195     return CGImageCreate(size.width(), size.height(), 8, 32, data.m_bytesPerRow,
    196                          data.m_colorSpace, data.m_bitmapInfo, data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
    197 }
    198 
    199 void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
    200                        CompositeOperator op, bool useLowQualityScale)
     208        image = wkIOSurfaceContextCreateImage(context()->platformContext());
     209#endif
     210
     211    return image;
     212}
     213
     214void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect, CompositeOperator op, bool useLowQualityScale)
     215{
     216    ASSERT_UNUSED(useLowQualityScale, !useLowQualityScale);
     217    ColorSpace colorSpace = (destContext == m_context) ? ColorSpaceDeviceRGB : styleColorSpace;
     218
     219    RetainPtr<CGImageRef> image;
     220    if (destContext == m_context)
     221        image.adoptCF(copyNativeImage(CopyBackingStore)); // Drawing into our own buffer, need to deep copy.
     222    else
     223        image.adoptCF(copyNativeImage(DontCopyBackingStore));
     224
     225    destContext->drawNativeImage(image.get(), m_size, colorSpace, destRect, srcRect, op);
     226}
     227
     228void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform, const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
    201229{
    202230    if (!m_accelerateRendering) {
    203         if (destContext == context()) {
    204             // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
    205             RefPtr<Image> copy = copyImage();
    206             destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
     231        if (context == m_context) {
     232            RefPtr<Image> copy = copyImage(CopyBackingStore); // Drawing into our own buffer, need to deep copy.
     233            copy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    207234        } else {
    208             RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
    209             destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
     235            RefPtr<Image> imageForRendering = copyImage(DontCopyBackingStore);
     236            imageForRendering->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    210237        }
    211238    } else {
    212         RefPtr<Image> copy = copyImage();
    213         ColorSpace colorSpace = (destContext == context()) ? ColorSpaceDeviceRGB : styleColorSpace;
    214         destContext->drawImage(copy.get(), colorSpace, destRect, srcRect, op, useLowQualityScale);
    215     }
    216 }
    217 
    218 void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
    219                               const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
    220 {
    221     if (!m_accelerateRendering) {
    222         if (destContext == context()) {
    223             // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
    224             RefPtr<Image> copy = copyImage();
    225             copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    226         } else {
    227             RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
    228             imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    229         }
    230     } else {
    231         RefPtr<Image> copy = copyImage();
    232         copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
     239        RefPtr<Image> copy = copyImage(CopyBackingStore);
     240        copy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    233241    }
    234242}
     
    237245{
    238246    CGContextRef platformContextToClip = contextToClip->platformContext();
    239     RetainPtr<CGImageRef> image;
    240     if (!m_accelerateRendering)
    241         image.adoptCF(cgImage(m_size, m_data));
    242 #if USE(IOSURFACE_CANVAS_BACKING_STORE)
    243     else
    244         image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
    245 #endif
     247    RetainPtr<CGImageRef> image(AdoptCF, copyNativeImage(DontCopyBackingStore));
    246248    CGContextTranslateCTM(platformContextToClip, rect.x(), rect.y() + rect.height());
    247249    CGContextScaleCTM(platformContextToClip, 1, -1);
     
    347349    ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
    348350
    349     RetainPtr<CGImageRef> image;
    350     if (!m_accelerateRendering)
    351         image.adoptCF(CGBitmapContextCreateImage(context()->platformContext()));
    352 #if USE(IOSURFACE_CANVAS_BACKING_STORE)
    353     else
    354         image.adoptCF(wkIOSurfaceContextCreateImage(context()->platformContext()));
    355 #endif
     351    RetainPtr<CGImageRef> image(AdoptCF, copyNativeImage(CopyBackingStore));
    356352
    357353    if (!image)
  • trunk/Source/WebCore/platform/graphics/cg/ImageCG.cpp

    r88321 r91332  
    129129}
    130130
    131 static RetainPtr<CGImageRef> imageWithColorSpace(CGImageRef originalImage, ColorSpace colorSpace)
     131RetainPtr<CGImageRef> Image::imageWithColorSpace(CGImageRef originalImage, ColorSpace colorSpace)
    132132{
    133133    CGColorSpaceRef originalColorSpace = CGImageGetColorSpace(originalImage);
     
    196196    }
    197197
    198     float currHeight = CGImageGetHeight(image.get());
    199     if (currHeight <= srcRect.y())
    200         return;
    201 
    202     CGContextRef context = ctxt->platformContext();
    203     GraphicsContextStateSaver stateSaver(*ctxt);
    204 
    205     bool shouldUseSubimage = false;
    206 
    207     // If the source rect is a subportion of the image, then we compute an inflated destination rect that will hold the entire image
    208     // and then set a clip to the portion that we want to display.
    209     FloatRect adjustedDestRect = destRect;
    210198    FloatSize selfSize = currentFrameSize();
    211     if (srcRect.size() != selfSize) {
    212         CGInterpolationQuality interpolationQuality = CGContextGetInterpolationQuality(context);
    213         // When the image is scaled using high-quality interpolation, we create a temporary CGImage
    214         // containing only the portion we want to display. We need to do this because high-quality
    215         // interpolation smoothes sharp edges, causing pixels from outside the source rect to bleed
    216         // into the destination rect. See <rdar://problem/6112909>.
    217         shouldUseSubimage = (interpolationQuality != kCGInterpolationNone) && (srcRect.size() != destRect.size() || !ctxt->getCTM().isIdentityOrTranslationOrFlipped());
    218         float xScale = srcRect.width() / destRect.width();
    219         float yScale = srcRect.height() / destRect.height();
    220         if (shouldUseSubimage) {
    221             FloatRect subimageRect = srcRect;
    222             float leftPadding = srcRect.x() - floorf(srcRect.x());
    223             float topPadding = srcRect.y() - floorf(srcRect.y());
    224 
    225             subimageRect.move(-leftPadding, -topPadding);
    226             adjustedDestRect.move(-leftPadding / xScale, -topPadding / yScale);
    227 
    228             subimageRect.setWidth(ceilf(subimageRect.width() + leftPadding));
    229             adjustedDestRect.setWidth(subimageRect.width() / xScale);
    230 
    231             subimageRect.setHeight(ceilf(subimageRect.height() + topPadding));
    232             adjustedDestRect.setHeight(subimageRect.height() / yScale);
    233 
    234             image.adoptCF(CGImageCreateWithImageInRect(image.get(), subimageRect));
    235             if (currHeight < srcRect.maxY()) {
    236                 ASSERT(CGImageGetHeight(image.get()) == currHeight - CGRectIntegral(srcRect).origin.y);
    237                 adjustedDestRect.setHeight(CGImageGetHeight(image.get()) / yScale);
    238             }
    239         } else {
    240             adjustedDestRect.setLocation(FloatPoint(destRect.x() - srcRect.x() / xScale, destRect.y() - srcRect.y() / yScale));
    241             adjustedDestRect.setSize(FloatSize(selfSize.width() / xScale, selfSize.height() / yScale));
    242         }
    243 
    244         if (!destRect.contains(adjustedDestRect))
    245             CGContextClipToRect(context, destRect);
    246     }
    247 
    248     // If the image is only partially loaded, then shrink the destination rect that we're drawing into accordingly.
    249     if (!shouldUseSubimage && currHeight < selfSize.height())
    250         adjustedDestRect.setHeight(adjustedDestRect.height() * currHeight / selfSize.height());
    251 
    252     ctxt->setCompositeOperation(compositeOp);
    253 
    254     // Flip the coords.
    255     CGContextScaleCTM(context, 1, -1);
    256     adjustedDestRect.setY(-adjustedDestRect.maxY());
    257 
    258     // Adjust the color space.
    259     image = imageWithColorSpace(image.get(), styleColorSpace);
    260 
    261     // Draw the image.
    262     CGContextDrawImage(context, adjustedDestRect, image.get());
    263 
    264     stateSaver.restore();
     199
     200    ctxt->drawNativeImage(image.get(), selfSize, styleColorSpace, destRect, srcRect, compositeOp);
    265201
    266202    if (imageObserver())
     
    314250
    315251    // Adjust the color space.
    316     subImage = imageWithColorSpace(subImage.get(), styleColorSpace);
     252    subImage = Image::imageWithColorSpace(subImage.get(), styleColorSpace);
    317253   
    318254    // 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
  • trunk/Source/WebCore/platform/graphics/filters/FETile.cpp

    r75377 r91332  
    8080    tileImageContext->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, in->absolutePaintRect().location());
    8181
    82     RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
     82    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(CopyBackingStore), true, true);
    8383
    8484    AffineTransform patternTransform;
  • trunk/Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp

    r91228 r91332  
    122122}
    123123
    124 PassRefPtr<Image> ImageBuffer::copyImage() const
    125 {
     124PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyPreference) const
     125{
     126    ASSERT(copyPreference == CopyBackingStore);
    126127    return StillImage::create(m_data.m_pixmap);
    127128}
     
    132133    if (destContext == context()) {
    133134        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
    134         RefPtr<Image> copy = copyImage();
     135        RefPtr<Image> copy = copyImage(CopyBackingStore);
    135136        destContext->drawImage(copy.get(), ColorSpaceDeviceRGB, destRect, srcRect, op, useLowQualityScale);
    136137    } else
     
    143144    if (destContext == context()) {
    144145        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
    145         RefPtr<Image> copy = copyImage();
     146        RefPtr<Image> copy = copyImage(CopyBackingStore);
    146147        copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    147148    } else
  • trunk/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp

    r91228 r91332  
    9898}
    9999
    100 PassRefPtr<Image> ImageBuffer::copyImage() const
    101 {
     100PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyPreference) const
     101{
     102    ASSERT(copyPreference == CopyBackingStore);
    102103    m_context->platformContext()->makeGrContextCurrent();
    103104    return BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap(), true);
  • trunk/Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp

    r91228 r91332  
    9999}
    100100
    101 PassRefPtr<Image> ImageBuffer::copyImage() const
    102 {
     101PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyPreference) const
     102{
     103    ASSERT(copyPreference == CopyBackingStore);
    103104    return adoptRef(new BufferedImage(&m_data));
    104105}
     
    112113                       CompositeOperator op , bool useLowQualityScale)
    113114{
    114     RefPtr<Image> imageCopy = copyImage();
     115    RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
    115116    context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
    116117}
     
    119120                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
    120121{
    121     RefPtr<Image> imageCopy = copyImage();
     122    RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
    122123    imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    123124}
  • trunk/Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp

    r91228 r91332  
    8989}
    9090
    91 PassRefPtr<Image> ImageBuffer::copyImage() const
     91PassRefPtr<Image> ImageBuffer::copyImage(BackingStoreCopy copyPreference) const
    9292{
     93    ASSERT(copyPreference == CopyBackingStore);
    9394    notImplemented();
    9495    return 0;
     
    103104                       CompositeOperator op, bool useLowQualityScale)
    104105{
    105     RefPtr<Image> imageCopy = copyImage();
     106    RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
    106107    context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
    107108}
     
    110111                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
    111112{
    112     RefPtr<Image> imageCopy = copyImage();
     113    RefPtr<Image> imageCopy = copyImage(CopyBackingStore);
    113114    imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    114115}
  • trunk/Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp

    r85603 r91332  
    125125            return false;
    126126
    127         RefPtr<Image> copiedImage = tileImage->copyImage();
     127        RefPtr<Image> copiedImage = tileImage->copyImage(CopyBackingStore);
    128128        if (!copiedImage)
    129129            return false;
  • trunk/Source/WebCore/svg/SVGFEImageElement.cpp

    r90680 r91332  
    179179    }
    180180
    181     return FEImage::create(filter, m_targetImage ? m_targetImage->copyImage() : m_cachedImage->image(), preserveAspectRatio());
     181    return FEImage::create(filter, m_targetImage ? m_targetImage->copyImage(CopyBackingStore) : m_cachedImage->image(), preserveAspectRatio());
    182182}
    183183
  • trunk/Source/WebCore/svg/graphics/SVGImage.cpp

    r89216 r91332  
    228228            return 0;
    229229        draw(buffer->context(), rect(), rect(), ColorSpaceDeviceRGB, CompositeSourceOver);
    230         m_frameCache = buffer->copyImage();
     230        m_frameCache = buffer->copyImage(CopyBackingStore);
    231231    }
    232232    return m_frameCache->nativeImageForCurrentFrame();
Note: See TracChangeset for help on using the changeset viewer.