~centralelyon2010/inkscape/imagelinks2

« back to all changes in this revision

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

  • Committer: JazzyNico
  • Date: 2011-08-29 20:25:30 UTC
  • Revision ID: nicoduf@yahoo.fr-20110829202530-6deuoz11q90usldv
Code refactoring and merging with trunk (revision 10599).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#define __NR_COMPOSE_TRANSFORM_C__
2
 
 
3
 
/*
4
 
 * Pixel buffer rendering library
5
 
 *
6
 
 * Authors:
7
 
 *   Lauris Kaplinski <lauris@kaplinski.com>
8
 
 *
9
 
 * This code is in public domain
10
 
 */
11
 
 
12
 
#ifdef HAVE_CONFIG_H
13
 
# include "config.h"
14
 
#endif
15
 
 
16
 
#include "nr-pixops.h"
17
 
#include "nr-matrix.h"
18
 
 
19
 
/*#ifdef WITH_MMX
20
 
#ifdef __cplusplus
21
 
extern "C" {
22
 
#endif // __cplusplus
23
 
/ * fixme: * /
24
 
/ *int nr_have_mmx (void);
25
 
#define NR_PIXOPS_MMX (1 && nr_have_mmx ())
26
 
#ifdef __cplusplus
27
 
}
28
 
#endif //__cplusplus
29
 
#endif
30
 
*/
31
 
 
32
 
/* fixme: Implement missing (Lauris) */
33
 
/* fixme: PREMUL colors before calculating average (Lauris) */
34
 
 
35
 
/* Fixed point precision */
36
 
#define FBITS 12
37
 
#define FBITS_HP 18 // In some places we need a higher precision
38
 
 
39
 
void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
40
 
                                               const unsigned char *spx, int sw, int sh, int srs,
41
 
                                               const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
42
 
void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
43
 
                                               const unsigned char *spx, int sw, int sh, int srs,
44
 
                                               const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
45
 
void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
46
 
                                               const unsigned char *spx, int sw, int sh, int srs,
47
 
                                               const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
48
 
void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
49
 
                                               const unsigned char *spx, int sw, int sh, int srs,
50
 
                                               const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
51
 
 
52
 
void
53
 
nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
54
 
                                               const unsigned char *spx, int sw, int sh, int srs,
55
 
                                               const NR::Matrix &d2s, unsigned int alpha, int xd, int yd)
56
 
{
57
 
        int xsize, ysize, size, dbits;
58
 
        long FFs_x_x, FFs_x_y, FFs_y_x, FFs_y_y, FFs__x, FFs__y;
59
 
        long FFs_x_x_S, FFs_x_y_S, FFs_y_x_S, FFs_y_y_S;
60
 
        /* Subpixel positions */
61
 
        int FF_sx_S[256];
62
 
        int FF_sy_S[256];
63
 
        unsigned char *d0;
64
 
        int FFsx0, FFsy0;
65
 
        int x, y;
66
 
 
67
 
        if (alpha == 0) return;
68
 
    if (alpha>255) {
69
 
        g_warning("In transform PPN alpha=%u>255",alpha);
70
 
    }
71
 
 
72
 
    // The color component is stored temporarily with a range of [0,255^3], so more supersampling and we get an overflow (fortunately Inkscape's preferences also doesn't allow a higher setting)
73
 
    if (xd+yd>8) {
74
 
        xd = 4;
75
 
        yd = 4;
76
 
    }
77
 
 
78
 
        xsize = (1 << xd);
79
 
        ysize = (1 << yd);
80
 
        size = xsize * ysize;
81
 
        dbits = xd + yd;
82
 
    unsigned int rounding_fix = size/2;
83
 
 
84
 
        /* Set up fixed point matrix */
85
 
        FFs_x_x = (long) floor(d2s[0] * (1 << FBITS) + 0.5);
86
 
        FFs_x_y = (long) floor(d2s[1] * (1 << FBITS) + 0.5);
87
 
        FFs_y_x = (long) floor(d2s[2] * (1 << FBITS) + 0.5);
88
 
        FFs_y_y = (long) floor(d2s[3] * (1 << FBITS) + 0.5);
89
 
        FFs__x = (long) floor(d2s[4] * (1 << FBITS) + 0.5);
90
 
        FFs__y = (long) floor(d2s[5] * (1 << FBITS) + 0.5);
91
 
 
92
 
        FFs_x_x_S = FFs_x_x >> xd;
93
 
        FFs_x_y_S = FFs_x_y >> xd;
94
 
        FFs_y_x_S = FFs_y_x >> yd;
95
 
        FFs_y_y_S = FFs_y_y >> yd;
96
 
 
97
 
        /* Set up subpixel matrix */
98
 
        /* fixme: We can calculate that in floating point (Lauris) */
99
 
        for (y = 0; y < ysize; y++) {
100
 
                for (x = 0; x < xsize; x++) {
101
 
                        FF_sx_S[y * xsize + x] = FFs_x_x_S * x + FFs_y_x_S * y;
102
 
                        FF_sy_S[y * xsize + x] = FFs_x_y_S * x + FFs_y_y_S * y;
103
 
                }
104
 
        }
105
 
 
106
 
        d0 = px;
107
 
        FFsx0 = FFs__x;
108
 
        FFsy0 = FFs__y;
109
 
 
110
 
        for (y = 0; y < h; y++) {
111
 
                unsigned char *d;
112
 
                long FFsx, FFsy;
113
 
                d = d0;
114
 
                FFsx = FFsx0;
115
 
                FFsy = FFsy0;
116
 
                for (x = 0; x < w; x++) {
117
 
                        unsigned int r, g, b, a;
118
 
                        long sx, sy;
119
 
                        int i;
120
 
                        r = g = b = a = 0;
121
 
                        for (i = 0; i < size; i++) {
122
 
                                sx = (FFsx + FF_sx_S[i]) >> FBITS;
123
 
                                if ((sx >= 0) && (sx < sw)) {
124
 
                                        sy = (FFsy + FF_sy_S[i]) >> FBITS;
125
 
                                        if ((sy >= 0) && (sy < sh)) {
126
 
                                                const unsigned char *s;
127
 
                                                s = spx + sy * srs + sx * 4;
128
 
                                                r += NR_PREMUL_112 (s[0], s[3]); // s in [0,255]
129
 
                                                g += NR_PREMUL_112 (s[1], s[3]);
130
 
                                                b += NR_PREMUL_112 (s[2], s[3]);
131
 
                                                a += s[3];
132
 
                        // a=sum(s3)
133
 
                        // r,g,b in [0,sum(s3)*255]
134
 
                                        }
135
 
                                }
136
 
                        }
137
 
                        a = (a*alpha + rounding_fix) >> dbits;
138
 
            // a=sum(s3)*alpha/size=avg(s3)*alpha
139
 
            // Compare to nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P
140
 
                        if (a != 0) {
141
 
                                r = (r*alpha + rounding_fix) >> dbits;
142
 
                                g = (g*alpha + rounding_fix) >> dbits;
143
 
                                b = (b*alpha + rounding_fix) >> dbits;
144
 
                // r,g,b in [0,avg(s3)*alpha*255]=[0,a*255]
145
 
                if (a == 255*255) {
146
 
                                        /* Full coverage, demul src */
147
 
                                        d[0] = NR_NORMALIZE_31(r);
148
 
                                        d[1] = NR_NORMALIZE_31(g);
149
 
                                        d[2] = NR_NORMALIZE_31(b);
150
 
                                        d[3] = NR_NORMALIZE_21(a);
151
 
                } else if (d[3] == 0) {
152
 
                    /* Only foreground, demul src */
153
 
                    d[0] = NR_DEMUL_321(r,a);
154
 
                    d[1] = NR_DEMUL_321(g,a);
155
 
                    d[2] = NR_DEMUL_321(b,a);
156
 
                    d[3] = NR_NORMALIZE_21(a);
157
 
                                } else {
158
 
                                        unsigned int ca;
159
 
                                        /* Full composition */
160
 
                                        ca = NR_COMPOSEA_213(a, d[3]);
161
 
                                        d[0] = NR_COMPOSEPNN_321131 (r, a, d[0], d[3], ca);
162
 
                                        d[1] = NR_COMPOSEPNN_321131 (g, a, d[1], d[3], ca);
163
 
                                        d[2] = NR_COMPOSEPNN_321131 (b, a, d[2], d[3], ca);
164
 
                                        d[3] = NR_NORMALIZE_31(ca);
165
 
                                }
166
 
                        }
167
 
                        /* Advance pointers */
168
 
                        FFsx += FFs_x_x;
169
 
                        FFsy += FFs_x_y;
170
 
                        d += 4;
171
 
                }
172
 
                FFsx0 += FFs_y_x;
173
 
                FFsy0 += FFs_y_y;
174
 
                d0 += rs;
175
 
        }
176
 
}
177
 
 
178
 
void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
179
 
                                                    const unsigned char *spx, int sw, int sh, int srs,
180
 
                                                    const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
181
 
 
182
 
static void
183
 
nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (unsigned char *px, int w, int h, int rs,
184
 
                                                 const unsigned char *spx, int sw, int sh, int srs,
185
 
                                                 const long long *FFd2s, unsigned int alpha)
186
 
{
187
 
    unsigned char *d0;
188
 
        long long FFsx0, FFsy0;
189
 
        int x, y;
190
 
 
191
 
        d0 = px;
192
 
        FFsx0 = FFd2s[4];
193
 
        FFsy0 = FFd2s[5];
194
 
 
195
 
        for (y = 0; y < h; y++) {
196
 
                unsigned char *d;
197
 
                long long FFsx, FFsy;
198
 
                d = d0;
199
 
                FFsx = FFsx0;
200
 
                FFsy = FFsy0;
201
 
                for (x = 0; x < w; x++) {
202
 
                        long sx, sy;
203
 
                        sx = long(FFsx >> FBITS_HP);
204
 
                        if ((sx >= 0) && (sx < sw)) {
205
 
                                sy = long(FFsy >> FBITS_HP);
206
 
                                if ((sy >= 0) && (sy < sh)) {
207
 
                                        const unsigned char *s;
208
 
                                        unsigned int a;
209
 
                                        s = spx + sy * srs + sx * 4;
210
 
                                        a = NR_PREMUL_112 (s[3], alpha);
211
 
                                        if (a != 0) {
212
 
                                                if ((a == 255*255) || (d[3] == 0)) {
213
 
                                                        /* Transparent BG, premul src */
214
 
                                                        d[0] = NR_PREMUL_121 (s[0], a);
215
 
                                                        d[1] = NR_PREMUL_121 (s[1], a);
216
 
                                                        d[2] = NR_PREMUL_121 (s[2], a);
217
 
                                                        d[3] = NR_NORMALIZE_21(a);
218
 
                                                } else {
219
 
                                                        d[0] = NR_COMPOSENPP_1211 (s[0], a, d[0]);
220
 
                                                        d[1] = NR_COMPOSENPP_1211 (s[1], a, d[1]);
221
 
                                                        d[2] = NR_COMPOSENPP_1211 (s[2], a, d[2]);
222
 
                                                        d[3] = NR_COMPOSEA_211(a, d[3]);
223
 
                                                }
224
 
                                        }
225
 
                                }
226
 
                        }
227
 
                        /* Advance pointers */
228
 
                        FFsx += FFd2s[0];
229
 
                        FFsy += FFd2s[1];
230
 
                        d += 4;
231
 
                }
232
 
                FFsx0 += FFd2s[2];
233
 
                FFsy0 += FFd2s[3];
234
 
                d0 += rs;
235
 
        }
236
 
}
237
 
 
238
 
static void
239
 
nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h, int rs,
240
 
                                                 const unsigned char *spx, int sw, int sh, int srs,
241
 
                                                 const long long *FFd2s, const long *FF_S, unsigned int alpha, int dbits)
242
 
{
243
 
        int size;
244
 
        unsigned char *d0;
245
 
        long long FFsx0, FFsy0;
246
 
        int x, y;
247
 
 
248
 
        size = (1 << dbits);
249
 
    unsigned int rounding_fix = size/2;
250
 
 
251
 
        d0 = px;
252
 
        FFsx0 = FFd2s[4];
253
 
        FFsy0 = FFd2s[5];
254
 
 
255
 
        for (y = 0; y < h; y++) {
256
 
                unsigned char *d;
257
 
                long long FFsx, FFsy;
258
 
                d = d0;
259
 
                FFsx = FFsx0;
260
 
                FFsy = FFsy0;
261
 
                for (x = 0; x < w; x++) {
262
 
                        unsigned int r, g, b, a;
263
 
                        int i;
264
 
                        r = g = b = a = 0;
265
 
                        for (i = 0; i < size; i++) {
266
 
                                long sx, sy;
267
 
                                sx = (long (FFsx >> (FBITS_HP - FBITS)) + FF_S[2 * i]) >> FBITS;
268
 
                                if ((sx >= 0) && (sx < sw)) {
269
 
                                        sy = (long (FFsy >> (FBITS_HP - FBITS)) + FF_S[2 * i + 1]) >> FBITS;
270
 
                                        if ((sy >= 0) && (sy < sh)) {
271
 
                                                const unsigned char *s;
272
 
                                                s = spx + sy * srs + sx * 4;
273
 
                                                r += NR_PREMUL_112(s[0], s[3]);
274
 
                                                g += NR_PREMUL_112(s[1], s[3]);
275
 
                                                b += NR_PREMUL_112(s[2], s[3]);
276
 
                                                a += s[3];
277
 
                                        }
278
 
                                }
279
 
                        }
280
 
                        a = (a*alpha + rounding_fix) >> dbits;
281
 
                        if (a != 0) {
282
 
                                r = (r*alpha + rounding_fix) >> dbits;
283
 
                                g = (g*alpha + rounding_fix) >> dbits;
284
 
                                b = (b*alpha + rounding_fix) >> dbits;
285
 
                                if ((a == 255*255) || (d[3] == 0)) {
286
 
                                        /* Transparent BG, premul src */
287
 
                                        d[0] = NR_NORMALIZE_31(r);
288
 
                                        d[1] = NR_NORMALIZE_31(g);
289
 
                                        d[2] = NR_NORMALIZE_31(b);
290
 
                                        d[3] = NR_NORMALIZE_21(a);
291
 
                                } else {
292
 
                                        d[0] = NR_COMPOSEPPP_3211 (r, a, d[0]);
293
 
                                        d[1] = NR_COMPOSEPPP_3211 (g, a, d[1]);
294
 
                                        d[2] = NR_COMPOSEPPP_3211 (b, a, d[2]);
295
 
                                        d[3] = NR_COMPOSEA_211(a, d[3]);
296
 
                                }
297
 
                        }
298
 
                        /* Advance pointers */
299
 
                        FFsx += FFd2s[0];
300
 
                        FFsy += FFd2s[1];
301
 
                        d += 4;
302
 
                }
303
 
                FFsx0 += FFd2s[2];
304
 
                FFsy0 += FFd2s[3];
305
 
                d0 += rs;
306
 
        }
307
 
}
308
 
 
309
 
void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
310
 
                                                    const unsigned char *spx, int sw, int sh, int srs,
311
 
                                                    const NR::Matrix &d2s, unsigned int alpha, int xd, int yd)
312
 
{
313
 
        int dbits;
314
 
        long FFd2s[6];
315
 
        long long FFd2s_HP[6]; // with higher precision
316
 
        int i;
317
 
 
318
 
        if (alpha == 0) return;
319
 
    if (alpha>255) {
320
 
        g_warning("In transform PPN alpha=%u>255",alpha);
321
 
    }
322
 
 
323
 
    // The color component is stored temporarily with a range of [0,255^3], so more supersampling and we get an overflow (fortunately Inkscape's preferences also doesn't allow a higher setting)
324
 
    if (xd+yd>8) {
325
 
        xd = 4;
326
 
        yd = 4;
327
 
    }
328
 
 
329
 
    dbits = xd + yd;
330
 
 
331
 
        for (i = 0; i < 6; i++) {
332
 
                FFd2s[i] = (long) floor(d2s[i] * (1 << FBITS) + 0.5);
333
 
                FFd2s_HP[i] = (long long) floor(d2s[i] * (1 << FBITS_HP) + 0.5);;
334
 
        }
335
 
 
336
 
        if (dbits == 0) {
337
 
                nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (px, w, h, rs, spx, sw, sh, srs, FFd2s_HP, alpha);
338
 
        } else {
339
 
                int xsize, ysize;
340
 
                long FFs_x_x_S, FFs_x_y_S, FFs_y_x_S, FFs_y_y_S;
341
 
                long FF_S[2 * 256];
342
 
                int x, y;
343
 
 
344
 
                xsize = (1 << xd);
345
 
                ysize = (1 << yd);
346
 
 
347
 
                FFs_x_x_S = FFd2s[0] >> xd;
348
 
                FFs_x_y_S = FFd2s[1] >> xd;
349
 
                FFs_y_x_S = FFd2s[2] >> yd;
350
 
                FFs_y_y_S = FFd2s[3] >> yd;
351
 
 
352
 
                /* Set up subpixel matrix */
353
 
                /* fixme: We can calculate that in floating point (Lauris) */
354
 
                for (y = 0; y < ysize; y++) {
355
 
                        for (x = 0; x < xsize; x++) {
356
 
                                FF_S[2 * (y * xsize + x)] = FFs_x_x_S * x + FFs_y_x_S * y;
357
 
                                FF_S[2 * (y * xsize + x) + 1] = FFs_x_y_S * x + FFs_y_y_S * y;
358
 
                        }
359
 
                }
360
 
 
361
 
                nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (px, w, h, rs, spx, sw, sh, srs, FFd2s_HP, FF_S, alpha, dbits);
362
 
        }
363
 
}
364
 
 
365
 
void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
366
 
                                                    const unsigned char *spx, int sw, int sh, int srs,
367
 
                                                    const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);