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