Code

patch for rendering quality and speed from Jasper van de Gronde
[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 // Naming: nr_RESULT_BACKGROUND_FOREGROUND_extra
36 void
37 nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
38 {
39         unsigned int r, c;
41         for (r = h; r > 0; r--) {
42                 if (alpha == 0) {
43                         memset(px, 0x0, 4 * w);
44                 } else if (alpha == 255) {
45                         memcpy(px, spx, 4 * w);
46                 } else {
47                         unsigned char *d = px;
48                         const unsigned char *s = spx;
49                         for (c = w; c > 0; c--) {
50                                 *d++ = *s++;
51                                 *d++ = *s++;
52                                 *d++ = *s++;
53                                 *d++ = NR_PREMUL_111(*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         unsigned int r, c;
67         for (r = h; r > 0; r--) {
68                 if (alpha == 0) {
69                         memset(px, 0x0, 4 * w);
70                 } else {
71                         unsigned char *d = px;
72                         const unsigned char *s = spx;
73                         for (c = w; c > 0; c--) {
74                                 if (s[3] == 0) {
75                                         d[3] = 0;
76                                 } else if (s[3] == 255) {
77                                         memcpy(d, s, 4);
78                                 } else {
79                                         d[0] = NR_DEMUL_111(s[0], s[3]);
80                                         d[1] = NR_DEMUL_111(s[1], s[3]);
81                                         d[2] = NR_DEMUL_111(s[2], s[3]);
82                                         d[3] = NR_PREMUL_111(s[3], alpha);
83                                 }
84                                 d += 4;
85                                 s += 4;
86                         }
87                 }
88                 px += rs;
89                 spx += srs;
90         }
91 }
93 void
94 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
95 {
96         unsigned int r, c;
98         for (r = h; r > 0; r--) {
99                 unsigned char *d = px;
100                 const unsigned char *s = spx;
101                 if (alpha == 0) {
102                         memset(px, 0x0, 4 * w);
103                 } else if (alpha == 255) {
104                         for (c = w; c > 0; c--) {
105                                 d[0] = NR_PREMUL_111(s[0], s[3]);
106                                 d[1] = NR_PREMUL_111(s[1], s[3]);
107                                 d[2] = NR_PREMUL_111(s[2], s[3]);
108                                 d[3] = s[3];
109                                 d += 4;
110                                 s += 4;
111                         }
112                 } else {
113                         for (c = w; c > 0; c--) {
114                                 if (s[3] == 0) {
115                                         memset(d, 0, 4);
116                                 } else {
117                                         unsigned int a;
118                                         a = NR_PREMUL_112(s[3], alpha);
119                                         d[0] = NR_PREMUL_121(s[0], a);
120                                         d[1] = NR_PREMUL_121(s[1], a);
121                                         d[2] = NR_PREMUL_121(s[2], a);
122                                         d[3] = NR_NORMALIZE_21(a);
123                                 }
124                                 d += 4;
125                                 s += 4;
126                         }
127                 }
128                 px += rs;
129                 spx += srs;
130         }
133 void
134 nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
136         unsigned int r, c;
138         for (r = h; r > 0; r--) {
139                 if (alpha == 0) {
140                         memset(px, 0x0, 4 * w);
141                 } else if (alpha == 255) {
142                         memcpy(px, spx, 4 * w);
143                 } else {
144                         unsigned char *d = px;
145                         const unsigned char *s = spx;
146                         for (c = w; c > 0; c--) {
147                                 d[0] = NR_PREMUL_111(s[0], alpha);
148                                 d[1] = NR_PREMUL_111(s[1], alpha);
149                                 d[2] = NR_PREMUL_111(s[2], alpha);
150                                 d[3] = NR_PREMUL_111(s[3], alpha);
151                                 d += 4;
152                                 s += 4;
153                         }
154                 }
155                 px += rs;
156                 spx += srs;
157         }
160 void
161 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)
163         unsigned int r, c;
165         if (alpha == 0) {
166                 /* NOP */
167         } else if (alpha == 255) {
168                 for (r = h; r > 0; r--) {
169                         unsigned char *d = px;
170                         const unsigned char *s = spx;
171                         for (c = w; c > 0; c--) {
172                                 if (s[3] == 0) {
173                                         /* Transparent FG, NOP */
174                                 } else if ((s[3] == 255) || (d[3] == 0)) {
175                                         /* Full coverage, COPY */
176                                         memcpy(d, s, 4);
177                                 } else {
178                                         /* Full composition */
179                                         unsigned int ca;
180                                         ca = NR_COMPOSEA_112(s[3], d[3]);
181                                         d[0] = NR_COMPOSENNN_111121(s[0], s[3], d[0], d[3], ca);
182                                         d[1] = NR_COMPOSENNN_111121(s[1], s[3], d[1], d[3], ca);
183                                         d[2] = NR_COMPOSENNN_111121(s[2], s[3], d[2], d[3], ca);
184                                         d[3] = NR_NORMALIZE_21(ca);
185                                 }
186                                 d += 4;
187                                 s += 4;
188                         }
189                         px += rs;
190                         spx += srs;
191                 }
192         } else {
193                 for (r = h; r > 0; r--) {
194                         unsigned char *d = px;
195                         const unsigned char *s = spx;
196                         for (c = w; c > 0; c--) {
197                                 unsigned int a;
198                                 a = NR_PREMUL_112(s[3], alpha);
199                                 if (a == 0) {
200                                         /* Transparent FG, NOP */
201                                 } else if ((a == 255*255) || (d[3] == 0)) {
202                                         /* Full coverage, COPY */
203                                         d[0] = s[0];
204                                         d[1] = s[1];
205                                         d[2] = s[2];
206                                         d[3] = NR_NORMALIZE_21(a);
207                                 } else {
208                                         /* Full composition */
209                                         unsigned int ca;
210                                         ca = NR_COMPOSEA_213(a, d[3]);
211                                         d[0] = NR_COMPOSENNN_121131(s[0], a, d[0], d[3], ca);
212                                         d[1] = NR_COMPOSENNN_121131(s[1], a, d[1], d[3], ca);
213                                         d[2] = NR_COMPOSENNN_121131(s[2], a, d[2], d[3], ca);
214                                         d[3] = NR_NORMALIZE_31(ca);
215                                 }
216                                 d += 4;
217                                 s += 4;
218                         }
219                         px += rs;
220                         spx += srs;
221                 }
222         }
225 void
226 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)
228         unsigned int r, c;
230         if (alpha == 0) {
231                 /* NOP */
232         } else if (alpha == 255) {
233                 for (r = h; r > 0; r--) {
234                         unsigned char *d = px;
235                         const unsigned char *s = spx;
236                         for (c = w; c > 0; c--) {
237                                 if (s[3] == 0) {
238                                         /* Transparent FG, NOP */
239                                 } else if (s[3] == 255) {
240                                         /* Full coverage, demul src */
241                                         //   dc' = ((1 - sa) * da*dc + sc)/da' = sc/da' = sc
242                                         //   da' = 1 - (1 - sa) * (1 - da) = 1 - 0 * (1 - da) = 1
243                                         memcpy(d, s, 4);
244                                 } else if (d[3] == 0) {
245                                         /* Full coverage, demul src */
246                                         //   dc' = ((1 - sa) * da*dc + sc)/da' = sc/da' = sc/sa = sc/sa
247                                         //   da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) = sa
248                                         d[0] = NR_DEMUL_111(s[0], s[3]);
249                                         d[1] = NR_DEMUL_111(s[1], s[3]);
250                                         d[2] = NR_DEMUL_111(s[2], s[3]);
251                                         d[3] = s[3];
252                                 } else {
253                                         /* Full composition */
254                                         //   dc' = ((1 - sa) * da*dc + sc)/da' = ((1 - sa) * da*dc + sc)/da'
255                                         //   da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) * (1 - da)
256                                         unsigned int da = NR_COMPOSEA_112(s[3], d[3]);
257                                         d[0] = NR_COMPOSEPNN_111121(s[0], s[3], d[0], d[3], da);
258                                         d[1] = NR_COMPOSEPNN_111121(s[1], s[3], d[1], d[3], da);
259                                         d[2] = NR_COMPOSEPNN_111121(s[2], s[3], d[2], d[3], da);
260                                         d[3] = NR_NORMALIZE_21(da);
261                                 }
262                                 d += 4;
263                                 s += 4;
264                         }
265                         px += rs;
266                         spx += srs;
267                 }
268         } else {
269                 for (r = h; r > 0; r--) {
270                         unsigned char *d = px;
271                         const unsigned char *s = spx;
272                         for (c = w; c > 0; c--) {
273                                 unsigned int a;
274                                 a = NR_PREMUL_112(s[3], alpha);
275                                 if (a == 0) {
276                                         /* Transparent FG, NOP */
277                                 } else if (d[3] == 0) {
278                                         /* Full coverage, demul src */
279                                         //   dc' = ((1 - alpha*sa) * da*dc + alpha*sc)/da' = alpha*sc/da' = alpha*sc/(alpha*sa) = sc/sa
280                                         //   da' = 1 - (1 - alpha*sa) * (1 - da) = 1 - (1 - alpha*sa) = alpha*sa
281                                         d[0] = NR_DEMUL_111(s[0], s[3]);
282                                         d[1] = NR_DEMUL_111(s[1], s[3]);
283                                         d[2] = NR_DEMUL_111(s[2], s[3]);
284                                         d[3] = NR_NORMALIZE_21(a);
285                                 } else {
286                                         //   dc' = ((1 - alpha*sa) * da*dc + alpha*sc)/da'
287                                         //   da' = 1 - (1 - alpha*sa) * (1 - da)
288                                         unsigned int da = NR_COMPOSEA_213(a, d[3]);
289                                         d[0] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[0], alpha), a, d[0], d[3], da);
290                                         d[1] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[1], alpha), a, d[1], d[3], da);
291                                         d[2] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[2], alpha), a, d[2], d[3], da);
292                                         d[3] = NR_NORMALIZE_31(da);
293                                 }
294                                 d += 4;
295                                 s += 4;
296                         }
297                         px += rs;
298                         spx += srs;
299                 }
300         }
303 void
304 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)
306         unsigned int r, c;
308         if (alpha == 0) {
309                 /* NOP */
310         } else if (alpha == 255) {
311                 for (r = h; r > 0; r--) {
312                         unsigned char *d = px;
313                         const unsigned char *s = spx;
314                         for (c = w; c > 0; c--) {
315                                 if (s[3] == 0) {
316                                         /* Transparent FG, NOP */
317                                 } else if (s[3] == 255) {
318                                         /* Opaque FG, COPY */
319                                         //   dc' = (1 - sa) * dc + sa*sc = sa*sc = sc
320                                         //   da' = 1 - (1 - sa) * (1 - da) = 1 - 0 * (1 - da) = 1 (= sa)
321                                         memcpy(d, s, 4);
322                                 } else if (d[3] == 0) {
323                                         /* Transparent BG, premul src */
324                                         //   dc' = (1 - sa) * dc + sa*sc = sa*sc
325                                         //   da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) = sa
326                                         d[0] = NR_PREMUL_111(s[0], s[3]);
327                                         d[1] = NR_PREMUL_111(s[1], s[3]);
328                                         d[2] = NR_PREMUL_111(s[2], s[3]);
329                                         d[3] = s[3];
330                                 } else {
331                                         //   dc' = (1 - sa) * dc + sa*sc
332                                         //   da' = 1 - (1 - sa) * (1 - da)
333                                         d[0] = NR_COMPOSENPP_1111(s[0], s[3], d[0]);
334                                         d[1] = NR_COMPOSENPP_1111(s[1], s[3], d[1]);
335                                         d[2] = NR_COMPOSENPP_1111(s[2], s[3], d[2]);
336                                         d[3] = NR_COMPOSEA_111(s[3], d[3]);
337                                 }
338                                 d += 4;
339                                 s += 4;
340                         }
341                         px += rs;
342                         spx += srs;
343                 }
344         } else {
345                 for (r = h; r > 0; r--) {
346                         unsigned char *d = px;
347                         const unsigned char *s = spx;
348                         for (c = w; c > 0; c--) {
349                                 unsigned int a;
350                                 a = NR_PREMUL_112 (s[3], alpha);
351                                 if (a == 0) {
352                                         /* Transparent FG, NOP */
353                                 } else if (d[3] == 0) {
354                                         /* Transparent BG, premul src */
355                                         //   dc' = (1 - alpha*sa) * dc + alpha*sa*sc = alpha*sa*sc
356                                         //   da' = 1 - (1 - alpha*sa) * (1 - da) = 1 - (1 - alpha*sa) = alpha*sa
357                                         d[0] = NR_PREMUL_121(s[0], a);
358                                         d[1] = NR_PREMUL_121(s[1], a);
359                                         d[2] = NR_PREMUL_121(s[2], a);
360                                         d[3] = NR_NORMALIZE_21(a);
361                                 } else {
362                                         //   dc' = (1 - alpha*sa) * dc + alpha*sa*sc
363                                         //   da' = 1 - (1 - alpha*sa) * (1 - da)
364                                         d[0] = NR_COMPOSENPP_1211(s[0], a, d[0]);
365                                         d[1] = NR_COMPOSENPP_1211(s[1], a, d[1]);
366                                         d[2] = NR_COMPOSENPP_1211(s[2], a, d[2]);
367                                         d[3] = NR_COMPOSEA_211(a, d[3]);
368                                 }
369                                 d += 4;
370                                 s += 4;
371                         }
372                         px += rs;
373                         spx += srs;
374                 }
375         }
378 void
379 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)
381         unsigned int r, c;
383         if (alpha == 0) {
384                 /* Transparent FG, NOP */
385         } else if (alpha == 255) {
386                 /* Simple */
387                 for (r = h; r > 0; r--) {
388                         unsigned char *d = px;
389                         const unsigned char *s = spx;
390                         for (c = w; c > 0; c--) {
391                                 if (s[3] == 0) {
392                                         /* Transparent FG, NOP */
393                                 } else if ((s[3] == 255) || (d[3] == 0)) {
394                                         /* Transparent BG, COPY */
395                                         memcpy(d, s, 4);
396                                 } else {
397                                         d[0] = NR_COMPOSEPPP_1111(s[0], s[3], d[0]);
398                                         d[1] = NR_COMPOSEPPP_1111(s[1], s[3], d[1]);
399                                         d[2] = NR_COMPOSEPPP_1111(s[2], s[3], d[2]);
400                                         d[3] = NR_COMPOSEA_111(s[3], d[3]);
401                                 }
402                                 d += 4;
403                                 s += 4;
404                         }
405                         px += rs;
406                         spx += srs;
407                 }
408         } else {
409                 for (r = h; r > 0; r--) {
410                         unsigned char *d = px;
411                         const unsigned char *s = spx;
412                         for (c = w; c > 0; c--) {
413                                 if (s[3] == 0) {
414                                         /* Transparent FG, NOP */
415                                 } else if (d[3] == 0) {
416                                         /* Transparent BG, COPY */
417                                         d[0] = NR_PREMUL_111(s[0], alpha);
418                                         d[1] = NR_PREMUL_111(s[1], alpha);
419                                         d[2] = NR_PREMUL_111(s[2], alpha);
420                                         d[3] = NR_PREMUL_111(s[3], alpha);
421                                 } else {
422                                         //   dc' = (1 - alpha*sa) * dc + alpha*sc
423                                         //   da' = 1 - (1 - alpha*sa) * (1 - da)
424                                         unsigned int a;
425                                         a = NR_PREMUL_112(s[3], alpha);
426                                         d[0] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[0]), a, d[0]);
427                                         d[1] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[1]), a, d[1]);
428                                         d[2] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[2]), a, d[2]);
429                                         d[3] = NR_COMPOSEA_211(a, d[3]);
430                                 }
431                                 d += 4;
432                                 s += 4;
433                         }
434                         px += rs;
435                         spx += srs;
436                 }
437         }
440 /* Masked operations */
442 void
443 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)
445         unsigned int r, c;
447         for (r = h; r > 0; r--) {
448                 unsigned char *d = px;
449                 const unsigned char *s = spx;
450                 const unsigned char *m = mpx;
451                 for (c = w; c > 0; c--) {
452                         d[0] = s[0];
453                         d[1] = s[1];
454                         d[2] = s[2];
455                         d[3] = NR_PREMUL_111(s[3], m[0]);
456                         d += 4;
457                         s += 4;
458                         m += 1;
459                 }
460                 px += rs;
461                 spx += srs;
462                 mpx += mrs;
463         }
466 void
467 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)
469         unsigned int r, c;
471         for (r = h; r > 0; r--) {
472                 unsigned char *d = px;
473                 const unsigned char *s = spx;
474                 const unsigned char *m = mpx;
475                 for (c = w; c > 0; c--) {
476                         unsigned int a;
477                         a = NR_PREMUL_112 (s[3], m[0]);
478                         if (a == 0) {
479                                 d[3] = 0;
480                         } else if (a == 255*255) {
481                                 memcpy(d, s, 4);
482                         } else {
483                                 //   dc' = ((1 - m*sa) * da*dc + m*sc)/da' = m*sc/da' = m*sc/(m*sa) = sc/sa
484                                 //   da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa) = m*sa
485                                 d[0] = NR_DEMUL_111(s[0], s[3]);
486                                 d[1] = NR_DEMUL_111(s[1], s[3]);
487                                 d[2] = NR_DEMUL_111(s[2], s[3]);
488                                 d[3] = NR_NORMALIZE_21(a);
489                         }
490                         d += 4;
491                         s += 4;
492                         m += 1;
493                 }
494                 px += rs;
495                 spx += srs;
496                 mpx += mrs;
497         }
500 void
501 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)
503         unsigned int r, c;
505         for (r = h; r > 0; r--) {
506                 unsigned char *d = px;
507                 const unsigned char *s = spx;
508                 const unsigned char *m = mpx;
509                 for (c = w; c > 0; c--) {
510                         unsigned int a;
511                         a = NR_PREMUL_112(s[3], m[0]);
512                         if (a == 0) {
513                                 memset(d, 0, 4);
514                         } else if (a == 255*255) {
515                                 memcpy(d, s, 4);
516                         } else {
517                                 d[0] = NR_PREMUL_121(s[0], a);
518                                 d[1] = NR_PREMUL_121(s[1], a);
519                                 d[2] = NR_PREMUL_121(s[2], a);
520                                 d[3] = NR_NORMALIZE_21(a);
521                         }
522                         d += 4;
523                         s += 4;
524                         m += 1;
525                 }
526                 px += rs;
527                 spx += srs;
528                 mpx += mrs;
529         }
532 void
533 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)
535         unsigned int r, c;
537         for (r = h; r > 0; r--) {
538                 unsigned char *d = px;
539                 const unsigned char *s = spx;
540                 const unsigned char *m = mpx;
541                 for (c = w; c > 0; c--) {
542                         d[0] = NR_PREMUL_111(s[0], m[0]);
543                         d[1] = NR_PREMUL_111(s[1], m[0]);
544                         d[2] = NR_PREMUL_111(s[2], m[0]);
545                         d[3] = NR_PREMUL_111(s[3], m[0]);
546                         d += 4;
547                         s += 4;
548                         m += 1;
549                 }
550                 px += rs;
551                 spx += srs;
552                 mpx += mrs;
553         }
556 void
557 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)
559         unsigned int r, c;
561         for (r = h; r > 0; r--) {
562                 unsigned char *d = px;
563                 const unsigned char *s = spx;
564                 const unsigned char *m = mpx;
565                 for (c = w; c > 0; c--) {
566                         unsigned int a;
567                         a = NR_PREMUL_112(s[3], m[0]);
568                         if (a == 0) {
569                                 /* Transparent FG, NOP */
570                         } else if ((a == 255*255) || (d[3] == 0)) {
571                                 /* Full coverage, COPY */
572                                 d[0] = s[0];
573                                 d[1] = s[1];
574                                 d[2] = s[2];
575                                 d[3] = NR_NORMALIZE_21(a);
576                         } else {
577                                 /* Full composition */
578                                 unsigned int ca;
579                                 ca = NR_COMPOSEA_213(a, d[3]);
580                                 d[0] = NR_COMPOSENNN_121131(s[0], a, d[0], d[3], ca);
581                                 d[1] = NR_COMPOSENNN_121131(s[1], a, d[1], d[3], ca);
582                                 d[2] = NR_COMPOSENNN_121131(s[2], a, d[2], d[3], ca);
583                                 d[3] = NR_NORMALIZE_31(ca);
584                         }
585                         d += 4;
586                         s += 4;
587                         m += 1;
588                 }
589                 px += rs;
590                 spx += srs;
591                 mpx += mrs;
592         }
595 void
596 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)
598         unsigned int r, c;
600         for (r = h; r > 0; r--) {
601                 unsigned char *d = px;
602                 const unsigned char *s = spx;
603                 const unsigned char *m = mpx;
604                 for (c = w; c > 0; c--) {
605                         unsigned int a;
606                         a = NR_PREMUL_112(s[3], m[0]);
607                         if (a == 0) {
608                                 /* Transparent FG, NOP */
609                         } else if (a == 255*255) {
610                                 /* Opaque FG, COPY */
611                                 memcpy(d, s, 4);
612                         } else if (d[3] == 0) {
613                                 /* Full coverage, demul src */
614                                 //   dc' = ((1 - m*sa) * da*dc + m*sc)/da' = m*sc/da' = m*sc/(m*sa) = sc/sa
615                                 //   da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa) = m*sa
616                                 d[0] = NR_DEMUL_111(s[0], s[3]);
617                                 d[1] = NR_DEMUL_111(s[1], s[3]);
618                                 d[2] = NR_DEMUL_111(s[2], s[3]);
619                                 d[3] = NR_NORMALIZE_21(a);
620                         } else if (m[0] == 255) {
621                                 /* Full composition */
622                                 //   dc' = ((1 - m*sa) * da*dc + m*sc)/da' = ((1 - sa) * da*dc + sc)/da'
623                                 //   da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - sa) * (1 - da)
624                                 unsigned int da = NR_COMPOSEA_112(s[3], d[3]);
625                                 d[0] = NR_COMPOSEPNN_111121(s[0], s[3], d[0], d[3], da);
626                                 d[1] = NR_COMPOSEPNN_111121(s[1], s[3], d[1], d[3], da);
627                                 d[2] = NR_COMPOSEPNN_111121(s[2], s[3], d[2], d[3], da);
628                                 d[3] = NR_NORMALIZE_21(da);
629                         } else {
630                                 //   dc' = ((1 - m*sa) * da*dc + m*sc)/da'
631                                 //   da' = 1 - (1 - m*sa) * (1 - da)
632                                 unsigned int da = NR_COMPOSEA_213(a, d[3]);
633                                 d[0] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[0], m[0]), a, d[0], d[3], da);
634                                 d[1] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[1], m[0]), a, d[1], d[3], da);
635                                 d[2] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[2], m[0]), a, d[2], d[3], da);
636                                 d[3] = NR_NORMALIZE_31(da);
637                         }
638                         d += 4;
639                         s += 4;
640                         m += 1;
641                 }
642                 px += rs;
643                 spx += srs;
644                 mpx += mrs;
645         }
648 void
649 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)
651         unsigned int r, c;
653         for (r = h; r>0; r--) {
654                 unsigned char *d = px;
655                 const unsigned char *s = spx;
656                 const unsigned char *m = mpx;
657                 for (c = w; c>0; c--) {
658                         unsigned int a;
659                         a = NR_PREMUL_112(s[3], m[0]);
660                         if (a == 0) {
661                                 /* Transparent FG, NOP */
662                         } else if (a == 255*255) {
663                                 memcpy(d, s, 4);
664                         } else {
665                                 d[0] = NR_COMPOSENPP_1211(s[0], a, d[0]);
666                                 d[1] = NR_COMPOSENPP_1211(s[1], a, d[1]);
667                                 d[2] = NR_COMPOSENPP_1211(s[2], a, d[2]);
668                                 d[3] = NR_COMPOSEA_211(a, d[3]);
669                         }
670                         d += 4;
671                         s += 4;
672                         m += 1;
673                 }
674                 px += rs;
675                 spx += srs;
676                 mpx += mrs;
677         }
680 void
681 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)
683         unsigned int r, c;
685         for (r = h; r > 0; r--) {
686                 unsigned char *d = px;
687                 const unsigned char *s = spx;
688                 const unsigned char *m = mpx;
689                 for (c = w; c > 0; c--) {
690                         unsigned int a;
691                         a = NR_PREMUL_112 (s[3], m[0]);
692                         if (a == 0) {
693                                 /* Transparent FG, NOP */
694                         } else if (a == 255*255) {
695                                 /* Opaque FG, COPY */
696                                 memcpy(d, s, 4);
697                         } else if (d[3] == 0) {
698                                 /* Transparent BG, COPY */
699                                 //   dc' = (1 - m*sa) * dc + m*sc = m*sc
700                                 //   da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa)  = m*sa
701                                 d[0] = NR_PREMUL_111 (s[0], m[0]);
702                                 d[1] = NR_PREMUL_111 (s[1], m[0]);
703                                 d[2] = NR_PREMUL_111 (s[2], m[0]);
704                                 d[3] = NR_NORMALIZE_21(a);
705                         } else {
706                                 //   dc' = (1 - m*sa) * dc + m*sc
707                                 //   da' = 1 - (1 - m*sa) * (1 - da)
708                                 d[0] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[0], m[0]), a, d[0]);
709                                 d[1] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[1], m[0]), a, d[1]);
710                                 d[2] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[2], m[0]), a, d[2]);
711                                 d[3] = NR_COMPOSEA_211(a, d[3]);
712                         }
713                         d += 4;
714                         s += 4;
715                         m += 1;
716                 }
717                 px += rs;
718                 spx += srs;
719                 mpx += mrs;
720         }
723 /* FINAL DST MASK COLOR */
725 void
726 nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
728         unsigned int r, g, b, a;
729         unsigned int x, y;
731         r = NR_RGBA32_R (rgba);
732         g = NR_RGBA32_G (rgba);
733         b = NR_RGBA32_B (rgba);
734         a = NR_RGBA32_A (rgba);
736         for (y = h; y > 0; y--) {
737                 if (a == 0) {
738                         memset(px, 0, w*4);
739                 } else {
740                         unsigned char *d = px;
741                         const unsigned char *m = mpx;
742                         for (x = w; x > 0; x--) {
743                                 d[0] = r;
744                                 d[1] = g;
745                                 d[2] = b;
746                                 d[3] = NR_PREMUL_111 (m[0], a);
747                                 d += 4;
748                                 m += 1;
749                         }
750                 }
751                 px += rs;
752                 mpx += mrs;
753         }
756 void
757 nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
759         unsigned int r, g, b, a;
760         unsigned int x, y;
762         r = NR_RGBA32_R (rgba);
763         g = NR_RGBA32_G (rgba);
764         b = NR_RGBA32_B (rgba);
765         a = NR_RGBA32_A (rgba);
767 #ifdef WITH_MMX
768         if (NR_PIXOPS_MMX) {
769                 unsigned char c[4];
770                 c[0] = NR_PREMUL_111 (r, a);
771                 c[1] = NR_PREMUL_111 (g, a);
772                 c[2] = NR_PREMUL_111 (b, a);
773                 c[3] = a;
774                 /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
775                 nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (px, w, h, rs, mpx, mrs, c);
776                 return;
777         }
778 #endif
780         if ( a != 255 ){
781                 // Pre-premultiply color values
782                 r *= a;
783                 g *= a;
784                 b *= a;
785         }
787         for (y = h; y > 0; y--) {
788                 unsigned char *d = px;
789                 const unsigned char *m = mpx;
790                 if (a == 0) {
791                         memset(px, 0, w*4);
792                 } else if (a == 255) {
793                         for (x = w; x > 0; x--) {
794                                 d[0] = NR_PREMUL_111(m[0], r);
795                                 d[1] = NR_PREMUL_111(m[0], g);
796                                 d[2] = NR_PREMUL_111(m[0], b);
797                                 d[3] = m[0];
798                                 d += 4;
799                                 m += 1;
800                         }
801                 } else {
802                         for (x = w; x > 0; x--) {
803                                 // Color values are already premultiplied with a
804                                 d[0] = NR_PREMUL_121(m[0], r);
805                                 d[1] = NR_PREMUL_121(m[0], g);
806                                 d[2] = NR_PREMUL_121(m[0], b);
807                                 d[3] = NR_PREMUL_111(m[0], a);
808                                 d += 4;
809                                 m += 1;
810                         }
811                 }
812                 px += rs;
813                 mpx += mrs;
814         }
817 void
818 nr_R8G8B8_R8G8B8_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
820         unsigned int r, g, b, a;
821         unsigned int x, y;
823         r = NR_RGBA32_R (rgba);
824         g = NR_RGBA32_G (rgba);
825         b = NR_RGBA32_B (rgba);
826         a = NR_RGBA32_A (rgba);
828         if (a == 0) {
829                 /* NOP */
830         } else if (a == 255) {
831                 for (y = h; y > 0; y--) {
832                         unsigned char *d = px;
833                         const unsigned char *m = mpx;
834                         for (x = w; x > 0; x--) {
835                                 d[0] = NR_COMPOSEN11_1111 (r, m[0], d[0]);
836                                 d[1] = NR_COMPOSEN11_1111 (g, m[0], d[1]);
837                                 d[2] = NR_COMPOSEN11_1111 (b, m[0], d[2]);
838                                 d += 3;
839                                 m += 1;
840                         }
841                         px += rs;
842                         mpx += mrs;
843                 }
844         } else {
845                 for (y = h; y > 0; y--) {
846                         unsigned char *d = px;
847                         const unsigned char *m = mpx;
848                         for (x = w; x > 0; x--) {
849                                 //   dc' = (1 - m*sa) * dc + m*sa*sc
850                                 unsigned int alpha;
851                                 alpha = NR_PREMUL_112 (a, m[0]);
852                                 d[0] = NR_COMPOSEN11_1211 (r, alpha, d[0]);
853                                 d[1] = NR_COMPOSEN11_1211 (g, alpha, d[1]);
854                                 d[2] = NR_COMPOSEN11_1211 (b, alpha, d[2]);
855                                 d += 3;
856                                 m += 1;
857                         }
858                         px += rs;
859                         mpx += mrs;
860                 }
861         }
864 void
865 nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
867         unsigned int r, g, b, a;
868         unsigned int x, y;
870         r = NR_RGBA32_R (rgba);
871         g = NR_RGBA32_G (rgba);
872         b = NR_RGBA32_B (rgba);
873         a = NR_RGBA32_A (rgba);
875         if (a == 0) {
876                 /* NOP */
877         } else if (a == 255) {
878                 for (y = h; y > 0; y--) {
879                         unsigned char *d = px;
880                         const unsigned char *m = mpx;
881                         for (x = w; x > 0; x--) {
882                                 if (m[0] == 0) {
883                                         /* Transparent FG, NOP */
884                                 } else if (m[0] == 255 || d[3] == 0) {
885                                         /* Full coverage, COPY */
886                                         d[0] = r;
887                                         d[1] = g;
888                                         d[2] = b;
889                                         d[3] = m[0];
890                                 } else {
891                                         /* Full composition */
892                                         unsigned int da = NR_COMPOSEA_112(m[0], d[3]);
893                                         d[0] = NR_COMPOSENNN_111121(r, m[0], d[0], d[3], da);
894                                         d[1] = NR_COMPOSENNN_111121(g, m[0], d[1], d[3], da);
895                                         d[2] = NR_COMPOSENNN_111121(b, m[0], d[2], d[3], da);
896                                         d[3] = NR_NORMALIZE_21(da);
897                                 }
898                                 d += 4;
899                                 m += 1;
900                         }
901                         px += rs;
902                         mpx += mrs;
903                 }
904         } else {
905                 for (y = h; y > 0; y--) {
906                         unsigned char *d = px;
907                         const unsigned char *m = mpx;
908                         for (x = w; x > 0; x--) {
909                                 unsigned int ca;
910                                 ca = NR_PREMUL_112 (m[0], a);
911                                 if (ca == 0) {
912                                         /* Transparent FG, NOP */
913                                 } else if (d[3] == 0) {
914                                         /* Full coverage, COPY */
915                                         d[0] = r;
916                                         d[1] = g;
917                                         d[2] = b;
918                                         d[3] = NR_NORMALIZE_21(ca);
919                                 } else {
920                                         /* Full composition */
921                                         unsigned int da = NR_COMPOSEA_213(ca, d[3]);
922                                         d[0] = NR_COMPOSENNN_121131(r, ca, d[0], d[3], da);
923                                         d[1] = NR_COMPOSENNN_121131(g, ca, d[1], d[3], da);
924                                         d[2] = NR_COMPOSENNN_121131(b, ca, d[2], d[3], da);
925                                         d[3] = NR_NORMALIZE_31(da);
926                                 }
927                                 d += 4;
928                                 m += 1;
929                         }
930                         px += rs;
931                         mpx += mrs;
932                 }
933         }
936 void
937 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)
939         unsigned int r, g, b, a;
940         unsigned int x, y;
942         r = NR_RGBA32_R (rgba);
943         g = NR_RGBA32_G (rgba);
944         b = NR_RGBA32_B (rgba);
945         a = NR_RGBA32_A (rgba);
947 #ifdef WITH_MMX
948         if (NR_PIXOPS_MMX && a != 0) {
949                 unsigned char c[4];
950                 c[0] = NR_PREMUL_111 (r, a);
951                 c[1] = NR_PREMUL_111 (g, a);
952                 c[2] = NR_PREMUL_111 (b, a);
953                 c[3] = a;
954                 /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
955                 nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP (px, w, h, rs, spx, srs, c);
956                 return;
957         }
958 #endif
960         if (a == 0) {
961                 /* Transparent FG, NOP */
962         } else if (a == 255) {
963                 /* Simple */
964                 for (y = h; y > 0; y--) {
965                         unsigned char *d, *s;
966                         d = (unsigned char *) px;
967                         s = (unsigned char *) spx;
968                         for (x = w; x > 0; x--) {
969                                 if (s[0] == 0) {
970                                         /* Transparent FG, NOP */
971                                 } else {
972                                         /* Full composition */
973                                         unsigned int invca = 255-s[0]; // By swapping the arguments GCC can better optimize these calls
974                                         d[0] = NR_COMPOSENPP_1111(d[0], invca, r);
975                                         d[1] = NR_COMPOSENPP_1111(d[1], invca, g);
976                                         d[2] = NR_COMPOSENPP_1111(d[2], invca, b);
977                                         d[3] = NR_COMPOSEA_111(s[0], d[3]);
978                                 }
979                                 d += 4;
980                                 s += 1;
981                         }
982                         px += rs;
983                         spx += srs;
984                 }
985         } else {
986                 for (y = h; y > 0; y--) {
987                         unsigned char *d, *s;
988                         d = (unsigned char *) px;
989                         s = (unsigned char *) spx;
990                         for (x = w; x > 0; x--) {
991                                 unsigned int ca;
992                                 ca = NR_PREMUL_112 (s[0], a);
993                                 if (ca == 0) {
994                                         /* Transparent FG, NOP */
995                                 } else {
996                                         /* Full composition */
997                                         unsigned int invca = 255*255-ca; // By swapping the arguments GCC can better optimize these calls
998                                         d[0] = NR_COMPOSENPP_1211(d[0], invca, r);
999                                         d[1] = NR_COMPOSENPP_1211(d[1], invca, g);
1000                                         d[2] = NR_COMPOSENPP_1211(d[2], invca, b);
1001                                         d[3] = NR_COMPOSEA_211(ca, d[3]);
1002                                 }
1003                                 d += 4;
1004                                 s += 1;
1005                         }
1006                         px += rs;
1007                         spx += srs;
1008                 }
1009         }
1012 /* RGB */
1014 void
1015 nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
1017         unsigned int r, c;
1019 #ifdef WITH_MMX
1020         if (NR_PIXOPS_MMX && alpha != 0) {
1021                 /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
1022                 nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (px, w, h, rs, spx, srs, alpha);
1023                 return;
1024         }
1025 #endif
1027         if (alpha == 0) {
1028                 /* NOP */
1029         } else if (alpha == 255) {
1030                 for (r = h; r > 0; r--) {
1031                         unsigned char *d = px;
1032                         const unsigned char *s = spx;
1033                         for (c = w; c > 0; c--) {
1034                                 //   dc' = (1 - alpha*sa) * dc + alpha*sc = (1 - sa) * dc + sc
1035                                 if (s[3] == 0) {
1036                                         /* NOP */
1037                                 } else if (s[3] == 255) {
1038                                         d[0] = s[0];
1039                                         d[1] = s[1];
1040                                         d[2] = s[2];
1041                                 } else {
1042                                         d[0] = NR_COMPOSEP11_1111(s[0], s[3], d[0]);
1043                                         d[1] = NR_COMPOSEP11_1111(s[1], s[3], d[1]);
1044                                         d[2] = NR_COMPOSEP11_1111(s[2], s[3], d[2]);
1045                                 }
1046                                 d += 3;
1047                                 s += 4;
1048                         }
1049                         px += rs;
1050                         spx += srs;
1051                 }
1052         } else {
1053                 for (r = h; r > 0; r--) {
1054                         unsigned char *d = px;
1055                         const unsigned char *s = spx;
1056                         for (c = w; c > 0; c--) {
1057                                 unsigned int a;
1058                                 a = NR_PREMUL_112(s[3], alpha);
1059                                 //   dc' = (1 - alpha*sa) * dc + alpha*sc
1060                                 if (a == 0) {
1061                                         /* NOP */
1062                                 } else {
1063                                         d[0] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[0], alpha), a, d[0]);
1064                                         d[1] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[1], alpha), a, d[1]);
1065                                         d[2] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[2], alpha), a, d[2]);
1066                                 }
1067                                 /* a == 255 is impossible, because alpha < 255 */
1068                                 d += 3;
1069                                 s += 4;
1070                         }
1071                         px += rs;
1072                         spx += srs;
1073                 }
1074         }
1077 void
1078 nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
1080         unsigned int r, c;
1082         if (alpha == 0) {
1083                 /* NOP */
1084         } else if (alpha == 255) {
1085                 for (r = h; r > 0; r--) {
1086                         unsigned char *d = px;
1087                         const unsigned char *s = spx;
1088                         for (c = w; c > 0; c--) {
1089                                 //   dc' = (1 - alpha*sa) * dc + alpha*sa*sc = (1 - sa) * dc + sa*sc
1090                                 if (s[3] == 0) {
1091                                         /* NOP */
1092                                 } else if (s[3] == 255) {
1093                                         d[0] = s[0];
1094                                         d[1] = s[1];
1095                                         d[2] = s[2];
1096                                 } else {
1097                                         d[0] = NR_COMPOSEN11_1111(s[0], s[3], d[0]);
1098                                         d[1] = NR_COMPOSEN11_1111(s[1], s[3], d[1]);
1099                                         d[2] = NR_COMPOSEN11_1111(s[2], s[3], d[2]);
1100                                 }
1101                                 d += 3;
1102                                 s += 4;
1103                         }
1104                         px += rs;
1105                         spx += srs;
1106                 }
1107         } else {
1108                 for (r = h; r > 0; r--) {
1109                         unsigned char *d = px;
1110                         const unsigned char *s = spx;
1111                         for (c = w; c > 0; c--) {
1112                                 unsigned int a;
1113                                 a = NR_PREMUL_112(s[3], alpha);
1114                                 //   dc' = (1 - alpha*sa) * dc + alpha*sa*sc
1115                                 if (a == 0) {
1116                                         /* NOP */
1117                                 } else {
1118                                         d[0] = NR_COMPOSEN11_1211(s[0], a, d[0]);
1119                                         d[1] = NR_COMPOSEN11_1211(s[1], a, d[1]);
1120                                         d[2] = NR_COMPOSEN11_1211(s[2], a, d[2]);
1121                                 }
1122                                 /* a == 255 is impossible, because alpha < 255 */
1123                                 d += 3;
1124                                 s += 4;
1125                         }
1126                         px += rs;
1127                         spx += srs;
1128                 }
1129         }
1132 void
1133 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)
1135         unsigned int x, y;
1137         for (y = h; y > 0; y--) {
1138                 unsigned char* d = px;
1139                 const unsigned char* s = spx;
1140                 const unsigned char* m = mpx;
1141                 for (x = w; x > 0; x--) {
1142                         unsigned int a;
1143                         a = NR_PREMUL_112(s[3], m[0]);
1144                         if (a == 0) {
1145                                 /* NOP */
1146                         } else if (a == 255*255) {
1147                                 memcpy(d, s, 3);
1148                         } else {
1149                                 //   dc' = (1 - m*sa) * dc + m*sc
1150                                 d[0] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[0], m[0]), a, d[0]);
1151                                 d[1] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[1], m[0]), a, d[1]);
1152                                 d[2] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[2], m[0]), a, d[2]);
1153                         }
1154                         d += 3;
1155                         s += 4;
1156                         m += 1;
1157                 }
1158                 px += rs;
1159                 spx += srs;
1160                 mpx += mrs;
1161         }
1164 void
1165 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)
1167         unsigned int x, y;
1169         for (y = h; y > 0; y--) {
1170                 unsigned char* d = px;
1171                 const unsigned char* s = spx;
1172                 const unsigned char* m = mpx;
1173                 for (x = w; x > 0; x--) {
1174                         unsigned int a;
1175                         a = NR_PREMUL_112(s[3], m[0]);
1176                         if (a == 0) {
1177                                 /* NOP */
1178                         } else if (a == 255*255) {
1179                                 memcpy(d, s, 3);
1180                         } else {
1181                                 //   dc' = (1 - m*sa) * dc + m*sa*sc
1182                                 d[0] = NR_COMPOSEN11_1211(s[0], a, d[0]);
1183                                 d[1] = NR_COMPOSEN11_1211(s[1], a, d[1]);
1184                                 d[2] = NR_COMPOSEN11_1211(s[2], a, d[2]);
1185                         }
1186                         d += 3;
1187                         s += 4;
1188                         m += 1;
1189                 }
1190                 px += rs;
1191                 spx += srs;
1192                 mpx += mrs;
1193         }