summaryrefslogtreecommitdiffstats
path: root/src/libnr/nr-compose-transform.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/libnr/nr-compose-transform.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/libnr/nr-compose-transform.cpp')
-rw-r--r--src/libnr/nr-compose-transform.cpp360
1 files changed, 360 insertions, 0 deletions
diff --git a/src/libnr/nr-compose-transform.cpp b/src/libnr/nr-compose-transform.cpp
new file mode 100644
index 000000000..bb5022a74
--- /dev/null
+++ b/src/libnr/nr-compose-transform.cpp
@@ -0,0 +1,360 @@
+#define __NR_COMPOSE_TRANSFORM_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 "nr-pixops.h"
+#include "nr-matrix.h"
+
+
+#ifdef WITH_MMX
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+/* fixme: */
+int nr_have_mmx (void);
+void nr_mmx_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const long *FFd2s, unsigned int alpha);
+void nr_mmx_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const long *FFd2s, const long *FF_S, unsigned int alpha, int dbits);
+#define NR_PIXOPS_MMX (1 && nr_have_mmx ())
+#ifdef __cplusplus
+}
+#endif //__cplusplus
+#endif
+
+/* fixme: Implement missing (Lauris) */
+/* fixme: PREMUL colors before calculating average (Lauris) */
+
+/* Fixed point precision */
+#define FBITS 12
+
+void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
+void nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
+void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
+void nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
+
+void
+nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const NR::Matrix &d2s, unsigned int alpha, int xd, int yd)
+{
+ int xsize, ysize, size, dbits;
+ long FFs_x_x, FFs_x_y, FFs_y_x, FFs_y_y, FFs__x, FFs__y;
+ long FFs_x_x_S, FFs_x_y_S, FFs_y_x_S, FFs_y_y_S;
+ /* Subpixel positions */
+ int FF_sx_S[256];
+ int FF_sy_S[256];
+ unsigned char *d0;
+ int FFsx0, FFsy0;
+ int x, y;
+
+ if (alpha == 0) return;
+
+ xsize = (1 << xd);
+ ysize = (1 << yd);
+ size = xsize * ysize;
+ dbits = xd + yd;
+
+ /* Set up fixed point matrix */
+ FFs_x_x = (long) (d2s[0] * (1 << FBITS) + 0.5);
+ FFs_x_y = (long) (d2s[1] * (1 << FBITS) + 0.5);
+ FFs_y_x = (long) (d2s[2] * (1 << FBITS) + 0.5);
+ FFs_y_y = (long) (d2s[3] * (1 << FBITS) + 0.5);
+ FFs__x = (long) (d2s[4] * (1 << FBITS) + 0.5);
+ FFs__y = (long) (d2s[5] * (1 << FBITS) + 0.5);
+
+ FFs_x_x_S = FFs_x_x >> xd;
+ FFs_x_y_S = FFs_x_y >> xd;
+ FFs_y_x_S = FFs_y_x >> yd;
+ FFs_y_y_S = FFs_y_y >> yd;
+
+ /* Set up subpixel matrix */
+ /* fixme: We can calculate that in floating point (Lauris) */
+ for (y = 0; y < ysize; y++) {
+ for (x = 0; x < xsize; x++) {
+ FF_sx_S[y * xsize + x] = FFs_x_x_S * x + FFs_y_x_S * y;
+ FF_sy_S[y * xsize + x] = FFs_x_y_S * x + FFs_y_y_S * y;
+ }
+ }
+
+ d0 = px;
+ FFsx0 = FFs__x;
+ FFsy0 = FFs__y;
+
+ for (y = 0; y < h; y++) {
+ unsigned char *d;
+ long FFsx, FFsy;
+ d = d0;
+ FFsx = FFsx0;
+ FFsy = FFsy0;
+ for (x = 0; x < w; x++) {
+ unsigned int r, g, b, a;
+ long sx, sy;
+ int i;
+ r = g = b = a = 0;
+ for (i = 0; i < size; i++) {
+ sx = (FFsx + FF_sx_S[i]) >> FBITS;
+ if ((sx >= 0) && (sx < sw)) {
+ sy = (FFsy + FF_sy_S[i]) >> FBITS;
+ if ((sy >= 0) && (sy < sh)) {
+ const unsigned char *s;
+ unsigned int ca;
+ s = spx + sy * srs + sx * 4;
+ ca = NR_PREMUL (s[3], alpha);
+ r += NR_PREMUL (s[0], ca);
+ g += NR_PREMUL (s[1], ca);
+ b += NR_PREMUL (s[2], ca);
+ a += ca;
+ }
+ }
+ }
+ a >>= dbits;
+ if (a != 0) {
+ r = r >> dbits;
+ g = g >> dbits;
+ b = b >> dbits;
+ if (a == 255) {
+ /* Transparent BG, premul src */
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = a;
+ } else {
+ unsigned int ca;
+ /* Full composition */
+ ca = 65025 - (255 - a) * (255 - d[3]);
+ d[0] = NR_COMPOSENNN_A7 (r, a, d[0], d[3], ca);
+ d[1] = NR_COMPOSENNN_A7 (g, a, d[1], d[3], ca);
+ d[2] = NR_COMPOSENNN_A7 (b, a, d[2], d[3], ca);
+ d[3] = (ca + 127) / 255;
+ }
+ }
+ /* Advance pointers */
+ FFsx += FFs_x_x;
+ FFsy += FFs_x_y;
+ d += 4;
+ }
+ FFsx0 += FFs_y_x;
+ FFsy0 += FFs_y_y;
+ d0 += rs;
+ }
+}
+
+void nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);
+
+static void
+nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const long *FFd2s, unsigned int alpha)
+{
+ unsigned char *d0;
+ int FFsx0, FFsy0;
+ int x, y;
+
+ d0 = px;
+ FFsx0 = FFd2s[4];
+ FFsy0 = FFd2s[5];
+
+ for (y = 0; y < h; y++) {
+ unsigned char *d;
+ long FFsx, FFsy;
+ d = d0;
+ FFsx = FFsx0;
+ FFsy = FFsy0;
+ for (x = 0; x < w; x++) {
+ long sx, sy;
+ sx = FFsx >> FBITS;
+ if ((sx >= 0) && (sx < sw)) {
+ sy = FFsy >> FBITS;
+ if ((sy >= 0) && (sy < sh)) {
+ const unsigned char *s;
+ unsigned int a;
+ s = spx + sy * srs + sx * 4;
+ a = NR_PREMUL (s[3], alpha);
+ if (a != 0) {
+ 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;
+ }
+ }
+ }
+ }
+ /* Advance pointers */
+ FFsx += FFd2s[0];
+ FFsy += FFd2s[1];
+ d += 4;
+ }
+ FFsx0 += FFd2s[2];
+ FFsy0 += FFd2s[3];
+ d0 += rs;
+ }
+}
+
+static void
+nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const long *FFd2s, const long *FF_S, unsigned int alpha, int dbits)
+{
+ int size;
+ unsigned char *d0;
+ int FFsx0, FFsy0;
+ int x, y;
+
+ size = (1 << dbits);
+ unsigned alpha_rounding_fix = size * 255;
+ unsigned rgb_rounding_fix = size * (255 * 256);
+ if (alpha > 127) ++alpha;
+
+ d0 = px;
+ FFsx0 = FFd2s[4];
+ FFsy0 = FFd2s[5];
+
+ for (y = 0; y < h; y++) {
+ unsigned char *d;
+ long FFsx, FFsy;
+ d = d0;
+ FFsx = FFsx0;
+ FFsy = FFsy0;
+ for (x = 0; x < w; x++) {
+ unsigned int r, g, b, a;
+ int i;
+ r = g = b = a = 0;
+ for (i = 0; i < size; i++) {
+ long sx, sy;
+ sx = (FFsx + FF_S[2 * i]) >> FBITS;
+ if ((sx >= 0) && (sx < sw)) {
+ sy = (FFsy + FF_S[2 * i + 1]) >> FBITS;
+ if ((sy >= 0) && (sy < sh)) {
+ const unsigned char *s;
+ unsigned int ca;
+ s = spx + sy * srs + sx * 4;
+ ca = s[3] * alpha;
+ r += s[0] * ca;
+ g += s[1] * ca;
+ b += s[2] * ca;
+ a += ca;
+ }
+ }
+ }
+ a = (a + alpha_rounding_fix) >> (8 + dbits);
+ if (a != 0) {
+ r = (r + rgb_rounding_fix) >> (16 + dbits);
+ g = (g + rgb_rounding_fix) >> (16 + dbits);
+ b = (b + rgb_rounding_fix) >> (16 + dbits);
+ if ((a == 255) || (d[3] == 0)) {
+ /* Transparent BG, premul src */
+ d[0] = r;
+ d[1] = g;
+ d[2] = b;
+ d[3] = a;
+ } else {
+ d[0] = NR_COMPOSEPPP (r, a, d[0], d[3]);
+ d[1] = NR_COMPOSEPPP (g, a, d[1], d[3]);
+ d[2] = NR_COMPOSEPPP (b, a, d[2], d[3]);
+ d[3] = (65025 - (255 - a) * (255 - d[3]) + 127) / 255;
+ }
+ }
+ /* Advance pointers */
+ FFsx += FFd2s[0];
+ FFsy += FFd2s[1];
+ d += 4;
+ }
+ FFsx0 += FFd2s[2];
+ FFsy0 += FFd2s[3];
+ d0 += rs;
+ }
+}
+
+void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const NR::Matrix &d2s, unsigned int alpha, int xd, int yd)
+{
+ int dbits;
+ long FFd2s[6];
+ int i;
+
+ if (alpha == 0) return;
+
+ dbits = xd + yd;
+
+ for (i = 0; i < 6; i++) {
+ FFd2s[i] = (long) (d2s[i] * (1 << FBITS) + 0.5);
+ }
+
+ if (dbits == 0) {
+#ifdef WITH_MMX
+ if (NR_PIXOPS_MMX) {
+ /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
+ nr_mmx_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (px, w, h, rs, spx, sw, sh, srs, FFd2s, alpha);
+ return;
+ }
+#endif
+ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_0 (px, w, h, rs, spx, sw, sh, srs, FFd2s, alpha);
+ } else {
+ int xsize, ysize;
+ long FFs_x_x_S, FFs_x_y_S, FFs_y_x_S, FFs_y_y_S;
+ long FF_S[2 * 256];
+ int x, y;
+
+ xsize = (1 << xd);
+ ysize = (1 << yd);
+
+ FFs_x_x_S = FFd2s[0] >> xd;
+ FFs_x_y_S = FFd2s[1] >> xd;
+ FFs_y_x_S = FFd2s[2] >> yd;
+ FFs_y_y_S = FFd2s[3] >> yd;
+
+ /* Set up subpixel matrix */
+ /* fixme: We can calculate that in floating point (Lauris) */
+ for (y = 0; y < ysize; y++) {
+ for (x = 0; x < xsize; x++) {
+ FF_S[2 * (y * xsize + x)] = FFs_x_x_S * x + FFs_y_x_S * y;
+ FF_S[2 * (y * xsize + x) + 1] = FFs_x_y_S * x + FFs_y_y_S * y;
+ }
+ }
+
+#ifdef WITH_MMX
+ if (NR_PIXOPS_MMX) {
+ /* WARNING: MMX composer REQUIRES w > 0 and h > 0 */
+ nr_mmx_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (px, w, h, rs, spx, sw, sh, srs, FFd2s, FF_S, alpha, dbits);
+ return;
+ }
+#endif
+ nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM_n (px, w, h, rs, spx, sw, sh, srs, FFd2s, FF_S, alpha, dbits);
+ }
+}
+
+void nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_TRANSFORM (unsigned char *px, int w, int h, int rs,
+ const unsigned char *spx, int sw, int sh, int srs,
+ const NR::Matrix &d2s, unsigned int alpha, int xd, int yd);