index 8eed6e84c99f4556ef94b7650d22e4e6c2bdf592..3b99678e26b40255080f69d65f685be95e78284f 100644 (file)
--- a/src/libnr/nr-compose.cpp
+++ b/src/libnr/nr-compose.cpp
@@ -31,26 +31,26 @@ void nr_mmx_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, c
#endif /* __cplusplus */
#endif
+// Naming: nr_RESULT_BACKGROUND_FOREGROUND_extra
+
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;
+ unsigned int r, c;
- for (r = 0; r < h; r++) {
+ for (r = h; r > 0; r--) {
if (alpha == 0) {
- memset (px, 0x0, 4 * w);
+ memset(px, 0x0, 4 * w);
} else if (alpha == 255) {
- memcpy (px, spx, 4 * w);
+ memcpy(px, spx, 4 * w);
} else {
- const unsigned char *s;
- unsigned char *d;
- d = px;
- s = spx;
- for (c = 0; c < w; c++) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
- *d++ = NR_PREMUL (*s, alpha);
+ *d++ = NR_PREMUL_111(*s, alpha);
s++;
}
}
@@ -62,50 +62,68 @@ nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const u
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;
+ unsigned int r, c;
- for (r = 0; r < h; r++) {
+ for (r = h; r > 0; r--) {
if (alpha == 0) {
- memset (px, 0x0, 4 * w);
+ 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;
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ if (s[3] == 0) {
+ d[3] = 0;
+ } else if (s[3] == 255) {
+ memcpy(d, s, 4);
+ } else {
+ d[0] = NR_DEMUL_111(s[0], s[3]);
+ d[1] = NR_DEMUL_111(s[1], s[3]);
+ d[2] = NR_DEMUL_111(s[2], s[3]);
+ d[3] = NR_PREMUL_111(s[3], alpha);
+ }
d += 4;
s += 4;
}
- px += rs;
- spx += srs;
}
+ 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;
+ unsigned 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;
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ if (alpha == 0) {
+ memset(px, 0x0, 4 * w);
+ } else if (alpha == 255) {
+ for (c = w; c > 0; c--) {
+ d[0] = NR_PREMUL_111(s[0], s[3]);
+ d[1] = NR_PREMUL_111(s[1], s[3]);
+ d[2] = NR_PREMUL_111(s[2], s[3]);
+ d[3] = s[3];
+ d += 4;
+ s += 4;
+ }
+ } else {
+ for (c = w; c > 0; c--) {
+ if (s[3] == 0) {
+ memset(d, 0, 4);
+ } else {
+ unsigned int a;
+ a = NR_PREMUL_112(s[3], alpha);
+ d[0] = NR_PREMUL_121(s[0], a);
+ d[1] = NR_PREMUL_121(s[1], a);
+ d[2] = NR_PREMUL_121(s[2], a);
+ d[3] = NR_NORMALIZE_21(a);
+ }
+ d += 4;
+ s += 4;
+ }
}
px += rs;
spx += srs;
@@ -115,26 +133,24 @@ nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const u
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);
+ unsigned int r, c;
+
+ for (r = h; r > 0; r--) {
+ if (alpha == 0) {
+ memset(px, 0x0, 4 * w);
+ } else if (alpha == 255) {
+ memcpy(px, spx, 4 * w);
+ } else {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ d[0] = NR_PREMUL_111(s[0], alpha);
+ d[1] = NR_PREMUL_111(s[1], alpha);
+ d[2] = NR_PREMUL_111(s[2], alpha);
+ d[3] = NR_PREMUL_111(s[3], alpha);
+ d += 4;
+ s += 4;
}
- d += 4;
- s += 4;
}
px += rs;
spx += srs;
@@ -144,167 +160,280 @@ nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const u
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;
+ unsigned int r, c;
+
+ if (alpha == 0) {
+ /* NOP */
+ } else if (alpha == 255) {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ if (s[3] == 0) {
+ /* Transparent FG, NOP */
+ } else if ((s[3] == 255) || (d[3] == 0)) {
+ /* Full coverage, COPY */
+ memcpy(d, s, 4);
+ } else {
+ /* Full composition */
+ unsigned int ca;
+ ca = NR_COMPOSEA_112(s[3], d[3]);
+ d[0] = NR_COMPOSENNN_111121(s[0], s[3], d[0], d[3], ca);
+ d[1] = NR_COMPOSENNN_111121(s[1], s[3], d[1], d[3], ca);
+ d[2] = NR_COMPOSENNN_111121(s[2], s[3], d[2], d[3], ca);
+ d[3] = NR_NORMALIZE_21(ca);
+ }
+ d += 4;
+ s += 4;
}
- d += 4;
- s += 4;
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ unsigned int a;
+ a = NR_PREMUL_112(s[3], alpha);
+ if (a == 0) {
+ /* Transparent FG, NOP */
+ } else if ((a == 255*255) || (d[3] == 0)) {
+ /* Full coverage, COPY */
+ d[0] = s[0];
+ d[1] = s[1];
+ d[2] = s[2];
+ d[3] = NR_NORMALIZE_21(a);
+ } else {
+ /* Full composition */
+ unsigned int ca;
+ ca = NR_COMPOSEA_213(a, d[3]);
+ d[0] = NR_COMPOSENNN_121131(s[0], a, d[0], d[3], ca);
+ d[1] = NR_COMPOSENNN_121131(s[1], a, d[1], d[3], ca);
+ d[2] = NR_COMPOSENNN_121131(s[2], a, d[2], d[3], ca);
+ d[3] = NR_NORMALIZE_31(ca);
+ }
+ d += 4;
+ s += 4;
+ }
+ px += rs;
+ spx += srs;
}
- 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;
+ unsigned int r, c;
+
+ if (alpha == 0) {
+ /* NOP */
+ } else if (alpha == 255) {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ if (s[3] == 0) {
+ /* Transparent FG, NOP */
+ } else if (s[3] == 255) {
+ /* Full coverage, demul src */
+ // dc' = ((1 - sa) * da*dc + sc)/da' = sc/da' = sc
+ // da' = 1 - (1 - sa) * (1 - da) = 1 - 0 * (1 - da) = 1
+ memcpy(d, s, 4);
+ } else if (d[3] == 0) {
+ /* Full coverage, demul src */
+ // dc' = ((1 - sa) * da*dc + sc)/da' = sc/da' = sc/sa = sc/sa
+ // da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) = sa
+ d[0] = NR_DEMUL_111(s[0], s[3]);
+ d[1] = NR_DEMUL_111(s[1], s[3]);
+ d[2] = NR_DEMUL_111(s[2], s[3]);
+ d[3] = s[3];
+ } else {
/* 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;
+ // dc' = ((1 - sa) * da*dc + sc)/da' = ((1 - sa) * da*dc + sc)/da'
+ // da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) * (1 - da)
+ unsigned int da = NR_COMPOSEA_112(s[3], d[3]);
+ d[0] = NR_COMPOSEPNN_111121(s[0], s[3], d[0], d[3], da);
+ d[1] = NR_COMPOSEPNN_111121(s[1], s[3], d[1], d[3], da);
+ d[2] = NR_COMPOSEPNN_111121(s[2], s[3], d[2], d[3], da);
+ d[3] = NR_NORMALIZE_21(da);
+ }
+ d += 4;
+ s += 4;
+ }
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ unsigned int a;
+ a = NR_PREMUL_112(s[3], alpha);
+ if (a == 0) {
+ /* Transparent FG, NOP */
+ } else if (d[3] == 0) {
+ /* Full coverage, demul src */
+ // dc' = ((1 - alpha*sa) * da*dc + alpha*sc)/da' = alpha*sc/da' = alpha*sc/(alpha*sa) = sc/sa
+ // da' = 1 - (1 - alpha*sa) * (1 - da) = 1 - (1 - alpha*sa) = alpha*sa
+ d[0] = NR_DEMUL_111(s[0], s[3]);
+ d[1] = NR_DEMUL_111(s[1], s[3]);
+ d[2] = NR_DEMUL_111(s[2], s[3]);
+ d[3] = NR_NORMALIZE_21(a);
} 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];
+ // dc' = ((1 - alpha*sa) * da*dc + alpha*sc)/da'
+ // da' = 1 - (1 - alpha*sa) * (1 - da)
+ unsigned int da = NR_COMPOSEA_213(a, d[3]);
+ d[0] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[0], alpha), a, d[0], d[3], da);
+ d[1] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[1], alpha), a, d[1], d[3], da);
+ d[2] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[2], alpha), a, d[2], d[3], da);
+ d[3] = NR_NORMALIZE_31(da);
}
+ d += 4;
+ s += 4;
}
- d += 4;
- s += 4;
+ px += rs;
+ spx += srs;
}
- 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;
+ unsigned int r, c;
+
+ if (alpha == 0) {
+ /* NOP */
+ } else if (alpha == 255) {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ if (s[3] == 0) {
+ /* Transparent FG, NOP */
+ } else if (s[3] == 255) {
+ /* Opaque FG, COPY */
+ // dc' = (1 - sa) * dc + sa*sc = sa*sc = sc
+ // da' = 1 - (1 - sa) * (1 - da) = 1 - 0 * (1 - da) = 1 (= sa)
+ memcpy(d, s, 4);
+ } else if (d[3] == 0) {
+ /* Transparent BG, premul src */
+ // dc' = (1 - sa) * dc + sa*sc = sa*sc
+ // da' = 1 - (1 - sa) * (1 - da) = 1 - (1 - sa) = sa
+ d[0] = NR_PREMUL_111(s[0], s[3]);
+ d[1] = NR_PREMUL_111(s[1], s[3]);
+ d[2] = NR_PREMUL_111(s[2], s[3]);
+ d[3] = s[3];
+ } else {
+ // dc' = (1 - sa) * dc + sa*sc
+ // da' = 1 - (1 - sa) * (1 - da)
+ d[0] = NR_COMPOSENPP_1111(s[0], s[3], d[0]);
+ d[1] = NR_COMPOSENPP_1111(s[1], s[3], d[1]);
+ d[2] = NR_COMPOSENPP_1111(s[2], s[3], d[2]);
+ d[3] = NR_COMPOSEA_111(s[3], d[3]);
+ }
+ d += 4;
+ s += 4;
}
- d += 4;
- s += 4;
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ unsigned int a;
+ a = NR_PREMUL_112 (s[3], alpha);
+ if (a == 0) {
+ /* Transparent FG, NOP */
+ } else if (d[3] == 0) {
+ /* Transparent BG, premul src */
+ // dc' = (1 - alpha*sa) * dc + alpha*sa*sc = alpha*sa*sc
+ // da' = 1 - (1 - alpha*sa) * (1 - da) = 1 - (1 - alpha*sa) = alpha*sa
+ d[0] = NR_PREMUL_121(s[0], a);
+ d[1] = NR_PREMUL_121(s[1], a);
+ d[2] = NR_PREMUL_121(s[2], a);
+ d[3] = NR_NORMALIZE_21(a);
+ } else {
+ // dc' = (1 - alpha*sa) * dc + alpha*sa*sc
+ // da' = 1 - (1 - alpha*sa) * (1 - da)
+ d[0] = NR_COMPOSENPP_1211(s[0], a, d[0]);
+ d[1] = NR_COMPOSENPP_1211(s[1], a, d[1]);
+ d[2] = NR_COMPOSENPP_1211(s[2], a, d[2]);
+ d[3] = NR_COMPOSEA_211(a, d[3]);
+ }
+ d += 4;
+ s += 4;
+ }
+ px += rs;
+ spx += srs;
}
- 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;
+ unsigned int r, c;
+
+ if (alpha == 0) {
+ /* Transparent FG, NOP */
+ } else if (alpha == 255) {
+ /* Simple */
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ if (s[3] == 0) {
+ /* Transparent FG, NOP */
+ } else if ((s[3] == 255) || (d[3] == 0)) {
+ /* Transparent BG, COPY */
+ memcpy(d, s, 4);
} 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[0] = NR_COMPOSEPPP_1111(s[0], s[3], d[0]);
+ d[1] = NR_COMPOSEPPP_1111(s[1], s[3], d[1]);
+ d[2] = NR_COMPOSEPPP_1111(s[2], s[3], d[2]);
+ d[3] = NR_COMPOSEA_111(s[3], d[3]);
}
+ d += 4;
+ s += 4;
}
- d += 4;
- s += 4;
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ if (s[3] == 0) {
+ /* Transparent FG, NOP */
+ } else if (d[3] == 0) {
+ /* Transparent BG, COPY */
+ d[0] = NR_PREMUL_111(s[0], alpha);
+ d[1] = NR_PREMUL_111(s[1], alpha);
+ d[2] = NR_PREMUL_111(s[2], alpha);
+ d[3] = NR_PREMUL_111(s[3], alpha);
+ } else {
+ // dc' = (1 - alpha*sa) * dc + alpha*sc
+ // da' = 1 - (1 - alpha*sa) * (1 - da)
+ unsigned int a;
+ a = NR_PREMUL_112(s[3], alpha);
+ d[0] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[0]), a, d[0]);
+ d[1] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[1]), a, d[1]);
+ d[2] = NR_COMPOSEPPP_2211(NR_PREMUL_112(alpha, s[2]), a, d[2]);
+ d[3] = NR_COMPOSEA_211(a, d[3]);
+ }
+ d += 4;
+ s += 4;
+ }
+ px += rs;
+ spx += srs;
}
- px += rs;
- spx += srs;
}
}
@@ -313,18 +442,17 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, co
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++) {
+ unsigned int r, c;
+
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ const unsigned char *m = mpx;
+ for (c = w; c > 0; c--) {
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
- d[3] = (s[3] * m[0] + 127) / 255;
+ d[3] = NR_PREMUL_111(s[3], m[0]);
d += 4;
s += 4;
m += 1;
@@ -338,23 +466,26 @@ nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, cons
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 r, c;
+
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ const unsigned char *m = mpx;
+ for (c = w; c > 0; c--) {
unsigned int a;
- a = NR_PREMUL (s[3], m[0]);
+ a = NR_PREMUL_112 (s[3], m[0]);
if (a == 0) {
d[3] = 0;
+ } else if (a == 255*255) {
+ memcpy(d, s, 4);
} 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;
+ // dc' = ((1 - m*sa) * da*dc + m*sc)/da' = m*sc/da' = m*sc/(m*sa) = sc/sa
+ // da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa) = m*sa
+ d[0] = NR_DEMUL_111(s[0], s[3]);
+ d[1] = NR_DEMUL_111(s[1], s[3]);
+ d[2] = NR_DEMUL_111(s[2], s[3]);
+ d[3] = NR_NORMALIZE_21(a);
}
d += 4;
s += 4;
@@ -369,20 +500,25 @@ nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, cons
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 r, c;
+
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ const unsigned char *m = mpx;
+ for (c = w; c > 0; 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;
+ a = NR_PREMUL_112(s[3], m[0]);
+ if (a == 0) {
+ memset(d, 0, 4);
+ } else if (a == 255*255) {
+ memcpy(d, s, 4);
+ } else {
+ d[0] = NR_PREMUL_121(s[0], a);
+ d[1] = NR_PREMUL_121(s[1], a);
+ d[2] = NR_PREMUL_121(s[2], a);
+ d[3] = NR_NORMALIZE_21(a);
+ }
d += 4;
s += 4;
m += 1;
@@ -396,25 +532,17 @@ nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs, cons
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]);
- }
+ unsigned int r, c;
+
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ const unsigned char *m = mpx;
+ for (c = w; c > 0; c--) {
+ d[0] = NR_PREMUL_111(s[0], m[0]);
+ d[1] = NR_PREMUL_111(s[1], m[0]);
+ d[2] = NR_PREMUL_111(s[2], m[0]);
+ d[3] = NR_PREMUL_111(s[3], m[0]);
d += 4;
s += 4;
m += 1;
@@ -428,32 +556,31 @@ nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, cons
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 r, c;
+
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ const unsigned char *m = mpx;
+ for (c = w; c > 0; c--) {
unsigned int a;
- a = NR_PREMUL (s[3], m[0]);
+ a = NR_PREMUL_112(s[3], m[0]);
if (a == 0) {
/* Transparent FG, NOP */
- } else if ((a == 255) || (d[3] == 0)) {
+ } else if ((a == 255*255) || (d[3] == 0)) {
/* Full coverage, COPY */
d[0] = s[0];
d[1] = s[1];
d[2] = s[2];
- d[3] = a;
+ d[3] = NR_NORMALIZE_21(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;
+ unsigned int ca;
+ ca = NR_COMPOSEA_213(a, d[3]);
+ d[0] = NR_COMPOSENNN_121131(s[0], a, d[0], d[3], ca);
+ d[1] = NR_COMPOSENNN_121131(s[1], a, d[1], d[3], ca);
+ d[2] = NR_COMPOSENNN_121131(s[2], a, d[2], d[3], ca);
+ d[3] = NR_NORMALIZE_31(ca);
}
d += 4;
s += 4;
@@ -468,45 +595,45 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs,
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 r, c;
+
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ const unsigned char *m = mpx;
+ for (c = w; c > 0; c--) {
unsigned int a;
- a = NR_PREMUL (s[3], m[0]);
+ a = NR_PREMUL_112(s[3], m[0]);
if (a == 0) {
/* Transparent FG, NOP */
- } else if ((a == 255) || (d[3] == 0)) {
+ } else if (a == 255*255) {
+ /* Opaque FG, COPY */
+ memcpy(d, s, 4);
+ } else if (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;
+ // dc' = ((1 - m*sa) * da*dc + m*sc)/da' = m*sc/da' = m*sc/(m*sa) = sc/sa
+ // da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa) = m*sa
+ d[0] = NR_DEMUL_111(s[0], s[3]);
+ d[1] = NR_DEMUL_111(s[1], s[3]);
+ d[2] = NR_DEMUL_111(s[2], s[3]);
+ d[3] = NR_NORMALIZE_21(a);
+ } else if (m[0] == 255) {
+ /* Full composition */
+ // dc' = ((1 - m*sa) * da*dc + m*sc)/da' = ((1 - sa) * da*dc + sc)/da'
+ // da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - sa) * (1 - da)
+ unsigned int da = NR_COMPOSEA_112(s[3], d[3]);
+ d[0] = NR_COMPOSEPNN_111121(s[0], s[3], d[0], d[3], da);
+ d[1] = NR_COMPOSEPNN_111121(s[1], s[3], d[1], d[3], da);
+ d[2] = NR_COMPOSEPNN_111121(s[2], s[3], d[2], d[3], da);
+ d[3] = NR_NORMALIZE_21(da);
} 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];
- }
+ // dc' = ((1 - m*sa) * da*dc + m*sc)/da'
+ // da' = 1 - (1 - m*sa) * (1 - da)
+ unsigned int da = NR_COMPOSEA_213(a, d[3]);
+ d[0] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[0], m[0]), a, d[0], d[3], da);
+ d[1] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[1], m[0]), a, d[1], d[3], da);
+ d[2] = NR_COMPOSEPNN_221131(NR_PREMUL_112(s[2], m[0]), a, d[2], d[3], da);
+ d[3] = NR_NORMALIZE_31(da);
}
d += 4;
s += 4;
@@ -521,29 +648,24 @@ nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs,
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 r, c;
+
+ for (r = h; r>0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ const unsigned char *m = mpx;
+ for (c = w; c>0; c--) {
unsigned int a;
- a = NR_PREMUL (s[3], m[0]);
+ a = NR_PREMUL_112(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 if (a == 255*255) {
+ memcpy(d, s, 4);
} 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[0] = NR_COMPOSENPP_1211(s[0], a, d[0]);
+ d[1] = NR_COMPOSENPP_1211(s[1], a, d[1]);
+ d[2] = NR_COMPOSENPP_1211(s[2], a, d[2]);
+ d[3] = NR_COMPOSEA_211(a, d[3]);
}
d += 4;
s += 4;
@@ -558,41 +680,35 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8 (unsigned char *px, int w, int h, int rs,
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 r, c;
+
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ const unsigned char *m = mpx;
+ for (c = w; c > 0; c--) {
unsigned int a;
- a = NR_PREMUL (s[3], m[0]);
+ a = NR_PREMUL_112 (s[3], m[0]);
if (a == 0) {
/* Transparent FG, NOP */
- } else if ((a == 255) || (d[3] == 0)) {
+ } else if (a == 255*255) {
+ /* Opaque FG, COPY */
+ memcpy(d, s, 4);
+ } else if (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]);
+ // dc' = (1 - m*sa) * dc + m*sc = m*sc
+ // da' = 1 - (1 - m*sa) * (1 - da) = 1 - (1 - m*sa) = m*sa
+ d[0] = NR_PREMUL_111 (s[0], m[0]);
+ d[1] = NR_PREMUL_111 (s[1], m[0]);
+ d[2] = NR_PREMUL_111 (s[2], m[0]);
+ d[3] = NR_NORMALIZE_21(a);
} 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]);
- }
+ // dc' = (1 - m*sa) * dc + m*sc
+ // da' = 1 - (1 - m*sa) * (1 - da)
+ d[0] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[0], m[0]), a, d[0]);
+ d[1] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[1], m[0]), a, d[1]);
+ d[2] = NR_COMPOSEPPP_2211 (NR_PREMUL_112 (s[2], m[0]), a, d[2]);
+ d[3] = NR_COMPOSEA_211(a, d[3]);
}
d += 4;
s += 4;
@@ -604,78 +720,97 @@ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs,
}
}
+/* FINAL DST MASK COLOR */
+
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)
+nr_R8G8B8A8_N_EMPTY_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;
+ unsigned 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;
+ for (y = h; y > 0; y--) {
+ if (a == 0) {
+ memset(px, 0, w*4);
+ } else {
+ unsigned char *d = px;
+ const unsigned char *m = mpx;
+ for (x = w; x > 0; x--) {
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = NR_PREMUL_111 (m[0], a);
+ d += 4;
+ m += 1;
+ }
}
px += rs;
- spx += srs;
+ mpx += mrs;
}
}
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)
+nr_R8G8B8A8_P_EMPTY_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;
+ unsigned 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[0] = NR_PREMUL_111 (r, a);
+ c[1] = NR_PREMUL_111 (g, a);
+ c[2] = NR_PREMUL_111 (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);
+ nr_mmx_R8G8B8A8_P_EMPTY_A8_RGBAP (px, w, h, rs, mpx, mrs, 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;
+ if ( a != 255 ){
+ // Pre-premultiply color values
+ r *= a;
+ g *= a;
+ b *= a;
+ }
+
+ for (y = h; y > 0; y--) {
+ unsigned char *d = px;
+ const unsigned char *m = mpx;
+ if (a == 0) {
+ memset(px, 0, w*4);
+ } else if (a == 255) {
+ for (x = w; x > 0; x--) {
+ d[0] = NR_PREMUL_111(m[0], r);
+ d[1] = NR_PREMUL_111(m[0], g);
+ d[2] = NR_PREMUL_111(m[0], b);
+ d[3] = m[0];
+ d += 4;
+ m += 1;
+ }
+ } else {
+ for (x = w; x > 0; x--) {
+ // Color values are already premultiplied with a
+ d[0] = NR_PREMUL_121(m[0], r);
+ d[1] = NR_PREMUL_121(m[0], g);
+ d[2] = NR_PREMUL_121(m[0], b);
+ d[3] = NR_PREMUL_111(m[0], a);
+ d += 4;
+ m += 1;
+ }
}
px += rs;
- spx += srs;
+ mpx += mrs;
}
}
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;
+ unsigned 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;
+ if (a == 0) {
+ /* NOP */
+ } else if (a == 255) {
+ for (y = h; y > 0; y--) {
+ unsigned char *d = px;
+ const unsigned char *m = mpx;
+ for (x = w; x > 0; x--) {
+ d[0] = NR_COMPOSEN11_1111 (r, m[0], d[0]);
+ d[1] = NR_COMPOSEN11_1111 (g, m[0], d[1]);
+ d[2] = NR_COMPOSEN11_1111 (b, m[0], d[2]);
+ d += 3;
+ m += 1;
+ }
+ px += rs;
+ mpx += mrs;
+ }
+ } else {
+ for (y = h; y > 0; y--) {
+ unsigned char *d = px;
+ const unsigned char *m = mpx;
+ for (x = w; x > 0; x--) {
+ // dc' = (1 - m*sa) * dc + m*sa*sc
+ unsigned int alpha;
+ alpha = NR_PREMUL_112 (a, m[0]);
+ d[0] = NR_COMPOSEN11_1211 (r, alpha, d[0]);
+ d[1] = NR_COMPOSEN11_1211 (g, alpha, d[1]);
+ d[2] = NR_COMPOSEN11_1211 (b, alpha, d[2]);
+ d += 3;
+ m += 1;
+ }
+ px += rs;
+ mpx += mrs;
}
- 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)
+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)
{
unsigned int r, g, b, a;
- int x, y;
+ unsigned 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;
+ if (a == 0) {
+ /* NOP */
+ } else if (a == 255) {
+ for (y = h; y > 0; y--) {
+ unsigned char *d = px;
+ const unsigned char *m = mpx;
+ for (x = w; x > 0; x--) {
+ if (m[0] == 0) {
+ /* Transparent FG, NOP */
+ } else if (m[0] == 255 || d[3] == 0) {
+ /* Full coverage, COPY */
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = m[0];
+ } else {
+ /* Full composition */
+ unsigned int da = NR_COMPOSEA_112(m[0], d[3]);
+ d[0] = NR_COMPOSENNN_111121(r, m[0], d[0], d[3], da);
+ d[1] = NR_COMPOSENNN_111121(g, m[0], d[1], d[3], da);
+ d[2] = NR_COMPOSENNN_111121(b, m[0], d[2], d[3], da);
+ d[3] = NR_NORMALIZE_21(da);
+ }
+ d += 4;
+ m += 1;
}
- d += 4;
- s += 1;
+ px += rs;
+ mpx += mrs;
+ }
+ } else {
+ for (y = h; y > 0; y--) {
+ unsigned char *d = px;
+ const unsigned char *m = mpx;
+ for (x = w; x > 0; x--) {
+ unsigned int ca;
+ ca = NR_PREMUL_112 (m[0], a);
+ if (ca == 0) {
+ /* Transparent FG, NOP */
+ } else if (d[3] == 0) {
+ /* Full coverage, COPY */
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = NR_NORMALIZE_21(ca);
+ } else {
+ /* Full composition */
+ unsigned int da = NR_COMPOSEA_213(ca, d[3]);
+ d[0] = NR_COMPOSENNN_121131(r, ca, d[0], d[3], da);
+ d[1] = NR_COMPOSENNN_121131(g, ca, d[1], d[3], da);
+ d[2] = NR_COMPOSENNN_121131(b, ca, d[2], d[3], da);
+ d[3] = NR_NORMALIZE_31(da);
+ }
+ d += 4;
+ m += 1;
+ }
+ px += rs;
+ mpx += mrs;
}
- px += rs;
- spx += srs;
}
}
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;
+ unsigned int x, y;
r = NR_RGBA32_R (rgba);
g = NR_RGBA32_G (rgba);
@@ -769,11 +945,11 @@ nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (unsigned char *px, int w, int h, int rs, con
a = NR_RGBA32_A (rgba);
#ifdef WITH_MMX
- if (NR_PIXOPS_MMX) {
+ if (NR_PIXOPS_MMX && a != 0) {
unsigned char c[4];
- c[0] = NR_PREMUL (r, a);
- c[1] = NR_PREMUL (g, a);
- c[2] = NR_PREMUL (b, a);
+ c[0] = NR_PREMUL_111 (r, a);
+ c[1] = NR_PREMUL_111 (g, a);
+ c[2] = NR_PREMUL_111 (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);
@@ -781,33 +957,55 @@ nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (unsigned char *px, int w, int h, int rs, con
}
#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;
+ if (a == 0) {
+ /* Transparent FG, NOP */
+ } else if (a == 255) {
+ /* Simple */
+ for (y = h; y > 0; y--) {
+ unsigned char *d, *s;
+ d = (unsigned char *) px;
+ s = (unsigned char *) spx;
+ for (x = w; x > 0; x--) {
+ if (s[0] == 0) {
+ /* Transparent FG, NOP */
+ } else {
+ /* Full composition */
+ unsigned int invca = 255-s[0]; // By swapping the arguments GCC can better optimize these calls
+ d[0] = NR_COMPOSENPP_1111(d[0], invca, r);
+ d[1] = NR_COMPOSENPP_1111(d[1], invca, g);
+ d[2] = NR_COMPOSENPP_1111(d[2], invca, b);
+ d[3] = NR_COMPOSEA_111(s[0], d[3]);
+ }
+ d += 4;
+ s += 1;
}
- d += 4;
- s += 1;
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ for (y = h; y > 0; y--) {
+ unsigned char *d, *s;
+ d = (unsigned char *) px;
+ s = (unsigned char *) spx;
+ for (x = w; x > 0; x--) {
+ unsigned int ca;
+ ca = NR_PREMUL_112 (s[0], a);
+ if (ca == 0) {
+ /* Transparent FG, NOP */
+ } else {
+ /* Full composition */
+ unsigned int invca = 255*255-ca; // By swapping the arguments GCC can better optimize these calls
+ d[0] = NR_COMPOSENPP_1211(d[0], invca, r);
+ d[1] = NR_COMPOSENPP_1211(d[1], invca, g);
+ d[2] = NR_COMPOSENPP_1211(d[2], invca, b);
+ d[3] = NR_COMPOSEA_211(ca, d[3]);
+ }
+ d += 4;
+ s += 1;
+ }
+ px += rs;
+ spx += srs;
}
- px += rs;
- spx += srs;
}
}
@@ -816,25 +1014,24 @@ nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32 (unsigned char *px, int w, int h, int rs, con
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;
+ unsigned int r, c;
#ifdef WITH_MMX
- if (NR_PIXOPS_MMX) {
+ if (NR_PIXOPS_MMX && alpha != 0) {
/* 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 (alpha == 0) {
+ /* NOP */
+ } else if (alpha == 255) {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ // dc' = (1 - alpha*sa) * dc + alpha*sc = (1 - sa) * dc + sc
if (s[3] == 0) {
/* NOP */
} else if (s[3] == 255) {
@@ -842,50 +1039,54 @@ nr_R8G8B8_R8G8B8_R8G8B8A8_P (unsigned char *px, int w, int h, int rs, const unsi
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[0] = NR_COMPOSEP11_1111(s[0], s[3], d[0]);
+ d[1] = NR_COMPOSEP11_1111(s[1], s[3], d[1]);
+ d[2] = NR_COMPOSEP11_1111(s[2], s[3], d[2]);
}
d += 3;
s += 4;
}
- } else {
- d = px;
- s = spx;
- for (c = 0; c < w; c++) {
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
unsigned int a;
- a = NR_PREMUL (s[3], alpha);
+ a = NR_PREMUL_112(s[3], alpha);
+ // dc' = (1 - alpha*sa) * dc + alpha*sc
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]);
+ d[0] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[0], alpha), a, d[0]);
+ d[1] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[1], alpha), a, d[1]);
+ d[2] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[2], alpha), a, d[2]);
}
/* a == 255 is impossible, because alpha < 255 */
d += 3;
s += 4;
}
+ px += rs;
+ spx += srs;
}
- 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++) {
+ unsigned int r, c;
+
+ if (alpha == 0) {
+ /* NOP */
+ } else if (alpha == 255) {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
+ // dc' = (1 - alpha*sa) * dc + alpha*sa*sc = (1 - sa) * dc + sa*sc
if (s[3] == 0) {
/* NOP */
} else if (s[3] == 255) {
@@ -893,57 +1094,62 @@ nr_R8G8B8_R8G8B8_R8G8B8A8_N (unsigned char *px, int w, int h, int rs, const unsi
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[0] = NR_COMPOSEN11_1111(s[0], s[3], d[0]);
+ d[1] = NR_COMPOSEN11_1111(s[1], s[3], d[1]);
+ d[2] = NR_COMPOSEN11_1111(s[2], s[3], d[2]);
}
d += 3;
s += 4;
}
- } else {
- d = px;
- s = spx;
- for (c = 0; c < w; c++) {
+ px += rs;
+ spx += srs;
+ }
+ } else {
+ for (r = h; r > 0; r--) {
+ unsigned char *d = px;
+ const unsigned char *s = spx;
+ for (c = w; c > 0; c--) {
unsigned int a;
- a = NR_PREMUL (s[3], alpha);
+ a = NR_PREMUL_112(s[3], alpha);
+ // dc' = (1 - alpha*sa) * dc + alpha*sa*sc
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]);
+ d[0] = NR_COMPOSEN11_1211(s[0], a, d[0]);
+ d[1] = NR_COMPOSEN11_1211(s[1], a, d[1]);
+ d[2] = NR_COMPOSEN11_1211(s[2], a, d[2]);
}
/* a == 255 is impossible, because alpha < 255 */
d += 3;
s += 4;
}
+ px += rs;
+ spx += srs;
}
- 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 x, y;
+
+ for (y = h; y > 0; y--) {
+ unsigned char* d = px;
+ const unsigned char* s = spx;
+ const unsigned char* m = mpx;
+ for (x = w; x > 0; 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]);
+ a = NR_PREMUL_112(s[3], m[0]);
+ if (a == 0) {
+ /* NOP */
+ } else if (a == 255*255) {
+ memcpy(d, s, 3);
+ } else {
+ // dc' = (1 - m*sa) * dc + m*sc
+ d[0] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[0], m[0]), a, d[0]);
+ d[1] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[1], m[0]), a, d[1]);
+ d[2] = NR_COMPOSEP11_2211(NR_PREMUL_112(s[2], m[0]), a, d[2]);
}
d += 3;
s += 4;
@@ -958,20 +1164,24 @@ nr_R8G8B8_R8G8B8_R8G8B8A8_P_A8 (unsigned char *px, int w, int h, int rs, const u
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 x, y;
+
+ for (y = h; y > 0; y--) {
+ unsigned char* d = px;
+ const unsigned char* s = spx;
+ const unsigned char* m = mpx;
+ for (x = w; x > 0; 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]);
+ a = NR_PREMUL_112(s[3], m[0]);
+ if (a == 0) {
+ /* NOP */
+ } else if (a == 255*255) {
+ memcpy(d, s, 3);
+ } else {
+ // dc' = (1 - m*sa) * dc + m*sa*sc
+ d[0] = NR_COMPOSEN11_1211(s[0], a, d[0]);
+ d[1] = NR_COMPOSEN11_1211(s[1], a, d[1]);
+ d[2] = NR_COMPOSEN11_1211(s[2], a, d[2]);
}
d += 3;
s += 4;