summaryrefslogtreecommitdiffstats
path: root/chalk/colorspaces/wet/wetdreams/wetpaint.c
blob: c1ac0d0c2ab18360cee9ddbee7a34e2950b940d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101

#include <stdlib.h>
#include <math.h>
#include "wetpix.h"
#include "wetphysics.h"
#include "wetpaint.h"

/* This function is not entirely satisfactory - the compositing is basically
   opaque, and it really should do wet compositing. */
void
wet_dab(WetLayer * layer,
	WetPix * paint,
	double x, double y, double r, double pressure, double strength)
{
	double r_fringe;
	int x0, y0;
	int x1, y1;
	WetPix *wet_line;
	int xp, yp;
	double xx, yy, rr;
	double eff_height;
	double press, contact;
	WetPixDbl wet_tmp, wet_tmp2;

	r_fringe = r + 1;
	x0 = floor(x - r_fringe);
	y0 = floor(y - r_fringe);
	x1 = ceil(x + r_fringe);
	y1 = ceil(y + r_fringe);
	if (x0 < 0)
		x0 = 0;
	if (y0 < 0)
		y0 = 0;
	if (x1 >= layer->width)
		x1 = layer->width;
	if (y1 >= layer->height)
		y1 = layer->height;

	wet_line = layer->buf + y0 * layer->rowstride;
	for (yp = y0; yp < y1; yp++) {
		yy = (yp + 0.5 - y);
		yy *= yy;
		for (xp = x0; xp < x1; xp++) {
			xx = (xp + 0.5 - x);
			xx *= xx;
			rr = yy + xx;
			if (rr < r * r)
				press = pressure * 0.25;
			else
				press = -1;
			eff_height =
			    (wet_line[xp].h + wet_line[xp].w -
			     192) * (1.0 / 255);
			contact = (press + eff_height) * 0.2;
			if (contact > 0.5)
				contact =
				    1 - 0.5 * exp(-2.0 * contact - 1);
			if (contact > 0.0001) {
				int v;
				double rnd = rand() * (1.0 / RAND_MAX);

				v = wet_line[xp].rd;
				wet_line[xp].rd =
				    floor(v +
					  (paint->rd * strength -
					   v) * contact + rnd);
				v = wet_line[xp].rw;
				wet_line[xp].rw =
				    floor(v +
					  (paint->rw * strength -
					   v) * contact + rnd);
				v = wet_line[xp].gd;
				wet_line[xp].gd =
				    floor(v +
					  (paint->gd * strength -
					   v) * contact + rnd);
				v = wet_line[xp].gw;
				wet_line[xp].gw =
				    floor(v +
					  (paint->gw * strength -
					   v) * contact + rnd);
				v = wet_line[xp].bd;
				wet_line[xp].bd =
				    floor(v +
					  (paint->bd * strength -
					   v) * contact + rnd);
				v = wet_line[xp].bw;
				wet_line[xp].bw =
				    floor(v +
					  (paint->bw * strength -
					   v) * contact + rnd);
				v = wet_line[xp].w;
				wet_line[xp].w =
				    floor(v + (paint->w - v) * contact +
					  rnd);

			}
		}
		wet_line += layer->rowstride;
	}
}