Home | History | Annotate | Download | only in filters
      1 /*
      2  * Copyright (C) Research In Motion Limited 2011. All rights reserved.
      3  * Copyright (C) 2013 Google Inc. All rights reserved.
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 #include "platform/graphics/filters/FEDropShadow.h"
     23 
     24 #include "platform/graphics/GraphicsContext.h"
     25 #include "platform/graphics/filters/FEGaussianBlur.h"
     26 #include "platform/graphics/filters/SkiaImageFilterBuilder.h"
     27 #include "platform/text/TextStream.h"
     28 #include "third_party/skia/include/core/SkColorFilter.h"
     29 #include "third_party/skia/include/effects/SkBlurImageFilter.h"
     30 #include "third_party/skia/include/effects/SkDropShadowImageFilter.h"
     31 
     32 namespace blink {
     33 
     34 FEDropShadow::FEDropShadow(Filter* filter, float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity)
     35     : FilterEffect(filter)
     36     , m_stdX(stdX)
     37     , m_stdY(stdY)
     38     , m_dx(dx)
     39     , m_dy(dy)
     40     , m_shadowColor(shadowColor)
     41     , m_shadowOpacity(shadowOpacity)
     42 {
     43 }
     44 
     45 PassRefPtr<FEDropShadow> FEDropShadow::create(Filter* filter, float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity)
     46 {
     47     return adoptRef(new FEDropShadow(filter, stdX, stdY, dx, dy, shadowColor, shadowOpacity));
     48 }
     49 
     50 FloatRect FEDropShadow::mapRect(const FloatRect& rect, bool forward)
     51 {
     52     FloatRect result = rect;
     53     Filter* filter = this->filter();
     54     ASSERT(filter);
     55 
     56     FloatRect offsetRect = rect;
     57     if (forward)
     58         offsetRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
     59     else
     60         offsetRect.move(-filter->applyHorizontalScale(m_dx), -filter->applyVerticalScale(m_dy));
     61     result.unite(offsetRect);
     62 
     63     IntSize kernelSize = FEGaussianBlur::calculateKernelSize(filter, FloatPoint(m_stdX, m_stdY));
     64 
     65     // We take the half kernel size and multiply it with three, because we run box blur three times.
     66     result.inflateX(3 * kernelSize.width() * 0.5f);
     67     result.inflateY(3 * kernelSize.height() * 0.5f);
     68     return result;
     69 }
     70 
     71 void FEDropShadow::applySoftware()
     72 {
     73     FilterEffect* in = inputEffect(0);
     74 
     75     ImageBuffer* resultImage = createImageBufferResult();
     76     if (!resultImage)
     77         return;
     78 
     79     Filter* filter = this->filter();
     80     FloatSize blurRadius(filter->applyHorizontalScale(m_stdX), filter->applyVerticalScale(m_stdY));
     81     FloatSize offset(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
     82 
     83     FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
     84     GraphicsContext* resultContext = resultImage->context();
     85     ASSERT(resultContext);
     86 
     87     Color color = adaptColorToOperatingColorSpace(m_shadowColor.combineWithAlpha(m_shadowOpacity));
     88     SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(blurRadius.width(), blurRadius.height()));
     89     SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(color.rgb(), SkXfermode::kSrcIn_Mode));
     90     SkPaint paint;
     91     paint.setImageFilter(blurFilter.get());
     92     paint.setColorFilter(colorFilter.get());
     93     paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
     94     RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
     95 
     96     RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame();
     97 
     98     if (!nativeImage)
     99         return;
    100 
    101     resultContext->drawBitmap(nativeImage->bitmap(), drawingRegion.x() + offset.width(), drawingRegion.y() + offset.height(), &paint);
    102     resultContext->drawBitmap(nativeImage->bitmap(), drawingRegion.x(), drawingRegion.y());
    103 }
    104 
    105 PassRefPtr<SkImageFilter> FEDropShadow::createImageFilter(SkiaImageFilterBuilder* builder)
    106 {
    107     RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
    108     float dx = filter()->applyHorizontalScale(m_dx);
    109     float dy = filter()->applyVerticalScale(m_dy);
    110     float stdX = filter()->applyHorizontalScale(m_stdX);
    111     float stdY = filter()->applyVerticalScale(m_stdY);
    112     Color color = adaptColorToOperatingColorSpace(m_shadowColor.combineWithAlpha(m_shadowOpacity));
    113     SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
    114     return adoptRef(SkDropShadowImageFilter::Create(SkFloatToScalar(dx), SkFloatToScalar(dy), SkFloatToScalar(stdX), SkFloatToScalar(stdY), color.rgb(), input.get(), &cropRect));
    115 }
    116 
    117 
    118 TextStream& FEDropShadow::externalRepresentation(TextStream& ts, int indent) const
    119 {
    120     writeIndent(ts, indent);
    121     ts << "[feDropShadow";
    122     FilterEffect::externalRepresentation(ts);
    123     ts << " stdDeviation=\"" << m_stdX << ", " << m_stdY << "\" dx=\"" << m_dx << "\" dy=\"" << m_dy << "\" flood-color=\"" << m_shadowColor.nameForRenderTreeAsText() <<"\" flood-opacity=\"" << m_shadowOpacity << "]\n";
    124     inputEffect(0)->externalRepresentation(ts, indent + 1);
    125     return ts;
    126 }
    127 
    128 } // namespace blink
    129