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 <glib/gmem.h>
14 #include "nr-pixops.h"
15 #include "nr-pixblock-pattern.h"
17 #define NR_NOISE_SIZE 1024
19 void
20 nr_pixblock_render_gray_noise (NRPixBlock *pb, NRPixBlock *mask)
21 {
22 static unsigned char *noise = NULL;
23 static unsigned int seed = 0;
24 unsigned int v;
25 NRRectL clip;
26 int x, y, bpp;
28 if (mask) {
29 if (mask->empty) return;
30 nr_rect_l_intersect (&clip, &pb->area, &mask->area);
31 if (nr_rect_l_test_empty (&clip)) return;
32 } else {
33 clip = pb->area;
34 }
36 if (!noise) {
37 int i;
38 noise = g_new (unsigned char, NR_NOISE_SIZE);
39 for (i = 0; i < NR_NOISE_SIZE; i++) noise[i] = (rand () / (RAND_MAX >> 8)) & 0xff;
40 }
42 bpp = NR_PIXBLOCK_BPP (pb);
44 v = (rand () / (RAND_MAX >> 8)) & 0xff;
46 if (mask) {
47 for (y = clip.y0; y < clip.y1; y++) {
48 unsigned char *d, *m;
49 d = NR_PIXBLOCK_PX (pb) + (y - pb->area.y0) * pb->rs + (clip.x0 - pb->area.x0) * bpp;
50 m = NR_PIXBLOCK_PX (mask) + (y - mask->area.y0) * pb->rs + (clip.x0 - mask->area.x0);
51 for (x = clip.x0; x < clip.x1; x++) {
52 v = v ^ noise[seed];
53 switch (pb->mode) {
54 case NR_PIXBLOCK_MODE_A8:
55 d[0] = NR_COMPOSEA_111(m[0], d[0]);
56 break;
57 case NR_PIXBLOCK_MODE_R8G8B8:
58 d[0] = NR_COMPOSEN11_1111 (v, m[0], d[0]);
59 d[1] = NR_COMPOSEN11_1111 (v, m[0], d[1]);
60 d[2] = NR_COMPOSEN11_1111 (v, m[0], d[2]);
61 break;
62 case NR_PIXBLOCK_MODE_R8G8B8A8N:
63 if (m[0] != 0) {
64 unsigned int ca;
65 ca = NR_COMPOSEA_112(m[0], d[3]);
66 d[0] = NR_COMPOSENNN_111121 (v, m[0], d[0], d[3], ca);
67 d[1] = NR_COMPOSENNN_111121 (v, m[0], d[1], d[3], ca);
68 d[2] = NR_COMPOSENNN_111121 (v, m[0], d[2], d[3], ca);
69 d[3] = NR_NORMALIZE_21(ca);
70 }
71 break;
72 case NR_PIXBLOCK_MODE_R8G8B8A8P:
73 d[0] = NR_COMPOSENPP_1111 (v, m[0], d[0]);
74 d[1] = NR_COMPOSENPP_1111 (v, m[0], d[1]);
75 d[2] = NR_COMPOSENPP_1111 (v, m[0], d[2]);
76 d[3] = NR_COMPOSEA_111(d[3], m[0]);
77 break;
78 default:
79 break;
80 }
81 d += bpp;
82 m += 1;
83 if (++seed >= NR_NOISE_SIZE) {
84 int i;
85 i = (rand () / (RAND_MAX / NR_NOISE_SIZE)) % NR_NOISE_SIZE;
86 noise[i] ^= v;
87 seed = i % (NR_NOISE_SIZE >> 2);
88 }
89 }
90 }
91 } else {
92 for (y = clip.y0; y < clip.y1; y++) {
93 unsigned char *d;
94 d = NR_PIXBLOCK_PX (pb) + (y - pb->area.y0) * pb->rs + (clip.x0 - pb->area.x0) * bpp;
95 for (x = clip.x0; x < clip.x1; x++) {
96 v = v ^ noise[seed];
97 switch (pb->mode) {
98 case NR_PIXBLOCK_MODE_A8:
99 d[0] = 255;
100 break;
101 case NR_PIXBLOCK_MODE_R8G8B8:
102 d[0] = v;
103 d[1] = v;
104 d[2] = v;
105 break;
106 case NR_PIXBLOCK_MODE_R8G8B8A8N:
107 case NR_PIXBLOCK_MODE_R8G8B8A8P:
108 d[0] = v;
109 d[1] = v;
110 d[2] = v;
111 d[3] = 255;
112 default:
113 break;
114 }
115 d += bpp;
116 if (++seed >= NR_NOISE_SIZE) {
117 int i;
118 i = (rand () / (RAND_MAX / NR_NOISE_SIZE)) % NR_NOISE_SIZE;
119 noise[i] ^= v;
120 seed = i % (NR_NOISE_SIZE >> 2);
121 }
122 }
123 }
124 }
126 pb->empty = 0;
127 }