| Differences between
and this patch
- WebCore/ChangeLog +22 lines
Lines 1-3 WebCore/ChangeLog_sec1
1
2009-12-20  Dirk Schulze  <krit@webkit.org>
2
3
        Reviewed by NOBODY (OOPS!).
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
1
2009-12-19  MORITA Hajime  <morrita@gmail.com>
23
2009-12-19  MORITA Hajime  <morrita@gmail.com>
2
24
3
        Reviewed by Darin Adler.
25
        Reviewed by Darin Adler.
- WebCore/svg/SVGMaskElement.cpp -9 / +18 lines
Lines 126-132 void SVGMaskElement::childrenChanged(boo WebCore/svg/SVGMaskElement.cpp_sec1
126
    m_masker->invalidate();
126
    m_masker->invalidate();
127
}
127
}
128
128
129
PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect) const
129
PassOwnPtr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetRect, FloatRect& maskDestRect, IntRect& paintRect) const
130
{    
130
{    
131
    // Determine specified mask size
131
    // Determine specified mask size
132
    if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
132
    if (maskUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
Lines 169-182 PassOwnPtr<ImageBuffer> SVGMaskElement:: WebCore/svg/SVGMaskElement.cpp_sec2
169
    GraphicsContext* maskImageContext = maskImage->context();
169
    GraphicsContext* maskImageContext = maskImage->context();
170
    ASSERT(maskImageContext);
170
    ASSERT(maskImageContext);
171
171
172
    maskImageContext->save();
172
    TransformationMatrix contextTransform;
173
    maskImageContext->translate(-maskContextLocation.x(), -maskContextLocation.y());
173
    contextTransform.translate(-maskContextLocation.x(), -maskContextLocation.y());
174
    if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
175
        contextTransform.scaleNonUniform(targetRect.width(), targetRect.height());
174
176
175
    if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
177
    maskImageContext->save();
176
        maskImageContext->save();
178
    maskImageContext->concatCTM(contextTransform);
177
        maskImageContext->scale(FloatSize(targetRect.width(), targetRect.height()));
178
    }
179
179
180
    FloatRect repaintRect;
180
    // Render subtree into ImageBuffer
181
    // Render subtree into ImageBuffer
181
    for (Node* n = firstChild(); n; n = n->nextSibling()) {
182
    for (Node* n = firstChild(); n; n = n->nextSibling()) {
182
        SVGElement* elem = 0;
183
        SVGElement* elem = 0;
Lines 191-200 PassOwnPtr<ImageBuffer> SVGMaskElement:: WebCore/svg/SVGMaskElement.cpp_sec3
191
            continue;
192
            continue;
192
193
193
        renderSubtreeToImage(maskImage.get(), item);
194
        renderSubtreeToImage(maskImage.get(), item);
195
        repaintRect.unite(item->repaintRectInLocalCoordinates());
194
    }
196
    }
195
197
196
    if (maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
198
    IntRect maskIntRect = enclosingIntRect(maskDestRect);
197
        maskImageContext->restore();
199
    maskIntRect.setLocation(IntPoint());
200
    if (contextTransform.isInvertible()) {
201
        contextTransform.inverse();
202
        repaintRect = contextTransform.mapRect(repaintRect);
203
        paintRect = enclosingIntRect(repaintRect);
204
        paintRect.intersect(maskIntRect);
205
    } else
206
        paintRect = maskIntRect;
198
207
199
    maskImageContext->restore();
208
    maskImageContext->restore();
200
    return maskImage.release();
209
    return maskImage.release();
- WebCore/svg/SVGMaskElement.h -1 / +1 lines
Lines 50-56 namespace WebCore { WebCore/svg/SVGMaskElement.h_sec1
50
        virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
50
        virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
51
        virtual SVGResource* canvasResource();
51
        virtual SVGResource* canvasResource();
52
52
53
        PassOwnPtr<ImageBuffer> drawMaskerContent(const FloatRect& targetRect, FloatRect& maskRect) const;
53
        PassOwnPtr<ImageBuffer> drawMaskerContent(const FloatRect& targetRect, FloatRect& maskRect, IntRect& paintRect) const;
54
54
55
    private:
55
    private:
56
        ANIMATED_PROPERTY_DECLARATIONS(SVGMaskElement, SVGNames::maskTagString, SVGNames::maskUnitsAttrString, int, MaskUnits, maskUnits)
56
        ANIMATED_PROPERTY_DECLARATIONS(SVGMaskElement, SVGNames::maskTagString, SVGNames::maskUnitsAttrString, int, MaskUnits, maskUnits)
- WebCore/svg/graphics/SVGResourceMasker.cpp -24 / +17 lines
Lines 1-5 WebCore/svg/graphics/SVGResourceMasker.cpp_sec1
1
/*
1
/*
2
 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
2
 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
3
 *               2009 Dirk Schulze <krit@webkit.org>
3
 *
4
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * modification, are permitted provided that the following conditions
Lines 38-45 WebCore/svg/graphics/SVGResourceMasker.cpp_sec2
38
#include "SVGRenderStyle.h"
39
#include "SVGRenderStyle.h"
39
#include "TextStream.h"
40
#include "TextStream.h"
40
41
41
#include <wtf/ByteArray.h>
42
43
using namespace std;
42
using namespace std;
44
43
45
namespace WebCore {
44
namespace WebCore {
Lines 63-101 void SVGResourceMasker::invalidate() WebCore/svg/graphics/SVGResourceMasker.cpp_sec3
63
void SVGResourceMasker::applyMask(GraphicsContext* context, const FloatRect& boundingBox)
62
void SVGResourceMasker::applyMask(GraphicsContext* context, const FloatRect& boundingBox)
64
{
63
{
65
    if (!m_mask)
64
    if (!m_mask)
66
        m_mask = m_ownerElement->drawMaskerContent(boundingBox, m_maskRect);
65
        m_mask = m_ownerElement->drawMaskerContent(boundingBox, m_maskRect, m_paintRect);
67
66
68
    if (!m_mask)
67
    if (!m_mask)
69
        return;
68
        return;
70
69
71
    IntSize imageSize(m_mask->size());
70
    if (!m_paintRect.width() || !m_paintRect.height()) {
72
    IntRect intImageRect(0, 0, imageSize.width(), imageSize.height());
71
        context->clipToImageBuffer(m_maskRect, m_mask.get());
73
74
    // Create new ImageBuffer to apply luminance
75
    OwnPtr<ImageBuffer> luminancedImage = ImageBuffer::create(imageSize);
76
    if (!luminancedImage)
77
        return;
72
        return;
73
    }
78
74
79
    PassRefPtr<CanvasPixelArray> srcPixelArray(m_mask->getUnmultipliedImageData(intImageRect)->data());
75
    RefPtr<ImageData> imageData(m_mask->getUnmultipliedImageData(m_paintRect));
80
    PassRefPtr<ImageData> destImageData(luminancedImage->getUnmultipliedImageData(intImageRect));
76
    CanvasPixelArray* srcPixelArray(imageData->data());
81
82
    for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset++) {
83
        unsigned pixelByteOffset = pixelOffset * 4;
84
77
85
        unsigned char r = 0, g = 0, b = 0, a = 0;
78
    for (unsigned pixelOffset = 0; pixelOffset < srcPixelArray->length(); pixelOffset += 4) {
86
        srcPixelArray->get(pixelByteOffset, r);
79
        unsigned char a = srcPixelArray->get(pixelOffset + 3);
87
        srcPixelArray->get(pixelByteOffset + 1, g);
80
        if (!a)
88
        srcPixelArray->get(pixelByteOffset + 2, b);
81
            continue;
89
        srcPixelArray->get(pixelByteOffset + 3, a);
82
        unsigned char r = srcPixelArray->get(pixelOffset);
83
        unsigned char g = srcPixelArray->get(pixelOffset + 1);
84
        unsigned char b = srcPixelArray->get(pixelOffset + 2);
90
85
91
        double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0);
86
        double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0);
92
87
        srcPixelArray->set(pixelOffset + 3, luma);
93
        destImageData->data()->set(pixelByteOffset + 3, luma);
94
    }
88
    }
95
89
96
    luminancedImage->putUnmultipliedImageData(destImageData.get(), intImageRect, IntPoint(0, 0));
90
    m_mask->putUnmultipliedImageData(imageData.get(), IntRect(IntPoint(), m_paintRect.size()), m_paintRect.location());
97
91
    context->clipToImageBuffer(m_maskRect, m_mask.get());
98
    context->clipToImageBuffer(m_maskRect, luminancedImage.get());
99
}
92
}
100
93
101
TextStream& SVGResourceMasker::externalRepresentation(TextStream& ts) const
94
TextStream& SVGResourceMasker::externalRepresentation(TextStream& ts) const
- WebCore/svg/graphics/SVGResourceMasker.h +1 lines
Lines 62-67 namespace WebCore { WebCore/svg/graphics/SVGResourceMasker.h_sec1
62
        
62
        
63
        OwnPtr<ImageBuffer> m_mask;
63
        OwnPtr<ImageBuffer> m_mask;
64
        FloatRect m_maskRect;
64
        FloatRect m_maskRect;
65
        IntRect m_paintRect;
65
    };
66
    };
66
67
67
    SVGResourceMasker* getMaskerById(Document*, const AtomicString&);
68
    SVGResourceMasker* getMaskerById(Document*, const AtomicString&);

Return to Bug 32738