Code

write no/unset fill/stroke to current style
[inkscape.git] / src / libnr / nr-compose.cpp
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }
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)
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         }