15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2011. All rights reserved.
353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved.
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
22a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/FEDropShadow.h"
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContext.h"
25a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/FEGaussianBlur.h"
26a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/SkiaImageFilterBuilder.h"
271e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/TextStream.h"
281fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch#include "third_party/skia/include/core/SkColorFilter.h"
291fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch#include "third_party/skia/include/effects/SkBlurImageFilter.h"
30a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "third_party/skia/include/effects/SkDropShadowImageFilter.h"
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
32c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
3302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FEDropShadow::FEDropShadow(Filter* filter, float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity)
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : FilterEffect(filter)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_stdX(stdX)
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_stdY(stdY)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_dx(dx)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_dy(dy)
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_shadowColor(shadowColor)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_shadowOpacity(shadowOpacity)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<FEDropShadow> FEDropShadow::create(Filter* filter, float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity)
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return adoptRef(new FEDropShadow(filter, stdX, stdY, dx, dy, shadowColor, shadowOpacity));
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
50e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)FloatRect FEDropShadow::mapRect(const FloatRect& rect, bool forward)
51e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles){
52e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    FloatRect result = rect;
53e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    Filter* filter = this->filter();
54e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    ASSERT(filter);
55e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
56e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    FloatRect offsetRect = rect;
57e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    if (forward)
58e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        offsetRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
59e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    else
60e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        offsetRect.move(-filter->applyHorizontalScale(m_dx), -filter->applyVerticalScale(m_dy));
61e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    result.unite(offsetRect);
62e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
6307a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    IntSize kernelSize = FEGaussianBlur::calculateKernelSize(filter, FloatPoint(m_stdX, m_stdY));
64e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
65e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    // We take the half kernel size and multiply it with three, because we run box blur three times.
6607a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    result.inflateX(3 * kernelSize.width() * 0.5f);
6707a852d8c1953036774d8f3b65d18dcfea3bb4a2Ben Murdoch    result.inflateY(3 * kernelSize.height() * 0.5f);
68e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)    return result;
69e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)}
70e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)
7153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void FEDropShadow::applySoftware()
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect* in = inputEffect(0);
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ImageBuffer* resultImage = createImageBufferResult();
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!resultImage)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Filter* filter = this->filter();
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize blurRadius(filter->applyHorizontalScale(m_stdX), filter->applyVerticalScale(m_stdY));
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize offset(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy));
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect());
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    GraphicsContext* resultContext = resultImage->context();
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(resultContext);
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Color color = adaptColorToOperatingColorSpace(m_shadowColor.combineWithAlpha(m_shadowOpacity));
8810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    SkAutoTUnref<SkImageFilter> blurFilter(SkBlurImageFilter::Create(blurRadius.width(), blurRadius.height()));
8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SkAutoTUnref<SkColorFilter> colorFilter(SkColorFilter::CreateModeFilter(color.rgb(), SkXfermode::kSrcIn_Mode));
901fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    SkPaint paint;
911fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    paint.setImageFilter(blurFilter.get());
921fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    paint.setColorFilter(colorFilter.get());
931fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
941fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    RefPtr<Image> image = in->asImageBuffer()->copyImage(DontCopyBackingStore);
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
961fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    RefPtr<NativeImageSkia> nativeImage = image->nativeImageForCurrentFrame();
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
981fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    if (!nativeImage)
991fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch        return;
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1011fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    resultContext->drawBitmap(nativeImage->bitmap(), drawingRegion.x() + offset.width(), drawingRegion.y() + offset.height(), &paint);
1021fad5ca6c42d689812b66fc493992aa6d747a6fbBen Murdoch    resultContext->drawBitmap(nativeImage->bitmap(), drawingRegion.x(), drawingRegion.y());
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
105a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)PassRefPtr<SkImageFilter> FEDropShadow::createImageFilter(SkiaImageFilterBuilder* builder)
106a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles){
107a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
108a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    float dx = filter()->applyHorizontalScale(m_dx);
109a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    float dy = filter()->applyVerticalScale(m_dy);
110a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    float stdX = filter()->applyHorizontalScale(m_stdX);
11109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    float stdY = filter()->applyVerticalScale(m_stdY);
11209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    Color color = adaptColorToOperatingColorSpace(m_shadowColor.combineWithAlpha(m_shadowOpacity));
113a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
11410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    return adoptRef(SkDropShadowImageFilter::Create(SkFloatToScalar(dx), SkFloatToScalar(dy), SkFloatToScalar(stdX), SkFloatToScalar(stdY), color.rgb(), input.get(), &cropRect));
115a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)}
116a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
117a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& FEDropShadow::externalRepresentation(TextStream& ts, int indent) const
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    writeIndent(ts, indent);
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << "[feDropShadow";
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FilterEffect::externalRepresentation(ts);
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ts << " stdDeviation=\"" << m_stdX << ", " << m_stdY << "\" dx=\"" << m_dx << "\" dy=\"" << m_dy << "\" flood-color=\"" << m_shadowColor.nameForRenderTreeAsText() <<"\" flood-opacity=\"" << m_shadowOpacity << "]\n";
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    inputEffect(0)->externalRepresentation(ts, indent + 1);
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return ts;
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
12702772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch
128c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
129