summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2010-07-25 03:57:02 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2010-07-25 03:57:02 +0000
commit0e1ae7c0cb32c76e6349249299cb794a8800d0c8 (patch)
tree7d5bdf2cc5e0c334c6fb00a60bca32dc91cef9c1 /src
parentMinor cleanups (diff)
downloadinkscape-0e1ae7c0cb32c76e6349249299cb794a8800d0c8.tar.gz
inkscape-0e1ae7c0cb32c76e6349249299cb794a8800d0c8.zip
Improve turbulence renderer
(bzr r9508.1.35)
Diffstat (limited to 'src')
-rw-r--r--src/display/cairo-templates.h4
-rw-r--r--src/display/nr-filter-turbulence.cpp588
-rw-r--r--src/display/nr-filter-turbulence.h14
3 files changed, 322 insertions, 284 deletions
diff --git a/src/display/cairo-templates.h b/src/display/cairo-templates.h
index e0b1bfd98..88f3bf41a 100644
--- a/src/display/cairo-templates.h
+++ b/src/display/cairo-templates.h
@@ -644,9 +644,11 @@ private:
};*/
// Some helpers for pixel manipulation
-
G_GNUC_CONST inline gint32
pxclamp(gint32 v, gint32 low, gint32 high) {
+ // NOTE: it is possible to write a "branchless" clamping operation.
+ // However, it will be slower than this function, because the code below
+ // is compiled to conditional moves.
if (v < low) return low;
if (v > high) return high;
return v;
diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp
index de46b1565..d60c4f617 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -30,45 +30,282 @@
namespace Inkscape {
namespace Filters{
-/* Produces results in the range [1, 2**31 - 2].
-Algorithm is: r = (a * r) mod m
-where a = 16807 and m = 2**31 - 1 = 2147483647
-See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
-To test: the algorithm should produce the result 1043618065
-as the 10,000th generated number if the original seed is 1.
-*/
-#define RAND_m 2147483647 /* 2**31 - 1 */
-#define RAND_a 16807 /* 7**5; primitive root of m */
-#define RAND_q 127773 /* m / a */
-#define RAND_r 2836 /* m % a */
-//#define BSize 0x100 // defined in the header
-#define BM 0xff
-#define PerlinN 0x1000
-#define NP 12 /* 2^PerlinN */
-#define NM 0xfff
-#define s_curve(t) ( t * t * (3. - 2. * t) )
-#define turb_lerp(t, a, b) ( a + t * (b - a) )
-
-struct StitchInfo
-{
- int nWidth; // How much to subtract to wrap for stitching.
- int nHeight;
- int nWrapX; // Minimum value to wrap.
- int nWrapY;
+class TurbulenceGenerator {
+public:
+ TurbulenceGenerator()
+ : _wrapx(0)
+ , _wrapy(0)
+ , _wrapw(0)
+ , _wraph(0)
+ , _inited(false)
+ {}
+
+ void init(long seed, Geom::Rect const &tile, Geom::Point const &freq, bool stitch,
+ bool fractalnoise, int octaves)
+ {
+ // setup random number generator
+ _setupSeed(seed);
+
+ // set values
+ _tile = tile;
+ _baseFreq = freq;
+ _stitchTiles = stitch;
+ _fractalnoise = fractalnoise;
+ _octaves = octaves;
+
+ int i;
+ for (int k = 0; k < 4; ++k) {
+ for (i = 0; i < BSize; ++i) {
+ _latticeSelector[i] = i;
+
+ _gradient[i][k][0] = static_cast<double>(_random() % (BSize*2) - BSize) / BSize;
+ _gradient[i][k][1] = static_cast<double>(_random() % (BSize*2) - BSize) / BSize;
+
+ // normalize gradient
+ double s = hypot(_gradient[i][k][0], _gradient[i][k][1]);
+ _gradient[i][k][0] /= s;
+ _gradient[i][k][1] /= s;
+ }
+ }
+ while (--i) {
+ // shuffle lattice selectors
+ int j = _random() % BSize;
+ std::swap(_latticeSelector[i], _latticeSelector[j]);
+ }
+
+ // fill out the remaining part of the gradient
+ for (i = 0; i < BSize + 2; ++i)
+ {
+ _latticeSelector[BSize + i] = _latticeSelector[i];
+
+ for(int k = 0; k < 4; ++k) {
+ _gradient[BSize + i][k][0] = _gradient[i][k][0];
+ _gradient[BSize + i][k][1] = _gradient[i][k][1];
+ }
+ }
+
+ // When stitching tiled turbulence, the frequencies must be adjusted
+ // so that the tile borders will be continuous.
+ if (_stitchTiles) {
+ if (_baseFreq[Geom::X] != 0.0)
+ {
+ double freq = _baseFreq[Geom::X];
+ double lo = floor(_tile.width() * freq) / _tile.width();
+ double hi = ceil(_tile.width() * freq) / _tile.width();
+ _baseFreq[Geom::X] = freq / lo < hi / freq ? lo : hi;
+ }
+ if (_baseFreq[Geom::Y] != 0.0)
+ {
+ double freq = _baseFreq[Geom::Y];
+ double lo = floor(_tile.height() * freq) / _tile.height();
+ double hi = ceil(_tile.height() * freq) / _tile.height();
+ _baseFreq[Geom::Y] = freq / lo < hi / freq ? lo : hi;
+ }
+
+ _wrapw = _tile.width() * _baseFreq[Geom::X] + 0.5;
+ _wraph = _tile.height() * _baseFreq[Geom::Y] + 0.5;
+ _wrapx = _tile.left() * _baseFreq[Geom::X] + PerlinOffset + _wrapw;
+ _wrapy = _tile.top() * _baseFreq[Geom::Y] + PerlinOffset + _wraph;
+ }
+ _inited = true;
+ }
+
+ G_GNUC_PURE
+ guint32 turbulencePixel(Geom::Point const &p) const {
+ int wrapx = _wrapx, wrapy = _wrapy, wrapw = _wrapw, wraph = _wraph;
+
+ double pixel[4];
+ double x = p[Geom::X] * _baseFreq[Geom::X];
+ double y = p[Geom::Y] * _baseFreq[Geom::Y];
+ double ratio = 1.0;
+
+ for (int k = 0; k < 4; ++k)
+ pixel[k] = 0.0;
+
+ for(int octave = 0; octave < _octaves; ++octave)
+ {
+ double tx = x + PerlinOffset;
+ double bx = floor(tx);
+ double rx0 = tx - bx, rx1 = rx0 - 1.0;
+ int bx0 = bx, bx1 = bx0 + 1;
+
+ double ty = y + PerlinOffset;
+ double by = floor(ty);
+ double ry0 = ty - by, ry1 = ry0 - 1.0;
+ int by0 = by, by1 = by0 + 1;
+
+ if (_stitchTiles) {
+ if (bx0 >= wrapx) bx0 -= wrapw;
+ if (bx1 >= wrapx) bx1 -= wrapw;
+ if (by0 >= wrapy) by0 -= wraph;
+ if (by1 >= wrapy) by1 -= wraph;
+ }
+ bx0 &= BMask;
+ bx1 &= BMask;
+ by0 &= BMask;
+ by1 &= BMask;
+
+ int i = _latticeSelector[bx0];
+ int j = _latticeSelector[bx1];
+ int b00 = _latticeSelector[i + by0];
+ int b01 = _latticeSelector[i + by1];
+ int b10 = _latticeSelector[j + by0];
+ int b11 = _latticeSelector[j + by1];
+
+ double sx = _scurve(rx0);
+ double sy = _scurve(ry0);
+
+ double result[4];
+ // channel numbering: R=0, G=1, B=2, A=3
+ for (int k = 0; k < 4; ++k) {
+ double const *qxa = _gradient[b00][k];
+ double const *qxb = _gradient[b10][k];
+ double a = _lerp(sx, rx0 * qxa[0] + ry0 * qxa[1],
+ rx1 * qxb[0] + ry0 * qxb[1]);
+ double const *qya = _gradient[b01][k];
+ double const *qyb = _gradient[b11][k];
+ double b = _lerp(sx, rx0 * qya[0] + ry1 * qya[1],
+ rx1 * qyb[0] + ry1 * qyb[1]);
+ result[k] = _lerp(sy, a, b);
+ }
+
+ if (_fractalnoise) {
+ for (int k = 0; k < 4; ++k)
+ pixel[k] += result[k] / ratio;
+ } else {
+ for (int k = 0; k < 4; ++k)
+ pixel[k] += fabs(result[k]) / ratio;
+ }
+
+ x *= 2;
+ y *= 2;
+ ratio *= 2;
+
+ if(_stitchTiles)
+ {
+ // Update stitch values. Subtracting PerlinOffset before the multiplication and
+ // adding it afterward simplifies to subtracting it once.
+ wrapw *= 2;
+ wraph *= 2;
+ wrapx = wrapx*2 - PerlinOffset;
+ wrapy = wrapy*2 - PerlinOffset;
+ }
+ }
+
+ if (_fractalnoise) {
+ guint32 r = CLAMP_D_TO_U8((pixel[0]*255.0 + 255.0) / 2);
+ guint32 g = CLAMP_D_TO_U8((pixel[1]*255.0 + 255.0) / 2);
+ guint32 b = CLAMP_D_TO_U8((pixel[2]*255.0 + 255.0) / 2);
+ guint32 a = CLAMP_D_TO_U8((pixel[3]*255.0 + 255.0) / 2);
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+ ASSEMBLE_ARGB32(pxout, a,r,g,b);
+ return pxout;
+ } else {
+ guint32 r = CLAMP_D_TO_U8(pixel[0]*255.0);
+ guint32 g = CLAMP_D_TO_U8(pixel[1]*255.0);
+ guint32 b = CLAMP_D_TO_U8(pixel[2]*255.0);
+ guint32 a = CLAMP_D_TO_U8(pixel[3]*255.0);
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+ ASSEMBLE_ARGB32(pxout, a,r,g,b);
+ return pxout;
+ }
+ }
+
+ //G_GNUC_PURE
+ /*guint32 turbulencePixel(Geom::Point const &p) const {
+ if (!_fractalnoise) {
+ guint32 r = CLAMP_D_TO_U8(turbulence(0, p)*255.0);
+ guint32 g = CLAMP_D_TO_U8(turbulence(1, p)*255.0);
+ guint32 b = CLAMP_D_TO_U8(turbulence(2, p)*255.0);
+ guint32 a = CLAMP_D_TO_U8(turbulence(3, p)*255.0);
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+ ASSEMBLE_ARGB32(pxout, a,r,g,b);
+ return pxout;
+ } else {
+ guint32 r = CLAMP_D_TO_U8((turbulence(0, p)*255.0 + 255.0) / 2);
+ guint32 g = CLAMP_D_TO_U8((turbulence(1, p)*255.0 + 255.0) / 2);
+ guint32 b = CLAMP_D_TO_U8((turbulence(2, p)*255.0 + 255.0) / 2);
+ guint32 a = CLAMP_D_TO_U8((turbulence(3, p)*255.0 + 255.0) / 2);
+ r = premul_alpha(r, a);
+ g = premul_alpha(g, a);
+ b = premul_alpha(b, a);
+ ASSEMBLE_ARGB32(pxout, a,r,g,b);
+ return pxout;
+ }
+ }*/
+
+ bool ready() const { return _inited; }
+ void dirty() { _inited = false; }
+
+private:
+ void _setupSeed(long seed) {
+ _seed = seed;
+ if (_seed <= 0) _seed = -(_seed % (RAND_m - 1)) + 1;
+ if (_seed > RAND_m - 1) _seed = RAND_m - 1;
+ }
+ long _random() {
+ /* Produces results in the range [1, 2**31 - 2].
+ * Algorithm is: r = (a * r) mod m
+ * where a = 16807 and m = 2**31 - 1 = 2147483647
+ * See [Park & Miller], CACM vol. 31 no. 10 p. 1195, Oct. 1988
+ * To test: the algorithm should produce the result 1043618065
+ * as the 10,000th generated number if the original seed is 1. */
+ _seed = RAND_a * (_seed % RAND_q) - RAND_r * (_seed / RAND_q);
+ if (_seed <= 0) _seed += RAND_m;
+ return _seed;
+ }
+ static inline double _scurve(double t) {
+ return t * t * (3.0 - 2.0*t);
+ }
+ static inline double _lerp(double t, double a, double b) {
+ return a + t * (b-a);
+ }
+
+ // random number generator constants
+ static long const
+ RAND_m = 2147483647, // 2**31 - 1
+ RAND_a = 16807, // 7**5; primitive root of m
+ RAND_q = 127773, // m / a
+ RAND_r = 2836; // m % a
+
+ // other constants
+ static int const
+ BSize = 0x100,
+ BMask = 0xff;
+ static double const
+ PerlinOffset = 4096.0;
+
+ Geom::Rect _tile;
+ Geom::Point _baseFreq;
+ int _latticeSelector[2*BSize + 2];
+ double _gradient[2*BSize + 2][4][2];
+ long _seed;
+ int _octaves;
+ bool _stitchTiles;
+ int _wrapx, _wrapy, _wrapw, _wraph;
+ bool _inited;
+ bool _fractalnoise;
};
FilterTurbulence::FilterTurbulence()
-: XbaseFrequency(0),
- YbaseFrequency(0),
- numOctaves(1),
- seed(0),
- updated(false),
- updated_area(NR::IPoint(), NR::IPoint()),
- pix(NULL),
- fTileWidth(10), //guessed
- fTileHeight(10), //guessed
- fTileX(1), //guessed
- fTileY(1) //guessed
+ : gen(new TurbulenceGenerator())
+ , XbaseFrequency(0)
+ , YbaseFrequency(0)
+ , numOctaves(1)
+ , seed(0)
+ , updated(false)
+ , updated_area(NR::IPoint(), NR::IPoint())
+ , pix(NULL)
+ , fTileWidth(10) //guessed
+ , fTileHeight(10) //guessed
+ , fTileX(1) //guessed
+ , fTileY(1) //guessed
{
}
@@ -78,6 +315,8 @@ FilterPrimitive * FilterTurbulence::create() {
FilterTurbulence::~FilterTurbulence()
{
+ delete gen;
+
if (pix) {
nr_pixblock_release(pix);
delete pix;
@@ -87,26 +326,30 @@ FilterTurbulence::~FilterTurbulence()
void FilterTurbulence::set_baseFrequency(int axis, double freq){
if (axis==0) XbaseFrequency=freq;
if (axis==1) YbaseFrequency=freq;
+ gen->dirty();
}
void FilterTurbulence::set_numOctaves(int num){
- numOctaves=num;
+ numOctaves = num;
+ gen->dirty();
}
void FilterTurbulence::set_seed(double s){
- seed=s;
+ seed = s;
+ gen->dirty();
}
void FilterTurbulence::set_stitchTiles(bool st){
- stitchTiles=st;
+ stitchTiles = st;
+ gen->dirty();
}
void FilterTurbulence::set_type(FilterTurbulenceType t){
- type=t;
+ type = t;
+ gen->dirty();
}
void FilterTurbulence::set_updated(bool u){
- updated=u;
}
void FilterTurbulence::render_area(NRPixBlock *pix, NR::IRect &full_area, FilterUnits const &units) {
@@ -160,7 +403,7 @@ void FilterTurbulence::update_pixbuffer(NR::IRect &area, FilterUnits const &unit
int bbox_x1 = area.max()[NR::X];
int bbox_y1 = area.max()[NR::Y];
- TurbulenceInit((long)seed);
+ //TurbulenceInit((long)seed);
if (!pix){
pix = new NRPixBlock;
@@ -192,67 +435,41 @@ void FilterTurbulence::update_pixbuffer(NR::IRect &area, FilterUnits const &unit
updated_area = area;
}
+struct Turbulence {
+ Turbulence(TurbulenceGenerator const &gen, Geom::Matrix const &trans, int x0, int y0)
+ : _gen(gen)
+ , _trans(trans)
+ , _x0(x0), _y0(y0)
+ {}
+ guint32 operator()(int x, int y) {
+ Geom::Point point(x + _x0, y + _y0);
+ point *= _trans;
+ return _gen.turbulencePixel(point);
+ }
+private:
+ TurbulenceGenerator const &_gen;
+ Geom::Matrix _trans;
+ int _x0, _y0;
+};
+
void FilterTurbulence::render_cairo(FilterSlot &slot)
{
cairo_surface_t *input = slot.getcairo(_input);
cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);
- if (!updated) {
- TurbulenceInit((long)seed);
- updated = true;
+ if (!gen->ready()) {
+ Geom::Point ta(fTileX, fTileY);
+ Geom::Point tb(fTileX + fTileWidth, fTileY + fTileHeight);
+ gen->init(seed, Geom::Rect(ta, tb),
+ Geom::Point(XbaseFrequency, YbaseFrequency), stitchTiles,
+ type == TURBULENCE_FRACTALNOISE, numOctaves);
}
// TODO: convert this to ink_cairo_surface_synthesize
Geom::Matrix unit_trans = slot.get_units().get_matrix_primitiveunits2pb().inverse();
NRRectL const &slot_area = slot.get_slot_area();
- int w = cairo_image_surface_get_width(out);
- int h = cairo_image_surface_get_height(out);
- int stride = cairo_image_surface_get_stride(out);
- unsigned char *data = cairo_image_surface_get_data(out);
-
- if (type == TURBULENCE_TURBULENCE) {
- for (int i = 0; i < h; ++i) {
- guint32 *out_p = reinterpret_cast<guint32*>(data + i*stride);
- for (int j = 0; j < w; ++j) {
- Geom::Point pt(slot_area.x0 + j, slot_area.y0 + i);
- pt *= unit_trans;
-
- guint32 r = CLAMP_D_TO_U8(turbulence(0, pt)*255);
- guint32 g = CLAMP_D_TO_U8(turbulence(1, pt)*255);
- guint32 b = CLAMP_D_TO_U8(turbulence(2, pt)*255);
- guint32 a = CLAMP_D_TO_U8(turbulence(3, pt)*255);
-
- r = premul_alpha(r, a);
- g = premul_alpha(g, a);
- b = premul_alpha(b, a);
-
- ASSEMBLE_ARGB32(result, a,r,g,b)
- *out_p++ = result;
- }
- }
- } else {
- // TURBULENCE_FRACTALNOISE
- for (int i = 0; i < h; ++i) {
- guint32 *out_p = reinterpret_cast<guint32*>(data + i*stride);
- for (int j = 0; j < w; ++j) {
- Geom::Point pt(slot_area.x0 + j, slot_area.y0 + i);
- pt *= unit_trans;
-
- guint32 r = CLAMP_D_TO_U8((turbulence(0, pt)*255 + 255)/2);
- guint32 g = CLAMP_D_TO_U8((turbulence(1, pt)*255 + 255)/2);
- guint32 b = CLAMP_D_TO_U8((turbulence(2, pt)*255 + 255)/2);
- guint32 a = CLAMP_D_TO_U8((turbulence(3, pt)*255 + 255)/2);
-
- r = premul_alpha(r, a);
- g = premul_alpha(g, a);
- b = premul_alpha(b, a);
-
- ASSEMBLE_ARGB32(result, a,r,g,b)
- *out_p++ = result;
- }
- }
- }
+ ink_cairo_surface_synthesize(out, Turbulence(*gen, unit_trans, slot_area.x0, slot_area.y0));
cairo_surface_mark_dirty(out);
@@ -260,193 +477,6 @@ void FilterTurbulence::render_cairo(FilterSlot &slot)
cairo_surface_destroy(out);
}
-#if 0
-int FilterTurbulence::render(FilterSlot &slot, FilterUnits const &units) {
- NR::IRect area = units.get_pixblock_filterarea_paraller();
- // TODO: could be faster - updated_area only has to be same size as area
- if (!updated || updated_area != area) update_pixbuffer(area, units);
-
- NRPixBlock *in = slot.get(_input);
- if (!in) {
- g_warning("Missing source image for feTurbulence (in=%d)", _input);
- return 1;
- }
-
- NRPixBlock *out = new NRPixBlock;
- int x0 = in->area.x0, y0 = in->area.y0;
- int x1 = in->area.x1, y1 = in->area.y1;
- nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N, x0, y0, x1, y1, true);
-
- if (pix_data) {
- /* If pre-rendered output of whole filter area exists, just copy it. */
- nr_blit_pixblock_pixblock(out, pix);
- } else {
- /* No pre-rendered output, render the required area here. */
- render_area(out, area, units);
- }
-
- out->empty = FALSE;
- slot.set(_output, out);
- return 0;
-}
-#endif
-
-long FilterTurbulence::Turbulence_setup_seed(long lSeed)
-{
- if (lSeed <= 0) lSeed = -(lSeed % (RAND_m - 1)) + 1;
- if (lSeed > RAND_m - 1) lSeed = RAND_m - 1;
- return lSeed;
-}
-
-long FilterTurbulence::TurbulenceRandom(long lSeed)
-{
- long result;
- result = RAND_a * (lSeed % RAND_q) - RAND_r * (lSeed / RAND_q);
- if (result <= 0) result += RAND_m;
- return result;
-}
-
-void FilterTurbulence::TurbulenceInit(long lSeed)
-{
- double s;
- int i, j, k;
- lSeed = Turbulence_setup_seed(lSeed);
- for(k = 0; k < 4; k++)
- {
- for(i = 0; i < BSize; i++)
- {
- uLatticeSelector[i] = i;
- for (j = 0; j < 2; j++)
- fGradient[k][i][j] = (double)(((lSeed = TurbulenceRandom(lSeed)) % (BSize + BSize)) - BSize) / BSize;
- s = double(sqrt(fGradient[k][i][0] * fGradient[k][i][0] + fGradient[k][i][1] * fGradient[k][i][1]));
- fGradient[k][i][0] /= s;
- fGradient[k][i][1] /= s;
- }
- }
- while(--i)
- {
- k = uLatticeSelector[i];
- uLatticeSelector[i] = uLatticeSelector[j = (lSeed = TurbulenceRandom(lSeed)) % BSize];
- uLatticeSelector[j] = k;
- }
- for(i = 0; i < BSize + 2; i++)
- {
- uLatticeSelector[BSize + i] = uLatticeSelector[i];
- for(k = 0; k < 4; k++)
- for(j = 0; j < 2; j++)
- fGradient[k][BSize + i][j] = fGradient[k][i][j];
- }
-}
-
-double FilterTurbulence::TurbulenceNoise2(int nColorChannel, double vec[2], StitchInfo *pStitchInfo)
-{
- int bx0, bx1, by0, by1, b00, b10, b01, b11;
- double rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
- int i, j;
- t = vec[0] + PerlinN;
- bx0 = (int)t;
- bx1 = bx0+1;
- rx0 = t - (int)t;
- rx1 = rx0 - 1.0f;
- t = vec[1] + PerlinN;
- by0 = (int)t;
- by1 = by0+1;
- ry0 = t - (int)t;
- ry1 = ry0 - 1.0f;
- // If stitching, adjust lattice points accordingly.
- if(pStitchInfo != NULL)
- {
- if(bx0 >= pStitchInfo->nWrapX)
- bx0 -= pStitchInfo->nWidth;
- if(bx1 >= pStitchInfo->nWrapX)
- bx1 -= pStitchInfo->nWidth;
- if(by0 >= pStitchInfo->nWrapY)
- by0 -= pStitchInfo->nHeight;
- if(by1 >= pStitchInfo->nWrapY)
- by1 -= pStitchInfo->nHeight;
- }
- bx0 &= BM;
- bx1 &= BM;
- by0 &= BM;
- by1 &= BM;
- i = uLatticeSelector[bx0];
- j = uLatticeSelector[bx1];
- b00 = uLatticeSelector[i + by0];
- b10 = uLatticeSelector[j + by0];
- b01 = uLatticeSelector[i + by1];
- b11 = uLatticeSelector[j + by1];
- sx = double(s_curve(rx0));
- sy = double(s_curve(ry0));
- q = fGradient[nColorChannel][b00]; u = rx0 * q[0] + ry0 * q[1];
- q = fGradient[nColorChannel][b10]; v = rx1 * q[0] + ry0 * q[1];
- a = turb_lerp(sx, u, v);
- q = fGradient[nColorChannel][b01]; u = rx0 * q[0] + ry1 * q[1];
- q = fGradient[nColorChannel][b11]; v = rx1 * q[0] + ry1 * q[1];
- b = turb_lerp(sx, u, v);
- return turb_lerp(sy, a, b);
-}
-
-double FilterTurbulence::turbulence(int nColorChannel, Geom::Point const &point)
-{
- StitchInfo stitch;
- StitchInfo *pStitchInfo = NULL; // Not stitching when NULL.
- // Adjust the base frequencies if necessary for stitching.
- if(stitchTiles)
- {
- // When stitching tiled turbulence, the frequencies must be adjusted
- // so that the tile borders will be continuous.
- if(XbaseFrequency != 0.0)
- {
- double fLoFreq = double(floor(fTileWidth * XbaseFrequency)) / fTileWidth;
- double fHiFreq = double(ceil(fTileWidth * XbaseFrequency)) / fTileWidth;
- if(XbaseFrequency / fLoFreq < fHiFreq / XbaseFrequency)
- XbaseFrequency = fLoFreq;
- else
- XbaseFrequency = fHiFreq;
- }
- if(YbaseFrequency != 0.0)
- {
- double fLoFreq = double(floor(fTileHeight * YbaseFrequency)) / fTileHeight;
- double fHiFreq = double(ceil(fTileHeight * YbaseFrequency)) / fTileHeight;
- if(YbaseFrequency / fLoFreq < fHiFreq / YbaseFrequency)
- YbaseFrequency = fLoFreq;
- else
- YbaseFrequency = fHiFreq;
- }
- // Set up TurbulenceInitial stitch values.
- pStitchInfo = &stitch;
- stitch.nWidth = int(fTileWidth * XbaseFrequency + 0.5f);
- stitch.nWrapX = int(fTileX * XbaseFrequency + PerlinN + stitch.nWidth);
- stitch.nHeight = int(fTileHeight * YbaseFrequency + 0.5f);
- stitch.nWrapY = int(fTileY * YbaseFrequency + PerlinN + stitch.nHeight);
- }
- double fSum = 0.0f;
- double vec[2];
- vec[0] = point[Geom::X] * XbaseFrequency;
- vec[1] = point[Geom::Y] * YbaseFrequency;
- double ratio = 1;
- for(int nOctave = 0; nOctave < numOctaves; nOctave++)
- {
- if(type==TURBULENCE_FRACTALNOISE)
- fSum += double(TurbulenceNoise2(nColorChannel, vec, pStitchInfo) / ratio);
- else
- fSum += double(fabs(TurbulenceNoise2(nColorChannel, vec, pStitchInfo)) / ratio);
- vec[0] *= 2;
- vec[1] *= 2;
- ratio *= 2;
- if(pStitchInfo != NULL)
- {
- // Update stitch values. Subtracting PerlinN before the multiplication and
- // adding it afterward simplifies to subtracting it once.
- stitch.nWidth *= 2;
- stitch.nWrapX = 2 * stitch.nWrapX - PerlinN;
- stitch.nHeight *= 2;
- stitch.nWrapY = 2 * stitch.nWrapY - PerlinN;
- }
- }
- return fSum;
-}
-
} /* namespace Filters */
} /* namespace Inkscape */
diff --git a/src/display/nr-filter-turbulence.h b/src/display/nr-filter-turbulence.h
index 53ea5dd39..b2bc3a185 100644
--- a/src/display/nr-filter-turbulence.h
+++ b/src/display/nr-filter-turbulence.h
@@ -38,7 +38,8 @@ enum FilterTurbulenceType {
struct StitchInfo;
-#define BSize 0x100
+//#define BSize 0x100
+class TurbulenceGenerator;
class FilterTurbulence : public FilterPrimitive {
public:
@@ -58,12 +59,16 @@ public:
void set_updated(bool u);
private:
+ TurbulenceGenerator *gen;
+
+ void turbulenceInit(long seed);
+/*
long Turbulence_setup_seed(long lSeed);
long TurbulenceRandom(long lSeed);
void TurbulenceInit(long lSeed);
double TurbulenceNoise2(int nColorChannel, double vec[2], StitchInfo *pStitchInfo);
double turbulence(int nColorChannel, Geom::Point const &point);
-
+*/
double XbaseFrequency, YbaseFrequency;
int numOctaves;
double seed;
@@ -74,14 +79,15 @@ private:
NRPixBlock *pix;
unsigned char *pix_data;
- int uLatticeSelector[BSize + BSize + 2];
- double fGradient[4][BSize + BSize + 2][2];
+ //int uLatticeSelector[BSize + BSize + 2];
+ //double fGradient[4][BSize + BSize + 2][2];
double fTileWidth;
double fTileHeight;
double fTileX;
double fTileY;
+
};
} /* namespace Filters */