summaryrefslogtreecommitdiff
path: root/draw
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-08-04 13:43:58 +0000
committerTor Andersson <tor@ghostscript.com>2010-08-04 13:43:58 +0000
commit2c036aab4670a93490d42de3492983feb389231d (patch)
tree1248816b579df9101cae086c88a568aeac5224f5 /draw
parent724d113ed8840470ded2b32a52c9b53a4e0a5c6b (diff)
downloadmupdf-2c036aab4670a93490d42de3492983feb389231d.tar.xz
Rearrange low level painting functions and add new functions for constant alpha painting.
Diffstat (limited to 'draw')
-rw-r--r--draw/blendmodes.c14
-rw-r--r--draw/imagedraw.c364
-rw-r--r--draw/meshdraw.c2
-rw-r--r--draw/pathscan.c4
-rw-r--r--draw/porterduff.c328
5 files changed, 351 insertions, 361 deletions
diff --git a/draw/blendmodes.c b/draw/blendmodes.c
index 0c8c7eec..184e1a28 100644
--- a/draw/blendmodes.c
+++ b/draw/blendmodes.c
@@ -326,12 +326,24 @@ fz_blendnonseparable(byte * restrict bp, byte * restrict sp, int w, fz_blendmode
}
void
-fz_blendpixmapswithmode(fz_pixmap *dst, fz_pixmap *src, fz_blendmode blendmode)
+fz_blendpixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_blendmode blendmode)
{
unsigned char *sp, *dp;
fz_bbox bbox;
int x, y, w, h, n;
+ /* TODO: fix this hack! */
+ if (alpha < 255)
+ {
+ sp = src->samples;
+ n = src->w * src->h * src->n;
+ while (n--)
+ {
+ *sp = fz_mul255(*sp, alpha);
+ sp++;
+ }
+ }
+
bbox = fz_boundpixmap(dst);
bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
diff --git a/draw/imagedraw.c b/draw/imagedraw.c
index a626deb7..b9bb2702 100644
--- a/draw/imagedraw.c
+++ b/draw/imagedraw.c
@@ -1,301 +1,194 @@
#include "fitz.h"
-#define noNEAREST
+#define LINEAR
typedef unsigned char byte;
-/* Sample image and clamp to edge */
-
-static inline byte
-getmask(byte *s, int w, int h, int u, int v)
+static inline float roundup(float x)
{
- if (u < 0) u = 0;
- if (v < 0) v = 0;
- if (u >= w) u = w - 1;
- if (v >= h) v = h - 1;
- return s[w * v + u];
+ return (x < 0) ? floorf(x) : ceilf(x);
}
-static inline byte *
-getga(byte *s, int w, int h, int u, int v)
+#ifdef LINEAR
+
+static inline int lerp(int a, int b, int t)
{
- if (u < 0) u = 0;
- if (v < 0) v = 0;
- if (u >= w) u = w - 1;
- if (v >= h) v = h - 1;
- return s + ((w * v + u) << 1);
+ return a + (((b - a) * t) >> 16);
}
-static inline byte *
-getrgba(byte *s, int w, int h, int u, int v)
+static inline int bilerp(int a, int b, int c, int d, int u, int v)
{
- if (u < 0) u = 0;
- if (v < 0) v = 0;
- if (u >= w) u = w - 1;
- if (v >= h) v = h - 1;
- return s + ((w * v + u) << 2);
+ return lerp(lerp(a, b, u), lerp(c, d, u), v);
}
-static inline int
-getcolor(byte *s, int w, int h, int n, int u, int v, int k)
+static inline byte *samplenearest(byte *s, int w, int h, int n, int u, int v)
{
if (u < 0) u = 0;
if (v < 0) v = 0;
if (u >= w) u = w - 1;
if (v >= h) v = h - 1;
- return s[w * v * n + u + k];
-}
-
-/* Bi-linear interpolation of sample */
-
-static inline int
-lerp(int a, int b, int t)
-{
- return a + (((b - a) * t) >> 16);
-}
-
-static inline void
-lerpga(byte *dst, byte *a, byte *b, int t)
-{
- dst[0] = lerp(a[0], b[0], t);
- dst[1] = lerp(a[1], b[1], t);
-}
-
-static inline void
-lerprgba(byte *dst, byte *a, byte *b, int t)
-{
- dst[0] = lerp(a[0], b[0], t);
- dst[1] = lerp(a[1], b[1], t);
- dst[2] = lerp(a[2], b[2], t);
- dst[3] = lerp(a[3], b[3], t);
-}
-
-static inline int
-samplemask(byte *s, int w, int h, int u, int v)
-{
-#ifdef NEAREST
- return getmask(s, w, h, u >> 16, v >> 16);
-#else
- int ui = u >> 16;
- int vi = v >> 16;
- int ud = u & 0xFFFF;
- int vd = v & 0xFFFF;
- int a = getmask(s, w, h, ui, vi);
- int b = getmask(s, w, h, ui+1, vi);
- int c = getmask(s, w, h, ui, vi+1);
- int d = getmask(s, w, h, ui+1, vi+1);
- int ab = lerp(a, b, ud);
- int cd = lerp(c, d, ud);
- return lerp(ab, cd, vd);
-#endif
+ return s + (v * w + u) * n;
}
-static inline void
-samplega(byte *s, int w, int h, int u, int v, int *gout, int *aout)
-{
-#ifdef NEAREST
- byte *ga = getga(s, w, h, u >> 16, v >> 16);
- *gout = ga[0];
- *aout = ga[1];
-#else
- byte ab[2];
- byte cd[2];
- byte abcd[2];
- int ui = u >> 16;
- int vi = v >> 16;
- int ud = u & 0xFFFF;
- int vd = v & 0xFFFF;
- byte *a = getga(s, w, h, ui, vi);
- byte *b = getga(s, w, h, ui+1, vi);
- byte *c = getga(s, w, h, ui, vi+1);
- byte *d = getga(s, w, h, ui+1, vi+1);
- lerpga(ab, a, b, ud);
- lerpga(cd, c, d, ud);
- lerpga(abcd, ab, cd, vd);
- *gout = abcd[0];
- *aout = abcd[1];
#endif
-}
-static inline void
-samplergba(byte *s, int w, int h, int u, int v, int *rout, int *gout, int *bout, int *aout)
-{
-#ifdef NEAREST
- byte *rgba = getrgba(s, w, h, u >> 16, v >> 16);
- *rout = rgba[0];
- *gout = rgba[1];
- *bout = rgba[2];
- *aout = rgba[3];
-#else
- byte ab[4];
- byte cd[4];
- byte abcd[4];
- int ui = u >> 16;
- int vi = v >> 16;
- int ud = u & 0xFFFF;
- int vd = v & 0xFFFF;
- byte *a = getrgba(s, w, h, ui, vi);
- byte *b = getrgba(s, w, h, ui+1, vi);
- byte *c = getrgba(s, w, h, ui, vi+1);
- byte *d = getrgba(s, w, h, ui+1, vi+1);
- lerprgba(ab, a, b, ud);
- lerprgba(cd, c, d, ud);
- lerprgba(abcd, ab, cd, vd);
- *rout = abcd[0];
- *gout = abcd[1];
- *bout = abcd[2];
- *aout = abcd[3];
-#endif
-}
+/* Blend premultiplied source image in constant alpha over destination */
static inline void
-samplecolor(byte *s, int w, int h, int n, int u, int v, byte *out)
+fz_paintaffinealphaN(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha)
{
-#ifdef NEAREST
- int k;
- for (k = 0; k < n; k++)
- out[k] = getcolor(s, w, h, n, u >> 16, v >> 16, k);
-#else
- int ui = u >> 16;
- int vi = v >> 16;
- int ud = u & 0xFFFF;
- int vd = v & 0xFFFF;
int k;
- for (k = 0; k < n; k++)
- {
- int a = getcolor(s, w, h, n, ui, vi, k);
- int b = getcolor(s, w, h, n, ui+1, vi, k);
- int c = getcolor(s, w, h, n, ui, vi+1, k);
- int d = getcolor(s, w, h, n, ui+1, vi+1, k);
- int ab = lerp(a, b, ud);
- int cd = lerp(c, d, ud);
- out[k] = lerp(ab, cd, vd);
- }
-#endif
-}
-
-/* Blend source image scanline over destination */
-#define INSIDEU u >= 0 && u <= (sw << 16)
-#define INSIDEV v >= 0 && v <= (sh << 16)
-#define INSIDE INSIDEU && INSIDEV
-
-static inline void
-fz_blendscan1(unsigned char *dp, unsigned char *sp, int sw, int sh,
- int u, int v, int fa, int fb, int w)
-{
while (w--)
{
- if (INSIDE)
+ int ui = u >> 16;
+ int vi = v >> 16;
+ if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- int a = samplemask(sp, sw, sh, u, v);
- dp[0] = a + fz_mul255(dp[0], 255 - a);
+#ifdef LINEAR
+ int uf = u & 0xffff;
+ int vf = v & 0xffff;
+ byte *a = samplenearest(sp, sw, sh, n, ui, vi);
+ byte *b = samplenearest(sp, sw, sh, n, ui+1, vi);
+ byte *c = samplenearest(sp, sw, sh, n, ui, vi+1);
+ byte *d = samplenearest(sp, sw, sh, n, ui+1, vi+1);
+ int x = bilerp(a[n-1], b[n-1], c[n-1], d[n-1], uf, vf);
+ int t = 255 - fz_mul255(x, alpha);
+ for (k = 0; k < n; k++)
+ {
+ x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
+ dp[k] = x + fz_mul255(dp[k], t);
+ }
+#else
+ byte *sample = sp + ((vi * sw + ui) * n);
+ int t = 255 - fz_mul255(sample[n-1], alpha);
+ for (k = 0; k < n; k++)
+ dp[k] = sample[k] + fz_mul255(dp[k], t);
+#endif
}
- dp ++;
+ dp += n;
u += fa;
v += fb;
}
}
+/* Blend premultiplied source image over destination */
+
static inline void
-fz_blendscan2(unsigned char *dp, unsigned char *sp, int sw, int sh,
- int u, int v, int fa, int fb, int w)
+fz_paintaffineN(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n)
{
+ int k;
+
while (w--)
{
- if (INSIDE)
+ int ui = u >> 16;
+ int vi = v >> 16;
+ if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- int g, a, t;
- samplega(sp, sw, sh, u, v, &g, &a);
- t = 255 - a;
- dp[0] = g + fz_mul255(dp[0], t);
- dp[1] = a + fz_mul255(dp[1], t);
+#ifdef LINEAR
+ int uf = u & 0xffff;
+ int vf = v & 0xffff;
+ byte *a = samplenearest(sp, sw, sh, n, ui, vi);
+ byte *b = samplenearest(sp, sw, sh, n, ui+1, vi);
+ byte *c = samplenearest(sp, sw, sh, n, ui, vi+1);
+ byte *d = samplenearest(sp, sw, sh, n, ui+1, vi+1);
+ int t = 255 - bilerp(a[n-1], b[n-1], c[n-1], d[n-1], uf, vf);
+ for (k = 0; k < n; k++)
+ {
+ int x = bilerp(a[k], b[k], c[k], d[k], uf, vf);
+ dp[k] = x + fz_mul255(dp[k], t);
+ }
+#else
+ byte *sample = sp + ((vi * sw + ui) * n);
+ int t = 255 - sample[n-1];
+ for (k = 0; k < n; k++)
+ dp[k] = sample[k] + fz_mul255(dp[k], t);
+#endif
}
- dp += 2;
+ dp += n;
u += fa;
v += fb;
}
}
+/* Blend non-premultiplied color in source image mask over destination */
+
static inline void
-fz_blendscan4(unsigned char *dp, unsigned char *sp, int sw, int sh,
- int u, int v, int fa, int fb, int w)
+fz_paintaffinecolorN(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color)
{
+ int sa = color[n-1];
+ int k;
+
while (w--)
{
- if (INSIDE)
+ int ui = u >> 16;
+ int vi = v >> 16;
+ if (ui >= 0 && ui < sw && vi >= 0 && vi < sh)
{
- int r, g, b, a, t;
- samplergba(sp, sw, sh, u, v, &r, &g, &b, &a);
- t = 255 - a;
- dp[0] = r + fz_mul255(dp[0], t);
- dp[1] = g + fz_mul255(dp[1], t);
- dp[2] = b + fz_mul255(dp[2], t);
- dp[3] = a + fz_mul255(dp[3], t);
+#ifdef LINEAR
+ int uf = u & 0xffff;
+ int vf = v & 0xffff;
+ byte *a = samplenearest(sp, sw, sh, 1, ui, vi);
+ byte *b = samplenearest(sp, sw, sh, 1, ui+1, vi);
+ byte *c = samplenearest(sp, sw, sh, 1, ui, vi+1);
+ byte *d = samplenearest(sp, sw, sh, 1, ui+1, vi+1);
+ int ma = bilerp(a[0], b[0], c[0], d[0], uf, vf);
+#else
+ int ma = sp[vi * sw + ui];
+#endif
+ int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
+ for (k = 0; k < n - 1; k++)
+ dp[k] = FZ_BLEND(color[k], dp[k], masa);
+ dp[k] = FZ_BLEND(255, dp[k], masa);
}
- dp += 4;
+ dp += n;
u += fa;
v += fb;
}
}
-static inline void
-fz_blendscan(unsigned char *dp, unsigned char *sp, int sw, int sh,
- int u, int v, int fa, int fb, int w, int n)
+void
+fz_paintaffine(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha)
{
- while (w--)
+ if (alpha == 255)
{
- if (INSIDE)
+ switch (n)
{
- unsigned char color[FZ_MAXCOLORS+1];
- int k, t;
- samplecolor(sp, sw, sh, n, u, v, color);
- t = 255 - color[n-1];
- for (k = 0; k < n; k++)
- dp[k] = color[k] + fz_mul255(dp[k], t);
+ case 1: fz_paintaffineN(dp, sp, sw, sh, u, v, fa, fb, w, 1); break;
+ case 2: fz_paintaffineN(dp, sp, sw, sh, u, v, fa, fb, w, 2); break;
+ case 4: fz_paintaffineN(dp, sp, sw, sh, u, v, fa, fb, w, 4); break;
+ default: fz_paintaffineN(dp, sp, sw, sh, u, v, fa, fb, w, n); break;
}
- dp += n;
- u += fa;
- v += fb;
}
-}
-
-/* Blend non-premultiplied color in image mask over destination */
-
-static inline void
-fz_blendscanwithcolor(unsigned char *dp, unsigned char *sp, int sw, int sh,
- int u, int v, int fa, int fb, int w, int n, unsigned char *color)
-{
- int sa = color[n-1];
- while (w--)
+ else if (alpha > 0)
{
- if (INSIDE)
+ switch (n)
{
- int ma = samplemask(sp, sw, sh, u, v);
- int masa = fz_mul255(sa, ma);
- int t = 255 - masa;
- int k;
- for (k = 0; k < n; k++)
- dp[k] = fz_mul255(color[k], ma) + fz_mul255(dp[k], t);
+ case 1: fz_paintaffinealphaN(dp, sp, sw, sh, u, v, fa, fb, w, 1, alpha); break;
+ case 2: fz_paintaffinealphaN(dp, sp, sw, sh, u, v, fa, fb, w, 2, alpha); break;
+ case 4: fz_paintaffinealphaN(dp, sp, sw, sh, u, v, fa, fb, w, 4, alpha); break;
+ default: fz_paintaffinealphaN(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha); break;
}
- dp += n;
- u += fa;
- v += fb;
}
}
-/* Draw an image with an affine transform on destination */
-
-static inline float roundup(float x)
+void
+fz_paintaffinecolor(byte *dp, byte *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, byte *color)
{
- return (x < 0) ? floorf(x) : ceilf(x);
+ switch (n)
+ {
+ case 2: fz_paintaffinecolorN(dp, sp, sw, sh, u, v, fa, fb, w, 2, color); break;
+ case 4: fz_paintaffinecolorN(dp, sp, sw, sh, u, v, fa, fb, w, 4, color); break;
+ default: fz_paintaffinecolorN(dp, sp, sw, sh, u, v, fa, fb, w, n, color); break;
+ }
}
+/* Draw an image with an affine transform on destination */
+
static void
-fz_blendimageimp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm,
- unsigned char *color)
+fz_paintimageimp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm, byte *color, int alpha)
{
- unsigned char *dp, *sp;
+ byte *dp, *sp;
int u, v, fa, fb, fc, fd;
int x, y, w, h;
int sw, sh, n;
@@ -339,22 +232,14 @@ fz_blendimageimp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm,
sw = img->w;
sh = img->h;
+ /* TODO: if (fb == 0 && fa == 1) call fz_paintspan */
+
while (h--)
{
if (color)
- {
- fz_blendscanwithcolor(dp, sp, sw, sh, u, v, fa, fb, w, n, color);
- }
+ fz_paintaffinecolor(dp, sp, sw, sh, u, v, fa, fb, w, n, color);
else
- {
- switch (n)
- {
- case 1: fz_blendscan1(dp, sp, sw, sh, u, v, fa, fb, w); break;
- case 2: fz_blendscan2(dp, sp, sw, sh, u, v, fa, fb, w); break;
- case 4: fz_blendscan4(dp, sp, sw, sh, u, v, fa, fb, w); break;
- default: fz_blendscan(dp, sp, sw, sh, u, v, fa, fb, w, n); break;
- }
- }
+ fz_paintaffine(dp, sp, sw, sh, u, v, fa, fb, w, n, alpha);
dp += dst->w * n;
u += fc;
v += fd;
@@ -362,16 +247,15 @@ fz_blendimageimp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm,
}
void
-fz_blendimagewithcolor(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm,
- unsigned char *color)
+fz_paintimagecolor(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm, byte *color)
{
assert(img->n == 1);
- fz_blendimageimp(dst, scissor, img, ctm, color);
+ fz_paintimageimp(dst, scissor, img, ctm, color, 255);
}
void
-fz_blendimage(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm)
+fz_paintimage(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm, int alpha)
{
assert(dst->n == img->n);
- fz_blendimageimp(dst, scissor, img, ctm, nil);
+ fz_paintimageimp(dst, scissor, img, ctm, nil, alpha);
}
diff --git a/draw/meshdraw.c b/draw/meshdraw.c
index 4fbdab70..61b678ab 100644
--- a/draw/meshdraw.c
+++ b/draw/meshdraw.c
@@ -378,7 +378,7 @@ fz_rendershade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox)
*d++ = clut[v][k];
*d++ = *s++;
}
- fz_blendpixmaps(dest, conv);
+ fz_paintpixmap(dest, conv, 255);
fz_droppixmap(conv);
fz_droppixmap(temp);
}
diff --git a/draw/pathscan.c b/draw/pathscan.c
index dc6c6ff8..459dd306 100644
--- a/draw/pathscan.c
+++ b/draw/pathscan.c
@@ -476,9 +476,9 @@ blit(fz_pixmap *dest, int x, int y, unsigned char *mp, int w, unsigned char *col
dp = dest->samples + ( (y - dest->y) * dest->w + (x - dest->x) ) * dest->n;
if (color)
- fz_blendwithcolormask(dp, color, mp, dest->n, w);
+ fz_paintspancolor(dp, mp, dest->n, w, color);
else
- fz_blendmasks(dp, mp, w);
+ fz_paintspan(dp, mp, 1, w, 255);
}
fz_error
diff --git a/draw/porterduff.c b/draw/porterduff.c
index e5070a5d..59a4f4d4 100644
--- a/draw/porterduff.c
+++ b/draw/porterduff.c
@@ -72,131 +72,172 @@ and stick to using the premultiplied form.
typedef unsigned char byte;
-/* Blend source alpha over destination alpha */
+/* Blend a non-premultiplied color in mask over destination */
-void
-fz_blendmasks(byte * restrict dp, byte * restrict sp, int w)
+static inline void
+fz_paintspancolor2(byte * restrict dp, byte * restrict mp, int w, byte *color)
{
+ int sa = FZ_EXPAND(color[1]);
+ int g = color[0];
while (w--)
{
- dp[0] = sp[0] + fz_mul255(dp[0], 255 - sp[0]);
- sp++;
- dp++;
+ int ma = *mp++;
+ int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
+ dp[0] = FZ_BLEND(g, dp[0], masa);
+ dp[1] = FZ_BLEND(255, dp[1], masa);
+ dp += 2;
}
}
-/* Blend a non-premultiplied color in mask over destination */
+static inline void
+fz_paintspancolor4(byte * restrict dp, byte * restrict mp, int w, byte *color)
+{
+ int sa = FZ_EXPAND(color[3]);
+ int r = color[0];
+ int g = color[1];
+ int b = color[2];
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
+ dp[0] = FZ_BLEND(r, dp[0], masa);
+ dp[1] = FZ_BLEND(g, dp[1], masa);
+ dp[2] = FZ_BLEND(b, dp[2], masa);
+ dp[3] = FZ_BLEND(255, dp[3], masa);
+ dp += 4;
+ }
+}
-void
-fz_blendwithcolormask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+static inline void
+fz_paintspancolorN(byte * restrict dp, byte * restrict mp, int n, int w, byte *color)
{
- int sa, r, g, b, k;
+ int sa = FZ_EXPAND(color[n-1]);
+ int k;
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
+ for (k = 0; k < n - 1; k++)
+ dp[k] = FZ_BLEND(color[k], dp[k], masa);
+ dp[k] = FZ_BLEND(255, dp[k], masa);
+ dp += n;
+ }
+}
+void
+fz_paintspancolor(byte * restrict dp, byte * restrict mp, int n, int w, byte *color)
+{
switch (n)
{
- case 2:
- sa = FZ_EXPAND(sp[1]);
- g = sp[0];
- while (w--)
- {
- int ma = *mp++;
- int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
- dp[0] = FZ_BLEND(g, dp[0], masa);
- dp[1] = FZ_BLEND(255, dp[1], masa);
- dp += 2;
- }
- break;
- case 4:
- sa = FZ_EXPAND(sp[3]);
- r = sp[0];
- g = sp[1];
- b = sp[2];
- while (w--)
- {
- int ma = *mp++;
- int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
- dp[0] = FZ_BLEND(r, dp[0], masa);
- dp[1] = FZ_BLEND(g, dp[1], masa);
- dp[2] = FZ_BLEND(b, dp[2], masa);
- dp[3] = FZ_BLEND(255, dp[3], masa);
- dp += 4;
- }
- break;
- default:
- sa = FZ_EXPAND(sp[n-1]);
- while (w--)
- {
- int ma = *mp++;
- int masa = FZ_COMBINE(FZ_EXPAND(ma), sa);
- for (k = 0; k < n - 1; k++)
- dp[k] = FZ_BLEND(sp[k], dp[k], masa);
- dp[k] = FZ_BLEND(255, dp[k], masa);
- dp += n;
- }
+ case 2: fz_paintspancolor2(dp, mp, w, color); break;
+ case 4: fz_paintspancolor4(dp, mp, w, color); break;
+ default: fz_paintspancolorN(dp, mp, n, w, color); break;
}
}
/* Blend source in mask over destination */
-void
-fz_blendwithmask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+static inline void
+fz_paintspanmask2(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+{
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[1], ma);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], t);
+ sp += 2;
+ dp += 2;
+ }
+}
+
+static inline void
+fz_paintspanmask4(byte * restrict dp, byte * restrict sp, byte * restrict mp, int w)
+{
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[3], ma);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], t);
+ dp[2] = fz_mul255(sp[2], ma) + fz_mul255(dp[2], t);
+ dp[3] = fz_mul255(sp[3], ma) + fz_mul255(dp[3], t);
+ sp += 4;
+ dp += 4;
+ }
+}
+
+static inline void
+fz_paintspanmaskN(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
{
int k;
+ while (w--)
+ {
+ int ma = *mp++;
+ int masa = fz_mul255(sp[n-1], ma);
+ int t = 255 - masa;
+ for (k = 0; k < n; k++)
+ dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], t);
+ sp += n;
+ dp += n;
+ }
+}
+void
+fz_paintspanmask(byte * restrict dp, byte * restrict sp, byte * restrict mp, int n, int w)
+{
switch (n)
{
- case 2:
- while (w--)
- {
- int ma = *mp++;
- int masa = fz_mul255(sp[1], ma);
- int t = 255 - masa;
- dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
- sp += 2;
- dp += 2;
- }
- break;
- case 4:
- while (w--)
- {
- int ma = *mp++;
- int masa = fz_mul255(sp[3], ma);
- int t = 255 - masa;
- dp[0] = fz_mul255(sp[0], ma) + fz_mul255(dp[0], t);
- dp[1] = fz_mul255(sp[1], ma) + fz_mul255(dp[1], t);
- dp[2] = fz_mul255(sp[2], ma) + fz_mul255(dp[2], t);
- dp[3] = fz_mul255(sp[3], ma) + fz_mul255(dp[3], t);
- sp += 4;
- dp += 4;
- }
- break;
- default:
- while (w--)
- {
- int ma = *mp++;
- int masa = fz_mul255(sp[n-1], ma);
- int t = 255 - masa;
- for (k = 0; k < n; k++)
- dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], t);
- sp += n;
- dp += n;
- }
+ case 2: fz_paintspanmask2(dp, sp, mp, w); break;
+ case 4: fz_paintspanmask4(dp, sp, mp, w); break;
+ default: fz_paintspanmaskN(dp, sp, mp, n, w); break;
}
}
-/* Blend source in (constant) alpha over destination */
+/* Blend source in constant alpha over destination */
-void
-fz_blendwithalpha(byte * restrict dp, byte * restrict sp, int ma, int n, int w)
+static inline void
+fz_paintspan2alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
{
- int k;
+ while (w--)
+ {
+ int masa = fz_mul255(sp[1], alpha);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], masa) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], masa) + fz_mul255(dp[1], t);
+ sp += 2;
+ dp += 2;
+ }
+}
+static inline void
+fz_paintspan4alpha(byte * restrict dp, byte * restrict sp, int w, int alpha)
+{
while (w--)
{
- int masa = fz_mul255(sp[n-1], ma);
+ int masa = fz_mul255(sp[3], alpha);
+ int t = 255 - masa;
+ dp[0] = fz_mul255(sp[0], masa) + fz_mul255(dp[0], t);
+ dp[1] = fz_mul255(sp[1], masa) + fz_mul255(dp[1], t);
+ dp[2] = fz_mul255(sp[2], masa) + fz_mul255(dp[2], t);
+ dp[3] = fz_mul255(sp[3], masa) + fz_mul255(dp[3], t);
+ sp += 4;
+ dp += 4;
+ }
+}
+
+static inline void
+fz_paintspanNalpha(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
+{
+ int k;
+ while (w--)
+ {
+ int masa = fz_mul255(sp[n-1], alpha);
int t = 255 - masa;
for (k = 0; k < n; k++)
- dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], t);
+ dp[k] = fz_mul255(sp[k], masa) + fz_mul255(dp[k], t);
sp += n;
dp += n;
}
@@ -204,11 +245,50 @@ fz_blendwithalpha(byte * restrict dp, byte * restrict sp, int ma, int n, int w)
/* Blend source over destination */
-void
-fz_blendnormal(byte * restrict dp, byte * restrict sp, int n, int w)
+static inline void
+fz_paintspan1(byte * restrict dp, byte * restrict sp, int w)
{
- int k;
+ while (w--)
+ {
+ int t = 255 - sp[0];
+ dp[0] = sp[0] + fz_mul255(dp[0], t);
+ sp ++;
+ dp ++;
+ }
+}
+static inline void
+fz_paintspan2(byte * restrict dp, byte * restrict sp, int w)
+{
+ while (w--)
+ {
+ int t = 255 - sp[1];
+ dp[0] = sp[0] + fz_mul255(dp[0], t);
+ dp[1] = sp[1] + fz_mul255(dp[1], t);
+ sp += 2;
+ dp += 2;
+ }
+}
+
+static inline void
+fz_paintspan4(byte * restrict dp, byte * restrict sp, int w)
+{
+ while (w--)
+ {
+ int t = 255 - sp[3];
+ dp[0] = sp[0] + fz_mul255(dp[0], t);
+ dp[1] = sp[1] + fz_mul255(dp[1], t);
+ dp[2] = sp[2] + fz_mul255(dp[2], t);
+ dp[3] = sp[3] + fz_mul255(dp[3], t);
+ sp += 4;
+ dp += 4;
+ }
+}
+
+static inline void
+fz_paintspanN(byte * restrict dp, byte * restrict sp, int n, int w)
+{
+ int k;
while (w--)
{
int t = 255 - sp[n-1];
@@ -219,23 +299,45 @@ fz_blendnormal(byte * restrict dp, byte * restrict sp, int n, int w)
}
}
+void
+fz_paintspan(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
+{
+ if (alpha == 255)
+ {
+ switch (n)
+ {
+ case 1: fz_paintspan1(dp, sp, w); break;
+ case 2: fz_paintspan2(dp, sp, w); break;
+ case 4: fz_paintspan4(dp, sp, w); break;
+ default: fz_paintspanN(dp, sp, n, w); break;
+ }
+ }
+ else if (alpha > 0)
+ {
+ switch (n)
+ {
+ case 2: fz_paintspan2alpha(dp, sp, w, alpha); break;
+ case 4: fz_paintspan4alpha(dp, sp, w, alpha); break;
+ default: fz_paintspanNalpha(dp, sp, n, w, alpha); break;
+ }
+ }
+}
+
/*
* Pixmap blending functions
*/
void
-fz_blendpixmapswithmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
+fz_paintpixmap(fz_pixmap *dst, fz_pixmap *src, int alpha)
{
- unsigned char *sp, *dp, *mp;
+ unsigned char *sp, *dp;
fz_bbox bbox;
int x, y, w, h, n;
assert(dst->n == src->n);
- assert(msk->n == 1);
bbox = fz_boundpixmap(dst);
bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
- bbox = fz_intersectbbox(bbox, fz_boundpixmap(msk));
x = bbox.x0;
y = bbox.y0;
@@ -244,53 +346,45 @@ fz_blendpixmapswithmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
n = src->n;
sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;
- mp = msk->samples + ((y - msk->y) * msk->w + (x - msk->x)) * msk->n;
dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
while (h--)
{
- fz_blendwithmask(dp, sp, mp, n, w);
+ fz_paintspan(dp, sp, n, w, alpha);
sp += src->w * n;
dp += dst->w * n;
- mp += msk->w;
}
}
void
-fz_blendpixmapswithalpha(fz_pixmap *dst, fz_pixmap *src, float alpha)
+fz_paintpixmapmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
{
- unsigned char *sp, *dp;
+ unsigned char *sp, *dp, *mp;
fz_bbox bbox;
- int x, y, w, h, n, a;
+ int x, y, w, h, n;
assert(dst->n == src->n);
+ assert(msk->n == 1);
bbox = fz_boundpixmap(dst);
bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
+ bbox = fz_intersectbbox(bbox, fz_boundpixmap(msk));
x = bbox.x0;
y = bbox.y0;
w = bbox.x1 - bbox.x0;
h = bbox.y1 - bbox.y0;
- a = alpha * 255;
n = src->n;
sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;
+ mp = msk->samples + ((y - msk->y) * msk->w + (x - msk->x)) * msk->n;
dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
while (h--)
{
- if (a == 255)
- fz_blendnormal(dp, sp, n, w);
- else
- fz_blendwithalpha(dp, sp, a, n, w);
+ fz_paintspanmask(dp, sp, mp, n, w);
sp += src->w * n;
dp += dst->w * n;
+ mp += msk->w;
}
}
-
-void
-fz_blendpixmaps(fz_pixmap *dst, fz_pixmap *src)
-{
- fz_blendpixmapswithalpha(dst, src, 1);
-}