1
#define __NR_COMPOSE_TRANSFORM_C__
4
* Pixel buffer rendering library
7
* Lauris Kaplinski <lauris@kaplinski.com>
9
* This code is in public domain
16
#include "nr-pixops.h"
17
#include "nr-matrix.h"
24
/ *int nr_have_mmx (void);
25
#define NR_PIXOPS_MMX (1 && nr_have_mmx ())
32
/* fixme: Implement missing (Lauris) */
33
/* fixme: PREMUL colors before calculating average (Lauris) */
35
/* Fixed point precision */
37
#define FBITS_HP 18 // In some places we need a higher precision
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);
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)
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 */
67
if (alpha == 0) return;
69
g_warning("In transform PPN alpha=%u>255",alpha);
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)
82
unsigned int rounding_fix = size/2;
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);
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;
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;
110
for (y = 0; y < h; y++) {
116
for (x = 0; x < w; x++) {
117
unsigned int r, g, b, a;
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]);
133
// r,g,b in [0,sum(s3)*255]
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
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]
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);
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);
167
/* Advance pointers */
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);
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)
188
long long FFsx0, FFsy0;
195
for (y = 0; y < h; y++) {
197
long long FFsx, FFsy;
201
for (x = 0; x < w; x++) {
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;
209
s = spx + sy * srs + sx * 4;
210
a = NR_PREMUL_112 (s[3], alpha);
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);
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]);
227
/* Advance pointers */
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)
245
long long FFsx0, FFsy0;
249
unsigned int rounding_fix = size/2;
255
for (y = 0; y < h; y++) {
257
long long FFsx, FFsy;
261
for (x = 0; x < w; x++) {
262
unsigned int r, g, b, a;
265
for (i = 0; i < size; i++) {
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]);
280
a = (a*alpha + rounding_fix) >> dbits;
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);
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]);
298
/* Advance pointers */
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)
315
long long FFd2s_HP[6]; // with higher precision
318
if (alpha == 0) return;
320
g_warning("In transform PPN alpha=%u>255",alpha);
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)
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);;
337
nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (px, w, h, rs, spx, sw, sh, srs, FFd2s_HP, alpha);
340
long FFs_x_x_S, FFs_x_y_S, FFs_y_x_S, FFs_y_y_S;
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;
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;
361
nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (px, w, h, rs, spx, sw, sh, srs, FFd2s_HP, FF_S, alpha, dbits);
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);