1 #define __NR_BLIT_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 */
12 #include "nr-pixops.h"
13 #include "nr-compose.h"
14 #include "nr-blit.h"
16 void
17 nr_blit_pixblock_pixblock_alpha (NRPixBlock *d, NRPixBlock *s, unsigned int alpha)
18 {
19 NRRectL clip;
20 unsigned char *dpx, *spx;
21 int dbpp, sbpp;
22 int w, h;
24 if (alpha == 0) return;
25 if (s->empty) return;
26 /* fixme: */
27 if (s->mode == NR_PIXBLOCK_MODE_A8) return;
28 /* fixme: */
29 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) return;
31 /*
32 * Possible variants as of now:
33 *
34 * 0. SRC EP - DST EP *
35 * 1. SRC EP - DST EN *
36 * 2. SRC EP - DST P *
37 * 3. SRC EP - DST N *
38 * 4. SRC EN - DST EP *
39 * 5. SRC EN - DST EN *
40 * 6. SRC EN - DST P *
41 * 7. SRC EN - DST N *
42 * 8. SRC P - DST EP *
43 * 9. SRC P - DST EN *
44 * A. SRC P - DST P *
45 * B. SRC P - DST N *
46 * C. SRC N - DST EP *
47 * D. SRC N - DST EN *
48 * E. SRC N - DST P *
49 * F. SRC N - DST N *
50 *
51 */
53 nr_rect_l_intersect (&clip, &d->area, &s->area);
55 if (nr_rect_l_test_empty (&clip)) return;
57 /* Pointers */
58 dbpp = NR_PIXBLOCK_BPP (d);
59 dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + dbpp * (clip.x0 - d->area.x0);
60 sbpp = NR_PIXBLOCK_BPP (s);
61 spx = NR_PIXBLOCK_PX (s) + (clip.y0 - s->area.y0) * s->rs + sbpp * (clip.x0 - s->area.x0);
62 w = clip.x1 - clip.x0;
63 h = clip.y1 - clip.y0;
65 switch (d->mode) {
66 case NR_PIXBLOCK_MODE_A8:
67 /* No rendering into alpha at moment */
68 break;
69 case NR_PIXBLOCK_MODE_R8G8B8:
70 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
71 nr_R8G8B8_R8G8B8_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
72 } else {
73 nr_R8G8B8_R8G8B8_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
74 }
75 break;
76 case NR_PIXBLOCK_MODE_R8G8B8A8P:
77 if (d->empty) {
78 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
79 /* Case 8 */
80 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
81 } else {
82 /* Case C */
83 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
84 }
85 } else {
86 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
87 /* case A */
88 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
89 } else {
90 /* case E */
91 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
92 }
93 }
94 break;
95 case NR_PIXBLOCK_MODE_R8G8B8A8N:
96 if (d->empty) {
97 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
98 /* Case 9 */
99 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
100 } else {
101 /* Case D */
102 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
103 }
104 } else {
105 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
106 /* case B */
107 nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P (dpx, w, h, d->rs, spx, s->rs, alpha);
108 } else {
109 /* case F */
110 nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (dpx, w, h, d->rs, spx, s->rs, alpha);
111 }
112 }
113 break;
114 }
115 }
117 void
118 nr_blit_pixblock_pixblock_mask (NRPixBlock *d, NRPixBlock *s, NRPixBlock *m)
119 {
120 NRRectL clip;
121 unsigned char *dpx, *spx, *mpx;
122 int dbpp, sbpp;
123 int w, h;
125 if (s->empty) return;
126 /* fixme: */
127 if (s->mode == NR_PIXBLOCK_MODE_A8) return;
128 /* fixme: */
129 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8) return;
131 /*
132 * Possible variants as of now:
133 *
134 * 0. SRC EP - DST EP *
135 * 1. SRC EP - DST EN *
136 * 2. SRC EP - DST P *
137 * 3. SRC EP - DST N *
138 * 4. SRC EN - DST EP *
139 * 5. SRC EN - DST EN *
140 * 6. SRC EN - DST P *
141 * 7. SRC EN - DST N *
142 * 8. SRC P - DST EP *
143 * 9. SRC P - DST EN *
144 * A. SRC P - DST P *
145 * B. SRC P - DST N *
146 * C. SRC N - DST EP *
147 * D. SRC N - DST EN *
148 * E. SRC N - DST P *
149 * F. SRC N - DST N *
150 *
151 */
153 nr_rect_l_intersect (&clip, &d->area, &s->area);
154 nr_rect_l_intersect (&clip, &clip, &m->area);
156 if (nr_rect_l_test_empty (&clip)) return;
158 /* Pointers */
159 dbpp = NR_PIXBLOCK_BPP (d);
160 dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + dbpp * (clip.x0 - d->area.x0);
161 sbpp = NR_PIXBLOCK_BPP (s);
162 spx = NR_PIXBLOCK_PX (s) + (clip.y0 - s->area.y0) * s->rs + sbpp * (clip.x0 - s->area.x0);
163 mpx = NR_PIXBLOCK_PX (m) + (clip.y0 - m->area.y0) * m->rs + 1 * (clip.x0 - m->area.x0);
164 w = clip.x1 - clip.x0;
165 h = clip.y1 - clip.y0;
167 switch (d->mode) {
168 case NR_PIXBLOCK_MODE_A8:
169 /* No rendering into alpha at moment */
170 break;
171 case NR_PIXBLOCK_MODE_R8G8B8:
172 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
173 nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
174 } else {
175 nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
176 }
177 break;
178 case NR_PIXBLOCK_MODE_R8G8B8A8P:
179 if (d->empty) {
180 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
181 /* Case 8 */
182 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
183 } else {
184 /* Case C */
185 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
186 }
187 } else {
188 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
189 /* case A */
190 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
191 } else {
192 /* case E */
193 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
194 }
195 }
196 break;
197 case NR_PIXBLOCK_MODE_R8G8B8A8N:
198 if (d->empty) {
199 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
200 /* Case 9 */
201 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
202 } else {
203 /* Case D */
204 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
205 }
206 } else {
207 if (s->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
208 /* case B */
209 nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
210 } else {
211 /* case F */
212 nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8 (dpx, w, h, d->rs, spx, s->rs, mpx, m->rs);
213 }
214 }
215 break;
216 }
217 }
219 void
220 nr_blit_pixblock_mask_rgba32 (NRPixBlock *d, NRPixBlock *m, unsigned long rgba)
221 {
222 if (!(rgba & 0xff)) return;
224 if (m) {
225 NRRectL clip;
226 unsigned char *dpx, *mpx;
227 int w, h;
229 if (m->mode != NR_PIXBLOCK_MODE_A8) return;
231 if (!nr_rect_l_test_intersect (&d->area, &m->area)) return;
233 nr_rect_l_intersect (&clip, &d->area, &m->area);
235 /* Pointers */
236 dpx = NR_PIXBLOCK_PX (d) + (clip.y0 - d->area.y0) * d->rs + NR_PIXBLOCK_BPP (d) * (clip.x0 - d->area.x0);
237 mpx = NR_PIXBLOCK_PX (m) + (clip.y0 - m->area.y0) * m->rs + (clip.x0 - m->area.x0);
238 w = clip.x1 - clip.x0;
239 h = clip.y1 - clip.y0;
241 if (d->empty) {
242 if (d->mode == NR_PIXBLOCK_MODE_R8G8B8) {
243 nr_R8G8B8_R8G8B8_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
244 } else if (d->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
245 nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
246 } else {
247 nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
248 }
249 d->empty = 0;
250 } else {
251 if (d->mode == NR_PIXBLOCK_MODE_R8G8B8) {
252 nr_R8G8B8_R8G8B8_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
253 } else if (d->mode == NR_PIXBLOCK_MODE_R8G8B8A8P) {
254 nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
255 } else {
256 nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (dpx, w, h, d->rs, mpx, m->rs, rgba);
257 }
258 }
259 } else {
260 unsigned int r, g, b, a;
261 int x, y;
262 r = NR_RGBA32_R (rgba);
263 g = NR_RGBA32_G (rgba);
264 b = NR_RGBA32_B (rgba);
265 a = NR_RGBA32_A (rgba);
266 for (y = d->area.y0; y < d->area.y1; y++) {
267 unsigned char *p;
268 p = NR_PIXBLOCK_PX (d) + (y - d->area.y0) * d->rs;
269 for (x = d->area.x0; x < d->area.x1; x++) {
270 unsigned int da;
271 switch (d->mode) {
272 case NR_PIXBLOCK_MODE_R8G8B8:
273 p[0] = NR_COMPOSEN11 (r, a, p[0]);
274 p[1] = NR_COMPOSEN11 (g, a, p[1]);
275 p[2] = NR_COMPOSEN11 (b, a, p[2]);
276 p += 3;
277 break;
278 case NR_PIXBLOCK_MODE_R8G8B8A8P:
279 p[0] = NR_COMPOSENPP (r, a, p[0], p[3]);
280 p[1] = NR_COMPOSENPP (g, a, p[1], p[3]);
281 p[2] = NR_COMPOSENPP (b, a, p[2], p[3]);
282 p[3] = (65025 - (255 - a) * (255 - p[3]) + 127) / 255;
283 p += 4;
284 break;
285 case NR_PIXBLOCK_MODE_R8G8B8A8N:
286 da = 65025 - (255 - a) * (255 - p[3]);
287 p[0] = NR_COMPOSENNN_A7 (r, a, p[0], p[3], da);
288 p[1] = NR_COMPOSENNN_A7 (g, a, p[1], p[3], da);
289 p[2] = NR_COMPOSENNN_A7 (b, a, p[2], p[3], da);
290 p[3] = (da + 127) / 255;
291 p += 4;
292 break;
293 default:
294 break;
295 }
296 }
297 }
298 }
299 }