15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org> 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2005 Eric Seidel <eric@webkit.org> 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2010 Zoltan Herczeg <zherczeg@webkit.org> 753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved. 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 26a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/FEConvolveMatrix.h" 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 28a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "SkMatrixConvolutionImageFilter.h" 29a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/ParallelJobs.h" 30a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/SkiaImageFilterBuilder.h" 311e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/TextStream.h" 321e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "wtf/OwnPtr.h" 337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/Uint8ClampedArray.h" 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FEConvolveMatrix::FEConvolveMatrix(Filter* filter, const IntSize& kernelSize, 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode, 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix) 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : FilterEffect(filter) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_kernelSize(kernelSize) 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_divisor(divisor) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_bias(bias) 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_targetOffset(targetOffset) 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_edgeMode(edgeMode) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_kernelUnitLength(kernelUnitLength) 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_preserveAlpha(preserveAlpha) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_kernelMatrix(kernelMatrix) 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_kernelSize.width() > 0); 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_kernelSize.height() > 0); 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<FEConvolveMatrix> FEConvolveMatrix::create(Filter* filter, const IntSize& kernelSize, 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float divisor, float bias, const IntPoint& targetOffset, EdgeModeType edgeMode, 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const FloatPoint& kernelUnitLength, bool preserveAlpha, const Vector<float>& kernelMatrix) 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return adoptRef(new FEConvolveMatrix(filter, kernelSize, divisor, bias, targetOffset, edgeMode, kernelUnitLength, 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) preserveAlpha, kernelMatrix)); 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)FloatRect FEConvolveMatrix::mapPaintRect(const FloatRect& rect, bool forward) 6309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){ 6409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) FloatRect result = rect; 6509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) 6609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.moveBy(forward ? -m_targetOffset : m_targetOffset - m_kernelSize); 6709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) result.expand(m_kernelSize); 6809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) return result; 6909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)} 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntSize FEConvolveMatrix::kernelSize() const 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_kernelSize; 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FEConvolveMatrix::setKernelSize(const IntSize& kernelSize) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(kernelSize.width() > 0); 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(kernelSize.height() > 0); 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_kernelSize = kernelSize; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)const Vector<float>& FEConvolveMatrix::kernel() const 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch return m_kernelMatrix; 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FEConvolveMatrix::setKernel(const Vector<float>& kernel) 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch m_kernelMatrix = kernel; 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FEConvolveMatrix::divisor() const 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 9502772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch return m_divisor; 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEConvolveMatrix::setDivisor(float divisor) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(divisor); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_divisor == divisor) 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_divisor = divisor; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FEConvolveMatrix::bias() const 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 10902772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch return m_bias; 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEConvolveMatrix::setBias(float bias) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_bias == bias) 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_bias = bias; 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntPoint FEConvolveMatrix::targetOffset() const 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 12202772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch return m_targetOffset; 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEConvolveMatrix::setTargetOffset(const IntPoint& targetOffset) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_targetOffset == targetOffset) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_targetOffset = targetOffset; 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)EdgeModeType FEConvolveMatrix::edgeMode() const 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_edgeMode; 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEConvolveMatrix::setEdgeMode(EdgeModeType edgeMode) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_edgeMode == edgeMode) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_edgeMode = edgeMode; 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FloatPoint FEConvolveMatrix::kernelUnitLength() const 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14802772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch return m_kernelUnitLength; 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEConvolveMatrix::setKernelUnitLength(const FloatPoint& kernelUnitLength) 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(kernelUnitLength.x() > 0); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(kernelUnitLength.y() > 0); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_kernelUnitLength == kernelUnitLength) 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_kernelUnitLength = kernelUnitLength; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEConvolveMatrix::preserveAlpha() const 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 16302772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch return m_preserveAlpha; 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FEConvolveMatrix::setPreserveAlpha(bool preserveAlpha) 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_preserveAlpha == preserveAlpha) 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_preserveAlpha = preserveAlpha; 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ----------------------------------- 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ConvolveMatrix implementation 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ----------------------------------- 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) The image rectangle is split in the following way: 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) +---------------------+ 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) | A | 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) +---------------------+ 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) | | | | 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) | B | C | D | 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) | | | | 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) +---------------------+ 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) | E | 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) +---------------------+ 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Where region C contains those pixels, whose values 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) can be calculated without crossing the edge of the rectangle. 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Example: 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Image size: width: 10, height: 10 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Order (kernel matrix size): width: 3, height 4 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Target: x:1, y:3 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) The following figure shows the target inside the kernel matrix: 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ... 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ... 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ... 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) .X. 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) The regions in this case are the following: 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Note: (x1, y1) top-left and (x2, y2) is the bottom-right corner 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Note: row x2 and column y2 is not part of the region 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) only those (x, y) pixels, where x1 <= x < x2 and y1 <= y < y2 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Region A: x1: 0, y1: 0, x2: 10, y2: 3 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Region B: x1: 0, y1: 3, x2: 1, y2: 10 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Region C: x1: 1, y1: 3, x2: 9, y2: 10 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Region D: x1: 9, y1: 3, x2: 10, y2: 10 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Region E: x1: 0, y1: 10, x2: 10, y2: 10 (empty region) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Since region C (often) contains most of the pixels, we implemented 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) a fast algoritm to calculate these values, called fastSetInteriorPixels. 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) For other regions, fastSetOuterPixels is used, which calls getPixelValue, 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) to handle pixels outside of the image. In a rare situations, when 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) kernel matrix is bigger than the image, all pixels are calculated by this 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) function. 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Although these two functions have lot in common, I decided not to make 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) common a template for them, since there are key differences as well, 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) and would make it really hard to understand. 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*/ 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static ALWAYS_INLINE unsigned char clampRGBAValue(float channel, unsigned char max = 255) 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (channel <= 0) 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return 0; 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (channel >= max) 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return max; 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return channel; 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template<bool preserveAlphaValues> 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE void setDestinationPixels(Uint8ClampedArray* image, int& pixel, float* totals, float divisor, float bias, Uint8ClampedArray* src) 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned char maxAlpha = preserveAlphaValues ? 255 : clampRGBAValue(totals[3] / divisor + bias); 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = 0; i < 3; ++i) 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) image->set(pixel++, clampRGBAValue(totals[i] / divisor + bias, maxAlpha)); 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (preserveAlphaValues) { 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) image->set(pixel, src->item(pixel)); 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++pixel; 249a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) } else { 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) image->set(pixel++, maxAlpha); 251a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) } 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if defined(_MSC_VER) && (_MSC_VER >= 1700) 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Incorrectly diagnosing overwrite of stack in |totals| due to |preserveAlphaValues|. 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#pragma warning(push) 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#pragma warning(disable: 4789) 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Only for region C 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template<bool preserveAlphaValues> 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE void FEConvolveMatrix::fastSetInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom, int yStart, int yEnd) 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // edge mode does not affect these pixels 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int pixel = (m_targetOffset.y() * paintingData.width + m_targetOffset.x()) * 4; 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int kernelIncrease = clipRight * 4; 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int xIncrease = (m_kernelSize.width() - 1) * 4; 2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Contains the sum of rgb(a) components 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float totals[3 + (preserveAlphaValues ? 0 : 1)]; 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_divisor); 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Skip the first '(clipBottom - yEnd)' lines 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixel += (clipBottom - yEnd) * (xIncrease + (clipRight + 1) * 4); 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int startKernelPixel = (clipBottom - yEnd) * (xIncrease + (clipRight + 1) * 4); 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int y = yEnd + 1; y > yStart; --y) { 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int x = clipRight + 1; x > 0; --x) { 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int kernelValue = m_kernelMatrix.size() - 1; 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int kernelPixel = startKernelPixel; 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int width = m_kernelSize.width(); 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[0] = 0; 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[1] = 0; 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[2] = 0; 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!preserveAlphaValues) 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[3] = 0; 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (kernelValue >= 0) { 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++)); 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++)); 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel++)); 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!preserveAlphaValues) 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(kernelPixel)); 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++kernelPixel; 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) --kernelValue; 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!--width) { 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) kernelPixel += kernelIncrease; 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = m_kernelSize.width(); 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setDestinationPixels<preserveAlphaValues>(paintingData.dstPixelArray, pixel, totals, m_divisor, paintingData.bias, paintingData.srcPixelArray); 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startKernelPixel += 4; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixel += xIncrease; 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startKernelPixel += xIncrease; 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE int FEConvolveMatrix::getPixelValue(PaintingData& paintingData, int x, int y) 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (x >= 0 && x < paintingData.width && y >= 0 && y < paintingData.height) 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (y * paintingData.width + x) << 2; 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (m_edgeMode) { 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) default: // EDGEMODE_NONE 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return -1; 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case EDGEMODE_DUPLICATE: 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (x < 0) 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x = 0; 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (x >= paintingData.width) 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x = paintingData.width - 1; 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (y < 0) 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) y = 0; 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else if (y >= paintingData.height) 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) y = paintingData.height - 1; 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (y * paintingData.width + x) << 2; 3305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case EDGEMODE_WRAP: 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (x < 0) 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x += paintingData.width; 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) x %= paintingData.width; 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (y < 0) 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) y += paintingData.height; 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) y %= paintingData.height; 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return (y * paintingData.width + x) << 2; 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// For other regions than C 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)template<bool preserveAlphaValues> 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FEConvolveMatrix::fastSetOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2) 3445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int pixel = (y1 * paintingData.width + x1) * 4; 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int height = y2 - y1; 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int width = x2 - x1; 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int beginKernelPixelX = x1 - m_targetOffset.x(); 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int startKernelPixelX = beginKernelPixelX; 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int startKernelPixelY = y1 - m_targetOffset.y(); 3515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int xIncrease = (paintingData.width - width) * 4; 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Contains the sum of rgb(a) components 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float totals[3 + (preserveAlphaValues ? 0 : 1)]; 3545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // m_divisor cannot be 0, SVGFEConvolveMatrixElement ensures this 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(m_divisor); 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int y = height; y > 0; --y) { 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int x = width; x > 0; --x) { 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int kernelValue = m_kernelMatrix.size() - 1; 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int kernelPixelX = startKernelPixelX; 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int kernelPixelY = startKernelPixelY; 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int width = m_kernelSize.width(); 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[0] = 0; 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[1] = 0; 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[2] = 0; 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!preserveAlphaValues) 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[3] = 0; 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) while (kernelValue >= 0) { 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int pixelIndex = getPixelValue(paintingData, kernelPixelX, kernelPixelY); 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (pixelIndex >= 0) { 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[0] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex)); 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[1] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 1)); 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[2] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 2)); 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!preserveAlphaValues && pixelIndex >= 0) 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) totals[3] += m_kernelMatrix[kernelValue] * static_cast<float>(paintingData.srcPixelArray->item(pixelIndex + 3)); 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++kernelPixelX; 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) --kernelValue; 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!--width) { 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) kernelPixelX = startKernelPixelX; 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++kernelPixelY; 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) width = m_kernelSize.width(); 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setDestinationPixels<preserveAlphaValues>(paintingData.dstPixelArray, pixel, totals, m_divisor, paintingData.bias, paintingData.srcPixelArray); 3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++startKernelPixelX; 3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixel += xIncrease; 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startKernelPixelX = beginKernelPixelX; 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++startKernelPixelY; 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#if defined(_MSC_VER) && (_MSC_VER >= 1700) 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#pragma warning(pop) // Disable of 4789 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 4015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE void FEConvolveMatrix::setInteriorPixels(PaintingData& paintingData, int clipRight, int clipBottom, int yStart, int yEnd) 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Must be implemented here, since it refers another ALWAYS_INLINE 4055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // function, which defined in this C++ source file as well 4065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_preserveAlpha) 4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fastSetInteriorPixels<true>(paintingData, clipRight, clipBottom, yStart, yEnd); 4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fastSetInteriorPixels<false>(paintingData, clipRight, clipBottom, yStart, yEnd); 4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)ALWAYS_INLINE void FEConvolveMatrix::setOuterPixels(PaintingData& paintingData, int x1, int y1, int x2, int y2) 4135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Although this function can be moved to the header, it is implemented here 4155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // because setInteriorPixels is also implemented here 4165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_preserveAlpha) 4175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fastSetOuterPixels<true>(paintingData, x1, y1, x2, y2); 4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fastSetOuterPixels<false>(paintingData, x1, y1, x2, y2); 4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FEConvolveMatrix::setInteriorPixelsWorker(InteriorPixelParameters* param) 4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) param->filter->setInteriorPixels(*param->paintingData, param->clipRight, param->clipBottom, param->yStart, param->yEnd); 4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 42753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void FEConvolveMatrix::applySoftware() 4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FilterEffect* in = inputEffect(0); 4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Uint8ClampedArray* resultImage; 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_preserveAlpha) 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) resultImage = createUnmultipliedImageResult(); 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) resultImage = createPremultipliedImageResult(); 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!resultImage) 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect effectDrawingRect = requestedRegionOfInputImageData(in->absolutePaintRect()); 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<Uint8ClampedArray> srcPixelArray; 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_preserveAlpha) 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) srcPixelArray = in->asUnmultipliedImage(effectDrawingRect); 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) srcPixelArray = in->asPremultipliedImage(effectDrawingRect); 4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntSize paintSize = absolutePaintRect().size(); 4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PaintingData paintingData; 4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.srcPixelArray = srcPixelArray.get(); 4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.dstPixelArray = resultImage; 4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.width = paintSize.width(); 4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.height = paintSize.height(); 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.bias = m_bias * 255; 4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Drawing fully covered pixels 4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int clipRight = paintSize.width() - m_kernelSize.width(); 4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int clipBottom = paintSize.height() - m_kernelSize.height(); 4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipRight >= 0 && clipBottom >= 0) { 4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension; 4625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (optimalThreadNumber > 1) { 463e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) ParallelJobs<InteriorPixelParameters> parallelJobs(&FEConvolveMatrix::setInteriorPixelsWorker, optimalThreadNumber); 4645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const int numOfThreads = parallelJobs.numberOfJobs(); 4655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Split the job into "heightPerThread" jobs but there a few jobs that need to be slightly larger since 4675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // heightPerThread * jobs < total size. These extras are handled by the remainder "jobsWithExtra". 4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const int heightPerThread = clipBottom / numOfThreads; 4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const int jobsWithExtra = clipBottom % numOfThreads; 4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int startY = 0; 4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int job = 0; job < numOfThreads; ++job) { 4735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) InteriorPixelParameters& param = parallelJobs.parameter(job); 4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) param.filter = this; 4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) param.paintingData = &paintingData; 4765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) param.clipRight = clipRight; 4775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) param.clipBottom = clipBottom; 4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) param.yStart = startY; 4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startY += job < jobsWithExtra ? heightPerThread + 1 : heightPerThread; 4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) param.yEnd = startY; 4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) parallelJobs.execute(); 4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 4855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fallback to single threaded mode. 4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setInteriorPixels(paintingData, clipRight, clipBottom, 0, clipBottom); 4875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clipRight += m_targetOffset.x() + 1; 4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) clipBottom += m_targetOffset.y() + 1; 4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_targetOffset.y() > 0) 4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setOuterPixels(paintingData, 0, 0, paintSize.width(), m_targetOffset.y()); 4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipBottom < paintSize.height()) 4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setOuterPixels(paintingData, 0, clipBottom, paintSize.width(), paintSize.height()); 4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_targetOffset.x() > 0) 4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setOuterPixels(paintingData, 0, m_targetOffset.y(), m_targetOffset.x(), clipBottom); 4975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (clipRight < paintSize.width()) 4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setOuterPixels(paintingData, clipRight, m_targetOffset.y(), paintSize.width(), clipBottom); 4995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Rare situation, not optimizied for speed 5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setOuterPixels(paintingData, 0, 0, paintSize.width(), paintSize.height()); 5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 505e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)SkMatrixConvolutionImageFilter::TileMode toSkiaTileMode(EdgeModeType edgeMode) 5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 50753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) switch (edgeMode) { 508e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) case EDGEMODE_DUPLICATE: 50953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return SkMatrixConvolutionImageFilter::kClamp_TileMode; 510e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) case EDGEMODE_WRAP: 51153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return SkMatrixConvolutionImageFilter::kRepeat_TileMode; 512e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) case EDGEMODE_NONE: 51353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return SkMatrixConvolutionImageFilter::kClampToBlack_TileMode; 51453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) default: 51553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) return SkMatrixConvolutionImageFilter::kClamp_TileMode; 51653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) } 51753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)} 51853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 5193c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben MurdochPassRefPtr<SkImageFilter> FEConvolveMatrix::createImageFilter(SkiaImageFilterBuilder* builder) 52053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles){ 5213c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben Murdoch RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace())); 52253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) 52353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) SkISize kernelSize(SkISize::Make(m_kernelSize.width(), m_kernelSize.height())); 52453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) int numElements = kernelSize.width() * kernelSize.height(); 52553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) SkScalar gain = SkFloatToScalar(1.0f / m_divisor); 526e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) SkScalar bias = SkFloatToScalar(m_bias * 255); 52753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) SkIPoint target = SkIPoint::Make(m_targetOffset.x(), m_targetOffset.y()); 52853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) SkMatrixConvolutionImageFilter::TileMode tileMode = toSkiaTileMode(m_edgeMode); 52953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) bool convolveAlpha = !m_preserveAlpha; 5301e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles) OwnPtr<SkScalar[]> kernel = adoptArrayPtr(new SkScalar[numElements]); 53153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) for (int i = 0; i < numElements; ++i) 53253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) kernel[i] = SkFloatToScalar(m_kernelMatrix[numElements - 1 - i]); 533f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles) SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset()); 53410f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch return adoptRef(SkMatrixConvolutionImageFilter::Create(kernelSize, kernel.get(), gain, bias, target, tileMode, convolveAlpha, input.get(), &cropRect)); 5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static TextStream& operator<<(TextStream& ts, const EdgeModeType& type) 5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (type) { 5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case EDGEMODE_UNKNOWN: 5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << "UNKNOWN"; 5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case EDGEMODE_DUPLICATE: 5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << "DUPLICATE"; 5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case EDGEMODE_WRAP: 5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << "WRAP"; 5485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case EDGEMODE_NONE: 5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << "NONE"; 5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 5525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ts; 5545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& FEConvolveMatrix::externalRepresentation(TextStream& ts, int indent) const 5575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 5585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) writeIndent(ts, indent); 5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << "[feConvolveMatrix"; 5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FilterEffect::externalRepresentation(ts); 5615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << " order=\"" << m_kernelSize << "\" " 5625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "kernelMatrix=\"" << m_kernelMatrix << "\" " 5635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "divisor=\"" << m_divisor << "\" " 5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "bias=\"" << m_bias << "\" " 5655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "target=\"" << m_targetOffset << "\" " 5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "edgeMode=\"" << m_edgeMode << "\" " 5675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "kernelUnitLength=\"" << m_kernelUnitLength << "\" " 5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "preserveAlpha=\"" << m_preserveAlpha << "\"]\n"; 5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) inputEffect(0)->externalRepresentation(ts, indent + 1); 5705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ts; 5715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 5725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 573c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)}; // namespace blink 574