1/* 2 * Copyright (C) Research In Motion Limited 2011. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21 22#if ENABLE(FILTERS) 23#include "FEDropShadow.h" 24 25#include "ColorSpace.h" 26#include "FEGaussianBlur.h" 27#include "Filter.h" 28#include "GraphicsContext.h" 29#include "RenderTreeAsText.h" 30#include "ShadowBlur.h" 31#include "TextStream.h" 32#include <wtf/MathExtras.h> 33#include <wtf/Uint8ClampedArray.h> 34 35using namespace std; 36 37namespace WebCore { 38 39FEDropShadow::FEDropShadow(Filter* filter, float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity) 40 : FilterEffect(filter) 41 , m_stdX(stdX) 42 , m_stdY(stdY) 43 , m_dx(dx) 44 , m_dy(dy) 45 , m_shadowColor(shadowColor) 46 , m_shadowOpacity(shadowOpacity) 47{ 48} 49 50PassRefPtr<FEDropShadow> FEDropShadow::create(Filter* filter, float stdX, float stdY, float dx, float dy, const Color& shadowColor, float shadowOpacity) 51{ 52 return adoptRef(new FEDropShadow(filter, stdX, stdY, dx, dy, shadowColor, shadowOpacity)); 53} 54 55void FEDropShadow::determineAbsolutePaintRect() 56{ 57 Filter* filter = this->filter(); 58 ASSERT(filter); 59 60 FloatRect absolutePaintRect = inputEffect(0)->absolutePaintRect(); 61 FloatRect absoluteOffsetPaintRect(absolutePaintRect); 62 absoluteOffsetPaintRect.move(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); 63 absolutePaintRect.unite(absoluteOffsetPaintRect); 64 65 unsigned kernelSizeX = 0; 66 unsigned kernelSizeY = 0; 67 FEGaussianBlur::calculateKernelSize(filter, kernelSizeX, kernelSizeY, m_stdX, m_stdY); 68 69 // We take the half kernel size and multiply it with three, because we run box blur three times. 70 absolutePaintRect.inflateX(3 * kernelSizeX * 0.5f); 71 absolutePaintRect.inflateY(3 * kernelSizeY * 0.5f); 72 73 if (clipsToBounds()) 74 absolutePaintRect.intersect(maxEffectRect()); 75 else 76 absolutePaintRect.unite(maxEffectRect()); 77 78 setAbsolutePaintRect(enclosingIntRect(absolutePaintRect)); 79} 80 81void FEDropShadow::platformApplySoftware() 82{ 83 FilterEffect* in = inputEffect(0); 84 85 ImageBuffer* resultImage = createImageBufferResult(); 86 if (!resultImage) 87 return; 88 89 Filter* filter = this->filter(); 90 FloatSize blurRadius(filter->applyHorizontalScale(m_stdX), filter->applyVerticalScale(m_stdY)); 91 FloatSize offset(filter->applyHorizontalScale(m_dx), filter->applyVerticalScale(m_dy)); 92 93 FloatRect drawingRegion = drawingRegionOfInputImage(in->absolutePaintRect()); 94 FloatRect drawingRegionWithOffset(drawingRegion); 95 drawingRegionWithOffset.move(offset); 96 97 ImageBuffer* sourceImage = in->asImageBuffer(); 98 ASSERT(sourceImage); 99 GraphicsContext* resultContext = resultImage->context(); 100 ASSERT(resultContext); 101 resultContext->setAlpha(m_shadowOpacity); 102 resultContext->drawImageBuffer(sourceImage, ColorSpaceDeviceRGB, drawingRegionWithOffset); 103 resultContext->setAlpha(1); 104 105 ShadowBlur contextShadow(blurRadius, offset, m_shadowColor, ColorSpaceDeviceRGB); 106 107 // TODO: Direct pixel access to ImageBuffer would avoid copying the ImageData. 108 IntRect shadowArea(IntPoint(), resultImage->internalSize()); 109 RefPtr<Uint8ClampedArray> srcPixelArray = resultImage->getPremultipliedImageData(shadowArea); 110 111 contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width()); 112 113 resultImage->putByteArray(Premultiplied, srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint()); 114 115 resultContext->setCompositeOperation(CompositeSourceIn); 116 resultContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), m_shadowColor, ColorSpaceDeviceRGB); 117 resultContext->setCompositeOperation(CompositeDestinationOver); 118 119 resultImage->context()->drawImageBuffer(sourceImage, ColorSpaceDeviceRGB, drawingRegion); 120} 121 122void FEDropShadow::dump() 123{ 124} 125 126TextStream& FEDropShadow::externalRepresentation(TextStream& ts, int indent) const 127{ 128 writeIndent(ts, indent); 129 ts << "[feDropShadow"; 130 FilterEffect::externalRepresentation(ts); 131 ts << " stdDeviation=\"" << m_stdX << ", " << m_stdY << "\" dx=\"" << m_dx << "\" dy=\"" << m_dy << "\" flood-color=\"" << m_shadowColor.nameForRenderTreeAsText() <<"\" flood-opacity=\"" << m_shadowOpacity << "]\n"; 132 inputEffect(0)->externalRepresentation(ts, indent + 1); 133 return ts; 134} 135 136} // namespace WebCore 137 138#endif // ENABLE(FILTERS) 139