~ubuntu-branches/debian/experimental/inkscape/experimental

« back to all changes in this revision

Viewing changes to src/libnr/nr-compose.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
31
31
#endif /* __cplusplus */
32
32
#endif
33
33
 
 
34
// Naming: nr_RESULT_BACKGROUND_FOREGROUND_extra
 
35
 
34
36
void
35
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)
36
38
{
37
 
        int r, c;
 
39
        unsigned int r, c;
38
40
 
39
 
        for (r = 0; r < h; r++) {
 
41
        for (r = h; r > 0; r--) {
40
42
                if (alpha == 0) {
41
 
                        memset (px, 0x0, 4 * w);
 
43
                        memset(px, 0x0, 4 * w);
42
44
                } else if (alpha == 255) {
43
 
                        memcpy (px, spx, 4 * w);
 
45
                        memcpy(px, spx, 4 * w);
44
46
                } 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);
 
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
54
                                s++;
55
55
                        }
56
56
                }
62
62
void
63
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
64
{
65
 
        int r, c;
 
65
        unsigned int r, c;
66
66
 
67
 
        for (r = 0; r < h; r++) {
 
67
        for (r = h; r > 0; r--) {
68
68
                if (alpha == 0) {
69
 
                        memset (px, 0x0, 4 * w);
 
69
                        memset(px, 0x0, 4 * w);
70
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;
 
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
                                }
82
84
                                d += 4;
83
85
                                s += 4;
84
86
                        }
85
 
                        px += rs;
86
 
                        spx += srs;
87
87
                }
 
88
                px += rs;
 
89
                spx += srs;
88
90
        }
89
91
}
90
92
 
91
93
void
92
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)
93
95
{
94
 
        int r, c;
 
96
        unsigned int r, c;
95
97
 
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;
 
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
                        }
109
127
                }
110
128
                px += rs;
111
129
                spx += srs;
115
133
void
116
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)
117
135
{
118
 
        int r, c;
 
136
        unsigned int r, c;
119
137
 
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);
 
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;
135
153
                        }
136
 
                        d += 4;
137
 
                        s += 4;
138
154
                }
139
155
                px += rs;
140
156
                spx += srs;
144
160
void
145
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)
146
162
{
147
 
        int r, c;
 
163
        unsigned int r, c;
148
164
 
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;
 
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
                }
178
222
        }
179
223
}
180
224
 
181
225
void
182
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)
183
227
{
184
 
        int r, c;
 
228
        unsigned int r, c;
185
229
 
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;
 
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 {
204
253
                                        /* 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;
 
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);
210
285
                                } 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];
 
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);
221
293
                                }
 
294
                                d += 4;
 
295
                                s += 4;
222
296
                        }
223
 
                        d += 4;
224
 
                        s += 4;
 
297
                        px += rs;
 
298
                        spx += srs;
225
299
                }
226
 
                px += rs;
227
 
                spx += srs;
228
300
        }
229
301
}
230
302
 
231
303
void
232
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)
233
305
{
234
 
        int r, c;
 
306
        unsigned int r, c;
235
307
 
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;
 
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
                }
262
375
        }
263
376
}
264
377
 
265
378
void
266
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)
267
380
{
268
 
        int r, c;
 
381
        unsigned int r, c;
269
382
 
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;
 
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
                }
308
437
        }
309
438
}
310
439
 
313
442
void
314
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)
315
444
{
316
 
        int x, y;
 
445
        unsigned int r, c;
317
446
 
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++) {
 
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--) {
324
452
                        d[0] = s[0];
325
453
                        d[1] = s[1];
326
454
                        d[2] = s[2];
327
 
                        d[3] = (s[3] * m[0] + 127) / 255;
 
455
                        d[3] = NR_PREMUL_111(s[3], m[0]);
328
456
                        d += 4;
329
457
                        s += 4;
330
458
                        m += 1;
338
466
void
339
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)
340
468
{
341
 
        int x, y;
 
469
        unsigned int r, c;
342
470
 
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++) {
 
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--) {
349
476
                        unsigned int a;
350
 
                        a = NR_PREMUL (s[3], m[0]);
 
477
                        a = NR_PREMUL_112 (s[3], m[0]);
351
478
                        if (a == 0) {
352
479
                                d[3] = 0;
 
480
                        } else if (a == 255*255) {
 
481
                                memcpy(d, s, 4);
353
482
                        } 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;
 
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);
358
489
                        }
359
490
                        d += 4;
360
491
                        s += 4;
369
500
void
370
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)
371
502
{
372
 
        int r, c;
 
503
        unsigned int r, c;
373
504
 
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++) {
 
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--) {
380
510
                        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;
 
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
                        }
386
522
                        d += 4;
387
523
                        s += 4;
388
524
                        m += 1;
396
532
void
397
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)
398
534
{
399
 
        int r, c;
 
535
        unsigned int r, c;
400
536
 
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
 
                        }
 
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]);
418
546
                        d += 4;
419
547
                        s += 4;
420
548
                        m += 1;
428
556
void
429
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)
430
558
{
431
 
        int r, c;
 
559
        unsigned int r, c;
432
560
 
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++) {
 
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--) {
439
566
                        unsigned int a;
440
 
                        a = NR_PREMUL (s[3], m[0]);
 
567
                        a = NR_PREMUL_112(s[3], m[0]);
441
568
                        if (a == 0) {
442
569
                                /* Transparent FG, NOP */
443
 
                        } else if ((a == 255) || (d[3] == 0)) {
 
570
                        } else if ((a == 255*255) || (d[3] == 0)) {
444
571
                                /* Full coverage, COPY */
445
572
                                d[0] = s[0];
446
573
                                d[1] = s[1];
447
574
                                d[2] = s[2];
448
 
                                d[3] = a;
 
575
                                d[3] = NR_NORMALIZE_21(a);
449
576
                        } else {
 
577
                                /* Full composition */
450
578
                                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;
 
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);
457
584
                        }
458
585
                        d += 4;
459
586
                        s += 4;
468
595
void
469
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)
470
597
{
471
 
        int r, c;
 
598
        unsigned int r, c;
472
599
 
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++) {
 
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--) {
479
605
                        unsigned int a;
480
 
                        a = NR_PREMUL (s[3], m[0]);
 
606
                        a = NR_PREMUL_112(s[3], m[0]);
481
607
                        if (a == 0) {
482
608
                                /* Transparent FG, NOP */
483
 
                        } else if ((a == 255) || (d[3] == 0)) {
 
609
                        } else if (a == 255*255) {
 
610
                                /* Opaque FG, COPY */
 
611
                                memcpy(d, s, 4);
 
612
                        } else if (d[3] == 0) {
484
613
                                /* 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;
 
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);
489
629
                        } 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
 
                                }
 
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);
510
637
                        }
511
638
                        d += 4;
512
639
                        s += 4;
521
648
void
522
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)
523
650
{
524
 
        int r, c;
 
651
        unsigned int r, c;
525
652
 
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++) {
 
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--) {
532
658
                        unsigned int a;
533
 
                        a = NR_PREMUL (s[3], m[0]);
 
659
                        a = NR_PREMUL_112(s[3], m[0]);
534
660
                        if (a == 0) {
535
661
                                /* 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;
 
662
                        } else if (a == 255*255) {
 
663
                                memcpy(d, s, 4);
542
664
                        } 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;
 
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]);
547
669
                        }
548
670
                        d += 4;
549
671
                        s += 4;
558
680
void
559
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)
560
682
{
561
 
        int r, c;
 
683
        unsigned int r, c;
562
684
 
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++) {
 
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--) {
569
690
                        unsigned int a;
570
 
                        a = NR_PREMUL (s[3], m[0]);
 
691
                        a = NR_PREMUL_112 (s[3], m[0]);
571
692
                        if (a == 0) {
572
693
                                /* Transparent FG, NOP */
573
 
                        } else if ((a == 255) || (d[3] == 0)) {
 
694
                        } else if (a == 255*255) {
 
695
                                /* Opaque FG, COPY */
 
696
                                memcpy(d, s, 4);
 
697
                        } else if (d[3] == 0) {
574
698
                                /* 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]);
 
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);
579
705
                        } 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
 
                                }
 
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]);
596
712
                        }
597
713
                        d += 4;
598
714
                        s += 4;
604
720
        }
605
721
}
606
722
 
607
 
void
608
 
nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba)
609
 
{
610
 
        unsigned int r, g, b, a;
611
 
        int x, y;
612
 
 
613
 
        r = NR_RGBA32_R (rgba);
614
 
        g = NR_RGBA32_G (rgba);
615
 
        b = NR_RGBA32_B (rgba);
616
 
        a = NR_RGBA32_A (rgba);
617
 
 
618
 
        if (a == 0) return;
619
 
 
620
 
        for (y = 0; y < h; y++) {
621
 
                unsigned char *d, *s;
622
 
                d = (unsigned char *) px;
623
 
                s = (unsigned char *) spx;
624
 
                for (x = 0; x < w; x++) {
625
 
                        d[0] = r;
626
 
                        d[1] = g;
627
 
                        d[2] = b;
628
 
                        d[3] = NR_PREMUL (s[0], a);
629
 
                        d += 4;
630
 
                        s += 1;
631
 
                }
632
 
                px += rs;
633
 
                spx += srs;
634
 
        }
635
 
}
636
 
 
637
 
void
638
 
nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba)
639
 
{
640
 
        unsigned int r, g, b, a;
641
 
        int x, y;
642
 
 
643
 
        r = NR_RGBA32_R (rgba);
644
 
        g = NR_RGBA32_G (rgba);
645
 
        b = NR_RGBA32_B (rgba);
646
 
        a = NR_RGBA32_A (rgba);
647
 
 
648
 
        if (a == 0) return;
649
 
 
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
662
 
 
663
 
        for (y = 0; y < h; y++) {
664
 
                unsigned char *d, *s;
665
 
                d = (unsigned char *) px;
666
 
                s = (unsigned char *) spx;
667
 
                for (x = 0; x < w; x++) {
668
 
                        unsigned int ca;
669
 
                        ca = s[0] * a;
670
 
                        d[0] = (r * ca + 32512) / 65025;
671
 
                        d[1] = (g * ca + 32512) / 65025;
672
 
                        d[2] = (b * ca + 32512) / 65025;
673
 
                        d[3] = (ca + 127) / 255;
674
 
                        d += 4;
675
 
                        s += 1;
676
 
                }
677
 
                px += rs;
678
 
                spx += srs;
679
 
        }
680
 
}
681
 
 
682
 
void
683
 
nr_R8G8B8_R8G8B8_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba)
684
 
{
685
 
        unsigned int r, g, b, a;
686
 
        int x, y;
687
 
 
688
 
        r = NR_RGBA32_R (rgba);
689
 
        g = NR_RGBA32_G (rgba);
690
 
        b = NR_RGBA32_B (rgba);
691
 
        a = NR_RGBA32_A (rgba);
692
 
 
693
 
        if (a == 0) return;
694
 
 
695
 
        for (y = 0; y < h; y++) {
696
 
                unsigned char *d, *m;
697
 
                d = (unsigned char *) px;
698
 
                m = (unsigned char *) mpx;
699
 
                for (x = 0; x < w; x++) {
700
 
                        unsigned int alpha;
701
 
                        alpha = NR_PREMUL (a, m[0]);
702
 
                        d[0] = NR_COMPOSEN11 (r, alpha, d[0]);
703
 
                        d[1] = NR_COMPOSEN11 (g, alpha, d[1]);
704
 
                        d[2] = NR_COMPOSEN11 (b, alpha, d[2]);
705
 
                        d += 3;
706
 
                        m += 1;
707
 
                }
708
 
                px += rs;
709
 
                mpx += mrs;
710
 
        }
711
 
}
712
 
 
713
 
void
714
 
nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba)
715
 
{
716
 
        unsigned int r, g, b, a;
717
 
        int x, y;
718
 
 
719
 
        r = NR_RGBA32_R (rgba);
720
 
        g = NR_RGBA32_G (rgba);
721
 
        b = NR_RGBA32_B (rgba);
722
 
        a = NR_RGBA32_A (rgba);
723
 
 
724
 
        if (a == 0) return;
725
 
 
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 */
 
723
/* FINAL DST MASK COLOR */
 
724
 
 
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)
 
727
{
 
728
        unsigned int r, g, b, a;
 
729
        unsigned int x, y;
 
730
 
 
731
        r = NR_RGBA32_R (rgba);
 
732
        g = NR_RGBA32_G (rgba);
 
733
        b = NR_RGBA32_B (rgba);
 
734
        a = NR_RGBA32_A (rgba);
 
735
 
 
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--) {
737
743
                                d[0] = r;
738
744
                                d[1] = g;
739
745
                                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;
 
746
                                d[3] = NR_PREMUL_111 (m[0], a);
 
747
                                d += 4;
 
748
                                m += 1;
 
749
                        }
 
750
                }
 
751
                px += rs;
 
752
                mpx += mrs;
 
753
        }
 
754
}
 
755
 
 
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)
 
758
{
 
759
        unsigned int r, g, b, a;
 
760
        unsigned int x, y;
 
761
 
 
762
        r = NR_RGBA32_R (rgba);
 
763
        g = NR_RGBA32_G (rgba);
 
764
        b = NR_RGBA32_B (rgba);
 
765
        a = NR_RGBA32_A (rgba);
 
766
 
 
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
 
779
 
 
780
        if ( a != 255 ){
 
781
                // Pre-premultiply color values
 
782
                r *= a;
 
783
                g *= a;
 
784
                b *= a;
 
785
        }
 
786
 
 
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
        }
 
815
}
 
816
 
 
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)
 
819
{
 
820
        unsigned int r, g, b, a;
 
821
        unsigned int x, y;
 
822
 
 
823
        r = NR_RGBA32_R (rgba);
 
824
        g = NR_RGBA32_G (rgba);
 
825
        b = NR_RGBA32_B (rgba);
 
826
        a = NR_RGBA32_A (rgba);
 
827
 
 
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
        }
 
862
}
 
863
 
 
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)
 
866
{
 
867
        unsigned int r, g, b, a;
 
868
        unsigned int x, y;
 
869
 
 
870
        r = NR_RGBA32_R (rgba);
 
871
        g = NR_RGBA32_G (rgba);
 
872
        b = NR_RGBA32_B (rgba);
 
873
        a = NR_RGBA32_A (rgba);
 
874
 
 
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
                }
755
933
        }
756
934
}
757
935
 
759
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)
760
938
{
761
939
        unsigned int r, g, b, a;
762
 
        int x, y;
763
 
 
764
 
        if (!(rgba & 0xff)) return;
 
940
        unsigned int x, y;
765
941
 
766
942
        r = NR_RGBA32_R (rgba);
767
943
        g = NR_RGBA32_G (rgba);
769
945
        a = NR_RGBA32_A (rgba);
770
946
 
771
947
#ifdef WITH_MMX
772
 
        if (NR_PIXOPS_MMX) {
 
948
        if (NR_PIXOPS_MMX && a != 0) {
773
949
                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);
 
950
                c[0] = NR_PREMUL_111 (r, a);
 
951
                c[1] = NR_PREMUL_111 (g, a);
 
952
                c[2] = NR_PREMUL_111 (b, a);
777
953
                c[3] = a;
778
954
                /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
779
955
                nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP (px, w, h, rs, spx, srs, c);
781
957
        }
782
958
#endif
783
959
 
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;
 
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
                }
811
1009
        }
812
1010
}
813
1011
 
816
1014
void
817
1015
nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
818
1016
{
819
 
        int r, c;
820
 
 
821
 
        if (alpha == 0) return;
 
1017
        unsigned int r, c;
822
1018
 
823
1019
#ifdef WITH_MMX
824
 
        if (NR_PIXOPS_MMX) {
 
1020
        if (NR_PIXOPS_MMX && alpha != 0) {
825
1021
                /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
826
1022
                nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (px, w, h, rs, spx, srs, alpha);
827
1023
                return;
828
1024
        }
829
1025
#endif
830
1026
 
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++) {
 
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
838
1035
                                if (s[3] == 0) {
839
1036
                                        /* NOP */
840
1037
                                } else if (s[3] == 255) {
842
1039
                                        d[1] = s[1];
843
1040
                                        d[2] = s[2];
844
1041
                                } 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]);
 
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]);
848
1045
                                }
849
1046
                                d += 3;
850
1047
                                s += 4;
851
1048
                        }
852
 
                } else {
853
 
                        d = px;
854
 
                        s = spx;
855
 
                        for (c = 0; c < w; c++) {
 
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--) {
856
1057
                                unsigned int a;
857
 
                                a = NR_PREMUL (s[3], alpha);
 
1058
                                a = NR_PREMUL_112(s[3], alpha);
 
1059
                                //   dc' = (1 - alpha*sa) * dc + alpha*sc
858
1060
                                if (a == 0) {
859
1061
                                        /* NOP */
860
1062
                                } 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]);
 
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]);
864
1066
                                }
865
1067
                                /* a == 255 is impossible, because alpha < 255 */
866
1068
                                d += 3;
867
1069
                                s += 4;
868
1070
                        }
 
1071
                        px += rs;
 
1072
                        spx += srs;
869
1073
                }
870
 
                px += rs;
871
 
                spx += srs;
872
1074
        }
873
1075
}
874
1076
 
875
1077
void
876
1078
nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha)
877
1079
{
878
 
        int r, c;
 
1080
        unsigned int r, c;
879
1081
 
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++) {
 
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
889
1090
                                if (s[3] == 0) {
890
1091
                                        /* NOP */
891
1092
                                } else if (s[3] == 255) {
893
1094
                                        d[1] = s[1];
894
1095
                                        d[2] = s[2];
895
1096
                                } 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]);
 
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]);
899
1100
                                }
900
1101
                                d += 3;
901
1102
                                s += 4;
902
1103
                        }
903
 
                } else {
904
 
                        d = px;
905
 
                        s = spx;
906
 
                        for (c = 0; c < w; c++) {
 
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--) {
907
1112
                                unsigned int a;
908
 
                                a = NR_PREMUL (s[3], alpha);
 
1113
                                a = NR_PREMUL_112(s[3], alpha);
 
1114
                                //   dc' = (1 - alpha*sa) * dc + alpha*sa*sc
909
1115
                                if (a == 0) {
910
1116
                                        /* NOP */
911
1117
                                } 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]);
 
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]);
915
1121
                                }
916
1122
                                /* a == 255 is impossible, because alpha < 255 */
917
1123
                                d += 3;
918
1124
                                s += 4;
919
1125
                        }
 
1126
                        px += rs;
 
1127
                        spx += srs;
920
1128
                }
921
 
                px += rs;
922
 
                spx += srs;
923
1129
        }
924
1130
}
925
1131
 
926
1132
void
927
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)
928
1134
{
929
 
        int x, y;
 
1135
        unsigned int x, y;
930
1136
 
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++) {
 
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--) {
937
1142
                        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]);
 
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]);
947
1153
                        }
948
1154
                        d += 3;
949
1155
                        s += 4;
958
1164
void
959
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)
960
1166
{
961
 
        int x, y;
 
1167
        unsigned int x, y;
962
1168
 
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++) {
 
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--) {
969
1174
                        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]);
 
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]);
975
1185
                        }
976
1186
                        d += 3;
977
1187
                        s += 4;