summaryrefslogtreecommitdiffstats
path: root/src/libnr/nr-compose.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libnr/nr-compose.cpp')
-rw-r--r--src/libnr/nr-compose.cpp986
1 files changed, 986 insertions, 0 deletions
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 <lauris@kaplinski.com>
+ *
+ * This code is in public domain
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <string.h>
+#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;
+ }
+}
+
+