Changeset 52395 in webkit


Ignore:
Timestamp:
Dec 19, 2009 1:58:51 PM (14 years ago)
Author:
eric@webkit.org
Message:

2009-12-19 Dirk Schulze <krit@webkit.org>

Reviewed by Nikolas Zimmermann.

Speed-up SVG Masking
https://bugs.webkit.org/show_bug.cgi?id=32738

This patch makes SVG Masking faster. At the moment we create a new ImageBuffer
and copy the complete pixel array. That is rather inefficient. This patch
uses the mask image directly.
It also bounds the direct pixel manipultation to the viewable area to minimize
the calculation of the mask.

No change in functionality. So no new test.

  • svg/SVGMaskElement.cpp: (WebCore::SVGMaskElement::drawMaskerContent):
  • svg/SVGMaskElement.h:
  • svg/graphics/SVGResourceMasker.cpp: (WebCore::SVGResourceMasker::applyMask):
  • svg/graphics/SVGResourceMasker.h:
Location:
trunk/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r52394 r52395  
     12009-12-19  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Nikolas Zimmermann.
     4
     5        Speed-up SVG Masking
     6        https://bugs.webkit.org/show_bug.cgi?id=32738
     7
     8        This patch makes SVG Masking faster. At the moment we create a new ImageBuffer
     9        and copy the complete pixel array. That is rather inefficient. This patch
     10        uses the mask image directly.
     11        It also bounds the direct pixel manipultation to the viewable area to minimize
     12        the calculation of the mask.
     13
     14        No change in functionality. So no new test.
     15
     16        * svg/SVGMaskElement.cpp:
     17        (WebCore::SVGMaskElement::drawMaskerContent):
     18        * svg/SVGMaskElement.h:
     19        * svg/graphics/SVGResourceMasker.cpp:
     20        (WebCore::SVGResourceMasker::applyMask):
     21        * svg/graphics/SVGResourceMasker.h:
     22
    1232009-12-19  Dirk Schulze  <krit@webkit.org>
    224
  • trunk/WebCore/svg/SVGMaskElement.cpp

    r51496 r52395  
    127127}
    128128
    129 PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect) const
     129PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect, IntRect& paintRect) const
    130130{   
    131131    // Determine specified mask size
     
    170170    ASSERT(maskImageContext);
    171171
     172    TransformationMatrix contextTransform;
     173    contextTransform.translate(-maskContextLocation.x(), -maskContextLocation.y());
     174    if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
     175        contextTransform.scaleNonUniform(targetRect.width(), targetRect.height());
     176
    172177    maskImageContext->save();
    173     maskImageContext->translate(-maskContextLocation.x(), -maskContextLocation.y());
    174 
    175     if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
    176         maskImageContext->save();
    177         maskImageContext->scale(FloatSize(targetRect.width(), targetRect.height()));
    178     }
    179 
     178    maskImageContext->concatCTM(contextTransform);
     179
     180    FloatRect repaintRect;
    180181    // Render subtree into ImageBuffer
    181182    for (Node* n = firstChild(); n; n = n->nextSibling()) {
     
    192193
    193194        renderSubtreeToImage(maskImage.get(), item);
     195        repaintRect.unite(item->repaintRectInLocalCoordinates());
    194196    }
    195197
    196     if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
    197         maskImageContext->restore();
     198    if (contextTransform.isInvertible()) {
     199        contextTransform.inverse();
     200        repaintRect = contextTransform.mapRect(repaintRect);
     201        repaintRect.intersect(FloatRect(FloatPoint(), maskDestRect.size()));
     202        paintRect = enclosingIntRect(repaintRect);
     203    } else
     204        paintRect = enclosingIntRect(FloatRect(FloatPoint(), maskDestRect.size()));
    198205
    199206    maskImageContext->restore();
  • trunk/WebCore/svg/SVGMaskElement.h

    r49602 r52395  
    5151        virtual SVGResource* canvasResource();
    5252
    53         PassOwnPtr<ImageBuffer> drawMaskerContent(const FloatRect& targetRect, FloatRect& maskRect) const;
     53        PassOwnPtr<ImageBuffer> drawMaskerContent(const FloatRect& targetRect, FloatRect& maskRect, IntRect& paintRect) const;
    5454
    5555    private:
  • trunk/WebCore/svg/graphics/SVGResourceMasker.cpp

    r47099 r52395  
    11/*
    22 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
     3 *               2009 Dirk Schulze <krit@webkit.org>
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    3940#include "TextStream.h"
    4041
    41 #include <wtf/ByteArray.h>
    42 
    4342using namespace std;
    4443
     
    6463{
    6564    if (!m_mask)
    66         m_mask = m_ownerElement->drawMaskerContent(boundingBox, m_maskRect);
     65        m_mask = m_ownerElement->drawMaskerContent(boundingBox, m_maskRect, m_paintRect);
    6766
    6867    if (!m_mask)
    6968        return;
    7069
    71     IntSize imageSize(m_mask->size());
    72     IntRect intImageRect(0, 0, imageSize.width(), imageSize.height());
     70    RefPtr<ImageData> imageData(m_mask->getUnmultipliedImageData(m_paintRect));
     71    CanvasPixelArray* srcPixelArray(imageData->data());
    7372
    74     // Create new ImageBuffer to apply luminance
    75     OwnPtr<ImageBuffer> luminancedImage = ImageBuffer::create(imageSize);
    76     if (!luminancedImage)
    77         return;
    78 
    79     PassRefPtr<CanvasPixelArray> srcPixelArray(m_mask->getUnmultipliedImageData(intImageRect)->data());
    80     PassRefPtr<ImageData> destImageData(luminancedImage->getUnmultipliedImageData(intImageRect));
    81 
    82     for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset++) {
    83         unsigned pixelByteOffset = pixelOffset * 4;
    84 
    85         unsigned char r = 0, g = 0, b = 0, a = 0;
    86         srcPixelArray->get(pixelByteOffset, r);
    87         srcPixelArray->get(pixelByteOffset + 1, g);
    88         srcPixelArray->get(pixelByteOffset + 2, b);
    89         srcPixelArray->get(pixelByteOffset + 3, a);
     73    for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) {
     74        unsigned char a = srcPixelArray->get(pixelOffset + 3);
     75        if (!a)
     76            continue;
     77        unsigned char r = srcPixelArray->get(pixelOffset);
     78        unsigned char g = srcPixelArray->get(pixelOffset + 1);
     79        unsigned char b = srcPixelArray->get(pixelOffset + 2);
    9080
    9181        double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0);
    92 
    93         destImageData->data()->set(pixelByteOffset + 3, luma);
     82        srcPixelArray->set(pixelOffset + 3, luma);
    9483    }
    9584
    96     luminancedImage->putUnmultipliedImageData(destImageData.get(), intImageRect, IntPoint(0, 0));
    97 
    98     context->clipToImageBuffer(m_maskRect, luminancedImage.get());
     85    m_mask->putUnmultipliedImageData(imageData.get(), IntRect(IntPoint(), m_paintRect.size()), m_paintRect.location());
     86    context->clipToImageBuffer(m_maskRect, m_mask.get());
    9987}
    10088
  • trunk/WebCore/svg/graphics/SVGResourceMasker.h

    r30430 r52395  
    6363        OwnPtr<ImageBuffer> m_mask;
    6464        FloatRect m_maskRect;
     65        IntRect m_paintRect;
    6566    };
    6667
Note: See TracChangeset for help on using the changeset viewer.