1 #define __NR_COMPOSE_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 #ifdef HAVE_CONFIG_H
13 # include "config.h"
14 #endif
16 #include <string.h>
17 #include "nr-pixops.h"
19 #ifdef WITH_MMX
20 /* fixme: */
21 #ifdef __cplusplus
22 extern "C" {
23 #endif /* __cplusplus */
24 int nr_have_mmx (void);
25 void nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned char *c);
26 void nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned char *c);
27 void nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha);
28 #define NR_PIXOPS_MMX nr_have_mmx ()
29 #ifdef __cplusplus
30 }
31 #endif /* __cplusplus */
32 #endif
34 void
35 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
36 {
37 int r, c;
39 for (r = 0; r < h; r++) {
40 if (alpha == 0) {
41 memset (px, 0x0, 4 * w);
42 } else if (alpha == 255) {
43 memcpy (px, spx, 4 * w);
44 } else {
45 const unsigned char *s;
46 unsigned char *d;
47 d = px;
48 s = spx;
49 for (c = 0; c < w; c++) {
50 *d++ = *s++;
51 *d++ = *s++;
52 *d++ = *s++;
53 *d++ = NR_PREMUL (*s, alpha);
54 s++;
55 }
56 }
57 px += rs;
58 spx += srs;
59 }
60 }
62 void
63 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
64 {
65 int r, c;
67 for (r = 0; r < h; r++) {
68 if (alpha == 0) {
69 memset (px, 0x0, 4 * w);
70 } else {
71 const unsigned char *s;
72 unsigned char *d;
73 s = spx;
74 d = px;
75 for (c = 0; c < w; c++) {
76 unsigned int a;
77 a = NR_PREMUL (s[3], alpha);
78 d[0] = s[0];
79 d[1] = s[1];
80 d[2] = s[2];
81 d[3] = a;
82 d += 4;
83 s += 4;
84 }
85 px += rs;
86 spx += srs;
87 }
88 }
89 }
91 void
92 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
93 {
94 int r, c;
96 for (r = 0; r < h; r++) {
97 unsigned char *d, *s;
98 d = (unsigned char *) px;
99 s = (unsigned char *) spx;
100 for (c = 0; c < w; c++) {
101 unsigned int a;
102 a = (s[3] * alpha + 127) / 255;
103 d[0] = (s[0] * a + 127) / 255;
104 d[1] = (s[1] * a + 127) / 255;
105 d[2] = (s[2] * a + 127) / 255;
106 d[3] = a;
107 d += 4;
108 s += 4;
109 }
110 px += rs;
111 spx += srs;
112 }
113 }
115 void
116 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
117 {
118 int r, c;
120 for (r = 0; r < h; r++) {
121 unsigned char *d, *s;
122 d = (unsigned char *) px;
123 s = (unsigned char *) spx;
124 for (c = 0; c < w; c++) {
125 if (alpha == 255) {
126 d[0] = s[0];
127 d[1] = s[1];
128 d[2] = s[2];
129 d[3] = s[3];
130 } else {
131 d[0] = NR_PREMUL (s[0], alpha);
132 d[1] = NR_PREMUL (s[1], alpha);
133 d[2] = NR_PREMUL (s[2], alpha);
134 d[3] = NR_PREMUL (s[3], alpha);
135 }
136 d += 4;
137 s += 4;
138 }
139 px += rs;
140 spx += srs;
141 }
142 }
144 void
145 nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
146 {
147 int r, c;
149 for (r = 0; r < h; r++) {
150 unsigned char *d, *s;
151 d = (unsigned char *) px;
152 s = (unsigned char *) spx;
153 for (c = 0; c < w; c++) {
154 unsigned int a;
155 a = NR_PREMUL (s[3], alpha);
156 if (a == 0) {
157 /* Transparent FG, NOP */
158 } else if ((a == 255) || (d[3] == 0)) {
159 /* Full coverage, COPY */
160 d[0] = s[0];
161 d[1] = s[1];
162 d[2] = s[2];
163 d[3] = a;
164 } else {
165 unsigned int ca;
166 /* Full composition */
167 ca = 65025 - (255 - a) * (255 - d[3]);
168 d[0] = NR_COMPOSENNN_A7 (s[0], a, d[0], d[3], ca);
169 d[1] = NR_COMPOSENNN_A7 (s[1], a, d[1], d[3], ca);
170 d[2] = NR_COMPOSENNN_A7 (s[2], a, d[2], d[3], ca);
171 d[3] = (ca + 127) / 255;
172 }
173 d += 4;
174 s += 4;
175 }
176 px += rs;
177 spx += srs;
178 }
179 }
181 void
182 nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
183 {
184 int r, c;
186 for (r = 0; r < h; r++) {
187 unsigned char *d, *s;
188 d = (unsigned char *) px;
189 s = (unsigned char *) spx;
190 for (c = 0; c < w; c++) {
191 unsigned int a;
192 a = NR_PREMUL (s[3], alpha);
193 if (a == 0) {
194 /* Transparent FG, NOP */
195 } else if ((a == 255) || (d[3] == 0)) {
196 /* Full coverage, demul src */
197 d[0] = (s[0] * 255 + (s[3] >> 1)) / s[3];
198 d[1] = (s[1] * 255 + (s[3] >> 1)) / s[3];
199 d[2] = (s[2] * 255 + (s[3] >> 1)) / s[3];
200 d[3] = a;
201 } else {
202 if (alpha == 255) {
203 unsigned int ca;
204 /* Full composition */
205 ca = 65025 - (255 - s[3]) * (255 - d[3]);
206 d[0] = NR_COMPOSEPNN_A7 (s[0], s[3], d[0], d[3], ca);
207 d[1] = NR_COMPOSEPNN_A7 (s[1], s[3], d[1], d[3], ca);
208 d[2] = NR_COMPOSEPNN_A7 (s[2], s[3], d[2], d[3], ca);
209 d[3] = (65025 - (255 - s[3]) * (255 - d[3]) + 127) / 255;
210 } else {
211 // calculate premultiplied from two premultiplieds:
212 d[0] = NR_COMPOSEPPP(NR_PREMUL (s[0], alpha), a, NR_PREMUL (d[0], d[3]), 0); // last parameter not used
213 d[1] = NR_COMPOSEPPP(NR_PREMUL (s[1], alpha), a, NR_PREMUL (d[1], d[3]), 0);
214 d[2] = NR_COMPOSEPPP(NR_PREMUL (s[2], alpha), a, NR_PREMUL (d[2], d[3]), 0);
215 // total opacity:
216 d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255;
217 // un-premultiply channels:
218 d[0] = d[0]*255/d[3];
219 d[1] = d[1]*255/d[3];
220 d[2] = d[2]*255/d[3];
221 }
222 }
223 d += 4;
224 s += 4;
225 }
226 px += rs;
227 spx += srs;
228 }
229 }
231 void
232 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
233 {
234 int r, c;
236 for (r = 0; r < h; r++) {
237 unsigned char *d, *s;
238 d = (unsigned char *) px;
239 s = (unsigned char *) spx;
240 for (c = 0; c < w; c++) {
241 unsigned int a;
242 a = NR_PREMUL (s[3], alpha);
243 if (a == 0) {
244 /* Transparent FG, NOP */
245 } else if ((a == 255) || (d[3] == 0)) {
246 /* Transparent BG, premul src */
247 d[0] = NR_PREMUL (s[0], a);
248 d[1] = NR_PREMUL (s[1], a);
249 d[2] = NR_PREMUL (s[2], a);
250 d[3] = a;
251 } else {
252 d[0] = NR_COMPOSENPP (s[0], a, d[0], d[3]);
253 d[1] = NR_COMPOSENPP (s[1], a, d[1], d[3]);
254 d[2] = NR_COMPOSENPP (s[2], a, d[2], d[3]);
255 d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255;
256 }
257 d += 4;
258 s += 4;
259 }
260 px += rs;
261 spx += srs;
262 }
263 }
265 void
266 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
267 {
268 int r, c;
270 for (r = 0; r < h; r++) {
271 unsigned char *d, *s;
272 d = (unsigned char *) px;
273 s = (unsigned char *) spx;
274 for (c = 0; c < w; c++) {
275 unsigned int a;
276 a = NR_PREMUL (s[3], alpha);
277 if (a == 0) {
278 /* Transparent FG, NOP */
279 } else if ((a == 255) || (d[3] == 0)) {
280 /* Transparent BG, COPY */
281 d[0] = NR_PREMUL (s[0], alpha);
282 d[1] = NR_PREMUL (s[1], alpha);
283 d[2] = NR_PREMUL (s[2], alpha);
284 d[3] = NR_PREMUL (s[3], alpha);
285 } else {
286 if (alpha == 255) {
287 /* Simple */
288 d[0] = NR_COMPOSEPPP (s[0], s[3], d[0], d[3]);
289 d[1] = NR_COMPOSEPPP (s[1], s[3], d[1], d[3]);
290 d[2] = NR_COMPOSEPPP (s[2], s[3], d[2], d[3]);
291 d[3] = (65025 - (255 - s[3]) * (255 - d[3]) + 127) / 255;
292 } else {
293 unsigned int c;
294 c = NR_PREMUL (s[0], alpha);
295 d[0] = NR_COMPOSEPPP (c, a, d[0], d[3]);
296 c = NR_PREMUL (s[1], alpha);
297 d[1] = NR_COMPOSEPPP (c, a, d[1], d[3]);
298 c = NR_PREMUL (s[2], alpha);
299 d[2] = NR_COMPOSEPPP (c, a, d[2], d[3]);
300 d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255;
301 }
302 }
303 d += 4;
304 s += 4;
305 }
306 px += rs;
307 spx += srs;
308 }
309 }
311 /* Masked operations */
313 void
314 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
315 {
316 int x, y;
318 for (y = 0; y < h; y++) {
319 unsigned char *d, *s, *m;
320 d = (unsigned char *) px;
321 s = (unsigned char *) spx;
322 m = (unsigned char *) mpx;
323 for (x = 0; x < w; x++) {
324 d[0] = s[0];
325 d[1] = s[1];
326 d[2] = s[2];
327 d[3] = (s[3] * m[0] + 127) / 255;
328 d += 4;
329 s += 4;
330 m += 1;
331 }
332 px += rs;
333 spx += srs;
334 mpx += mrs;
335 }
336 }
338 void
339 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
340 {
341 int x, y;
343 for (y = 0; y < h; y++) {
344 unsigned char *d, *s, *m;
345 d = (unsigned char *) px;
346 s = (unsigned char *) spx;
347 m = (unsigned char *) mpx;
348 for (x = 0; x < w; x++) {
349 unsigned int a;
350 a = NR_PREMUL (s[3], m[0]);
351 if (a == 0) {
352 d[3] = 0;
353 } else {
354 d[0] = (s[0] * 255 + (a >> 1)) / a;
355 d[1] = (s[1] * 255 + (a >> 1)) / a;
356 d[2] = (s[2] * 255 + (a >> 1)) / a;
357 d[3] = a;
358 }
359 d += 4;
360 s += 4;
361 m += 1;
362 }
363 px += rs;
364 spx += srs;
365 mpx += mrs;
366 }
367 }
369 void
370 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
371 {
372 int r, c;
374 for (r = 0; r < h; r++) {
375 unsigned char *d, *s, *m;
376 d = (unsigned char *) px;
377 s = (unsigned char *) spx;
378 m = (unsigned char *) mpx;
379 for (c = 0; c < w; c++) {
380 unsigned int a;
381 a = NR_PREMUL (s[3], m[0]);
382 d[0] = NR_PREMUL (s[0], a);
383 d[1] = NR_PREMUL (s[1], a);
384 d[2] = NR_PREMUL (s[2], a);
385 d[3] = a;
386 d += 4;
387 s += 4;
388 m += 1;
389 }
390 px += rs;
391 spx += srs;
392 mpx += mrs;
393 }
394 }
396 void
397 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
398 {
399 int r, c;
401 for (r = 0; r < h; r++) {
402 unsigned char *d, *s, *m;
403 d = (unsigned char *) px;
404 s = (unsigned char *) spx;
405 m = (unsigned char *) mpx;
406 for (c = 0; c < w; c++) {
407 if (m[0] == 255) {
408 d[0] = s[0];
409 d[1] = s[1];
410 d[2] = s[2];
411 d[3] = s[3];
412 } else {
413 d[0] = NR_PREMUL (s[0], m[0]);
414 d[1] = NR_PREMUL (s[1], m[0]);
415 d[2] = NR_PREMUL (s[2], m[0]);
416 d[3] = NR_PREMUL (s[3], m[0]);
417 }
418 d += 4;
419 s += 4;
420 m += 1;
421 }
422 px += rs;
423 spx += srs;
424 mpx += mrs;
425 }
426 }
428 void
429 nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
430 {
431 int r, c;
433 for (r = 0; r < h; r++) {
434 unsigned char *d, *s, *m;
435 d = (unsigned char *) px;
436 s = (unsigned char *) spx;
437 m = (unsigned char *) mpx;
438 for (c = 0; c < w; c++) {
439 unsigned int a;
440 a = NR_PREMUL (s[3], m[0]);
441 if (a == 0) {
442 /* Transparent FG, NOP */
443 } else if ((a == 255) || (d[3] == 0)) {
444 /* Full coverage, COPY */
445 d[0] = s[0];
446 d[1] = s[1];
447 d[2] = s[2];
448 d[3] = a;
449 } else {
450 unsigned int ca;
451 /* Full composition */
452 ca = 65025 - (255 - a) * (255 - d[3]);
453 d[0] = NR_COMPOSENNN_A7 (s[0], a, d[0], d[3], ca);
454 d[1] = NR_COMPOSENNN_A7 (s[1], a, d[1], d[3], ca);
455 d[2] = NR_COMPOSENNN_A7 (s[2], a, d[2], d[3], ca);
456 d[3] = (ca + 127) / 255;
457 }
458 d += 4;
459 s += 4;
460 m += 1;
461 }
462 px += rs;
463 spx += srs;
464 mpx += mrs;
465 }
466 }
468 void
469 nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
470 {
471 int r, c;
473 for (r = 0; r < h; r++) {
474 unsigned char *d, *s, *m;
475 d = (unsigned char *) px;
476 s = (unsigned char *) spx;
477 m = (unsigned char *) mpx;
478 for (c = 0; c < w; c++) {
479 unsigned int a;
480 a = NR_PREMUL (s[3], m[0]);
481 if (a == 0) {
482 /* Transparent FG, NOP */
483 } else if ((a == 255) || (d[3] == 0)) {
484 /* Full coverage, demul src */
485 d[0] = (s[0] * 255 + (s[3] >> 1)) / s[3];
486 d[1] = (s[1] * 255 + (s[3] >> 1)) / s[3];
487 d[2] = (s[2] * 255 + (s[3] >> 1)) / s[3];
488 d[3] = a;
489 } else {
490 if (m[0] == 255) {
491 unsigned int ca;
492 /* Full composition */
493 ca = 65025 - (255 - s[3]) * (255 - d[3]);
494 d[0] = NR_COMPOSEPNN_A7 (s[0], s[3], d[0], d[3], ca);
495 d[1] = NR_COMPOSEPNN_A7 (s[1], s[3], d[1], d[3], ca);
496 d[2] = NR_COMPOSEPNN_A7 (s[2], s[3], d[2], d[3], ca);
497 d[3] = (65025 - (255 - s[3]) * (255 - d[3]) + 127) / 255;
498 } else {
499 // calculate premultiplied from two premultiplieds:
500 d[0] = NR_COMPOSEPPP(NR_PREMUL (s[0], m[0]), a, NR_PREMUL (d[0], d[3]), 0); // last parameter not used
501 d[1] = NR_COMPOSEPPP(NR_PREMUL (s[1], m[0]), a, NR_PREMUL (d[1], d[3]), 0);
502 d[2] = NR_COMPOSEPPP(NR_PREMUL (s[2], m[0]), a, NR_PREMUL (d[2], d[3]), 0);
503 // total opacity:
504 d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255;
505 // un-premultiply channels:
506 d[0] = d[0]*255/d[3];
507 d[1] = d[1]*255/d[3];
508 d[2] = d[2]*255/d[3];
509 }
510 }
511 d += 4;
512 s += 4;
513 m += 1;
514 }
515 px += rs;
516 spx += srs;
517 mpx += mrs;
518 }
519 }
521 void
522 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
523 {
524 int r, c;
526 for (r = 0; r < h; r++) {
527 unsigned char *d, *s, *m;
528 d = (unsigned char *) px;
529 s = (unsigned char *) spx;
530 m = (unsigned char *) mpx;
531 for (c = 0; c < w; c++) {
532 unsigned int a;
533 a = NR_PREMUL (s[3], m[0]);
534 if (a == 0) {
535 /* Transparent FG, NOP */
536 } else if ((a == 255) || (d[3] == 0)) {
537 /* Transparent BG, premul src */
538 d[0] = NR_PREMUL (s[0], a);
539 d[1] = NR_PREMUL (s[1], a);
540 d[2] = NR_PREMUL (s[2], a);
541 d[3] = a;
542 } else {
543 d[0] = NR_COMPOSENPP (s[0], a, d[0], d[3]);
544 d[1] = NR_COMPOSENPP (s[1], a, d[1], d[3]);
545 d[2] = NR_COMPOSENPP (s[2], a, d[2], d[3]);
546 d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255;
547 }
548 d += 4;
549 s += 4;
550 m += 1;
551 }
552 px += rs;
553 spx += srs;
554 mpx += mrs;
555 }
556 }
558 void
559 nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
560 {
561 int r, c;
563 for (r = 0; r < h; r++) {
564 unsigned char *d, *s, *m;
565 d = (unsigned char *) px;
566 s = (unsigned char *) spx;
567 m = (unsigned char *) mpx;
568 for (c = 0; c < w; c++) {
569 unsigned int a;
570 a = NR_PREMUL (s[3], m[0]);
571 if (a == 0) {
572 /* Transparent FG, NOP */
573 } else if ((a == 255) || (d[3] == 0)) {
574 /* Transparent BG, COPY */
575 d[0] = NR_PREMUL (s[0], m[0]);
576 d[1] = NR_PREMUL (s[1], m[0]);
577 d[2] = NR_PREMUL (s[2], m[0]);
578 d[3] = NR_PREMUL (s[3], m[0]);
579 } else {
580 if (m[0] == 255) {
581 /* Simple */
582 d[0] = NR_COMPOSEPPP (s[0], s[3], d[0], d[3]);
583 d[1] = NR_COMPOSEPPP (s[1], s[3], d[1], d[3]);
584 d[2] = NR_COMPOSEPPP (s[2], s[3], d[2], d[3]);
585 d[3] = NR_A7_NORMALIZED(s[3], d[3]);
586 } else {
587 unsigned int c;
588 c = NR_PREMUL (s[0], m[0]);
589 d[0] = NR_COMPOSEPPP (c, a, d[0], d[3]);
590 c = NR_PREMUL (s[1], m[0]);
591 d[1] = NR_COMPOSEPPP (c, a, d[1], d[3]);
592 c = NR_PREMUL (s[2], m[0]);
593 d[2] = NR_COMPOSEPPP (c, a, d[2], d[3]);
594 d[3] = NR_A7_NORMALIZED(a, d[3]);
595 }
596 }
597 d += 4;
598 s += 4;
599 m += 1;
600 }
601 px += rs;
602 spx += srs;
603 mpx += mrs;
604 }
605 }
607 void
608 nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba)
609 {
610 unsigned int r, g, b, a;
611 int x, y;
613 r = NR_RGBA32_R (rgba);
614 g = NR_RGBA32_G (rgba);
615 b = NR_RGBA32_B (rgba);
616 a = NR_RGBA32_A (rgba);
618 if (a == 0) return;
620 for (y = 0; y < h; y++) {
621 unsigned char *d, *s;
622 d = (unsigned char *) px;
623 s = (unsigned char *) spx;
624 for (x = 0; x < w; x++) {
625 d[0] = r;
626 d[1] = g;
627 d[2] = b;
628 d[3] = NR_PREMUL (s[0], a);
629 d += 4;
630 s += 1;
631 }
632 px += rs;
633 spx += srs;
634 }
635 }
637 void
638 nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba)
639 {
640 unsigned int r, g, b, a;
641 int x, y;
643 r = NR_RGBA32_R (rgba);
644 g = NR_RGBA32_G (rgba);
645 b = NR_RGBA32_B (rgba);
646 a = NR_RGBA32_A (rgba);
648 if (a == 0) return;
650 #ifdef WITH_MMX
651 if (NR_PIXOPS_MMX) {
652 unsigned char c[4];
653 c[0] = NR_PREMUL (r, a);
654 c[1] = NR_PREMUL (g, a);
655 c[2] = NR_PREMUL (b, a);
656 c[3] = a;
657 /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
658 nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (px, w, h, rs, spx, srs, c);
659 return;
660 }
661 #endif
663 for (y = 0; y < h; y++) {
664 unsigned char *d, *s;
665 d = (unsigned char *) px;
666 s = (unsigned char *) spx;
667 for (x = 0; x < w; x++) {
668 unsigned int ca;
669 ca = s[0] * a;
670 d[0] = (r * ca + 32512) / 65025;
671 d[1] = (g * ca + 32512) / 65025;
672 d[2] = (b * ca + 32512) / 65025;
673 d[3] = (ca + 127) / 255;
674 d += 4;
675 s += 1;
676 }
677 px += rs;
678 spx += srs;
679 }
680 }
682 void
683 nr_R8G8B8_R8G8B8_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
684 {
685 unsigned int r, g, b, a;
686 int x, y;
688 r = NR_RGBA32_R (rgba);
689 g = NR_RGBA32_G (rgba);
690 b = NR_RGBA32_B (rgba);
691 a = NR_RGBA32_A (rgba);
693 if (a == 0) return;
695 for (y = 0; y < h; y++) {
696 unsigned char *d, *m;
697 d = (unsigned char *) px;
698 m = (unsigned char *) mpx;
699 for (x = 0; x < w; x++) {
700 unsigned int alpha;
701 alpha = NR_PREMUL (a, m[0]);
702 d[0] = NR_COMPOSEN11 (r, alpha, d[0]);
703 d[1] = NR_COMPOSEN11 (g, alpha, d[1]);
704 d[2] = NR_COMPOSEN11 (b, alpha, d[2]);
705 d += 3;
706 m += 1;
707 }
708 px += rs;
709 mpx += mrs;
710 }
711 }
713 void
714 nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba)
715 {
716 unsigned int r, g, b, a;
717 int x, y;
719 r = NR_RGBA32_R (rgba);
720 g = NR_RGBA32_G (rgba);
721 b = NR_RGBA32_B (rgba);
722 a = NR_RGBA32_A (rgba);
724 if (a == 0) return;
726 for (y = 0; y < h; y++) {
727 unsigned char *d, *s;
728 d = (unsigned char *) px;
729 s = (unsigned char *) spx;
730 for (x = 0; x < w; x++) {
731 unsigned int ca;
732 ca = NR_PREMUL (s[0], a);
733 if (ca == 0) {
734 /* Transparent FG, NOP */
735 } else if ((ca == 255) || (d[3] == 0)) {
736 /* Full coverage, COPY */
737 d[0] = r;
738 d[1] = g;
739 d[2] = b;
740 d[3] = ca;
741 } else {
742 unsigned int da;
743 /* Full composition */
744 da = 65025 - (255 - ca) * (255 - d[3]);
745 d[0] = NR_COMPOSENNN_A7 (r, ca, d[0], d[3], da);
746 d[1] = NR_COMPOSENNN_A7 (g, ca, d[1], d[3], da);
747 d[2] = NR_COMPOSENNN_A7 (b, ca, d[2], d[3], da);
748 d[3] = (da + 127) / 255;
749 }
750 d += 4;
751 s += 1;
752 }
753 px += rs;
754 spx += srs;
755 }
756 }
758 void
759 nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba)
760 {
761 unsigned int r, g, b, a;
762 int x, y;
764 if (!(rgba & 0xff)) return;
766 r = NR_RGBA32_R (rgba);
767 g = NR_RGBA32_G (rgba);
768 b = NR_RGBA32_B (rgba);
769 a = NR_RGBA32_A (rgba);
771 #ifdef WITH_MMX
772 if (NR_PIXOPS_MMX) {
773 unsigned char c[4];
774 c[0] = NR_PREMUL (r, a);
775 c[1] = NR_PREMUL (g, a);
776 c[2] = NR_PREMUL (b, a);
777 c[3] = a;
778 /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
779 nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP (px, w, h, rs, spx, srs, c);
780 return;
781 }
782 #endif
784 for (y = 0; y < h; y++) {
785 unsigned char *d, *s;
786 d = (unsigned char *) px;
787 s = (unsigned char *) spx;
788 for (x = 0; x < w; x++) {
789 unsigned int ca;
790 ca = NR_PREMUL (s[0], a);
791 if (ca == 0) {
792 /* Transparent FG, NOP */
793 } else if ((ca == 255) || (d[3] == 0)) {
794 /* Full coverage, COPY */
795 d[0] = NR_PREMUL (r, ca);
796 d[1] = NR_PREMUL (g, ca);
797 d[2] = NR_PREMUL (b, ca);
798 d[3] = ca;
799 } else {
800 /* Full composition */
801 d[0] = NR_COMPOSENPP (r, ca, d[0], d[3]);
802 d[1] = NR_COMPOSENPP (g, ca, d[1], d[3]);
803 d[2] = NR_COMPOSENPP (b, ca, d[2], d[3]);
804 d[3] = (65025 - (255 - ca) * (255 - d[3]) + 127) / 255;
805 }
806 d += 4;
807 s += 1;
808 }
809 px += rs;
810 spx += srs;
811 }
812 }
814 /* RGB */
816 void
817 nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
818 {
819 int r, c;
821 if (alpha == 0) return;
823 #ifdef WITH_MMX
824 if (NR_PIXOPS_MMX) {
825 /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
826 nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (px, w, h, rs, spx, srs, alpha);
827 return;
828 }
829 #endif
831 for (r = 0; r < h; r++) {
832 const unsigned char *s;
833 unsigned char *d;
834 if (alpha == 255) {
835 d = px;
836 s = spx;
837 for (c = 0; c < w; c++) {
838 if (s[3] == 0) {
839 /* NOP */
840 } else if (s[3] == 255) {
841 d[0] = s[0];
842 d[1] = s[1];
843 d[2] = s[2];
844 } else {
845 d[0] = NR_COMPOSEP11 (s[0], s[3], d[0]);
846 d[1] = NR_COMPOSEP11 (s[1], s[3], d[1]);
847 d[2] = NR_COMPOSEP11 (s[2], s[3], d[2]);
848 }
849 d += 3;
850 s += 4;
851 }
852 } else {
853 d = px;
854 s = spx;
855 for (c = 0; c < w; c++) {
856 unsigned int a;
857 a = NR_PREMUL (s[3], alpha);
858 if (a == 0) {
859 /* NOP */
860 } else {
861 d[0] = NR_COMPOSEP11 (s[0], a, d[0]);
862 d[1] = NR_COMPOSEP11 (s[1], a, d[1]);
863 d[2] = NR_COMPOSEP11 (s[2], a, d[2]);
864 }
865 /* a == 255 is impossible, because alpha < 255 */
866 d += 3;
867 s += 4;
868 }
869 }
870 px += rs;
871 spx += srs;
872 }
873 }
875 void
876 nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
877 {
878 int r, c;
880 for (r = 0; r < h; r++) {
881 const unsigned char *s;
882 unsigned char *d;
883 if (alpha == 0) {
884 /* NOP */
885 } else if (alpha == 255) {
886 d = px;
887 s = spx;
888 for (c = 0; c < w; c++) {
889 if (s[3] == 0) {
890 /* NOP */
891 } else if (s[3] == 255) {
892 d[0] = s[0];
893 d[1] = s[1];
894 d[2] = s[2];
895 } else {
896 d[0] = NR_COMPOSEN11 (s[0], s[3], d[0]);
897 d[1] = NR_COMPOSEN11 (s[1], s[3], d[1]);
898 d[2] = NR_COMPOSEN11 (s[2], s[3], d[2]);
899 }
900 d += 3;
901 s += 4;
902 }
903 } else {
904 d = px;
905 s = spx;
906 for (c = 0; c < w; c++) {
907 unsigned int a;
908 a = NR_PREMUL (s[3], alpha);
909 if (a == 0) {
910 /* NOP */
911 } else {
912 d[0] = NR_COMPOSEN11 (s[0], a, d[0]);
913 d[1] = NR_COMPOSEN11 (s[1], a, d[1]);
914 d[2] = NR_COMPOSEN11 (s[2], a, d[2]);
915 }
916 /* a == 255 is impossible, because alpha < 255 */
917 d += 3;
918 s += 4;
919 }
920 }
921 px += rs;
922 spx += srs;
923 }
924 }
926 void
927 nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
928 {
929 int x, y;
931 for (y = 0; y < h; y++) {
932 unsigned char *d, *s, *m;
933 d = (unsigned char *) px;
934 s = (unsigned char *) spx;
935 m = (unsigned char *) mpx;
936 for (x = 0; x < w; x++) {
937 unsigned int a;
938 a = NR_PREMUL (s[3], m[0]);
939 if (a != 0) {
940 unsigned int r, g, b;
941 r = NR_PREMUL (s[0], m[0]);
942 d[0] = NR_COMPOSEP11 (r, a, d[0]);
943 g = NR_PREMUL (s[1], m[0]);
944 d[1] = NR_COMPOSEP11 (g, a, d[1]);
945 b = NR_PREMUL (s[2], m[0]);
946 d[2] = NR_COMPOSEP11 (b, a, d[2]);
947 }
948 d += 3;
949 s += 4;
950 m += 1;
951 }
952 px += rs;
953 spx += srs;
954 mpx += mrs;
955 }
956 }
958 void
959 nr_R8G8B8_R8G8B8_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, const unsigned char *mpx, int mrs)
960 {
961 int x, y;
963 for (y = 0; y < h; y++) {
964 unsigned char *d, *s, *m;
965 d = (unsigned char *) px;
966 s = (unsigned char *) spx;
967 m = (unsigned char *) mpx;
968 for (x = 0; x < w; x++) {
969 unsigned int a;
970 a = NR_PREMUL (s[3], m[0]);
971 if (a != 0) {
972 d[0] = NR_COMPOSEP11 (s[0], a, d[0]);
973 d[1] = NR_COMPOSEP11 (s[1], a, d[1]);
974 d[2] = NR_COMPOSEP11 (s[2], a, d[2]);
975 }
976 d += 3;
977 s += 4;
978 m += 1;
979 }
980 px += rs;
981 spx += srs;
982 mpx += mrs;
983 }
984 }