From 179fa413b047bede6e32109e2ce82437c5fb8d34 Mon Sep 17 00:00:00 2001 From: MenTaLguY Date: Mon, 16 Jan 2006 02:36:01 +0000 Subject: moving trunk for module inkscape (bzr r1) --- src/libnr/nr-compose.cpp | 986 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 986 insertions(+) create mode 100644 src/libnr/nr-compose.cpp (limited to 'src/libnr/nr-compose.cpp') diff --git a/src/libnr/nr-compose.cpp b/src/libnr/nr-compose.cpp new file mode 100644 index 000000000..8eed6e84c --- /dev/null +++ b/src/libnr/nr-compose.cpp @@ -0,0 +1,986 @@ +#define __NR_COMPOSE_C__ + +/* + * Pixel buffer rendering library + * + * Authors: + * Lauris Kaplinski + * + * This code is in public domain + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "nr-pixops.h" + +#ifdef WITH_MMX +/* fixme: */ +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ +int nr_have_mmx (void); +void nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned char *c); +void nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned char *c); +void nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha); +#define NR_PIXOPS_MMX nr_have_mmx () +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif + +void +nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) +{ + int r, c; + + for (r = 0; r < h; r++) { + if (alpha == 0) { + memset (px, 0x0, 4 * w); + } else if (alpha == 255) { + memcpy (px, spx, 4 * w); + } else { + const unsigned char *s; + unsigned char *d; + d = px; + s = spx; + for (c = 0; c < w; c++) { + *d++ = *s++; + *d++ = *s++; + *d++ = *s++; + *d++ = NR_PREMUL (*s, alpha); + s++; + } + } + px += rs; + spx += srs; + } +} + +void +nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) +{ + int r, c; + + for (r = 0; r < h; r++) { + if (alpha == 0) { + memset (px, 0x0, 4 * w); + } else { + const unsigned char *s; + unsigned char *d; + s = spx; + d = px; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], alpha); + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + d[3] = a; + d += 4; + s += 4; + } + px += rs; + spx += srs; + } + } +} + +void +nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (c = 0; c < w; c++) { + unsigned int a; + a = (s[3] * alpha + 127) / 255; + d[0] = (s[0] * a + 127) / 255; + d[1] = (s[1] * a + 127) / 255; + d[2] = (s[2] * a + 127) / 255; + d[3] = a; + d += 4; + s += 4; + } + px += rs; + spx += srs; + } +} + +void +nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (c = 0; c < w; c++) { + if (alpha == 255) { + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + d[3] = s[3]; + } else { + d[0] = NR_PREMUL (s[0], alpha); + d[1] = NR_PREMUL (s[1], alpha); + d[2] = NR_PREMUL (s[2], alpha); + d[3] = NR_PREMUL (s[3], alpha); + } + d += 4; + s += 4; + } + px += rs; + spx += srs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], alpha); + if (a == 0) { + /* Transparent FG, NOP */ + } else if ((a == 255) || (d[3] == 0)) { + /* Full coverage, COPY */ + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + d[3] = a; + } else { + unsigned int ca; + /* Full composition */ + ca = 65025 - (255 - a) * (255 - d[3]); + d[0] = NR_COMPOSENNN_A7 (s[0], a, d[0], d[3], ca); + d[1] = NR_COMPOSENNN_A7 (s[1], a, d[1], d[3], ca); + d[2] = NR_COMPOSENNN_A7 (s[2], a, d[2], d[3], ca); + d[3] = (ca + 127) / 255; + } + d += 4; + s += 4; + } + px += rs; + spx += srs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], alpha); + if (a == 0) { + /* Transparent FG, NOP */ + } else if ((a == 255) || (d[3] == 0)) { + /* Full coverage, demul src */ + d[0] = (s[0] * 255 + (s[3] >> 1)) / s[3]; + d[1] = (s[1] * 255 + (s[3] >> 1)) / s[3]; + d[2] = (s[2] * 255 + (s[3] >> 1)) / s[3]; + d[3] = a; + } else { + if (alpha == 255) { + unsigned int ca; + /* Full composition */ + ca = 65025 - (255 - s[3]) * (255 - d[3]); + d[0] = NR_COMPOSEPNN_A7 (s[0], s[3], d[0], d[3], ca); + d[1] = NR_COMPOSEPNN_A7 (s[1], s[3], d[1], d[3], ca); + d[2] = NR_COMPOSEPNN_A7 (s[2], s[3], d[2], d[3], ca); + d[3] = (65025 - (255 - s[3]) * (255 - d[3]) + 127) / 255; + } else { + // calculate premultiplied from two premultiplieds: + d[0] = NR_COMPOSEPPP(NR_PREMUL (s[0], alpha), a, NR_PREMUL (d[0], d[3]), 0); // last parameter not used + d[1] = NR_COMPOSEPPP(NR_PREMUL (s[1], alpha), a, NR_PREMUL (d[1], d[3]), 0); + d[2] = NR_COMPOSEPPP(NR_PREMUL (s[2], alpha), a, NR_PREMUL (d[2], d[3]), 0); + // total opacity: + d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255; + // un-premultiply channels: + d[0] = d[0]*255/d[3]; + d[1] = d[1]*255/d[3]; + d[2] = d[2]*255/d[3]; + } + } + d += 4; + s += 4; + } + px += rs; + spx += srs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], alpha); + if (a == 0) { + /* Transparent FG, NOP */ + } else if ((a == 255) || (d[3] == 0)) { + /* Transparent BG, premul src */ + d[0] = NR_PREMUL (s[0], a); + d[1] = NR_PREMUL (s[1], a); + d[2] = NR_PREMUL (s[2], a); + d[3] = a; + } else { + d[0] = NR_COMPOSENPP (s[0], a, d[0], d[3]); + d[1] = NR_COMPOSENPP (s[1], a, d[1], d[3]); + d[2] = NR_COMPOSENPP (s[2], a, d[2], d[3]); + d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255; + } + d += 4; + s += 4; + } + px += rs; + spx += srs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], alpha); + if (a == 0) { + /* Transparent FG, NOP */ + } else if ((a == 255) || (d[3] == 0)) { + /* Transparent BG, COPY */ + d[0] = NR_PREMUL (s[0], alpha); + d[1] = NR_PREMUL (s[1], alpha); + d[2] = NR_PREMUL (s[2], alpha); + d[3] = NR_PREMUL (s[3], alpha); + } else { + if (alpha == 255) { + /* Simple */ + d[0] = NR_COMPOSEPPP (s[0], s[3], d[0], d[3]); + d[1] = NR_COMPOSEPPP (s[1], s[3], d[1], d[3]); + d[2] = NR_COMPOSEPPP (s[2], s[3], d[2], d[3]); + d[3] = (65025 - (255 - s[3]) * (255 - d[3]) + 127) / 255; + } else { + unsigned int c; + c = NR_PREMUL (s[0], alpha); + d[0] = NR_COMPOSEPPP (c, a, d[0], d[3]); + c = NR_PREMUL (s[1], alpha); + d[1] = NR_COMPOSEPPP (c, a, d[1], d[3]); + c = NR_PREMUL (s[2], alpha); + d[2] = NR_COMPOSEPPP (c, a, d[2], d[3]); + d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255; + } + } + d += 4; + s += 4; + } + px += rs; + spx += srs; + } +} + +/* Masked operations */ + +void +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) +{ + int x, y; + + for (y = 0; y < h; y++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (x = 0; x < w; x++) { + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + d[3] = (s[3] * m[0] + 127) / 255; + d += 4; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +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) +{ + int x, y; + + for (y = 0; y < h; y++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (x = 0; x < w; x++) { + unsigned int a; + a = NR_PREMUL (s[3], m[0]); + if (a == 0) { + d[3] = 0; + } else { + d[0] = (s[0] * 255 + (a >> 1)) / a; + d[1] = (s[1] * 255 + (a >> 1)) / a; + d[2] = (s[2] * 255 + (a >> 1)) / a; + d[3] = a; + } + d += 4; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], m[0]); + d[0] = NR_PREMUL (s[0], a); + d[1] = NR_PREMUL (s[1], a); + d[2] = NR_PREMUL (s[2], a); + d[3] = a; + d += 4; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (c = 0; c < w; c++) { + if (m[0] == 255) { + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + d[3] = s[3]; + } else { + d[0] = NR_PREMUL (s[0], m[0]); + d[1] = NR_PREMUL (s[1], m[0]); + d[2] = NR_PREMUL (s[2], m[0]); + d[3] = NR_PREMUL (s[3], m[0]); + } + d += 4; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], m[0]); + if (a == 0) { + /* Transparent FG, NOP */ + } else if ((a == 255) || (d[3] == 0)) { + /* Full coverage, COPY */ + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + d[3] = a; + } else { + unsigned int ca; + /* Full composition */ + ca = 65025 - (255 - a) * (255 - d[3]); + d[0] = NR_COMPOSENNN_A7 (s[0], a, d[0], d[3], ca); + d[1] = NR_COMPOSENNN_A7 (s[1], a, d[1], d[3], ca); + d[2] = NR_COMPOSENNN_A7 (s[2], a, d[2], d[3], ca); + d[3] = (ca + 127) / 255; + } + d += 4; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], m[0]); + if (a == 0) { + /* Transparent FG, NOP */ + } else if ((a == 255) || (d[3] == 0)) { + /* Full coverage, demul src */ + d[0] = (s[0] * 255 + (s[3] >> 1)) / s[3]; + d[1] = (s[1] * 255 + (s[3] >> 1)) / s[3]; + d[2] = (s[2] * 255 + (s[3] >> 1)) / s[3]; + d[3] = a; + } else { + if (m[0] == 255) { + unsigned int ca; + /* Full composition */ + ca = 65025 - (255 - s[3]) * (255 - d[3]); + d[0] = NR_COMPOSEPNN_A7 (s[0], s[3], d[0], d[3], ca); + d[1] = NR_COMPOSEPNN_A7 (s[1], s[3], d[1], d[3], ca); + d[2] = NR_COMPOSEPNN_A7 (s[2], s[3], d[2], d[3], ca); + d[3] = (65025 - (255 - s[3]) * (255 - d[3]) + 127) / 255; + } else { + // calculate premultiplied from two premultiplieds: + d[0] = NR_COMPOSEPPP(NR_PREMUL (s[0], m[0]), a, NR_PREMUL (d[0], d[3]), 0); // last parameter not used + d[1] = NR_COMPOSEPPP(NR_PREMUL (s[1], m[0]), a, NR_PREMUL (d[1], d[3]), 0); + d[2] = NR_COMPOSEPPP(NR_PREMUL (s[2], m[0]), a, NR_PREMUL (d[2], d[3]), 0); + // total opacity: + d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255; + // un-premultiply channels: + d[0] = d[0]*255/d[3]; + d[1] = d[1]*255/d[3]; + d[2] = d[2]*255/d[3]; + } + } + d += 4; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], m[0]); + if (a == 0) { + /* Transparent FG, NOP */ + } else if ((a == 255) || (d[3] == 0)) { + /* Transparent BG, premul src */ + d[0] = NR_PREMUL (s[0], a); + d[1] = NR_PREMUL (s[1], a); + d[2] = NR_PREMUL (s[2], a); + d[3] = a; + } else { + d[0] = NR_COMPOSENPP (s[0], a, d[0], d[3]); + d[1] = NR_COMPOSENPP (s[1], a, d[1], d[3]); + d[2] = NR_COMPOSENPP (s[2], a, d[2], d[3]); + d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255; + } + d += 4; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +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) +{ + int r, c; + + for (r = 0; r < h; r++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], m[0]); + if (a == 0) { + /* Transparent FG, NOP */ + } else if ((a == 255) || (d[3] == 0)) { + /* Transparent BG, COPY */ + d[0] = NR_PREMUL (s[0], m[0]); + d[1] = NR_PREMUL (s[1], m[0]); + d[2] = NR_PREMUL (s[2], m[0]); + d[3] = NR_PREMUL (s[3], m[0]); + } else { + if (m[0] == 255) { + /* Simple */ + d[0] = NR_COMPOSEPPP (s[0], s[3], d[0], d[3]); + d[1] = NR_COMPOSEPPP (s[1], s[3], d[1], d[3]); + d[2] = NR_COMPOSEPPP (s[2], s[3], d[2], d[3]); + d[3] = NR_A7_NORMALIZED(s[3], d[3]); + } else { + unsigned int c; + c = NR_PREMUL (s[0], m[0]); + d[0] = NR_COMPOSEPPP (c, a, d[0], d[3]); + c = NR_PREMUL (s[1], m[0]); + d[1] = NR_COMPOSEPPP (c, a, d[1], d[3]); + c = NR_PREMUL (s[2], m[0]); + d[2] = NR_COMPOSEPPP (c, a, d[2], d[3]); + d[3] = NR_A7_NORMALIZED(a, d[3]); + } + } + d += 4; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +nr_R8G8B8A8_N_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba) +{ + unsigned int r, g, b, a; + int x, y; + + r = NR_RGBA32_R (rgba); + g = NR_RGBA32_G (rgba); + b = NR_RGBA32_B (rgba); + a = NR_RGBA32_A (rgba); + + if (a == 0) return; + + for (y = 0; y < h; y++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (x = 0; x < w; x++) { + d[0] = r; + d[1] = g; + d[2] = b; + d[3] = NR_PREMUL (s[0], a); + d += 4; + s += 1; + } + px += rs; + spx += srs; + } +} + +void +nr_R8G8B8A8_P_EMPTY_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned long rgba) +{ + unsigned int r, g, b, a; + int x, y; + + r = NR_RGBA32_R (rgba); + g = NR_RGBA32_G (rgba); + b = NR_RGBA32_B (rgba); + a = NR_RGBA32_A (rgba); + + if (a == 0) return; + +#ifdef WITH_MMX + if (NR_PIXOPS_MMX) { + unsigned char c[4]; + c[0] = NR_PREMUL (r, a); + c[1] = NR_PREMUL (g, a); + c[2] = NR_PREMUL (b, a); + c[3] = a; + /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */ + nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (px, w, h, rs, spx, srs, c); + return; + } +#endif + + for (y = 0; y < h; y++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (x = 0; x < w; x++) { + unsigned int ca; + ca = s[0] * a; + d[0] = (r * ca + 32512) / 65025; + d[1] = (g * ca + 32512) / 65025; + d[2] = (b * ca + 32512) / 65025; + d[3] = (ca + 127) / 255; + d += 4; + s += 1; + } + px += rs; + spx += srs; + } +} + +void +nr_R8G8B8_R8G8B8_A8_RGBA32 (unsigned char *px, int w, int h, int rs, const unsigned char *mpx, int mrs, unsigned long rgba) +{ + unsigned int r, g, b, a; + int x, y; + + r = NR_RGBA32_R (rgba); + g = NR_RGBA32_G (rgba); + b = NR_RGBA32_B (rgba); + a = NR_RGBA32_A (rgba); + + if (a == 0) return; + + for (y = 0; y < h; y++) { + unsigned char *d, *m; + d = (unsigned char *) px; + m = (unsigned char *) mpx; + for (x = 0; x < w; x++) { + unsigned int alpha; + alpha = NR_PREMUL (a, m[0]); + d[0] = NR_COMPOSEN11 (r, alpha, d[0]); + d[1] = NR_COMPOSEN11 (g, alpha, d[1]); + d[2] = NR_COMPOSEN11 (b, alpha, d[2]); + d += 3; + m += 1; + } + px += rs; + mpx += mrs; + } +} + +void +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) +{ + unsigned int r, g, b, a; + int x, y; + + r = NR_RGBA32_R (rgba); + g = NR_RGBA32_G (rgba); + b = NR_RGBA32_B (rgba); + a = NR_RGBA32_A (rgba); + + if (a == 0) return; + + for (y = 0; y < h; y++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (x = 0; x < w; x++) { + unsigned int ca; + ca = NR_PREMUL (s[0], a); + if (ca == 0) { + /* Transparent FG, NOP */ + } else if ((ca == 255) || (d[3] == 0)) { + /* Full coverage, COPY */ + d[0] = r; + d[1] = g; + d[2] = b; + d[3] = ca; + } else { + unsigned int da; + /* Full composition */ + da = 65025 - (255 - ca) * (255 - d[3]); + d[0] = NR_COMPOSENNN_A7 (r, ca, d[0], d[3], da); + d[1] = NR_COMPOSENNN_A7 (g, ca, d[1], d[3], da); + d[2] = NR_COMPOSENNN_A7 (b, ca, d[2], d[3], da); + d[3] = (da + 127) / 255; + } + d += 4; + s += 1; + } + px += rs; + spx += srs; + } +} + +void +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) +{ + unsigned int r, g, b, a; + int x, y; + + if (!(rgba & 0xff)) return; + + r = NR_RGBA32_R (rgba); + g = NR_RGBA32_G (rgba); + b = NR_RGBA32_B (rgba); + a = NR_RGBA32_A (rgba); + +#ifdef WITH_MMX + if (NR_PIXOPS_MMX) { + unsigned char c[4]; + c[0] = NR_PREMUL (r, a); + c[1] = NR_PREMUL (g, a); + c[2] = NR_PREMUL (b, a); + c[3] = a; + /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */ + nr_mmx_R8G8B8A8_P_R8G8B8A8_P_A8_RGBAP (px, w, h, rs, spx, srs, c); + return; + } +#endif + + for (y = 0; y < h; y++) { + unsigned char *d, *s; + d = (unsigned char *) px; + s = (unsigned char *) spx; + for (x = 0; x < w; x++) { + unsigned int ca; + ca = NR_PREMUL (s[0], a); + if (ca == 0) { + /* Transparent FG, NOP */ + } else if ((ca == 255) || (d[3] == 0)) { + /* Full coverage, COPY */ + d[0] = NR_PREMUL (r, ca); + d[1] = NR_PREMUL (g, ca); + d[2] = NR_PREMUL (b, ca); + d[3] = ca; + } else { + /* Full composition */ + d[0] = NR_COMPOSENPP (r, ca, d[0], d[3]); + d[1] = NR_COMPOSENPP (g, ca, d[1], d[3]); + d[2] = NR_COMPOSENPP (b, ca, d[2], d[3]); + d[3] = (65025 - (255 - ca) * (255 - d[3]) + 127) / 255; + } + d += 4; + s += 1; + } + px += rs; + spx += srs; + } +} + +/* RGB */ + +void +nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) +{ + int r, c; + + if (alpha == 0) return; + +#ifdef WITH_MMX + if (NR_PIXOPS_MMX) { + /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */ + nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (px, w, h, rs, spx, srs, alpha); + return; + } +#endif + + for (r = 0; r < h; r++) { + const unsigned char *s; + unsigned char *d; + if (alpha == 255) { + d = px; + s = spx; + for (c = 0; c < w; c++) { + if (s[3] == 0) { + /* NOP */ + } else if (s[3] == 255) { + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + } else { + d[0] = NR_COMPOSEP11 (s[0], s[3], d[0]); + d[1] = NR_COMPOSEP11 (s[1], s[3], d[1]); + d[2] = NR_COMPOSEP11 (s[2], s[3], d[2]); + } + d += 3; + s += 4; + } + } else { + d = px; + s = spx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], alpha); + if (a == 0) { + /* NOP */ + } else { + d[0] = NR_COMPOSEP11 (s[0], a, d[0]); + d[1] = NR_COMPOSEP11 (s[1], a, d[1]); + d[2] = NR_COMPOSEP11 (s[2], a, d[2]); + } + /* a == 255 is impossible, because alpha < 255 */ + d += 3; + s += 4; + } + } + px += rs; + spx += srs; + } +} + +void +nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsigned char *spx, int srs, unsigned int alpha) +{ + int r, c; + + for (r = 0; r < h; r++) { + const unsigned char *s; + unsigned char *d; + if (alpha == 0) { + /* NOP */ + } else if (alpha == 255) { + d = px; + s = spx; + for (c = 0; c < w; c++) { + if (s[3] == 0) { + /* NOP */ + } else if (s[3] == 255) { + d[0] = s[0]; + d[1] = s[1]; + d[2] = s[2]; + } else { + d[0] = NR_COMPOSEN11 (s[0], s[3], d[0]); + d[1] = NR_COMPOSEN11 (s[1], s[3], d[1]); + d[2] = NR_COMPOSEN11 (s[2], s[3], d[2]); + } + d += 3; + s += 4; + } + } else { + d = px; + s = spx; + for (c = 0; c < w; c++) { + unsigned int a; + a = NR_PREMUL (s[3], alpha); + if (a == 0) { + /* NOP */ + } else { + d[0] = NR_COMPOSEN11 (s[0], a, d[0]); + d[1] = NR_COMPOSEN11 (s[1], a, d[1]); + d[2] = NR_COMPOSEN11 (s[2], a, d[2]); + } + /* a == 255 is impossible, because alpha < 255 */ + d += 3; + s += 4; + } + } + px += rs; + spx += srs; + } +} + +void +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) +{ + int x, y; + + for (y = 0; y < h; y++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (x = 0; x < w; x++) { + unsigned int a; + a = NR_PREMUL (s[3], m[0]); + if (a != 0) { + unsigned int r, g, b; + r = NR_PREMUL (s[0], m[0]); + d[0] = NR_COMPOSEP11 (r, a, d[0]); + g = NR_PREMUL (s[1], m[0]); + d[1] = NR_COMPOSEP11 (g, a, d[1]); + b = NR_PREMUL (s[2], m[0]); + d[2] = NR_COMPOSEP11 (b, a, d[2]); + } + d += 3; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + +void +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) +{ + int x, y; + + for (y = 0; y < h; y++) { + unsigned char *d, *s, *m; + d = (unsigned char *) px; + s = (unsigned char *) spx; + m = (unsigned char *) mpx; + for (x = 0; x < w; x++) { + unsigned int a; + a = NR_PREMUL (s[3], m[0]); + if (a != 0) { + d[0] = NR_COMPOSEP11 (s[0], a, d[0]); + d[1] = NR_COMPOSEP11 (s[1], a, d[1]); + d[2] = NR_COMPOSEP11 (s[2], a, d[2]); + } + d += 3; + s += 4; + m += 1; + } + px += rs; + spx += srs; + mpx += mrs; + } +} + + -- cgit v1.2.3