Changeset 47456 in webkit


Ignore:
Timestamp:
Aug 18, 2009 2:37:17 PM (15 years ago)
Author:
krit@webkit.org
Message:

2009-08-18 Dirk Schulze <krit@webkit.org>

Reviewed by Oliver Hunt.

SVG Filter feBlend implementation missing
https://bugs.webkit.org/show_bug.cgi?id=28133

Implementation of SVG Filter feBlend.

FilterEffect.cp needed changes to optimize the rendering. With the old code
we drew a subEffect on the current FilterEffect by drawImage, got the PixelArray,
cleared the drawing area, drew the next FilterEffect with drawImage and picked this
PixelArray again. This was unefficient and slow. Now we calculate the requested area
of the subEffect and ask the FilterEffect's ImageBuffer for the PixelArray directly,
without any drawing operations on GraphicsContext.

There is already a test case
Test: svg/W3C-SVG-1.1/filters-blend-01-b.svg

  • html/canvas/CanvasPixelArray.h: (WebCore::CanvasPixelArray::set): (WebCore::CanvasPixelArray::get):
  • platform/graphics/filters/FEBlend.cpp: (WebCore::unknown): (WebCore::normal): (WebCore::multiply): (WebCore::screen): (WebCore::darken): (WebCore::lighten): (WebCore::FEBlend::apply):
  • platform/graphics/filters/FEBlend.h:
  • platform/graphics/filters/FilterEffect.cpp: (WebCore::FilterEffect::calculateDrawingIntRect):
  • platform/graphics/filters/FilterEffect.h:

2009-08-18 Dirk Schulze <krit@webkit.org>

Reviewed by Oliver Hunt.

Added additional getter to ByteArray with an unsigned char as return.
ByteArray can take unsigned char directly now.

  • wtf/ByteArray.h: (WTF::ByteArray::set): (WTF::ByteArray::get):
Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/ChangeLog

    r47430 r47456  
     12009-08-18  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        Added additional getter to ByteArray with an unsigned char as return.
     6        ByteArray can take unsigned char directly now.
     7
     8        * wtf/ByteArray.h:
     9        (WTF::ByteArray::set):
     10        (WTF::ByteArray::get):
     11
    1122009-08-18  Peter Kasting  <pkasting@google.com>
    213
  • trunk/JavaScriptCore/wtf/ByteArray.h

    r46204 r47456  
    4646        }
    4747
     48        void set(unsigned index, unsigned char value)
     49        {
     50            if (index >= m_size)
     51                return;
     52            m_data[index] = value;
     53        }
     54
    4855        bool get(unsigned index, unsigned char& result) const
    4956        {
     
    5259            result = m_data[index];
    5360            return true;
     61        }
     62
     63        unsigned char get(unsigned index) const
     64        {
     65            ASSERT(index < m_size);
     66            return m_data[index];
    5467        }
    5568
  • trunk/WebCore/ChangeLog

    r47455 r47456  
     12009-08-18  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Oliver Hunt.
     4
     5        SVG Filter feBlend implementation missing
     6        [https://bugs.webkit.org/show_bug.cgi?id=28133]
     7
     8        Implementation of SVG Filter feBlend.
     9
     10        FilterEffect.cp needed changes to optimize the rendering. With the old code
     11        we drew a subEffect on the current FilterEffect by drawImage, got the PixelArray,
     12        cleared the drawing area, drew the next FilterEffect with drawImage and picked this
     13        PixelArray again. This was unefficient and slow. Now we calculate the requested area
     14        of the subEffect and ask the FilterEffect's ImageBuffer for the PixelArray directly,
     15        without any drawing operations on GraphicsContext.
     16
     17        There is already a test case
     18        Test: svg/W3C-SVG-1.1/filters-blend-01-b.svg
     19
     20        * html/canvas/CanvasPixelArray.h:
     21        (WebCore::CanvasPixelArray::set):
     22        (WebCore::CanvasPixelArray::get):
     23        * platform/graphics/filters/FEBlend.cpp:
     24        (WebCore::unknown):
     25        (WebCore::normal):
     26        (WebCore::multiply):
     27        (WebCore::screen):
     28        (WebCore::darken):
     29        (WebCore::lighten):
     30        (WebCore::FEBlend::apply):
     31        * platform/graphics/filters/FEBlend.h:
     32        * platform/graphics/filters/FilterEffect.cpp:
     33        (WebCore::FilterEffect::calculateDrawingIntRect):
     34        * platform/graphics/filters/FilterEffect.h:
     35
    1362009-08-18  Pavel Feldman  <pfeldman@chromium.org>
    237
  • trunk/WebCore/html/canvas/CanvasPixelArray.h

    r46937 r47456  
    4949            m_data->set(index, value);
    5050        }
     51
     52        void set(unsigned index, unsigned char value)
     53        {
     54            m_data->set(index, value);
     55        }
    5156       
    5257        bool get(unsigned index, unsigned char& result) const
    5358        {
    5459            return m_data->get(index, result);
     60        }
     61
     62        unsigned char get(unsigned index) const
     63        {
     64            return m_data->get(index);
    5565        }
    5666
  • trunk/WebCore/platform/graphics/filters/FEBlend.cpp

    r44296 r47456  
    33                  2004, 2005 Rob Buis <buis@kde.org>
    44                  2005 Eric Seidel <eric@webkit.org>
     5                  2009 Dirk Schulze <krit@webkit.org>
    56
    67    This library is free software; you can redistribute it and/or
     
    2526#include "FEBlend.h"
    2627
     28#include "CanvasPixelArray.h"
    2729#include "Filter.h"
     30#include "FloatPoint.h"
     31#include "GraphicsContext.h"
     32#include "ImageData.h"
     33
     34typedef unsigned char (*BlendType)(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB);
    2835
    2936namespace WebCore {
     
    6269}
    6370
    64 void FEBlend::apply(Filter*)
     71static unsigned char unknown(unsigned char, unsigned char, unsigned char, unsigned char)
    6572{
     73    return 0;
     74}
     75
     76static unsigned char normal(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char)
     77{
     78    return (((255 - alphaA) * colorB + colorA * 255) / 255);
     79}
     80
     81static unsigned char multiply(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
     82{
     83    return (((255 - alphaA) * colorB + (255 - alphaB + colorB) * colorA) / 255);
     84}
     85
     86static unsigned char screen(unsigned char colorA, unsigned char colorB, unsigned char, unsigned char)
     87{
     88    return (((colorB + colorA) * 255 - colorA * colorB) / 255);
     89}
     90
     91static unsigned char darken(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
     92{
     93    return ((std::min((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
     94}
     95
     96static unsigned char lighten(unsigned char colorA, unsigned char colorB, unsigned char alphaA, unsigned char alphaB)
     97{
     98    return ((std::max((255 - alphaA) * colorB + colorA * 255, (255 - alphaB) * colorA + colorB * 255)) / 255);
     99}
     100
     101void FEBlend::apply(Filter* filter)
     102{
     103    m_in->apply(filter);
     104    m_in2->apply(filter);
     105    if (!m_in->resultImage() || !m_in2->resultImage())
     106        return;
     107
     108    if (m_mode == FEBLEND_MODE_UNKNOWN)
     109        return;
     110
     111    if (!getEffectContext())
     112        return;
     113
     114    IntRect effectADrawingRect = calculateDrawingIntRect(m_in->subRegion());
     115    RefPtr<CanvasPixelArray> srcPixelArrayA(m_in->resultImage()->getPremultipliedImageData(effectADrawingRect)->data());
     116
     117    IntRect effectBDrawingRect = calculateDrawingIntRect(m_in2->subRegion());
     118    RefPtr<CanvasPixelArray> srcPixelArrayB(m_in2->resultImage()->getPremultipliedImageData(effectBDrawingRect)->data());
     119
     120    IntRect imageRect(IntPoint(), resultImage()->size());
     121    RefPtr<ImageData> imageData = ImageData::create(imageRect.width(), imageRect.height());
     122
     123    // Keep synchronized with BlendModeType
     124    static const BlendType callEffect[] = {unknown, normal, multiply, screen, darken, lighten};
     125
     126    ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
     127    for (unsigned pixelOffset = 0; pixelOffset < srcPixelArrayA->length(); pixelOffset += 4) {
     128        unsigned char alphaA = srcPixelArrayA->get(pixelOffset + 3);
     129        unsigned char alphaB = srcPixelArrayB->get(pixelOffset + 3);
     130        for (unsigned channel = 0; channel < 3; ++channel) {
     131            unsigned char colorA = srcPixelArrayA->get(pixelOffset + channel);
     132            unsigned char colorB = srcPixelArrayB->get(pixelOffset + channel);
     133
     134            unsigned char result = (*callEffect[m_mode])(colorA, colorB, alphaA, alphaB);
     135            imageData->data()->set(pixelOffset + channel, result);
     136        }
     137        unsigned char alphaR = 255 - ((255 - alphaA) * (255 - alphaB)) / 255;
     138        imageData->data()->set(pixelOffset + 3, alphaR);
     139    }
     140
     141    resultImage()->putPremultipliedImageData(imageData.get(), imageRect, IntPoint());
    66142}
    67143
  • trunk/WebCore/platform/graphics/filters/FEBlend.h

    r44655 r47456  
    4242    public:
    4343        static PassRefPtr<FEBlend> create(FilterEffect*, FilterEffect*, BlendModeType);
    44        
     44
    4545        FilterEffect* in2() const;
    4646        void setIn2(FilterEffect*);
  • trunk/WebCore/platform/graphics/filters/FilterEffect.cpp

    r46956 r47456  
    6060}
    6161
     62IntRect FilterEffect::calculateDrawingIntRect(const FloatRect& effectRect)
     63{
     64    IntPoint location = roundedIntPoint(FloatPoint(subRegion().x() - effectRect.x(),
     65                                                   subRegion().y() - effectRect.y()));
     66    return IntRect(location, resultImage()->size());
     67}
     68
    6269FloatRect FilterEffect::calculateDrawingRect(const FloatRect& srcRect)
    6370{
  • trunk/WebCore/platform/graphics/filters/FilterEffect.h

    r44840 r47456  
    7878        GraphicsContext* getEffectContext();
    7979        FloatRect calculateDrawingRect(const FloatRect&);
     80        IntRect calculateDrawingIntRect(const FloatRect&);
    8081
    8182        virtual FloatRect uniteChildEffectSubregions(Filter* filter) { return filter->filterRegion(); }
Note: See TracChangeset for help on using the changeset viewer.