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 Renata Hodovan <reni@inf.u-szeged.hu> 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Gabor Loki <loki@webkit.org> 853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles) * Copyright (C) 2013 Google Inc. All rights reserved. 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 27a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/FETurbulence.h" 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 29521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "SkPerlinNoiseShader.h" 30521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)#include "SkRectShaderImageFilter.h" 31a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/ParallelJobs.h" 32a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/filters/SkiaImageFilterBuilder.h" 331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/text/TextStream.h" 347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/MathExtras.h" 357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/Uint8ClampedArray.h" 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 37c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Produces results in the range [1, 2**31 - 2]. Algorithm is: 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) r = (a * r) mod m where a = randAmplitude = 16807 and 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m = randMaximum = 2**31 - 1 = 2147483647, r = seed. 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) To test: the algorithm should produce the result 1043618065 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) as the 10,000th generated number if the original seed is 1. 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)*/ 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int s_perlinNoise = 4096; 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const long s_randMaximum = 2147483647; // 2**31 - 1 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int s_randAmplitude = 16807; // 7**5; primitive root of m 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int s_randQ = 127773; // m / a 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static const int s_randR = 2836; // m % a 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FETurbulence::FETurbulence(Filter* filter, TurbulenceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles) 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : FilterEffect(filter) 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_type(type) 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_baseFrequencyX(baseFrequencyX) 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_baseFrequencyY(baseFrequencyY) 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_numOctaves(numOctaves) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_seed(seed) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_stitchTiles(stitchTiles) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)PassRefPtr<FETurbulence> FETurbulence::create(Filter* filter, TurbulenceType type, float baseFrequencyX, float baseFrequencyY, int numOctaves, float seed, bool stitchTiles) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return adoptRef(new FETurbulence(filter, type, baseFrequencyX, baseFrequencyY, numOctaves, seed, stitchTiles)); 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TurbulenceType FETurbulence::type() const 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_type; 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FETurbulence::setType(TurbulenceType type) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_type == type) 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_type = type; 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FETurbulence::baseFrequencyY() const 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_baseFrequencyY; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FETurbulence::setBaseFrequencyY(float baseFrequencyY) 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_baseFrequencyY == baseFrequencyY) 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_baseFrequencyY = baseFrequencyY; 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FETurbulence::baseFrequencyX() const 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_baseFrequencyX; 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FETurbulence::setBaseFrequencyX(float baseFrequencyX) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_baseFrequencyX == baseFrequencyX) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_baseFrequencyX = baseFrequencyX; 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FETurbulence::seed() const 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 11002772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch return m_seed; 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FETurbulence::setSeed(float seed) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_seed == seed) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_seed = seed; 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int FETurbulence::numOctaves() const 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_numOctaves; 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FETurbulence::setNumOctaves(int numOctaves) 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_numOctaves == numOctaves) 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_numOctaves = numOctaves; 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FETurbulence::stitchTiles() const 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return m_stitchTiles; 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool FETurbulence::setStitchTiles(bool stitch) 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_stitchTiles == stitch) 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_stitchTiles = stitch; 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// The turbulence calculation code is an adapted version of what appears in the SVG 1.1 specification: 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// http://www.w3.org/TR/SVG11/filters.html#feTurbulence 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// Compute pseudo random number. 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline long FETurbulence::PaintingData::random() 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) long result = s_randAmplitude * (seed % s_randQ) - s_randR * (seed / s_randQ); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (result <= 0) 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) result += s_randMaximum; 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) seed = result; 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return result; 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline float smoothCurve(float t) 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return t * t * (3 - 2 * t); 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline float linearInterpolation(float t, float a, float b) 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return a + t * (b - a); 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline void FETurbulence::initPaint(PaintingData& paintingData) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float normalizationFactor; 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The seed value clamp to the range [1, s_randMaximum - 1]. 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paintingData.seed <= 0) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.seed = -(paintingData.seed % (s_randMaximum - 1)) + 1; 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (paintingData.seed > s_randMaximum - 1) 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.seed = s_randMaximum - 1; 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* gradient; 1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int channel = 0; channel < 4; ++channel) { 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = 0; i < s_blockSize; ++i) { 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.latticeSelector[i] = i; 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradient = paintingData.gradient[channel][i]; 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradient[0] = static_cast<float>((paintingData.random() % (2 * s_blockSize)) - s_blockSize) / s_blockSize; 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradient[1] = static_cast<float>((paintingData.random() % (2 * s_blockSize)) - s_blockSize) / s_blockSize; 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) normalizationFactor = sqrtf(gradient[0] * gradient[0] + gradient[1] * gradient[1]); 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradient[0] /= normalizationFactor; 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) gradient[1] /= normalizationFactor; 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = s_blockSize - 1; i > 0; --i) { 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int k = paintingData.latticeSelector[i]; 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int j = paintingData.random() % s_blockSize; 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(j >= 0); 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(j < 2 * s_blockSize + 2); 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.latticeSelector[i] = paintingData.latticeSelector[j]; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.latticeSelector[j] = k; 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int i = 0; i < s_blockSize + 2; ++i) { 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.latticeSelector[s_blockSize + i] = paintingData.latticeSelector[i]; 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int channel = 0; channel < 4; ++channel) { 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.gradient[channel][s_blockSize + i][0] = paintingData.gradient[channel][i][0]; 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) paintingData.gradient[channel][s_blockSize + i][1] = paintingData.gradient[channel][i][1]; 2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)inline void checkNoise(int& noiseValue, int limitValue, int newValue) 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (noiseValue >= limitValue) 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) noiseValue -= newValue; 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (noiseValue >= limitValue - 1) 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) noiseValue -= newValue - 1; 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float FETurbulence::noise2D(int channel, PaintingData& paintingData, StitchData& stitchData, const FloatPoint& noiseVector) 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) struct Noise { 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int noisePositionIntegerValue; 2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float noisePositionFractionValue; 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Noise(float component) 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) { 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float position = component + s_perlinNoise; 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) noisePositionIntegerValue = static_cast<int>(position); 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) noisePositionFractionValue = position - noisePositionIntegerValue; 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) }; 2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Noise noiseX(noiseVector.x()); 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Noise noiseY(noiseVector.y()); 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float* q; 2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float sx, sy, a, b, u, v; 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // If stitching, adjust lattice points accordingly. 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_stitchTiles) { 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) checkNoise(noiseX.noisePositionIntegerValue, stitchData.wrapX, stitchData.width); 2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) checkNoise(noiseY.noisePositionIntegerValue, stitchData.wrapY, stitchData.height); 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) noiseX.noisePositionIntegerValue &= s_blockMask; 2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) noiseY.noisePositionIntegerValue &= s_blockMask; 2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int latticeIndex = paintingData.latticeSelector[noiseX.noisePositionIntegerValue]; 2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int nextLatticeIndex = paintingData.latticeSelector[(noiseX.noisePositionIntegerValue + 1) & s_blockMask]; 2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sx = smoothCurve(noiseX.noisePositionFractionValue); 2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) sy = smoothCurve(noiseY.noisePositionFractionValue); 2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // This is taken 1:1 from SVG spec: http://www.w3.org/TR/SVG11/filters.html#feTurbulenceElement. 2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue]; 2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) q = paintingData.gradient[channel][temp]; 2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) u = noiseX.noisePositionFractionValue * q[0] + noiseY.noisePositionFractionValue * q[1]; 2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue]; 2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) q = paintingData.gradient[channel][temp]; 2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) v = (noiseX.noisePositionFractionValue - 1) * q[0] + noiseY.noisePositionFractionValue * q[1]; 2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) a = linearInterpolation(sx, u, v); 2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) temp = paintingData.latticeSelector[latticeIndex + noiseY.noisePositionIntegerValue + 1]; 2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) q = paintingData.gradient[channel][temp]; 2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) u = noiseX.noisePositionFractionValue * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; 2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) temp = paintingData.latticeSelector[nextLatticeIndex + noiseY.noisePositionIntegerValue + 1]; 2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) q = paintingData.gradient[channel][temp]; 2635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) v = (noiseX.noisePositionFractionValue - 1) * q[0] + (noiseY.noisePositionFractionValue - 1) * q[1]; 2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) b = linearInterpolation(sx, u, v); 2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return linearInterpolation(sy, a, b); 2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 268591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochunsigned char FETurbulence::calculateTurbulenceValueForPoint(int channel, PaintingData& paintingData, StitchData& stitchData, const FloatPoint& point, float baseFrequencyX, float baseFrequencyY) 2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float tileWidth = paintingData.filterSize.width(); 2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float tileHeight = paintingData.filterSize.height(); 2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(tileWidth > 0 && tileHeight > 0); 2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Adjust the base frequencies if necessary for stitching. 2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_stitchTiles) { 2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // When stitching tiled turbulence, the frequencies must be adjusted 2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // so that the tile borders will be continuous. 2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (baseFrequencyX) { 2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float lowFrequency = floorf(tileWidth * baseFrequencyX) / tileWidth; 2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float highFrequency = ceilf(tileWidth * baseFrequencyX) / tileWidth; 2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // BaseFrequency should be non-negative according to the standard. 2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (baseFrequencyX / lowFrequency < highFrequency / baseFrequencyX) 2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) baseFrequencyX = lowFrequency; 2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) baseFrequencyX = highFrequency; 2855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (baseFrequencyY) { 2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float lowFrequency = floorf(tileHeight * baseFrequencyY) / tileHeight; 2885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float highFrequency = ceilf(tileHeight * baseFrequencyY) / tileHeight; 2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (baseFrequencyY / lowFrequency < highFrequency / baseFrequencyY) 2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) baseFrequencyY = lowFrequency; 2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) baseFrequencyY = highFrequency; 2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Set up TurbulenceInitial stitch values. 2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stitchData.width = roundf(tileWidth * baseFrequencyX); 2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stitchData.wrapX = s_perlinNoise + stitchData.width; 2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stitchData.height = roundf(tileHeight * baseFrequencyY); 2985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stitchData.wrapY = s_perlinNoise + stitchData.height; 2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float turbulenceFunctionResult = 0; 3015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatPoint noiseVector(point.x() * baseFrequencyX, point.y() * baseFrequencyY); 3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float ratio = 1; 3035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int octave = 0; octave < m_numOctaves; ++octave) { 3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) 3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) turbulenceFunctionResult += noise2D(channel, paintingData, stitchData, noiseVector) / ratio; 3065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) else 3075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) turbulenceFunctionResult += fabsf(noise2D(channel, paintingData, stitchData, noiseVector)) / ratio; 3085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) noiseVector.setX(noiseVector.x() * 2); 3095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) noiseVector.setY(noiseVector.y() * 2); 3105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ratio *= 2; 3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_stitchTiles) { 3125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Update stitch values. Subtracting s_perlinNoiseoise before the multiplication and 3135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // adding it afterward simplifies to subtracting it once. 3145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stitchData.width *= 2; 3155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stitchData.wrapX = 2 * stitchData.wrapX - s_perlinNoise; 3165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stitchData.height *= 2; 3175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) stitchData.wrapY = 2 * stitchData.wrapY - s_perlinNoise; 3185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The value of turbulenceFunctionResult comes from ((turbulenceFunctionResult * 255) + 255) / 2 by fractalNoise 3225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // and (turbulenceFunctionResult * 255) by turbulence. 3235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_type == FETURBULENCE_TYPE_FRACTALNOISE) 3245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) turbulenceFunctionResult = turbulenceFunctionResult * 0.5f + 0.5f; 3255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clamp result 3265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) turbulenceFunctionResult = std::max(std::min(turbulenceFunctionResult, 1.f), 0.f); 3275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return static_cast<unsigned char>(turbulenceFunctionResult * 255); 3285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 330591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochinline void FETurbulence::fillRegion(Uint8ClampedArray* pixelArray, PaintingData& paintingData, int startY, int endY, float baseFrequencyX, float baseFrequencyY) 3315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntRect filterRegion = absolutePaintRect(); 3335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) IntPoint point(0, filterRegion.y() + startY); 3345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int indexOfPixelChannel = startY * (filterRegion.width() << 2); 3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int channel; 3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) StitchData stitchData; 3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int y = startY; y < endY; ++y) { 3395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) point.setY(point.y() + 1); 3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) point.setX(filterRegion.x()); 3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (int x = 0; x < filterRegion.width(); ++x) { 3425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) point.setX(point.x() + 1); 3435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (channel = 0; channel < 4; ++channel, ++indexOfPixelChannel) 344591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch pixelArray->set(indexOfPixelChannel, calculateTurbulenceValueForPoint(channel, paintingData, stitchData, filter()->mapAbsolutePointToLocalPoint(point), baseFrequencyX, baseFrequencyY)); 3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void FETurbulence::fillRegionWorker(FillRegionParameters* parameters) 3505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 351591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch parameters->filter->fillRegion(parameters->pixelArray, *parameters->paintingData, parameters->startY, parameters->endY, parameters->baseFrequencyX, parameters->baseFrequencyY); 3525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 3535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 35453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)void FETurbulence::applySoftware() 3555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 3565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Uint8ClampedArray* pixelArray = createUnmultipliedImageResult(); 3575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!pixelArray) 3585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (absolutePaintRect().isEmpty()) { 3615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) pixelArray->zeroFill(); 3625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) PaintingData paintingData(m_seed, roundedIntSize(filterPrimitiveSubregion().size())); 3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) initPaint(paintingData); 3675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int optimalThreadNumber = (absolutePaintRect().width() * absolutePaintRect().height()) / s_minimalRectDimension; 3695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (optimalThreadNumber > 1) { 3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Initialize parallel jobs 371e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles) ParallelJobs<FillRegionParameters> parallelJobs(&FETurbulence::fillRegionWorker, optimalThreadNumber); 3725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fill the parameter array 3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int i = parallelJobs.numberOfJobs(); 3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (i > 1) { 3765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Split the job into "stepY"-sized jobs but there a few jobs that need to be slightly larger since 3775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // stepY * jobs < total size. These extras are handled by the remainder "jobsWithExtra". 3785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const int stepY = absolutePaintRect().height() / i; 3795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const int jobsWithExtra = absolutePaintRect().height() % i; 3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int startY = 0; 3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (; i > 0; --i) { 3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FillRegionParameters& params = parallelJobs.parameter(i-1); 3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) params.filter = this; 3855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) params.pixelArray = pixelArray; 3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) params.paintingData = &paintingData; 3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) params.startY = startY; 3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) startY += i < jobsWithExtra ? stepY + 1 : stepY; 3895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) params.endY = startY; 39009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) params.baseFrequencyX = m_baseFrequencyX; 39109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) params.baseFrequencyY = m_baseFrequencyY; 3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Execute parallel jobs 3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) parallelJobs.execute(); 3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 3975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 3995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Fallback to single threaded mode if there is no room for a new thread or the paint area is too small. 40109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) fillRegion(pixelArray, paintingData, 0, absolutePaintRect().height(), m_baseFrequencyX, m_baseFrequencyY); 4025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4045d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)SkShader* FETurbulence::createShader() 405521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){ 4065d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) const SkISize size = SkISize::Make(effectBoundaries().width(), effectBoundaries().height()); 407a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // Frequency should be scaled by page zoom, but not by primitiveUnits. 408a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // So we apply only the transform scale (as Filter::apply*Scale() do) 409a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // and not the target bounding box scale (as SVGFilter::apply*Scale() 410a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // would do). Note also that we divide by the scale since this is 411a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch // a frequency, not a period. 412a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch const AffineTransform& absoluteTransform = filter()->absoluteTransform(); 413a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch float baseFrequencyX = m_baseFrequencyX / absoluteTransform.a(); 414a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch float baseFrequencyY = m_baseFrequencyY / absoluteTransform.d(); 415521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) return (type() == FETURBULENCE_TYPE_FRACTALNOISE) ? 416591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkPerlinNoiseShader::CreateFractalNoise(SkFloatToScalar(baseFrequencyX), 417591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkFloatToScalar(baseFrequencyY), numOctaves(), SkFloatToScalar(seed()), 418521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) stitchTiles() ? &size : 0) : 4196f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch SkPerlinNoiseShader::CreateTurbulence(SkFloatToScalar(baseFrequencyX), 420591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SkFloatToScalar(baseFrequencyY), numOctaves(), SkFloatToScalar(seed()), 421521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) stitchTiles() ? &size : 0); 422521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)} 423521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 4243c9e4aeaee9f9b0a9a814da07bcb33319c7ea363Ben MurdochPassRefPtr<SkImageFilter> FETurbulence::createImageFilter(SkiaImageFilterBuilder* builder) 425521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles){ 4265d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) SkAutoTUnref<SkShader> shader(createShader()); 427bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) SkImageFilter::CropRect rect = getCropRect(builder->cropOffset()); 428bfe3590b1806e3ff18f46ee3af5d4b83078f305aTorne (Richard Coles) return adoptRef(SkRectShaderImageFilter::Create(shader, &rect)); 429521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)} 430521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) 4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static TextStream& operator<<(TextStream& ts, const TurbulenceType& type) 4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) switch (type) { 4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case FETURBULENCE_TYPE_UNKNOWN: 4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << "UNKNOWN"; 4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case FETURBULENCE_TYPE_TURBULENCE: 438521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles) ts << "TURBULENCE"; 4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) case FETURBULENCE_TYPE_FRACTALNOISE: 4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << "NOISE"; 4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) break; 4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ts; 4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextStream& FETurbulence::externalRepresentation(TextStream& ts, int indent) const 4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) writeIndent(ts, indent); 4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << "[feTurbulence"; 4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FilterEffect::externalRepresentation(ts); 4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ts << " type=\"" << type() << "\" " 4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "baseFrequency=\"" << baseFrequencyX() << ", " << baseFrequencyY() << "\" " 4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "seed=\"" << seed() << "\" " 4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "numOctaves=\"" << numOctaves() << "\" " 4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) << "stitchTiles=\"" << stitchTiles() << "\"]\n"; 4575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return ts; 4585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 460c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 461