summaryrefslogtreecommitdiff
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
parent724d113ed8840470ded2b32a52c9b53a4e0a5c6b (diff)
downloadmupdf-2c036aab4670a93490d42de3492983feb389231d.tar.xz
Rearrange low level painting functions and add new functions for constant alpha painting.
-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
-rw-r--r--fitz/dev_draw.c138
-rw-r--r--fitz/fitz.h66
-rw-r--r--fitz/res_font.c8
8 files changed, 451 insertions, 473 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);
-}
diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c
index 964ab4f6..4f7e41a0 100644
--- a/fitz/dev_draw.c
+++ b/fitz/dev_draw.c
@@ -53,18 +53,12 @@ fz_drawfillpath(void *user, fz_path *path, int evenodd, fz_matrix ctm,
if (fz_isemptyrect(bbox))
return;
- if (model)
- {
- fz_convertcolor(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
- fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, colorbv);
- }
- else
- {
- fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, nil);
- }
+ fz_convertcolor(colorspace, color, model, colorfv);
+ for (i = 0; i < model->n; i++)
+ colorbv[i] = colorfv[i] * 255;
+ colorbv[i] = alpha * 255;
+
+ fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, colorbv);
}
static void
@@ -97,18 +91,12 @@ fz_drawstrokepath(void *user, fz_path *path, fz_strokestate *stroke, fz_matrix c
if (fz_isemptyrect(bbox))
return;
- if (model)
- {
- fz_convertcolor(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
- fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, colorbv);
- }
- else
- {
- fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil);
- }
+ fz_convertcolor(colorspace, color, model, colorfv);
+ for (i = 0; i < model->n; i++)
+ colorbv[i] = colorfv[i] * 255;
+ colorbv[i] = alpha * 255;
+
+ fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, colorbv);
}
static void
@@ -235,9 +223,9 @@ drawglyph(unsigned char *colorbv, fz_pixmap *dst, fz_pixmap *msk,
while (h--)
{
if (dst->colorspace)
- fz_blendwithcolormask(dp, colorbv, mp, dst->n, w);
+ fz_paintspancolor(dp, mp, dst->n, w, colorbv);
else
- fz_blendmasks(dp, mp, w);
+ fz_paintspan(dp, mp, 1, w, 255);
dp += dst->w * dst->n;
mp += msk->w;
}
@@ -255,13 +243,10 @@ fz_drawfilltext(void *user, fz_text *text, fz_matrix ctm,
fz_pixmap *glyph;
int i, x, y, gid;
- if (model)
- {
- fz_convertcolor(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
- }
+ fz_convertcolor(colorspace, color, model, colorfv);
+ for (i = 0; i < model->n; i++)
+ colorbv[i] = colorfv[i] * 255;
+ colorbv[i] = alpha * 255;
tm = text->trm;
@@ -282,10 +267,7 @@ fz_drawfilltext(void *user, fz_text *text, fz_matrix ctm,
glyph = fz_renderglyph(dev->cache, text->font, gid, trm);
if (glyph)
{
- if (model)
- drawglyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
- else
- drawglyph(nil, dev->dest, glyph, x, y, dev->scissor);
+ drawglyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
fz_droppixmap(glyph);
}
}
@@ -303,13 +285,10 @@ fz_drawstroketext(void *user, fz_text *text, fz_strokestate *stroke, fz_matrix c
fz_pixmap *glyph;
int i, x, y, gid;
- if (model)
- {
- fz_convertcolor(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
- }
+ fz_convertcolor(colorspace, color, model, colorfv);
+ for (i = 0; i < model->n; i++)
+ colorbv[i] = colorfv[i] * 255;
+ colorbv[i] = alpha * 255;
tm = text->trm;
@@ -330,10 +309,7 @@ fz_drawstroketext(void *user, fz_text *text, fz_strokestate *stroke, fz_matrix c
glyph = fz_renderstrokedglyph(dev->cache, text->font, gid, trm, ctm, stroke);
if (glyph)
{
- if (model)
- drawglyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
- else
- drawglyph(nil, dev->dest, glyph, x, y, dev->scissor);
+ drawglyph(colorbv, dev->dest, glyph, x, y, dev->scissor);
fz_droppixmap(glyph);
}
}
@@ -413,7 +389,7 @@ fz_drawcliptext(void *user, fz_text *text, fz_matrix ctm, int accumulate)
glyph = fz_renderglyph(dev->cache, text->font, gid, trm);
if (glyph)
{
- drawglyph(NULL, mask, glyph, x, y, bbox);
+ drawglyph(nil, mask, glyph, x, y, bbox);
fz_droppixmap(glyph);
}
}
@@ -475,7 +451,7 @@ fz_drawclipstroketext(void *user, fz_text *text, fz_strokestate *stroke, fz_matr
glyph = fz_renderstrokedglyph(dev->cache, text->font, gid, trm, ctm, stroke);
if (glyph)
{
- drawglyph(NULL, mask, glyph, x, y, bbox);
+ drawglyph(nil, mask, glyph, x, y, bbox);
fz_droppixmap(glyph);
}
}
@@ -548,7 +524,7 @@ fz_drawfillshade(void *user, fz_shade *shade, fz_matrix ctm, float alpha)
if (alpha < 1)
{
- fz_blendpixmapswithalpha(dev->dest, dest, alpha);
+ fz_paintpixmap(dev->dest, dest, alpha * 255);
fz_droppixmap(dest);
}
}
@@ -604,21 +580,7 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm, float alpha)
}
#endif
- if (alpha < 1)
- {
- fz_pixmap *temp;
- fz_bbox bbox;
- bbox = fz_roundrect(fz_transformrect(ctm, fz_unitrect));
- bbox = fz_intersectbbox(bbox, dev->scissor);
- temp = fz_newpixmapwithrect(dev->dest->colorspace, bbox);
- fz_blendimage(temp, bbox, image, ctm);
- fz_blendpixmapswithalpha(dev->dest, temp, alpha);
- fz_droppixmap(temp);
- }
- else
- {
- fz_blendimage(dev->dest, dev->scissor, image, ctm);
- }
+ fz_paintimage(dev->dest, dev->scissor, image, ctm, alpha * 255);
if (scaled)
fz_droppixmap(scaled);
@@ -657,18 +619,12 @@ fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm,
}
#endif
- if (dev->dest->colorspace)
- {
- fz_convertcolor(colorspace, color, model, colorfv);
- for (i = 0; i < model->n; i++)
- colorbv[i] = colorfv[i] * 255;
- colorbv[i] = alpha * 255;
- fz_blendimagewithcolor(dev->dest, dev->scissor, image, ctm, colorbv);
- }
- else
- {
- fz_blendimage(dev->dest, dev->scissor, image, ctm);
- }
+ fz_convertcolor(colorspace, color, model, colorfv);
+ for (i = 0; i < model->n; i++)
+ colorbv[i] = colorfv[i] * 255;
+ colorbv[i] = alpha * 255;
+
+ fz_paintimagecolor(dev->dest, dev->scissor, image, ctm, colorbv);
if (scaled)
fz_droppixmap(scaled);
@@ -725,7 +681,7 @@ fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm)
}
#endif
- fz_blendimage(mask, bbox, image, ctm);
+ fz_paintimage(mask, bbox, image, ctm, 255);
if (scaled)
fz_droppixmap(scaled);
@@ -752,7 +708,7 @@ fz_drawpopclip(void *user)
if (mask && dest)
{
fz_pixmap *scratch = dev->dest;
- fz_blendpixmapswithmask(dest, scratch, mask);
+ fz_paintpixmapmask(dest, scratch, mask);
fz_droppixmap(mask);
fz_droppixmap(scratch);
dev->dest = dest;
@@ -884,27 +840,9 @@ fz_drawendgroup(void *user)
dev->scissor = dev->stack[dev->top].scissor;
if (blendmode == FZ_BNORMAL)
- {
- if (alpha < 1)
- fz_blendpixmapswithalpha(dev->dest, group, alpha);
- else
- fz_blendpixmaps(dev->dest, group);
- }
+ fz_paintpixmap(dev->dest, group, alpha * 255);
else
- {
- if (alpha < 1)
- {
- unsigned char *p = group->samples;
- int n = group->w * group->h * group->n;
- int a = alpha * 255;
- while (n--)
- {
- *p = fz_mul255(*p, a);
- p++;
- }
- }
- fz_blendpixmapswithmode(dev->dest, group, blendmode);
- }
+ fz_blendpixmap(dev->dest, group, alpha * 255, blendmode);
fz_droppixmap(group);
}
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 44f1c070..8cd351ae 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -1030,6 +1030,50 @@ void fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix ctm);
* They can be replaced by cpu-optimized versions.
*/
+/*
+These are the blending primitives:
+
+span over span (text and path drawing to clip mask)
+span in alpha over span
+span in span over span
+color in span over span (text and path drawing)
+
+ fz_paintspan(dp, sp);
+ fz_paintspanalpha(dp, sp, alpha)
+ fz_paintspanmask(dp, sp, mask);
+ fz_paintspancolor(dp, color, mask);
+
+pixmap over pixmap (shading with function lookup)
+pixmap in alpha over pixmap (xobject/shading with ca)
+pixmap in pixmap over pixmap (xobject with softmask / clip)
+
+ fz_paintpixmap()
+ fz_paintpixmapalpha()
+ fz_paintpixmapmask()
+
+affine over span
+affine in alpha over span
+color in affine over span
+
+ fz_paintaffine()
+ fz_paintaffinealpha()
+ fz_paintaffinecolor()
+
+image over pixmap (image fill)
+image in alpha over pixmap (image fill with ca)
+color in image over pixmap (image mask fill)
+
+ fz_paintimage()
+ fz_paintimagealpha()
+ fz_paintimagecolor()
+
+pixmap BLEND pixmap
+pixmap in alpha BLEND pixmap
+
+ fz_blendpixmap()
+ fz_blendpixmapalpha()
+*/
+
void fz_accelerate(void);
void fz_acceleratearch(void);
@@ -1037,18 +1081,20 @@ void fz_decodetile(fz_pixmap *pix, float *decode);
void fz_decodeindexedtile(fz_pixmap *pix, float *decode, int maxval);
void fz_unpacktile(fz_pixmap *dst, unsigned char * restrict src, int n, int depth, int stride, int scale);
-void fz_blendpixmapswithmode(fz_pixmap *dst, fz_pixmap *src, fz_blendmode blendmode);
-void fz_blendpixmapswithmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk);
-void fz_blendpixmapswithalpha(fz_pixmap *dst, fz_pixmap *src, float alpha);
-void fz_blendpixmaps(fz_pixmap *dst, fz_pixmap *src);
+void fz_paintspan(unsigned char * restrict dp, unsigned char * restrict sp, int n, int w, int alpha);
+void fz_paintspancolor(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color);
+void fz_paintspanmask(unsigned char * restrict dp, unsigned char * restrict sp, unsigned char * restrict mp, int n, int w);
+
+void fz_paintaffine(unsigned char *dp, unsigned char *sp, int sw, int sh, int u, int v, int fa, int fb, int w, int n, int alpha);
+void fz_paintaffinecolor(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);
+
+void fz_paintimage(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm, int alpha);
+void fz_paintimagecolor(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm, unsigned char *colorbv);
-void fz_blendmasks(unsigned char * restrict dp, unsigned char * restrict sp, int w);
-void fz_blendwithcolormask(unsigned char * restrict dp, unsigned char * restrict sp, unsigned char * restrict mp, int n, int w);
-void fz_blendnormal(unsigned char * restrict dp, unsigned char * restrict sp, int n, int w);
-void fz_blendwithmask(unsigned char * restrict dp, unsigned char * restrict sp, unsigned char * restrict mp, int n, int w);
+void fz_paintpixmap(fz_pixmap *dst, fz_pixmap *src, int alpha);
+void fz_paintpixmapmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk);
-void fz_blendimage(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 *colorbv);
+void fz_blendpixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_blendmode blendmode);
extern void (*fz_srown)(unsigned char *restrict, unsigned char *restrict, int w, int denom, int n);
extern void (*fz_srow1)(unsigned char *restrict, unsigned char *restrict, int w, int denom);
diff --git a/fitz/res_font.c b/fitz/res_font.c
index 68b761b2..fd3bbe3f 100644
--- a/fitz/res_font.c
+++ b/fitz/res_font.c
@@ -458,6 +458,7 @@ fz_rendert3glyph(fz_font *font, int gid, fz_matrix trm)
fz_device *dev;
fz_glyphcache *cache;
fz_pixmap *glyph;
+ fz_pixmap *result;
if (gid < 0 || gid > 255)
return NULL;
@@ -473,7 +474,7 @@ fz_rendert3glyph(fz_font *font, int gid, fz_matrix trm)
fz_catch(error, "cannot draw type3 glyph");
fz_freedevice(dev);
- glyph = fz_newpixmap(nil, bbox.x0-1, bbox.y0-1, bbox.x1 - bbox.x0 + 1, bbox.y1 - bbox.y0 + 1);
+ glyph = fz_newpixmap(fz_devicegray, bbox.x0-1, bbox.y0-1, bbox.x1 - bbox.x0 + 1, bbox.y1 - bbox.y0 + 1);
fz_clearpixmap(glyph, 0);
cache = fz_newglyphcache();
@@ -484,7 +485,10 @@ fz_rendert3glyph(fz_font *font, int gid, fz_matrix trm)
fz_freedevice(dev);
fz_freeglyphcache(cache);
- return glyph;
+ result = fz_alphafromgray(glyph, 0);
+ fz_droppixmap(glyph);
+
+ return result;
}
void