1 #define __NR_PIXBLOCK_PATTERN_C__
3 /*
4 * Pixel buffer rendering library
5 *
6 * Authors:
7 * Lauris Kaplinski <lauris@kaplinski.com>
8 *
9 * This code is in public domain
10 */
13 #include "nr-pixops.h"
14 #include "nr-pixblock-pattern.h"
16 #define NR_NOISE_SIZE 1024
18 void
19 nr_pixblock_render_gray_noise (NRPixBlock *pb, NRPixBlock *mask)
20 {
21 static unsigned char *noise = NULL;
22 static unsigned int seed = 0;
23 unsigned int v;
24 NRRectL clip;
25 int x, y, bpp;
27 if (mask) {
28 if (mask->empty) return;
29 nr_rect_l_intersect (&clip, &pb->area, &mask->area);
30 if (nr_rect_l_test_empty (&clip)) return;
31 } else {
32 clip = pb->area;
33 }
35 if (!noise) {
36 int i;
37 noise = nr_new (unsigned char, NR_NOISE_SIZE);
38 for (i = 0; i < NR_NOISE_SIZE; i++) noise[i] = (rand () / (RAND_MAX >> 8)) & 0xff;
39 }
41 bpp = NR_PIXBLOCK_BPP (pb);
43 v = (rand () / (RAND_MAX >> 8)) & 0xff;
45 if (mask) {
46 for (y = clip.y0; y < clip.y1; y++) {
47 unsigned char *d, *m;
48 d = NR_PIXBLOCK_PX (pb) + (y - pb->area.y0) * pb->rs + (clip.x0 - pb->area.x0) * bpp;
49 m = NR_PIXBLOCK_PX (mask) + (y - mask->area.y0) * pb->rs + (clip.x0 - mask->area.x0);
50 for (x = clip.x0; x < clip.x1; x++) {
51 v = v ^ noise[seed];
52 switch (pb->mode) {
53 case NR_PIXBLOCK_MODE_A8:
54 d[0] = (65025 - (255 - m[0]) * (255 - d[0]) + 127) / 255;
55 break;
56 case NR_PIXBLOCK_MODE_R8G8B8:
57 d[0] = NR_COMPOSEN11 (v, m[0], d[0]);
58 d[1] = NR_COMPOSEN11 (v, m[0], d[1]);
59 d[2] = NR_COMPOSEN11 (v, m[0], d[2]);
60 break;
61 case NR_PIXBLOCK_MODE_R8G8B8A8N:
62 if (m[0] != 0) {
63 unsigned int ca;
64 ca = NR_A7 (m[0], d[3]);
65 d[0] = NR_COMPOSENNN_A7 (v, m[0], d[0], d[3], ca);
66 d[1] = NR_COMPOSENNN_A7 (v, m[0], d[1], d[3], ca);
67 d[2] = NR_COMPOSENNN_A7 (v, m[0], d[2], d[3], ca);
68 d[3] = (ca + 127) / 255;
69 }
70 break;
71 case NR_PIXBLOCK_MODE_R8G8B8A8P:
72 d[0] = NR_COMPOSENPP (v, m[0], d[0], d[3]);
73 d[1] = NR_COMPOSENPP (v, m[0], d[1], d[3]);
74 d[2] = NR_COMPOSENPP (v, m[0], d[2], d[3]);
75 d[3] = (NR_A7 (d[3], m[0]) + 127) / 255;
76 break;
77 default:
78 break;
79 }
80 d += bpp;
81 m += 1;
82 if (++seed >= NR_NOISE_SIZE) {
83 int i;
84 i = (rand () / (RAND_MAX / NR_NOISE_SIZE)) % NR_NOISE_SIZE;
85 noise[i] ^= v;
86 seed = i % (NR_NOISE_SIZE >> 2);
87 }
88 }
89 }
90 } else {
91 for (y = clip.y0; y < clip.y1; y++) {
92 unsigned char *d;
93 d = NR_PIXBLOCK_PX (pb) + (y - pb->area.y0) * pb->rs + (clip.x0 - pb->area.x0) * bpp;
94 for (x = clip.x0; x < clip.x1; x++) {
95 v = v ^ noise[seed];
96 switch (pb->mode) {
97 case NR_PIXBLOCK_MODE_A8:
98 d[0] = 255;
99 break;
100 case NR_PIXBLOCK_MODE_R8G8B8:
101 d[0] = v;
102 d[1] = v;
103 d[2] = v;
104 break;
105 case NR_PIXBLOCK_MODE_R8G8B8A8N:
106 case NR_PIXBLOCK_MODE_R8G8B8A8P:
107 d[0] = v;
108 d[1] = v;
109 d[2] = v;
110 d[3] = 255;
111 default:
112 break;
113 }
114 d += bpp;
115 if (++seed >= NR_NOISE_SIZE) {
116 int i;
117 i = (rand () / (RAND_MAX / NR_NOISE_SIZE)) % NR_NOISE_SIZE;
118 noise[i] ^= v;
119 seed = i % (NR_NOISE_SIZE >> 2);
120 }
121 }
122 }
123 }
125 pb->empty = 0;
126 }