Code

03bd688ba0dbb62933eabb6bc8a737973365c057
[inkscape.git] / src / libnr / nr-pixblock-pattern.cpp
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;