Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2004, 2005 Rob Buis <buis (at) kde.org>
      4  * Copyright (C) 2005 Eric Seidel <eric (at) webkit.org>
      5  * Copyright (C) 2009 Dirk Schulze <krit (at) webkit.org>
      6  * Copyright (C) Research In Motion Limited 2010. All rights reserved.
      7  * Copyright (C) 2013 Google Inc. All rights reserved.
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  */
     24 
     25 #include "config.h"
     26 #include "platform/graphics/filters/FEDisplacementMap.h"
     27 
     28 #include "SkBitmapSource.h"
     29 #include "SkDisplacementMapEffect.h"
     30 #include "platform/graphics/GraphicsContext.h"
     31 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
     32 #include "platform/graphics/skia/NativeImageSkia.h"
     33 #include "platform/text/TextStream.h"
     34 #include "wtf/Uint8ClampedArray.h"
     35 
     36 namespace WebCore {
     37 
     38 FEDisplacementMap::FEDisplacementMap(Filter* filter, ChannelSelectorType xChannelSelector, ChannelSelectorType yChannelSelector, float scale)
     39     : FilterEffect(filter)
     40     , m_xChannelSelector(xChannelSelector)
     41     , m_yChannelSelector(yChannelSelector)
     42     , m_scale(scale)
     43 {
     44 }
     45 
     46 PassRefPtr<FEDisplacementMap> FEDisplacementMap::create(Filter* filter, ChannelSelectorType xChannelSelector,
     47     ChannelSelectorType yChannelSelector, float scale)
     48 {
     49     return adoptRef(new FEDisplacementMap(filter, xChannelSelector, yChannelSelector, scale));
     50 }
     51 
     52 FloatRect FEDisplacementMap::mapPaintRect(const FloatRect& rect, bool)
     53 {
     54     FloatRect result = rect;
     55     result.inflateX(filter()->applyHorizontalScale(m_scale / 2));
     56     result.inflateY(filter()->applyVerticalScale(m_scale / 2));
     57     return result;
     58 }
     59 
     60 ChannelSelectorType FEDisplacementMap::xChannelSelector() const
     61 {
     62     return m_xChannelSelector;
     63 }
     64 
     65 bool FEDisplacementMap::setXChannelSelector(const ChannelSelectorType xChannelSelector)
     66 {
     67     if (m_xChannelSelector == xChannelSelector)
     68         return false;
     69     m_xChannelSelector = xChannelSelector;
     70     return true;
     71 }
     72 
     73 ChannelSelectorType FEDisplacementMap::yChannelSelector() const
     74 {
     75     return m_yChannelSelector;
     76 }
     77 
     78 bool FEDisplacementMap::setYChannelSelector(const ChannelSelectorType yChannelSelector)
     79 {
     80     if (m_yChannelSelector == yChannelSelector)
     81         return false;
     82     m_yChannelSelector = yChannelSelector;
     83     return true;
     84 }
     85 
     86 float FEDisplacementMap::scale() const
     87 {
     88     return m_scale;
     89 }
     90 
     91 bool FEDisplacementMap::setScale(float scale)
     92 {
     93     if (m_scale == scale)
     94         return false;
     95     m_scale = scale;
     96     return true;
     97 }
     98 
     99 void FEDisplacementMap::setResultColorSpace(ColorSpace)
    100 {
    101     // Spec: The 'color-interpolation-filters' property only applies to the 'in2' source image
    102     // and does not apply to the 'in' source image. The 'in' source image must remain in its
    103     // current color space.
    104     // The result is in that smae color space because it is a displacement of the 'in' image.
    105     FilterEffect::setResultColorSpace(inputEffect(0)->resultColorSpace());
    106 }
    107 
    108 void FEDisplacementMap::transformResultColorSpace(FilterEffect* in, const int index)
    109 {
    110     // Do not transform the first primitive input, as per the spec.
    111     if (index)
    112         in->transformResultColorSpace(operatingColorSpace());
    113 }
    114 
    115 void FEDisplacementMap::applySoftware()
    116 {
    117     FilterEffect* in = inputEffect(0);
    118     FilterEffect* in2 = inputEffect(1);
    119 
    120     ASSERT(m_xChannelSelector != CHANNEL_UNKNOWN);
    121     ASSERT(m_yChannelSelector != CHANNEL_UNKNOWN);
    122 
    123     Uint8ClampedArray* dstPixelArray = createPremultipliedImageResult();
    124     if (!dstPixelArray)
    125         return;
    126 
    127     IntRect effectADrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect());
    128     RefPtr<Uint8ClampedArray> srcPixelArrayA = in->asPremultipliedImage(effectADrawingRect);
    129 
    130     IntRect effectBDrawingRect = requestedRegionOfInputImageData(in2->absolutePaintRect());
    131     RefPtr<Uint8ClampedArray> srcPixelArrayB = in2->asUnmultipliedImage(effectBDrawingRect);
    132 
    133     ASSERT(srcPixelArrayA->length() == srcPixelArrayB->length());
    134 
    135     Filter* filter = this->filter();
    136     IntSize paintSize = absolutePaintRect().size();
    137     float scaleX = filter->applyHorizontalScale(m_scale);
    138     float scaleY = filter->applyVerticalScale(m_scale);
    139     float scaleForColorX = scaleX / 255.0;
    140     float scaleForColorY = scaleY / 255.0;
    141     float scaledOffsetX = 0.5 - scaleX * 0.5;
    142     float scaledOffsetY = 0.5 - scaleY * 0.5;
    143     int stride = paintSize.width() * 4;
    144     for (int y = 0; y < paintSize.height(); ++y) {
    145         int line = y * stride;
    146         for (int x = 0; x < paintSize.width(); ++x) {
    147             int dstIndex = line + x * 4;
    148             int srcX = x + static_cast<int>(scaleForColorX * srcPixelArrayB->item(dstIndex + m_xChannelSelector - 1) + scaledOffsetX);
    149             int srcY = y + static_cast<int>(scaleForColorY * srcPixelArrayB->item(dstIndex + m_yChannelSelector - 1) + scaledOffsetY);
    150             for (unsigned channel = 0; channel < 4; ++channel) {
    151                 if (srcX < 0 || srcX >= paintSize.width() || srcY < 0 || srcY >= paintSize.height()) {
    152                     dstPixelArray->set(dstIndex + channel, static_cast<unsigned char>(0));
    153                 } else {
    154                     unsigned char pixelValue = srcPixelArrayA->item(srcY * stride + srcX * 4 + channel);
    155                     dstPixelArray->set(dstIndex + channel, pixelValue);
    156                 }
    157             }
    158         }
    159     }
    160 }
    161 
    162 static SkDisplacementMapEffect::ChannelSelectorType toSkiaMode(ChannelSelectorType type)
    163 {
    164     switch (type) {
    165     case CHANNEL_R:
    166         return SkDisplacementMapEffect::kR_ChannelSelectorType;
    167     case CHANNEL_G:
    168         return SkDisplacementMapEffect::kG_ChannelSelectorType;
    169     case CHANNEL_B:
    170         return SkDisplacementMapEffect::kB_ChannelSelectorType;
    171     case CHANNEL_A:
    172         return SkDisplacementMapEffect::kA_ChannelSelectorType;
    173     case CHANNEL_UNKNOWN:
    174     default:
    175         return SkDisplacementMapEffect::kUnknown_ChannelSelectorType;
    176     }
    177 }
    178 
    179 PassRefPtr<SkImageFilter> FEDisplacementMap::createImageFilter(SkiaImageFilterBuilder* builder)
    180 {
    181     RefPtr<SkImageFilter> color = builder->build(inputEffect(0), operatingColorSpace());
    182     RefPtr<SkImageFilter> displ = builder->build(inputEffect(1), operatingColorSpace());
    183     SkDisplacementMapEffect::ChannelSelectorType typeX = toSkiaMode(m_xChannelSelector);
    184     SkDisplacementMapEffect::ChannelSelectorType typeY = toSkiaMode(m_yChannelSelector);
    185     SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
    186     // FIXME : Only applyHorizontalScale is used and applyVerticalScale is ignored
    187     // This can be fixed by adding a 2nd scale parameter to SkDisplacementMapEffect
    188     return adoptRef(SkDisplacementMapEffect::Create(typeX, typeY, SkFloatToScalar(filter()->applyHorizontalScale(m_scale)), displ.get(), color.get(), &cropRect));
    189 }
    190 
    191 static TextStream& operator<<(TextStream& ts, const ChannelSelectorType& type)
    192 {
    193     switch (type) {
    194     case CHANNEL_UNKNOWN:
    195         ts << "UNKNOWN";
    196         break;
    197     case CHANNEL_R:
    198         ts << "RED";
    199         break;
    200     case CHANNEL_G:
    201         ts << "GREEN";
    202         break;
    203     case CHANNEL_B:
    204         ts << "BLUE";
    205         break;
    206     case CHANNEL_A:
    207         ts << "ALPHA";
    208         break;
    209     }
    210     return ts;
    211 }
    212 
    213 TextStream& FEDisplacementMap::externalRepresentation(TextStream& ts, int indent) const
    214 {
    215     writeIndent(ts, indent);
    216     ts << "[feDisplacementMap";
    217     FilterEffect::externalRepresentation(ts);
    218     ts << " scale=\"" << m_scale << "\" "
    219        << "xChannelSelector=\"" << m_xChannelSelector << "\" "
    220        << "yChannelSelector=\"" << m_yChannelSelector << "\"]\n";
    221     inputEffect(0)->externalRepresentation(ts, indent + 1);
    222     inputEffect(1)->externalRepresentation(ts, indent + 1);
    223     return ts;
    224 }
    225 
    226 } // namespace WebCore
    227