nr-filter-turbulence.cpp revision 2350bae9c3f4a1f5f2963d2634a134fb7e611e98
/*
* feTurbulence filter primitive renderer
*
* Authors:
* World Wide Web Consortium <http://www.w3.org/>
* Felipe Corrêa da Silva Sanches <juca@members.fsf.org>
*
* This file has a considerable amount of code adapted from
* the W3C SVG filter specs, available at:
* http://www.w3.org/TR/SVG11/filters.html#feTurbulence
*
* W3C original code is licensed under the terms of
* the (GPL compatible) W3C® SOFTWARE NOTICE AND LICENSE:
*
* Copyright (C) 2007 authors
* Released under GNU GPL version 2 (or later), read the file 'COPYING' for more information
*/
#include "display/cairo-templates.h"
#include "display/cairo-utils.h"
#include "display/nr-filter.h"
#include "display/nr-filter-turbulence.h"
#include "display/nr-filter-units.h"
#include "display/nr-filter-utils.h"
#include "libnr/nr-rect-l.h"
#include <math.h>
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 BSize 0x100 // defined in the header
#define BM 0xff
#define PerlinN 0x1000
#define NM 0xfff
#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;
};
: XbaseFrequency(0),
YbaseFrequency(0),
numOctaves(1),
seed(0),
updated(false),
{
}
return new FilterTurbulence();
}
{
if (pix) {
delete pix;
}
}
}
}
void FilterTurbulence::set_seed(double s){
seed=s;
}
}
type=t;
}
void FilterTurbulence::set_updated(bool u){
updated=u;
}
void FilterTurbulence::render_area(NRPixBlock *pix, NR::IRect &full_area, FilterUnits const &units) {
#if 0
double point[2];
if (type==TURBULENCE_TURBULENCE){
}
}
} else {
}
}
}
#endif
}
TurbulenceInit((long)seed);
if (!pix){
pix = new NRPixBlock;
}
{
/* TODO: release-setup cycle not actually needed, if pixblock
* width and height don't change */
}
/* This limits pre-rendered turbulence to two megapixels. This is
* arbitary limit and could be something other, too.
* If bigger area is needed, visible area is rendered on demand. */
return;
}
updated=true;
updated_area = area;
}
{
if (!updated) {
TurbulenceInit((long)seed);
updated = true;
}
// TODO: convert this to ink_cairo_surface_synthesize
int w = cairo_image_surface_get_width(out);
int h = cairo_image_surface_get_height(out);
if (type == TURBULENCE_TURBULENCE) {
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
pt *= unit_trans;
r = premul_alpha(r, a);
g = premul_alpha(g, a);
b = premul_alpha(b, a);
ASSEMBLE_ARGB32(result, a,r,g,b)
}
}
} else {
// TURBULENCE_FRACTALNOISE
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
pt *= unit_trans;
r = premul_alpha(r, a);
g = premul_alpha(g, a);
b = premul_alpha(b, a);
ASSEMBLE_ARGB32(result, a,r,g,b)
}
}
}
}
#if 0
// TODO: could be faster - updated_area only has to be same size as area
if (!in) {
return 1;
}
if (pix_data) {
/* If pre-rendered output of whole filter area exists, just copy it. */
} else {
/* No pre-rendered output, render the required area here. */
}
return 0;
}
#endif
{
return lSeed;
}
{
long result;
return result;
}
{
double s;
int i, j, k;
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[j] = k;
}
for(i = 0; i < BSize + 2; i++)
{
for(k = 0; k < 4; k++)
for(j = 0; j < 2; j++)
}
}
double FilterTurbulence::TurbulenceNoise2(int nColorChannel, double vec[2], StitchInfo *pStitchInfo)
{
int i, j;
bx0 = (int)t;
rx0 = t - (int)t;
by0 = (int)t;
ry0 = t - (int)t;
// If stitching, adjust lattice points accordingly.
if(pStitchInfo != NULL)
{
}
i = uLatticeSelector[bx0];
j = uLatticeSelector[bx1];
}
{
// 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)
{
else
}
if(YbaseFrequency != 0.0)
{
else
}
// Set up TurbulenceInitial stitch values.
pStitchInfo = &stitch;
}
double fSum = 0.0f;
double vec[2];
double ratio = 1;
{
else
vec[0] *= 2;
ratio *= 2;
if(pStitchInfo != NULL)
{
// Update stitch values. Subtracting PerlinN before the multiplication and
// adding it afterward simplifies to subtracting it once.
}
}
return fSum;
}
} /* namespace Filters */
} /* namespace Inkscape */
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :