Changeset 65449 in webkit


Ignore:
Timestamp:
Aug 16, 2010 1:44:01 PM (14 years ago)
Author:
hyatt@apple.com
Message:

https://bugs.webkit.org/show_bug.cgi?id=43507, stop ImageBuffer from copying its data when rendering after canvas changes happen.

Reviewed by Anders Carlsson.

This patch renames ImageBuffer::image() to ImageBuffer::copyImage(). The new method always returns a new copy that is a current
snapshot of the ImageBuffer.

To draw an ImageBuffer, you now use new GraphicsContext calls: drawImageBuffer. Platforms can then optimize these calls to draw
efficiently without having to copy the bits of the ImageBuffer into an Image.

  • WebCore.xcodeproj/project.pbxproj:
  • css/CSSCanvasValue.cpp:

(WebCore::CSSCanvasValue::image):

  • html/HTMLCanvasElement.cpp:

(WebCore::HTMLCanvasElement::willDraw):
(WebCore::HTMLCanvasElement::reset):
(WebCore::HTMLCanvasElement::paint):
(WebCore::HTMLCanvasElement::setSurfaceSize):
(WebCore::HTMLCanvasElement::copiedImage):
(WebCore::HTMLCanvasElement::clearCopiedImage):

  • html/HTMLCanvasElement.h:
  • html/canvas/CanvasPattern.cpp:

(WebCore::CanvasPattern::CanvasPattern):

  • html/canvas/CanvasPattern.h:

(WebCore::CanvasPattern::create):

  • html/canvas/CanvasRenderingContext2D.cpp:

(WebCore::CanvasRenderingContext2D::drawImage):
(WebCore::CanvasRenderingContext2D::createPattern):
(WebCore::CanvasRenderingContext2D::drawTextInternal):

  • html/canvas/WebGLRenderingContext.cpp:

(WebCore::WebGLRenderingContext::paintRenderingResultsToCanvas):
(WebCore::WebGLRenderingContext::reshape):
(WebCore::WebGLRenderingContext::texImage2D):
(WebCore::WebGLRenderingContext::texSubImage2D):

  • html/canvas/WebGLRenderingContext.h:

(WebCore::WebGLRenderingContext::paintsIntoCanvasBuffer):

  • platform/graphics/GeneratedImage.cpp:

(WebCore::GeneratedImage::drawPattern):

  • platform/graphics/GraphicsContext.cpp:

(WebCore::GraphicsContext::drawImageBuffer):
(WebCore::GraphicsContext::clipToImageBuffer):

  • platform/graphics/GraphicsContext.h:
  • platform/graphics/GraphicsContext3D.h:

(WebCore::GraphicsContext3D::paintsIntoCanvasBuffer):

  • platform/graphics/Image.h:
  • platform/graphics/ImageBuffer.h:

(WebCore::ImageBuffer::width):
(WebCore::ImageBuffer::height):

  • platform/graphics/Pattern.cpp:

(WebCore::Pattern::Pattern):

  • platform/graphics/Pattern.h:

(WebCore::Pattern::create):

  • platform/graphics/cairo/GraphicsContextCairo.cpp:
  • platform/graphics/cairo/ImageBufferCairo.cpp:

(WebCore::ImageBuffer::drawsUsingCopy):
(WebCore::ImageBuffer::copyImage):
(WebCore::ImageBuffer::clip):
(WebCore::ImageBuffer::draw):
(WebCore::ImageBuffer::drawPattern):

  • platform/graphics/cg/GraphicsContextCG.cpp:
  • platform/graphics/cg/ImageBufferCG.cpp:

(WebCore::ImageBuffer::ImageBuffer):
(WebCore::ImageBuffer::drawsUsingCopy):
(WebCore::ImageBuffer::copyImage):
(WebCore::ImageBuffer::draw):
(WebCore::ImageBuffer::drawPattern):
(WebCore::ImageBuffer::clip):

  • platform/graphics/cg/ImageBufferData.h:
  • platform/graphics/filters/FEColorMatrix.cpp:

(WebCore::FEColorMatrix::apply):

  • platform/graphics/filters/FEComposite.cpp:

(WebCore::FEComposite::apply):

  • platform/graphics/filters/SourceAlpha.cpp:

(WebCore::SourceAlpha::apply):

  • platform/graphics/filters/SourceGraphic.cpp:

(WebCore::SourceGraphic::apply):

  • platform/graphics/mac/GraphicsContext3DMac.mm:
  • platform/graphics/qt/GraphicsContext3DQt.cpp:
  • platform/graphics/qt/GraphicsContextQt.cpp:
  • platform/graphics/qt/ImageBufferData.h:
  • platform/graphics/qt/ImageBufferQt.cpp:

(WebCore::ImageBufferData::ImageBufferData):
(WebCore::ImageBuffer::drawsUsingCopy):
(WebCore::ImageBuffer::copyImage):
(WebCore::ImageBuffer::draw):
(WebCore::ImageBuffer::drawPattern):
(WebCore::ImageBuffer::clip):

  • platform/graphics/skia/GraphicsContextSkia.cpp:
  • platform/graphics/skia/ImageBufferSkia.cpp:

(WebCore::ImageBuffer::drawsUsingCopy):
(WebCore::ImageBuffer::copyImage):
(WebCore::ImageBuffer::clip):
(WebCore::):

  • platform/graphics/wx/GraphicsContextWx.cpp:
  • platform/graphics/wx/ImageBufferWx.cpp:

(WebCore::ImageBuffer::drawsUsingCopy):
(WebCore::ImageBuffer::copyImage):
(WebCore::ImageBuffer::clip):
(WebCore::ImageBuffer::draw):
(WebCore::ImageBuffer::drawPattern):

  • platform/mac/ScrollbarThemeMac.mm:

(WebCore::ScrollbarThemeMac::paint):

  • rendering/RenderBoxModelObject.cpp:

(WebCore::RenderBoxModelObject::paintFillLayerExtended):

  • rendering/RenderSVGResourceClipper.cpp:

(WebCore::RenderSVGResourceClipper::applyClippingToContext):

  • rendering/RenderSVGResourceFilter.cpp:

(WebCore::RenderSVGResourceFilter::postApplyResource):

  • rendering/RenderSVGResourceGradient.cpp:

(WebCore::clipToTextMask):

  • rendering/RenderSVGResourceMasker.cpp:

(WebCore::RenderSVGResourceMasker::applyResource):

  • rendering/RenderSVGResourcePattern.cpp:

(WebCore::RenderSVGResourcePattern::buildPattern):

  • rendering/RenderThemeMac.mm:

(WebCore::RenderThemeMac::paintProgressBar):

  • svg/SVGFEImageElement.cpp:

(WebCore::SVGFEImageElement::build):

  • svg/graphics/SVGImage.cpp:

(WebCore::SVGImage::nativeImageForCurrentFrame):

  • svg/graphics/SVGImage.h:
  • svg/graphics/filters/SVGFEMerge.cpp:

(WebCore::FEMerge::apply):

  • svg/graphics/filters/SVGFEOffset.cpp:

(WebCore::FEOffset::apply):

  • svg/graphics/filters/SVGFETile.cpp:

(WebCore::FETile::apply):

Location:
trunk/WebCore
Files:
49 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r65446 r65449  
     12010-08-16  David Hyatt  <hyatt@apple.com>
     2
     3        Reviewed by Anders Carlsson.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=43507, stop ImageBuffer from copying its data when rendering after canvas changes happen.
     6       
     7        This patch renames ImageBuffer::image() to ImageBuffer::copyImage(). The new method always returns a new copy that is a current
     8        snapshot of the ImageBuffer.
     9       
     10        To draw an ImageBuffer, you now use new GraphicsContext calls: drawImageBuffer.  Platforms can then optimize these calls to draw
     11        efficiently without having to copy the bits of the ImageBuffer into an Image.
     12
     13        * WebCore.xcodeproj/project.pbxproj:
     14        * css/CSSCanvasValue.cpp:
     15        (WebCore::CSSCanvasValue::image):
     16        * html/HTMLCanvasElement.cpp:
     17        (WebCore::HTMLCanvasElement::willDraw):
     18        (WebCore::HTMLCanvasElement::reset):
     19        (WebCore::HTMLCanvasElement::paint):
     20        (WebCore::HTMLCanvasElement::setSurfaceSize):
     21        (WebCore::HTMLCanvasElement::copiedImage):
     22        (WebCore::HTMLCanvasElement::clearCopiedImage):
     23        * html/HTMLCanvasElement.h:
     24        * html/canvas/CanvasPattern.cpp:
     25        (WebCore::CanvasPattern::CanvasPattern):
     26        * html/canvas/CanvasPattern.h:
     27        (WebCore::CanvasPattern::create):
     28        * html/canvas/CanvasRenderingContext2D.cpp:
     29        (WebCore::CanvasRenderingContext2D::drawImage):
     30        (WebCore::CanvasRenderingContext2D::createPattern):
     31        (WebCore::CanvasRenderingContext2D::drawTextInternal):
     32        * html/canvas/WebGLRenderingContext.cpp:
     33        (WebCore::WebGLRenderingContext::paintRenderingResultsToCanvas):
     34        (WebCore::WebGLRenderingContext::reshape):
     35        (WebCore::WebGLRenderingContext::texImage2D):
     36        (WebCore::WebGLRenderingContext::texSubImage2D):
     37        * html/canvas/WebGLRenderingContext.h:
     38        (WebCore::WebGLRenderingContext::paintsIntoCanvasBuffer):
     39        * platform/graphics/GeneratedImage.cpp:
     40        (WebCore::GeneratedImage::drawPattern):
     41        * platform/graphics/GraphicsContext.cpp:
     42        (WebCore::GraphicsContext::drawImageBuffer):
     43        (WebCore::GraphicsContext::clipToImageBuffer):
     44        * platform/graphics/GraphicsContext.h:
     45        * platform/graphics/GraphicsContext3D.h:
     46        (WebCore::GraphicsContext3D::paintsIntoCanvasBuffer):
     47        * platform/graphics/Image.h:
     48        * platform/graphics/ImageBuffer.h:
     49        (WebCore::ImageBuffer::width):
     50        (WebCore::ImageBuffer::height):
     51        * platform/graphics/Pattern.cpp:
     52        (WebCore::Pattern::Pattern):
     53        * platform/graphics/Pattern.h:
     54        (WebCore::Pattern::create):
     55        * platform/graphics/cairo/GraphicsContextCairo.cpp:
     56        * platform/graphics/cairo/ImageBufferCairo.cpp:
     57        (WebCore::ImageBuffer::drawsUsingCopy):
     58        (WebCore::ImageBuffer::copyImage):
     59        (WebCore::ImageBuffer::clip):
     60        (WebCore::ImageBuffer::draw):
     61        (WebCore::ImageBuffer::drawPattern):
     62        * platform/graphics/cg/GraphicsContextCG.cpp:
     63        * platform/graphics/cg/ImageBufferCG.cpp:
     64        (WebCore::ImageBuffer::ImageBuffer):
     65        (WebCore::ImageBuffer::drawsUsingCopy):
     66        (WebCore::ImageBuffer::copyImage):
     67        (WebCore::ImageBuffer::draw):
     68        (WebCore::ImageBuffer::drawPattern):
     69        (WebCore::ImageBuffer::clip):
     70        * platform/graphics/cg/ImageBufferData.h:
     71        * platform/graphics/filters/FEColorMatrix.cpp:
     72        (WebCore::FEColorMatrix::apply):
     73        * platform/graphics/filters/FEComposite.cpp:
     74        (WebCore::FEComposite::apply):
     75        * platform/graphics/filters/SourceAlpha.cpp:
     76        (WebCore::SourceAlpha::apply):
     77        * platform/graphics/filters/SourceGraphic.cpp:
     78        (WebCore::SourceGraphic::apply):
     79        * platform/graphics/mac/GraphicsContext3DMac.mm:
     80        * platform/graphics/qt/GraphicsContext3DQt.cpp:
     81        * platform/graphics/qt/GraphicsContextQt.cpp:
     82        * platform/graphics/qt/ImageBufferData.h:
     83        * platform/graphics/qt/ImageBufferQt.cpp:
     84        (WebCore::ImageBufferData::ImageBufferData):
     85        (WebCore::ImageBuffer::drawsUsingCopy):
     86        (WebCore::ImageBuffer::copyImage):
     87        (WebCore::ImageBuffer::draw):
     88        (WebCore::ImageBuffer::drawPattern):
     89        (WebCore::ImageBuffer::clip):
     90        * platform/graphics/skia/GraphicsContextSkia.cpp:
     91        * platform/graphics/skia/ImageBufferSkia.cpp:
     92        (WebCore::ImageBuffer::drawsUsingCopy):
     93        (WebCore::ImageBuffer::copyImage):
     94        (WebCore::ImageBuffer::clip):
     95        (WebCore::):
     96        * platform/graphics/wx/GraphicsContextWx.cpp:
     97        * platform/graphics/wx/ImageBufferWx.cpp:
     98        (WebCore::ImageBuffer::drawsUsingCopy):
     99        (WebCore::ImageBuffer::copyImage):
     100        (WebCore::ImageBuffer::clip):
     101        (WebCore::ImageBuffer::draw):
     102        (WebCore::ImageBuffer::drawPattern):
     103        * platform/mac/ScrollbarThemeMac.mm:
     104        (WebCore::ScrollbarThemeMac::paint):
     105        * rendering/RenderBoxModelObject.cpp:
     106        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
     107        * rendering/RenderSVGResourceClipper.cpp:
     108        (WebCore::RenderSVGResourceClipper::applyClippingToContext):
     109        * rendering/RenderSVGResourceFilter.cpp:
     110        (WebCore::RenderSVGResourceFilter::postApplyResource):
     111        * rendering/RenderSVGResourceGradient.cpp:
     112        (WebCore::clipToTextMask):
     113        * rendering/RenderSVGResourceMasker.cpp:
     114        (WebCore::RenderSVGResourceMasker::applyResource):
     115        * rendering/RenderSVGResourcePattern.cpp:
     116        (WebCore::RenderSVGResourcePattern::buildPattern):
     117        * rendering/RenderThemeMac.mm:
     118        (WebCore::RenderThemeMac::paintProgressBar):
     119        * svg/SVGFEImageElement.cpp:
     120        (WebCore::SVGFEImageElement::build):
     121        * svg/graphics/SVGImage.cpp:
     122        (WebCore::SVGImage::nativeImageForCurrentFrame):
     123        * svg/graphics/SVGImage.h:
     124        * svg/graphics/filters/SVGFEMerge.cpp:
     125        (WebCore::FEMerge::apply):
     126        * svg/graphics/filters/SVGFEOffset.cpp:
     127        (WebCore::FEOffset::apply):
     128        * svg/graphics/filters/SVGFETile.cpp:
     129        (WebCore::FETile::apply):
     130
    11312010-08-16  Paul Sawaya  <psawaya@apple.com>
    2132
  • trunk/WebCore/WebCore.xcodeproj/project.pbxproj

    r65448 r65449  
    40414041                B2A015AA0AF6CD53006BCE0E /* GraphicsTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A015940AF6CD53006BCE0E /* GraphicsTypes.cpp */; };
    40424042                B2A015AB0AF6CD53006BCE0E /* GraphicsTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A015950AF6CD53006BCE0E /* GraphicsTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
    4043                 B2A10B920B3818BD00099AA4 /* ImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A10B910B3818BD00099AA4 /* ImageBuffer.h */; };
     4043                B2A10B920B3818BD00099AA4 /* ImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A10B910B3818BD00099AA4 /* ImageBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
    40444044                B2A10B940B3818D700099AA4 /* ImageBufferCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A10B930B3818D700099AA4 /* ImageBufferCG.cpp */; };
    40454045                B2A1F2AA0CEF0ABF00442F6A /* SVGFontElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A1F2A10CEF0ABF00442F6A /* SVGFontElement.cpp */; };
     
    47734773                BCA8CA5F11E4E6D100812FB7 /* BackForwardListImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA8CA5D11E4E6D100812FB7 /* BackForwardListImpl.cpp */; };
    47744774                BCA8CA6011E4E6D100812FB7 /* BackForwardListImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA8CA5E11E4E6D100812FB7 /* BackForwardListImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
     4775                BCA979171215D055005C485C /* ImageBufferData.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA979161215D055005C485C /* ImageBufferData.h */; settings = {ATTRIBUTES = (Private, ); }; };
    47754776                BCAA90C30A7EBA60008B1229 /* Scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCAA90C20A7EBA60008B1229 /* Scrollbar.cpp */; };
    47764777                BCACF3BC1072921A00C0C8A3 /* UserContentURLPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCACF3BA1072921A00C0C8A3 /* UserContentURLPattern.cpp */; };
     
    1052710528                BCA8CA5D11E4E6D100812FB7 /* BackForwardListImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackForwardListImpl.cpp; sourceTree = "<group>"; };
    1052810529                BCA8CA5E11E4E6D100812FB7 /* BackForwardListImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardListImpl.h; sourceTree = "<group>"; };
     10530                BCA979161215D055005C485C /* ImageBufferData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageBufferData.h; sourceTree = "<group>"; };
    1052910531                BCAA90C20A7EBA60008B1229 /* Scrollbar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Scrollbar.cpp; path = platform/Scrollbar.cpp; sourceTree = SOURCE_ROOT; };
    1053010532                BCACF3BA1072921A00C0C8A3 /* UserContentURLPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserContentURLPattern.cpp; sourceTree = "<group>"; };
     
    1561615618                                A80D67070E9E9DEB00E420F0 /* GraphicsContextPlatformPrivateCG.h */,
    1561715619                                B2A10B930B3818D700099AA4 /* ImageBufferCG.cpp */,
     15620                                BCA979161215D055005C485C /* ImageBufferData.h */,
    1561815621                                B27535300B053814002CE64F /* ImageCG.cpp */,
    1561915622                                B27535310B053814002CE64F /* ImageSourceCG.cpp */,
     
    2018920192                                CE172E011136E8CE0062A533 /* ZoomMode.h in Headers */,
    2019020193                                C50B561712119D23008B46E0 /* GroupSettings.h in Headers */,
     20194                                BCA979171215D055005C485C /* ImageBufferData.h in Headers */,
    2019120195                                490707E71219C04300D90E51 /* ANGLEWebKitBridge.h in Headers */,
    2019220196                        );
     
    2024920253                        buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
    2025020254                        compatibilityVersion = "Xcode 2.4";
    20251                         developmentRegion = English;
    2025220255                        hasScannedForEncodings = 1;
    2025320256                        knownRegions = (
  • trunk/WebCore/css/CSSCanvasValue.cpp

    r47305 r65449  
    9191    if (!elt || !elt->buffer())
    9292        return 0;
    93     return elt->buffer()->image();
     93    return elt->copiedImage();
    9494}
    9595
  • trunk/WebCore/html/HTMLCanvasElement.cpp

    r65367 r65449  
    210210void HTMLCanvasElement::willDraw(const FloatRect& rect)
    211211{
    212     if (m_imageBuffer)
    213         m_imageBuffer->clearImage();
     212    m_copiedImage.clear(); // Clear our image snapshot if we have one.
    214213
    215214    if (RenderBox* ro = renderBox()) {
     
    243242
    244243    IntSize oldSize = size();
    245     setSurfaceSize(IntSize(w, h));
     244    setSurfaceSize(IntSize(w, h)); // The image buffer gets cleared here.
    246245
    247246#if ENABLE(3D_CANVAS)
    248     if (m_context && m_context->is3d())
     247    if (m_context && m_context->is3d() && oldSize != size())
    249248        static_cast<WebGLRenderingContext*>(m_context.get())->reshape(width(), height());
    250249#endif
     
    278277    if (m_context && m_context->is3d()) {
    279278        context3D = static_cast<WebGLRenderingContext*>(m_context.get());
    280         context3D->beginPaint();
     279        if (!context3D->paintsIntoCanvasBuffer())
     280            return;
     281        context3D->paintRenderingResultsToCanvas();
    281282    }
    282283#endif
     
    285286        ImageBuffer* imageBuffer = buffer();
    286287        if (imageBuffer) {
    287             Image* image = imageBuffer->imageForRendering();
    288             if (image)
    289                 context->drawImage(image, DeviceColorSpace, r);
     288            if (imageBuffer->drawsUsingCopy())
     289                context->drawImage(copiedImage(), DeviceColorSpace, r);
     290            else
     291                context->drawImageBuffer(imageBuffer, DeviceColorSpace, r);
    290292        }
    291293    }
    292 
    293 #if ENABLE(3D_CANVAS)
    294     if (context3D)
    295         context3D->endPaint();
    296 #endif
    297294}
    298295
     
    326323    m_hasCreatedImageBuffer = false;
    327324    m_imageBuffer.clear();
     325    m_copiedImage.clear();
    328326}
    329327
     
    421419}
    422420
     421Image* HTMLCanvasElement::copiedImage() const
     422{
     423    if (!m_copiedImage && buffer())
     424        m_copiedImage = buffer()->copyImage();
     425    return m_copiedImage.get();
     426}
     427
     428void HTMLCanvasElement::clearCopiedImage()
     429{
     430    m_copiedImage.clear();
     431}
     432
    423433AffineTransform HTMLCanvasElement::baseTransform() const
    424434{
  • trunk/WebCore/html/HTMLCanvasElement.h

    r63502 r65449  
    3939class GraphicsContext;
    4040class HTMLCanvasElement;
     41class Image;
    4142class ImageBuffer;
    4243class IntSize;
     
    9495
    9596    ImageBuffer* buffer() const;
     97    Image* copiedImage() const;
     98    void clearCopiedImage();
    9699
    97100    IntRect convertLogicalToDevice(const FloatRect&) const;
     
    150153    mutable bool m_hasCreatedImageBuffer;
    151154    mutable OwnPtr<ImageBuffer> m_imageBuffer;
     155   
     156    mutable RefPtr<Image> m_copiedImage; // FIXME: This is temporary for platforms that have to copy the image buffer to render (and for CSSCanvasValue).
    152157};
    153158
  • trunk/WebCore/html/canvas/CanvasPattern.cpp

    r49734 r65449  
    5858}
    5959
    60 CanvasPattern::CanvasPattern(Image* image, bool repeatX, bool repeatY, bool originClean)
     60CanvasPattern::CanvasPattern(PassRefPtr<Image> image, bool repeatX, bool repeatY, bool originClean)
    6161    : m_pattern(Pattern::create(image, repeatX, repeatY))
    6262    , m_originClean(originClean)
  • trunk/WebCore/html/canvas/CanvasPattern.h

    r65021 r65449  
    4242        static void parseRepetitionType(const String&, bool& repeatX, bool& repeatY, ExceptionCode&);
    4343
    44         static PassRefPtr<CanvasPattern> create(Image* image, bool repeatX, bool repeatY, bool originClean)
     44        static PassRefPtr<CanvasPattern> create(PassRefPtr<Image> image, bool repeatX, bool repeatY, bool originClean)
    4545        {
    4646            return adoptRef(new CanvasPattern(image, repeatX, repeatY, originClean));
     
    5252
    5353    private:
    54         CanvasPattern(Image*, bool repeatX, bool repeatY, bool originClean);
     54        CanvasPattern(PassRefPtr<Image>, bool repeatX, bool repeatY, bool originClean);
    5555
    5656        RefPtr<Pattern> m_pattern;
  • trunk/WebCore/html/canvas/CanvasRenderingContext2D.cpp

    r64980 r65449  
    12651265    sourceCanvas->makeRenderingResultsAvailable();
    12661266
    1267     c->drawImage(buffer->image(), DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
     1267    c->drawImageBuffer(buffer, DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
    12681268    willDraw(destRect); // This call comes after drawImage, since the buffer we draw into may be our own, and we need to make sure it is dirty.
    12691269                        // FIXME: Arguably willDraw should become didDraw and occur after drawing calls and not before them to avoid problems like this.
     
    14651465    if (ec)
    14661466        return 0;
    1467     return CanvasPattern::create(canvas->buffer()->image(), repeatX, repeatY, canvas->originClean());
     1467    return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas->originClean());
    14681468}
    14691469
     
    18211821
    18221822        c->save();
    1823         c->clipToImageBuffer(maskRect, maskImage.get());
     1823        c->clipToImageBuffer(maskImage.get(), maskRect);
    18241824        drawStyle->applyFillColor(c);
    18251825        c->fillRect(maskRect);
  • trunk/WebCore/html/canvas/WebGLRenderingContext.cpp

    r65330 r65449  
    159159void WebGLRenderingContext::paintRenderingResultsToCanvas()
    160160{
    161     if (m_markedCanvasDirty) {
    162         // FIXME: It should not be necessary to clear the image before doing a readback.
    163         // Investigate why this is needed and remove if possible.
    164         canvas()->buffer()->clearImage();
    165         m_markedCanvasDirty = false;
    166         m_context->paintRenderingResultsToCanvas(this);
    167     }
    168 }
    169 
    170 void WebGLRenderingContext::beginPaint()
    171 {
    172     if (m_markedCanvasDirty)
    173         m_context->beginPaint(this);
    174 }
    175 
    176 void WebGLRenderingContext::endPaint()
    177 {
    178     if (m_markedCanvasDirty) {
    179         m_markedCanvasDirty = false;
    180         m_context->endPaint();
    181     }
     161    if (!m_markedCanvasDirty)
     162        return;
     163    canvas()->clearCopiedImage();
     164    m_markedCanvasDirty = false;
     165    m_context->paintRenderingResultsToCanvas(this);
    182166}
    183167
     
    192176        m_needsUpdate = false;
    193177    }
    194    
     178
     179    // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
     180    // clear (and this matches what reshape will do).
    195181    m_context->reshape(width, height);
    196182}
     
    21982184        return;
    21992185    }
    2200     texImage2DImpl(target, level, internalformat, format, type, canvas->buffer()->image(),
     2186   
     2187    texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(),
    22012188                   m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
    22022189}
     
    23482335        return;
    23492336    }
    2350     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->buffer()->image(),
     2337   
     2338    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(),
    23512339                      m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
    23522340}
  • trunk/WebCore/html/canvas/WebGLRenderingContext.h

    r65192 r65449  
    280280    virtual void paintRenderingResultsToCanvas();
    281281
    282     // Helpers for notification about paint events.
    283     void beginPaint();
    284     void endPaint();
    285 
    286282    void removeObject(WebGLObject*);
     283
     284    bool paintsIntoCanvasBuffer() const { return m_context->paintsIntoCanvasBuffer(); }
    287285
    288286  private:
  • trunk/WebCore/platform/graphics/GeneratedImage.cpp

    r54503 r65449  
    6464    graphicsContext->fillRect(FloatRect(FloatPoint(), adjustedSize), *m_generator.get());
    6565
    66     // Grab the final image from the image buffer.
    67     Image* bitmap = imageBuffer->image();
    68 
    69     // Now just call drawTiled on that image.
    70     bitmap->drawPattern(context, adjustedSrcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect);
     66    // Tile the image buffer into the context.
     67    imageBuffer->drawPattern(context, adjustedSrcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect);
    7168}
    7269
  • trunk/WebCore/platform/graphics/GraphicsContext.cpp

    r61129 r65449  
    3131#include "Generator.h"
    3232#include "GraphicsContextPrivate.h"
     33#include "ImageBuffer.h"
    3334
    3435using namespace std;
     
    443444}
    444445
     446void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
     447{
     448    drawImageBuffer(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
     449}
     450
     451void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
     452{
     453    drawImageBuffer(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
     454}
     455
     456void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
     457{
     458    drawImageBuffer(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
     459}
     460
     461void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
     462{
     463    drawImageBuffer(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
     464}
     465
     466void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
     467{
     468    if (paintingDisabled() || !image)
     469        return;
     470       
     471    float tsw = src.width();
     472    float tsh = src.height();
     473    float tw = dest.width();
     474    float th = dest.height();
     475
     476    if (tsw == -1)
     477        tsw = image->width();
     478    if (tsh == -1)
     479        tsh = image->height();
     480
     481    if (tw == -1)
     482        tw = image->width();
     483    if (th == -1)
     484        th = image->height();
     485
     486    if (useLowQualityScale) {
     487        save();
     488        setImageInterpolationQuality(InterpolationNone);
     489    }
     490
     491    image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale);
     492   
     493    if (useLowQualityScale)
     494        restore();
     495}
     496
    445497void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
    446498    const IntSize& bottomLeft, const IntSize& bottomRight)
     
    459511
    460512    clipOut(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
     513}
     514
     515void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& rect)
     516{
     517    if (paintingDisabled())
     518        return;
     519    buffer->clip(this, rect);
    461520}
    462521
  • trunk/WebCore/platform/graphics/GraphicsContext.h

    r65097 r65449  
    239239                            CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
    240240
     241        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver);
     242        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
     243        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver);
     244        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
     245        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
     246                             CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
     247
    241248        void setImageInterpolationQuality(InterpolationQuality);
    242249        InterpolationQuality imageInterpolationQuality() const;
     
    249256        void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight);
    250257        void clipPath(WindRule);
    251         void clipToImageBuffer(const FloatRect&, const ImageBuffer*);
    252258        void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true);
     259        void clipToImageBuffer(ImageBuffer*, const FloatRect&);
    253260
    254261        int textDrawingMode();
  • trunk/WebCore/platform/graphics/GraphicsContext3D.h

    r65446 r65449  
    721721    void paintRenderingResultsToCanvas(CanvasRenderingContext* context);
    722722
    723     // Helpers for notification about paint events
    724     void beginPaint(CanvasRenderingContext* context);
    725     void endPaint();
    726723#if PLATFORM(QT)
    727724    void paint(QPainter* painter, const QRect& rect) const;
     725    bool paintsIntoCanvasBuffer() const { return true; }
     726#else
     727    bool paintsIntoCanvasBuffer() const { return false; }
    728728#endif
    729729
  • trunk/WebCore/platform/graphics/Image.h

    r64584 r65449  
    151151#endif
    152152
     153    virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
     154                             const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
     155
    153156protected:
    154157    Image(ImageObserver* = 0);
     
    168171    virtual Color solidColor() const { return Color(); }
    169172   
    170     virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
    171                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
    172 
    173173private:
    174174    RefPtr<SharedBuffer> m_data; // The encoded raw data for the image.
  • trunk/WebCore/platform/graphics/ImageBuffer.h

    r65021 r65449  
    3030
    3131#include "AffineTransform.h"
     32#include "FloatRect.h"
    3233#include "Image.h"
    3334#include "IntSize.h"
     
    7273
    7374        const IntSize& size() const { return m_size; }
     75        int width() const { return m_size.width(); }
     76        int height() const { return m_size.height(); }
     77       
    7478        GraphicsContext* context() const;
    7579
    76         Image* image() const;
    77 #if PLATFORM(QT)
    78         Image* imageForRendering() const;
    79 #else
    80         Image* imageForRendering() const { return image(); }
    81 #endif
    82 
    83         void clearImage() { m_image.clear(); }
     80        bool drawsUsingCopy() const; // If the image buffer has to render using a copied image, it will return true.
     81        PassRefPtr<Image> copyImage() const; // Return a new image that is a copy of the buffer.
    8482
    8583        PassRefPtr<ImageData> getUnmultipliedImageData(const IntRect&) const;
     
    9795        AffineTransform baseTransform() const { return AffineTransform(1, 0, 0, -1, 0, m_size.height()); }
    9896#endif
     97
     98    private:
     99        void clip(GraphicsContext*, const FloatRect&) const;
     100
     101        // The draw method draws the contents of the buffer without copying it.
     102        void draw(GraphicsContext*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
     103                             CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
     104        void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
     105                         const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
     106        friend class GraphicsContext;
     107        friend class GeneratedImage;
     108
    99109    private:
    100110        ImageBufferData m_data;
     
    102112        IntSize m_size;
    103113        OwnPtr<GraphicsContext> m_context;
    104         mutable RefPtr<Image> m_image;
    105114
    106115#if !PLATFORM(CG)
  • trunk/WebCore/platform/graphics/Pattern.cpp

    r54503 r65449  
    3232namespace WebCore {
    3333
    34 Pattern::Pattern(Image* image, bool repeatX, bool repeatY)
     34Pattern::Pattern(PassRefPtr<Image> image, bool repeatX, bool repeatY)
    3535    : m_tileImage(image)
    3636    , m_repeatX(repeatX)
     
    4040#endif
    4141{
    42     ASSERT(image);
     42    ASSERT(m_tileImage);
    4343}
    4444
  • trunk/WebCore/platform/graphics/Pattern.h

    r56391 r65449  
    3030
    3131#include "AffineTransform.h"
     32#include "Image.h"
    3233
    3334#include <wtf/PassRefPtr.h>
     
    6566
    6667class AffineTransform;
    67 class Image;
    6868
    6969class Pattern : public RefCounted<Pattern> {
    7070public:
    71     static PassRefPtr<Pattern> create(Image* tileImage, bool repeatX, bool repeatY)
     71    static PassRefPtr<Pattern> create(PassRefPtr<Image> tileImage, bool repeatX, bool repeatY)
    7272    {
    7373        return adoptRef(new Pattern(tileImage, repeatX, repeatY));
     
    9292
    9393private:
    94     Pattern(Image*, bool repeatX, bool repeatY);
     94    Pattern(PassRefPtr<Image>, bool repeatX, bool repeatY);
    9595
    9696    RefPtr<Image> m_tileImage;
  • trunk/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp

    r64490 r65449  
    907907    cairo_clip(cr);
    908908    cairo_set_fill_rule(cr, savedFillRule);
    909 }
    910 
    911 void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
    912 {
    913     if (paintingDisabled())
    914         return;
    915 
    916     notImplemented();
    917909}
    918910
  • trunk/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp

    r64506 r65449  
    9898}
    9999
    100 Image* ImageBuffer::image() const
    101 {
    102     if (!m_image) {
    103         // It's assumed that if image() is called, the actual rendering to the
    104         // GraphicsContext must be done.
    105         ASSERT(context());
    106 
    107         // This creates a COPY of the image and will cache that copy. This means
    108         // that if subsequent operations take place on the context, neither the
    109         // currently-returned image, nor the results of future image() calls,
    110         // will contain that operation.
    111         //
    112         // This seems silly, but is the way the CG port works: image() is
    113         // intended to be used only when rendering is "complete."
    114         cairo_surface_t* newsurface = copySurface(m_data.m_surface);
    115 
    116         // BitmapImage will release the passed in surface on destruction
    117         m_image = BitmapImage::create(newsurface);
    118     }
    119     return m_image.get();
     100bool ImageBuffer::drawsUsingCopy() const
     101{
     102    return true;
     103}
     104
     105PassRefPtr<Image> ImageBuffer::copyImage() const
     106{
     107    // BitmapImage will release the passed in surface on destruction
     108    return BitmapImage::create(copySurface(m_data.m_surface));
     109}
     110
     111void ImageBuffer::clip(GraphicsContext* context, const FloatRect&) const
     112{
     113    notImplemented();
     114}
     115
     116void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
     117                       CompositeOperator op , bool useLowQualityScale)
     118{
     119    RefPtr<Image> imageCopy = copyImage();
     120    context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
     121}
     122
     123void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
     124                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
     125{
     126    RefPtr<Image> imageCopy = copyImage();
     127    imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    120128}
    121129
  • trunk/WebCore/platform/graphics/cg/GraphicsContextCG.cpp

    r65118 r65449  
    754754}
    755755
    756 void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
    757 {
    758     if (paintingDisabled())
    759         return;
    760 
    761     CGContextTranslateCTM(platformContext(), rect.x(), rect.y() + rect.height());
    762     CGContextScaleCTM(platformContext(), 1, -1);
    763     CGContextClipToMask(platformContext(), FloatRect(FloatPoint(), rect.size()), imageBuffer->image()->getCGImageRef());
    764     CGContextScaleCTM(platformContext(), 1, -1);
    765     CGContextTranslateCTM(platformContext(), -rect.x(), -rect.y() - rect.height());
    766 }
    767 
    768756void GraphicsContext::beginTransparencyLayer(float opacity)
    769757{
  • trunk/WebCore/platform/graphics/cg/ImageBufferCG.cpp

    r64254 r65449  
    4747namespace WebCore {
    4848
     49static void releaseImageData(void*, const void* data, size_t)
     50{
     51    fastFree(const_cast<void*>(data));
     52}
     53
    4954ImageBufferData::ImageBufferData(const IntSize&)
    5055    : m_data(0)
     
    5762{
    5863    success = false;  // Make early return mean failure.
    59     unsigned bytesPerRow;
    6064    if (size.width() < 0 || size.height() < 0)
    6165        return;
    62     bytesPerRow = size.width();
     66
     67    unsigned bytesPerRow = size.width();
    6368    if (imageColorSpace != GrayScale) {
    6469        // Protect against overflow
     
    6772        bytesPerRow *= 4;
    6873    }
    69 
     74    m_data.m_bytesPerRow = bytesPerRow;
     75
     76    size_t dataSize = size.height() * bytesPerRow;
    7077    if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data))
    7178        return;
     
    7380    ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0);
    7481
    75     RetainPtr<CGColorSpaceRef> colorSpace;
    7682    switch(imageColorSpace) {
    7783        case DeviceRGB:
    78             colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
     84            m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
    7985            break;
    8086        case GrayScale:
    81             colorSpace.adoptCF(CGColorSpaceCreateDeviceGray());
     87            m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceGray());
    8288            break;
    8389#if ((PLATFORM(MAC) || PLATFORM(CHROMIUM)) && !defined(BUILDING_ON_TIGER))
    8490        case LinearRGB:
    85             colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear));
     91            m_data.m_colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear));
    8692            break;
     93           
    8794#endif
    8895        default:
    89             colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
     96            m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
    9097            break;
    9198    }
    9299
     100    m_data.m_grayScale = imageColorSpace == GrayScale;
     101    m_data.m_bitmapInfo = m_data.m_grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast;
    93102    RetainPtr<CGContextRef> cgContext(AdoptCF, CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow,
    94         colorSpace.get(), (imageColorSpace == GrayScale) ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast));
     103                                                                     m_data.m_colorSpace.get(), m_data.m_bitmapInfo));
    95104    if (!cgContext)
    96105        return;
     
    100109    m_context->translate(0, -size.height());
    101110    success = true;
     111   
     112    // Create a live image that wraps the data.
     113    m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize, releaseImageData));
    102114}
    103115
    104116ImageBuffer::~ImageBuffer()
    105117{
    106     fastFree(m_data.m_data);
    107118}
    108119
     
    112123}
    113124
    114 Image* ImageBuffer::image() const
    115 {
    116     if (!m_image) {
    117         // It's assumed that if image() is called, the actual rendering to the
    118         // GraphicsContext must be done.
    119         ASSERT(context());
    120         CGImageRef cgImage = CGBitmapContextCreateImage(context()->platformContext());
    121         // BitmapImage will release the passed in CGImage on destruction
    122         m_image = BitmapImage::create(cgImage);
    123     }
    124     return m_image.get();
     125bool ImageBuffer::drawsUsingCopy() const
     126{
     127    return false;
     128}
     129
     130PassRefPtr<Image> ImageBuffer::copyImage() const
     131{
     132    // BitmapImage will release the passed in CGImage on destruction
     133    return BitmapImage::create(CGBitmapContextCreateImage(context()->platformContext()));
     134}
     135
     136static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data)
     137{
     138    return CGImageCreate(size.width(), size.height(), 8, data.m_grayScale ? 8 : 32, data.m_bytesPerRow,
     139                         data.m_colorSpace.get(), data.m_bitmapInfo, data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
     140}
     141
     142void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
     143                       CompositeOperator op, bool useLowQualityScale)
     144{
     145    if (destContext == context()) {
     146        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
     147        RefPtr<Image> copy = copyImage();
     148        destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale);
     149    } else {
     150        RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
     151        destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
     152    }
     153}
     154
     155void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
     156                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
     157{
     158    if (destContext == context()) {
     159        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
     160        RefPtr<Image> copy = copyImage();
     161        copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
     162    } else {
     163        RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
     164        imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
     165    }
     166}
     167
     168void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
     169{
     170    RetainPtr<CGImageRef> image(AdoptCF, cgImage(m_size, m_data));
     171                                                                                         
     172    CGContextRef platformContext = context->platformContext();
     173    CGContextTranslateCTM(platformContext, rect.x(), rect.y() + rect.height());
     174    CGContextScaleCTM(platformContext, 1, -1);
     175    CGContextClipToMask(platformContext, FloatRect(FloatPoint(), rect.size()), image.get());
     176    CGContextScaleCTM(platformContext, 1, -1);
     177    CGContextTranslateCTM(platformContext, -rect.x(), -rect.y() - rect.height());
    125178}
    126179
  • trunk/WebCore/platform/graphics/cg/ImageBufferData.h

    r37948 r65449  
    2727#define ImageBufferData_h
    2828
     29#include "Image.h"
     30#include <wtf/RefPtr.h>
     31#include <wtf/RetainPtr.h>
     32
     33typedef struct CGColorSpace *CGColorSpaceRef;
     34typedef struct CGDataProvider *CGDataProviderRef;
     35typedef uint32_t CGBitmapInfo;
     36
    2937namespace WebCore {
    3038
     
    3644
    3745    void* m_data;
     46   
     47    RetainPtr<CGDataProviderRef> m_dataProvider;
     48    CGBitmapInfo m_bitmapInfo;
     49    bool m_grayScale;
     50    unsigned m_bytesPerRow;
     51    RetainPtr<CGColorSpaceRef> m_colorSpace;
    3852};
    3953
  • trunk/WebCore/platform/graphics/filters/FEColorMatrix.cpp

    r59069 r65449  
    165165        return;
    166166
    167     filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
     167    filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    168168
    169169    IntRect imageRect(IntPoint(), resultImage()->size());
  • trunk/WebCore/platform/graphics/filters/FEComposite.cpp

    r59069 r65449  
    132132    switch (m_type) {
    133133    case FECOMPOSITE_OPERATOR_OVER:
    134         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
    135         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
     134        filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
     135        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    136136        break;
    137137    case FECOMPOSITE_OPERATOR_IN:
    138138        filterContext->save();
    139         filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->scaledSubRegion()), m_in2->resultImage());
    140         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
     139        filterContext->clipToImageBuffer(m_in->resultImage(), calculateDrawingRect(m_in2->scaledSubRegion()));
     140        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    141141        filterContext->restore();
    142142        break;
    143143    case FECOMPOSITE_OPERATOR_OUT:
    144         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
    145         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut);
     144        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
     145        filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut);
    146146        break;
    147147    case FECOMPOSITE_OPERATOR_ATOP:
    148         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
    149         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop);
     148        filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
     149        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop);
    150150        break;
    151151    case FECOMPOSITE_OPERATOR_XOR:
    152         filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
    153         filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR);
     152        filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
     153        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR);
    154154        break;
    155155    case FECOMPOSITE_OPERATOR_ARITHMETIC: {
  • trunk/WebCore/platform/graphics/filters/SourceAlpha.cpp

    r59069 r65449  
    6464    setIsAlphaImage(true);
    6565
    66     FloatRect imageRect(FloatPoint(), filter->sourceImage()->image()->size());
     66    FloatRect imageRect(FloatPoint(), filter->sourceImage()->size());
    6767    filterContext->save();
    68     filterContext->clipToImageBuffer(imageRect, filter->sourceImage());
     68    filterContext->clipToImageBuffer(filter->sourceImage(), imageRect);
    6969    filterContext->fillRect(imageRect, Color::black, DeviceColorSpace);
    7070    filterContext->restore();
  • trunk/WebCore/platform/graphics/filters/SourceGraphic.cpp

    r59069 r65449  
    6161        return;
    6262
    63     filterContext->drawImage(filter->sourceImage()->image(), DeviceColorSpace, IntPoint());
     63    filterContext->drawImageBuffer(filter->sourceImage(), DeviceColorSpace, IntPoint());
    6464}
    6565
  • trunk/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm

    r65446 r65449  
    306306    paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
    307307                  canvas->width(), canvas->height(), imageBuffer->context()->platformContext());
    308 }
    309 
    310 void GraphicsContext3D::beginPaint(CanvasRenderingContext* context)
    311 {
    312     UNUSED_PARAM(context);
    313 }
    314 
    315 void GraphicsContext3D::endPaint()
    316 {
    317308}
    318309
  • trunk/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp

    r64685 r65449  
    513513}
    514514
    515 void GraphicsContext3D::beginPaint(CanvasRenderingContext* context)
    516 {
    517     paintRenderingResultsToCanvas();
    518 }
    519 
    520 void GraphicsContext3D::endPaint()
    521 {
    522 }
    523 
    524515void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context)
    525516{
  • trunk/WebCore/platform/graphics/qt/GraphicsContextQt.cpp

    r65425 r65449  
    12141214}
    12151215
    1216 void GraphicsContext::clipToImageBuffer(const FloatRect& floatRect, const ImageBuffer* image)
    1217 {
    1218     if (paintingDisabled())
    1219         return;
    1220 
    1221     QPixmap* nativeImage = image->image()->nativeImageForCurrentFrame();
    1222     if (!nativeImage)
    1223         return;
    1224 
    1225     IntRect rect(floatRect);
    1226     QPixmap alphaMask = *nativeImage;
    1227     if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height())
    1228         alphaMask = alphaMask.scaled(rect.width(), rect.height());
    1229 
    1230     m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask));
    1231 }
    1232 
    12331216void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
    12341217                                              int thickness)
  • trunk/WebCore/platform/graphics/qt/ImageBufferData.h

    r37948 r65449  
    2727#define ImageBufferData_h
    2828
     29#include "Image.h"
     30#include <wtf/RefPtr.h>
     31
    2932#include <QPainter>
    3033#include <QPixmap>
     
    4245    QPixmap m_pixmap;
    4346    OwnPtr<QPainter> m_painter;
     47    RefPtr<Image> m_image;
    4448};
    4549
  • trunk/WebCore/platform/graphics/qt/ImageBufferQt.cpp

    r64965 r65449  
    3434#include "MIMETypeRegistry.h"
    3535#include "StillImageQt.h"
     36#include "TransparencyLayer.h"
    3637#include <wtf/text/CString.h>
    3738
     
    7576    painter->setBrush(brush);
    7677    painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
     78   
     79    m_data.m_image = StillImage::createForRendering(&m_data.m_pixmap);
    7780}
    7881
     
    99102}
    100103
    101 Image* ImageBuffer::imageForRendering() const
    102 {
    103     if (!m_image)
    104         m_image = StillImage::createForRendering(&m_data.m_pixmap);
    105 
    106     return m_image.get();
    107 }
    108 
    109 Image* ImageBuffer::image() const
    110 {
    111     if (!m_image) {
    112         // It's assumed that if image() is called, the actual rendering to the
    113         // GraphicsContext must be done.
    114         ASSERT(context());
    115         m_image = StillImage::create(m_data.m_pixmap);
    116     }
    117 
    118     return m_image.get();
     104bool ImageBuffer::drawsUsingCopy() const
     105{
     106    return false;
     107}
     108
     109PassRefPtr<Image> ImageBuffer::copyImage() const
     110{
     111    return StillImage::create(m_data.m_pixmap);
     112}
     113
     114void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
     115                       CompositeOperator op, bool useLowQualityScale)
     116{
     117    if (destContext == context()) {
     118        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
     119        RefPtr<Image> copy = copyImage();
     120        destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale);
     121    } else
     122        destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
     123}
     124
     125void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
     126                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
     127{
     128    if (destContext == context()) {
     129        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
     130        RefPtr<Image> copy = copyImage();
     131        copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
     132    } else
     133        m_data.m_image->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
     134}
     135
     136void ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect)
     137{
     138    QPixmap* nativeImage = m_data.m_image->nativeImageForCurrentFrame();
     139    if (!nativeImage)
     140        return;
     141
     142    IntRect rect(floatRect);
     143    QPixmap alphaMask = *nativeImage;
     144    if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height())
     145        alphaMask = alphaMask.scaled(rect.width(), rect.height());
     146
     147    m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask));
    119148}
    120149
  • trunk/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp

    r65197 r65449  
    457457}
    458458
    459 void GraphicsContext::clipToImageBuffer(const FloatRect& rect,
    460                                         const ImageBuffer* imageBuffer)
    461 {
    462     if (paintingDisabled())
    463         return;
    464 
    465 #if OS(LINUX) || OS(WINDOWS)
    466     platformContext()->beginLayerClippedToImage(rect, imageBuffer);
    467 #endif
    468 }
    469 
    470459void GraphicsContext::concatCTM(const AffineTransform& affine)
    471460{
  • trunk/WebCore/platform/graphics/skia/ImageBufferSkia.cpp

    r64813 r65449  
    8888}
    8989
    90 Image* ImageBuffer::image() const
    91 {
    92     if (!m_image) {
    93         // This creates a COPY of the image and will cache that copy. This means
    94         // that if subsequent operations take place on the context, neither the
    95         // currently-returned image, nor the results of future image() calls,
    96         // will contain that operation.
    97         //
    98         // This seems silly, but is the way the CG port works: image() is
    99         // intended to be used only when rendering is "complete."
    100         m_image = BitmapImageSingleFrameSkia::create(
    101             *m_data.m_platformContext.bitmap());
    102     }
    103     return m_image.get();
     90bool ImageBuffer::drawsUsingCopy() const
     91{
     92    return true;
     93}
     94
     95PassRefPtr<Image> ImageBuffer::copyImage() const
     96{
     97    return BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap());
     98}
     99
     100void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
     101{
     102#if OS(LINUX) || OS(WINDOWS)
     103    context->platformContext()->beginLayerClippedToImage(rect, this);
     104#endif
     105}
     106
     107void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
     108                       CompositeOperator op, bool useLowQualityScale)
     109{
     110    RefPtr<Image> imageCopy = copyImage();
     111    context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
     112}
     113
     114void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
     115                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
     116{
     117    RefPtr<Image> imageCopy = copyImage();
     118    imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    104119}
    105120
  • trunk/WebCore/platform/graphics/wx/GraphicsContextWx.cpp

    r63864 r65449  
    379379}
    380380
    381 void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
    382 {
    383     notImplemented();
    384 }
    385 
    386381AffineTransform GraphicsContext::getCTM() const
    387382{
  • trunk/WebCore/platform/graphics/wx/ImageBufferWx.cpp

    r60675 r65449  
    8383}
    8484
    85 Image* ImageBuffer::image() const
     85bool ImageBuffer::drawsUsingCopy() const
     86{
     87    return true;
     88}
     89
     90PassRefPtr<Image> ImageBuffer::copyImage() const
    8691{
    8792    notImplemented();
    8893    return 0;
     94}
     95
     96void ImageBuffer::clip(GraphicsContext*, const FloatRect&) const
     97{
     98    notImplemented();
     99}
     100
     101void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
     102                       CompositeOperator op, bool useLowQualityScale)
     103{
     104    RefPtr<Image> imageCopy = copyImage();
     105    context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
     106}
     107
     108void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
     109                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
     110{
     111    RefPtr<Image> imageCopy = copyImage();
     112    imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
    89113}
    90114
  • trunk/WebCore/platform/mac/ScrollbarThemeMac.mm

    r53838 r65449  
    397397       
    398398        HIThemeDrawTrack(&trackInfo, 0, imageBuffer->context()->platformContext(), kHIThemeOrientationNormal);
    399         context->drawImage(imageBuffer->image(), DeviceColorSpace, scrollbar->frameRect().location());
     399        context->drawImageBuffer(imageBuffer.get(), DeviceColorSpace, scrollbar->frameRect().location());
    400400    }
    401401
  • trunk/WebCore/rendering/RenderBoxModelObject.cpp

    r64553 r65449  
    532532        // The mask has been created.  Now we just need to clip to it.
    533533        context->save();
    534         context->clipToImageBuffer(maskRect, maskImage.get());
     534        context->clipToImageBuffer(maskImage.get(), maskRect);
    535535    }
    536536   
  • trunk/WebCore/rendering/RenderSVGResourceClipper.cpp

    r65310 r65449  
    174174        return false;
    175175
    176     context->clipToImageBuffer(repaintRect, clipperData->clipMaskImage.get());
     176    context->clipToImageBuffer(clipperData->clipMaskImage.get(), repaintRect);
    177177    return true;
    178178}
  • trunk/WebCore/rendering/RenderSVGResourceFilter.cpp

    r65310 r65449  
    271271            resultImage->transformColorSpace(LinearRGB, DeviceRGB);
    272272#endif
    273             context->drawImage(resultImage->image(), object->style()->colorSpace(), lastEffect->subRegion());
     273            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->subRegion());
    274274        }
    275275    }
  • trunk/WebCore/rendering/RenderSVGResourcePattern.cpp

    r65310 r65449  
    298298void RenderSVGResourcePattern::buildPattern(PatternData* patternData, PassOwnPtr<ImageBuffer> tileImage) const
    299299{
    300     if (!tileImage->image()) {
     300    RefPtr<Image> copiedImage = tileImage->copyImage();
     301    if (!copiedImage) {
    301302        patternData->pattern = 0;
    302303        return;
    303304    }
    304 
    305     IntRect tileRect = tileImage->image()->rect();
     305   
     306    IntRect tileRect = copiedImage->rect();
    306307    if (tileRect.width() <= patternData->boundaries.width() && tileRect.height() <= patternData->boundaries.height()) {
    307         patternData->pattern = Pattern::create(tileImage->image(), true, true);
     308        patternData->pattern = Pattern::create(copiedImage, true, true);
    308309        return;
    309310    }
     
    331332        for (int j = numX; j > 0; --j) {
    332333            newTileImageContext->translate(patternData->boundaries.width(), 0);
    333             newTileImageContext->drawImage(tileImage->image(), style()->colorSpace(), tileRect, tileRect);
     334            newTileImageContext->drawImage(copiedImage.get(), style()->colorSpace(), tileRect, tileRect);
    334335        }
    335336        newTileImageContext->translate(-patternData->boundaries.width() * numX, 0);
     
    337338    newTileImageContext->restore();
    338339
    339     patternData->pattern = Pattern::create(newTileImage->image(), true, true);
     340    patternData->pattern = Pattern::create(newTileImage->copyImage(), true, true);
    340341}
    341342
  • trunk/WebCore/rendering/RenderThemeMac.mm

    r63643 r65449  
    964964        paintInfo.context->scale(FloatSize(-1, 1));
    965965    }
    966     paintInfo.context->drawImage(imageBuffer->image(), DeviceColorSpace, rect.location());
     966   
     967    paintInfo.context->drawImageBuffer(imageBuffer.get(), DeviceColorSpace, rect.location());
    967968
    968969    paintInfo.context->restore();
  • trunk/WebCore/rendering/SVGImageBufferTools.cpp

    r65232 r65449  
    6565    // So the actual masking process has to be done in the device coordinate space as well.
    6666    context->concatCTM(absoluteTransform.inverse());
    67     context->clipToImageBuffer(absoluteTargetRect, imageBuffer);
     67    context->clipToImageBuffer(imageBuffer, absoluteTargetRect);
    6868    context->concatCTM(absoluteTransform);
    6969}
  • trunk/WebCore/svg/SVGFEImageElement.cpp

    r64579 r65449  
    138138    }
    139139
    140     return FEImage::create(m_targetImage ? m_targetImage->image() : m_cachedImage->image(), preserveAspectRatio());
     140    return FEImage::create(m_targetImage ? m_targetImage->copyImage() : m_cachedImage->image(), preserveAspectRatio());
    141141}
    142142
  • trunk/WebCore/svg/graphics/SVGImage.cpp

    r65185 r65449  
    222222        if (!m_page)
    223223            return 0;
    224         m_frameCache = ImageBuffer::create(size());
    225         if (!m_frameCache) // failed to allocate image
     224        OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size());
     225        if (!buffer) // failed to allocate image
    226226            return 0;
    227         draw(m_frameCache->context(), rect(), rect(), DeviceColorSpace, CompositeSourceOver);
    228     }
    229     return m_frameCache->image()->nativeImageForCurrentFrame();
     227        draw(buffer->context(), rect(), rect(), DeviceColorSpace, CompositeSourceOver);
     228        m_frameCache = buffer->copyImage();
     229    }
     230    return m_frameCache->nativeImageForCurrentFrame();
    230231}
    231232
  • trunk/WebCore/svg/graphics/SVGImage.h

    r64579 r65449  
    3434namespace WebCore {
    3535
    36     class ImageBuffer;
    3736    class Page;
    3837    class SVGImageChromeClient;
     
    7372        OwnPtr<SVGImageChromeClient> m_chromeClient;
    7473        OwnPtr<Page> m_page;
    75         OwnPtr<ImageBuffer> m_frameCache;
     74        RefPtr<Image> m_frameCache;
    7675    };
    7776}
  • trunk/WebCore/svg/graphics/filters/SVGFEMerge.cpp

    r64579 r65449  
    8080    for (unsigned i = 0; i < m_mergeInputs.size(); i++) {
    8181        FloatRect destRect = calculateDrawingRect(m_mergeInputs[i]->scaledSubRegion());
    82         filterContext->drawImage(m_mergeInputs[i]->resultImage()->image(), DeviceColorSpace, destRect);
     82        filterContext->drawImageBuffer(m_mergeInputs[i]->resultImage(), DeviceColorSpace, destRect);
    8383    }
    8484}
  • trunk/WebCore/svg/graphics/filters/SVGFEOffset.cpp

    r64579 r65449  
    9292                                  m_in->scaledSubRegion().height());
    9393
    94     filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, dstRect);
     94    filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, dstRect);
    9595}
    9696
  • trunk/WebCore/svg/graphics/filters/SVGFETile.cpp

    r64579 r65449  
    7373    OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(tileRect.size());
    7474    GraphicsContext* tileImageContext = tileImage->context();
    75     tileImageContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, IntPoint());
    76     RefPtr<Pattern> pattern = Pattern::create(tileImage->image(), true, true);
     75    tileImageContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, IntPoint());
     76    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
    7777
    7878    AffineTransform matrix;
Note: See TracChangeset for help on using the changeset viewer.