summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-07-21 22:42:11 +0000
committerTor Andersson <tor@ghostscript.com>2010-07-21 22:42:11 +0000
commitd5d8d07709f6ad7d76ee1c466faf4d28549299a9 (patch)
tree4a5a49a4cf4edb527ac757068dfd3c6ec7d504e8
parentc7f031f2039aa6b8c681e377849208ebea4b6f01 (diff)
downloadmupdf-d5d8d07709f6ad7d76ee1c466faf4d28549299a9.tar.xz
Replace path blending with general blending functions. Rewrite image rendering loops so they don't depend on the scan converter.
-rw-r--r--draw/archport.c16
-rw-r--r--draw/imagedraw.c350
-rw-r--r--draw/pathscan.c101
-rw-r--r--draw/porterduff.c68
-rw-r--r--fitz/dev_draw.c136
-rw-r--r--fitz/fitz.h14
6 files changed, 254 insertions, 431 deletions
diff --git a/draw/archport.c b/draw/archport.c
index 16e80c99..c7be977a 100644
--- a/draw/archport.c
+++ b/draw/archport.c
@@ -4,6 +4,8 @@ typedef unsigned char byte;
/* These C implementations use SWAR (SIMD-within-a-register) techniques. */
+#if 0 /* TODO: move into porterduff.c functions */
+
#define MASK 0xFF00FF00;
static void
@@ -465,19 +467,17 @@ img_1o1_32bit(byte * restrict src, byte cov, int len, byte * restrict dst,
}
}
+#endif
+
void fz_accelerate(void)
{
if (sizeof(int) == 4 && sizeof(unsigned int) == 4 && !fz_isbigendian())
{
- fz_path_w4i1o4 = path_w4i1o4_32bit;
+// fz_path_w4i1o4 = path_w4i1o4_32bit;
// fz_text_w4i1o4 = text_w4i1o4_32bit;
- fz_img_4o4 = img_4o4_32bit;
- fz_img_w4i1o4 = img_w4i1o4_32bit;
- fz_img_1o1 = img_1o1_32bit;
- }
-
- if (sizeof(int) == 8)
- {
+// fz_img_4o4 = img_4o4_32bit;
+// fz_img_w4i1o4 = img_w4i1o4_32bit;
+// fz_img_1o1 = img_1o1_32bit;
}
#ifdef HAVE_CPUDEP
diff --git a/draw/imagedraw.c b/draw/imagedraw.c
index c43f9f24..8988a05f 100644
--- a/draw/imagedraw.c
+++ b/draw/imagedraw.c
@@ -1,7 +1,11 @@
#include "fitz.h"
+#define noNEAREST
+
typedef unsigned char byte;
+/* Sample image and clamp to edge */
+
static inline byte
getmask(byte *s, int w, int h, int u, int v)
{
@@ -13,23 +17,23 @@ getmask(byte *s, int w, int h, int u, int v)
}
static inline byte *
-getrgba(byte *s, int w, int h, int u, int v)
+getga(byte *s, int w, int h, 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 s + ((w * v + u) << 1);
}
static inline byte *
-getga(byte *s, int w, int h, int u, int v)
+getrgba(byte *s, int w, int h, 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) << 1);
+ return s + ((w * v + u) << 2);
}
static inline int
@@ -42,6 +46,8 @@ getcolor(byte *s, int w, int h, int n, int u, int v, int k)
return s[w * v * n + u + k];
}
+/* Bi-linear interpolation of sample */
+
static inline int
lerp(int a, int b, int t)
{
@@ -67,6 +73,9 @@ lerprgba(byte *dst, byte *a, byte *b, int 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;
@@ -78,13 +87,20 @@ samplemask(byte *s, int w, int h, int u, int v)
int ab = lerp(a, b, ud);
int cd = lerp(c, d, ud);
return lerp(ab, cd, vd);
+#endif
}
static inline void
-samplega(byte *s, int w, int h, int u, int v, byte *out)
+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;
@@ -95,14 +111,25 @@ samplega(byte *s, int w, int h, int u, int v, byte *out)
byte *d = getga(s, w, h, ui+1, vi+1);
lerpga(ab, a, b, ud);
lerpga(cd, c, d, ud);
- lerpga(out, ab, cd, vd);
+ lerpga(abcd, ab, cd, vd);
+ *gout = abcd[0];
+ *aout = abcd[0];
+#endif
}
static inline void
-samplergba(byte *s, int w, int h, int u, int v, byte *out)
+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;
@@ -113,12 +140,22 @@ samplergba(byte *s, int w, int h, int u, int v, byte *out)
byte *d = getrgba(s, w, h, ui+1, vi+1);
lerprgba(ab, a, b, ud);
lerprgba(cd, c, d, ud);
- lerprgba(out, ab, cd, vd);
+ lerprgba(abcd, ab, cd, vd);
+ *rout = abcd[0];
+ *gout = abcd[1];
+ *bout = abcd[2];
+ *aout = abcd[3];
+#endif
}
static inline void
samplecolor(byte *s, int w, int h, int n, int u, int v, byte *out)
{
+#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;
@@ -134,217 +171,190 @@ samplecolor(byte *s, int w, int h, int n, int u, int v, byte *out)
int cd = lerp(c, d, ud);
out[k] = lerp(ab, cd, vd);
}
+#endif
}
-static void
-img_1o1(byte * restrict src, byte cov, int len, byte * restrict dst,
- fz_pixmap *image, int u, int v, int fa, int fb)
-{
- byte *samples = image->samples;
- int w = image->w;
- int h = image->h;
+/* Blend source image scanline over destination */
- while (len--)
+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--)
{
- int sa;
- cov += *src; *src = 0; src++;
- if (cov != 0)
+ if (u >= 0 && u < sw << 16 && v >= 0 && v < sh << 16)
{
- sa = samplemask(samples, w, h, u, v);
- sa = FZ_COMBINE(FZ_EXPAND(sa), FZ_EXPAND(cov));
- if (sa != 0)
- {
- dst[0] = FZ_BLEND(255, dst[0], sa);
- }
+ int a = samplemask(sp, sw, sh, u, v);
+ dp[0] = a + fz_mul255(dp[0], 255 - a);
}
- dst++;
+ dp ++;
u += fa;
v += fb;
}
}
-static void
-img_2o2(byte * restrict src, byte cov, int len, byte * restrict dst,
- fz_pixmap *image, int u, int v, int fa, int fb)
+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)
{
- byte *samples = image->samples;
- int w = image->w;
- int h = image->h;
- byte ga[2];
-
- while (len--)
+ while (w--)
{
- int sa;
- cov += *src; *src = 0; src++;
- if (cov != 0)
+ if (u >= 0 && u < sw << 16 && v >= 0 && v < sh << 16)
{
- samplega(samples, w, h, u, v, ga);
- sa = FZ_COMBINE(FZ_EXPAND(ga[1]), FZ_EXPAND(cov));
- if (sa != 0)
- {
- dst[0] = FZ_BLEND(ga[0], dst[0], sa);
- dst[1] = FZ_BLEND(255, dst[1], sa);
- }
+ 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);
}
- dst += 2;
+ dp += 2;
u += fa;
v += fb;
}
}
-static void
-img_4o4(byte * restrict src, byte cov, int len, byte * restrict dst,
- fz_pixmap *image, int u, int v, int fa, int fb)
+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)
{
- byte *samples = image->samples;
- int w = image->w;
- int h = image->h;
- byte rgba[4];
-
- while (len--)
+ while (w--)
{
- int sa;
- cov += *src; *src = 0; src++;
- if (cov != 0)
+ if (u >= 0 && u < sw << 16 && v >= 0 && v < sh << 16)
{
- samplergba(samples, w, h, u, v, rgba);
- sa = FZ_COMBINE(FZ_EXPAND(rgba[3]), FZ_EXPAND(cov));
- if (sa != 0)
- {
- dst[0] = FZ_BLEND(rgba[0], dst[0], sa);
- dst[1] = FZ_BLEND(rgba[1], dst[1], sa);
- dst[2] = FZ_BLEND(rgba[2], dst[2], sa);
- dst[3] = FZ_BLEND(255, dst[3], sa);
- }
+ 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);
}
- dst += 4;
+ dp += 4;
u += fa;
v += fb;
}
}
-static void
-img_w2i1o2(byte *ga, byte * restrict src, byte cov, int len, byte * restrict dst,
- fz_pixmap *image, int u, int v, int fa, int 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)
{
- byte *samples = image->samples;
- int w = image->w;
- int h = image->h;
- byte g = ga[0];
- byte a = ga[1];
-
- if (a == 0)
- return;
- if (a != 255)
+ while (w--)
{
- while (len--)
+ if (u >= 0 && u < sw << 16 && v >= 0 && v < sh << 16)
{
- int ca;
- cov += *src; *src = 0; src++;
- if (cov != 0)
- {
- ca = samplemask(samples, w, h, u, v);
- ca = FZ_COMBINE(FZ_EXPAND(cov), FZ_EXPAND(ca));
- ca = FZ_COMBINE(ca, FZ_EXPAND(a));
- if (ca != 0)
- {
- dst[0] = FZ_BLEND(g, dst[0], ca);
- dst[1] = FZ_BLEND(255, dst[1], ca);
- }
- }
- dst += 2;
- u += fa;
- v += fb;
+ 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);
}
+ dp += n;
+ u += fa;
+ v += fb;
}
- else
+}
+
+/* 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--)
{
- while (len--)
+ if (u >= 0 && u < sw << 16 && v >= 0 && v < sh << 16)
{
- int ca;
- cov += *src; *src = 0; src++;
- if (cov != 0)
- {
- ca = samplemask(samples, w, h, u, v);
- ca = FZ_COMBINE(FZ_EXPAND(cov), FZ_EXPAND(ca));
- if (ca != 0)
- {
- dst[0] = FZ_BLEND(g, dst[0], ca);
- dst[1] = FZ_BLEND(255, dst[1], ca);
- }
- }
- dst += 2;
- u += fa;
- v += fb;
+ 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);
}
+ dp += n;
+ u += fa;
+ v += fb;
}
}
+/* Draw an image with an affine transform on destination */
+
static void
-img_w4i1o4(byte *rgba, byte * restrict src, byte cov, int len, byte * restrict dst,
- fz_pixmap *image, int u, int v, int fa, int fb)
+fz_blendimageimp(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm,
+ unsigned char *color)
{
- byte *samples = image->samples;
- int w = image->w;
- int h = image->h;
- byte r = rgba[0];
- byte g = rgba[1];
- byte b = rgba[2];
- byte a = rgba[3];
-
- if (a == 0)
- return;
- if (a != 255)
+ unsigned char *dp, *sp;
+ int u, v, fa, fb, fc, fd;
+ int x, y, w, h;
+ int sw, sh, n;
+ fz_matrix inv;
+ fz_bbox bbox;
+
+ /* map from screen space (x,y) to image space (u,v) */
+ inv = fz_scale(1.0f / img->w, -1.0f / img->h);
+ inv = fz_concat(inv, fz_translate(0, 1));
+ inv = fz_concat(inv, ctm);
+ inv = fz_invertmatrix(inv);
+ inv.e -= 0.5f;
+ inv.f -= 0.5f;
+
+ fa = inv.a * 65536;
+ fb = inv.b * 65536;
+ fc = inv.c * 65536;
+ fd = inv.d * 65536;
+
+ bbox = fz_roundrect(fz_transformrect(ctm, fz_unitrect));
+ bbox = fz_intersectbbox(bbox, scissor);
+ x = bbox.x0;
+ y = bbox.y0;
+ w = bbox.x1 - bbox.x0;
+ h = bbox.y1 - bbox.y0;
+
+ dp = dst->samples + ((bbox.y0 - dst->y) * dst->w + (bbox.x0 - dst->x)) * dst->n;
+ n = dst->n;
+ sp = img->samples;
+ sw = img->w;
+ sh = img->h;
+
+ u = (inv.a * (x+0.5) + inv.c * (y+0.5) + inv.e) * 65536;
+ v = (inv.b * (x+0.5) + inv.d * (y+0.5) + inv.f) * 65536;
+
+ while (h--)
{
- while (len--)
+ if (color)
{
- int ca;
- cov += *src; *src = 0; src++;
- if (cov != 0)
- {
- ca = samplemask(samples, w, h, u, v);
- ca = FZ_COMBINE(FZ_EXPAND(cov), FZ_EXPAND(ca));
- ca = FZ_COMBINE(ca, FZ_EXPAND(a));
- if (ca != 0)
- {
- dst[0] = FZ_BLEND(r, dst[0], ca);
- dst[1] = FZ_BLEND(g, dst[1], ca);
- dst[2] = FZ_BLEND(b, dst[2], ca);
- dst[3] = FZ_BLEND(255, dst[3], ca);
- }
- }
- dst += 4;
- u += fa;
- v += fb;
+ fz_blendscanwithcolor(dp, sp, sw, sh, u, v, fa, fb, w, n, color);
}
- }
- else
- {
- while (len--)
+ else
{
- int ca;
- cov += *src; *src = 0; src++;
- if (cov != 0)
+ switch (n)
{
- ca = samplemask(samples, w, h, u, v);
- ca = FZ_COMBINE(FZ_EXPAND(cov), FZ_EXPAND(ca));
- if (ca != 0)
- {
- dst[0] = FZ_BLEND(r, dst[0], ca);
- dst[1] = FZ_BLEND(g, dst[1], ca);
- dst[2] = FZ_BLEND(b, dst[2], ca);
- dst[3] = FZ_BLEND(255, dst[3], ca);
- }
+ 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;
}
- dst += 4;
- u += fa;
- v += fb;
}
+ dp += dst->w * n;
+ u += fc;
+ v += fd;
}
}
-void (*fz_img_1o1)(byte*restrict, byte, int, byte*restrict, fz_pixmap *image, int u, int v, int fa, int fb) = img_1o1;
-void (*fz_img_2o2)(byte*restrict, byte, int, byte*restrict, fz_pixmap *image, int u, int v, int fa, int fb) = img_2o2;
-void (*fz_img_4o4)(byte*restrict, byte, int, byte*restrict, fz_pixmap *image, int u, int v, int fa, int fb) = img_4o4;
-void (*fz_img_w2i1o2)(byte*, byte*restrict, byte, int, byte*restrict, fz_pixmap *image, int u, int v, int fa, int fb) = img_w2i1o2;
-void (*fz_img_w4i1o4)(byte*, byte*restrict, byte, int, byte*restrict, fz_pixmap *image, int u, int v, int fa, int fb) = img_w4i1o4;
+void
+fz_blendimagewithcolor(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm,
+ unsigned char *color)
+{
+ assert(img->n == 1);
+ fz_blendimageimp(dst, scissor, img, ctm, color);
+}
+
+void
+fz_blendimage(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matrix ctm)
+{
+ assert(dst->n == img->n);
+ fz_blendimageimp(dst, scissor, img, ctm, nil);
+}
diff --git a/draw/pathscan.c b/draw/pathscan.c
index e177d788..dc6c6ff8 100644
--- a/draw/pathscan.c
+++ b/draw/pathscan.c
@@ -457,7 +457,8 @@ evenodd(fz_ael *ael, unsigned char *list, int xofs)
}
}
-static inline void toalpha(unsigned char *list, int n)
+static inline void
+undelta(unsigned char *list, int n)
{
int d = 0;
while (n--)
@@ -467,97 +468,22 @@ static inline void toalpha(unsigned char *list, int n)
}
}
-static inline void blit(fz_pixmap *pix, int x, int y,
- unsigned char *list, int skipx, int len,
- unsigned char *color, fz_pixmap *image, fz_matrix *invmat)
+static inline void
+blit(fz_pixmap *dest, int x, int y, unsigned char *mp, int w, unsigned char *color)
{
- unsigned char *dst;
- unsigned char cov;
+ unsigned char *dp;
- dst = pix->samples + ( (y - pix->y) * pix->w + (x - pix->x) ) * pix->n;
- cov = 0;
+ dp = dest->samples + ( (y - dest->y) * dest->w + (x - dest->x) ) * dest->n;
- while (skipx--)
- {
- cov += *list;
- *list = 0;
- ++list;
- }
-
- if (image)
- {
- int u = (invmat->a * (x + 0.5f) + invmat->c * (y + 0.5f) + invmat->e) * 65536;
- int v = (invmat->b * (x + 0.5f) + invmat->d * (y + 0.5f) + invmat->f) * 65536;
- int fa = invmat->a * 65536;
- int fb = invmat->b * 65536;
- if (color)
- {
- assert(image->n == 1);
- switch (pix->n)
- {
- case 2:
- fz_img_w2i1o2(color, list, cov, len, dst, image, u, v, fa, fb);
- break;
- case 4:
- fz_img_w4i1o4(color, list, cov, len, dst, image, u, v, fa, fb);
- break;
- default:
- assert("Write fz_img_wni1on" != NULL);
- //fz_img_wni1on(color, list, cov, len, dst, image, u, v, fa, fb);
- break;
- }
- }
- else if (image->colorspace)
- {
- assert(image->colorspace->n == image->n - 1);
- assert(image->n == pix->n);
- switch (pix->n)
- {
- case 2:
- fz_img_2o2(list, cov, len, dst, image, u, v, fa, fb);
- break;
- case 4:
- fz_img_4o4(list, cov, len, dst, image, u, v, fa, fb);
- break;
- default:
- assert("Write fz_img_non" != NULL);
- //fz_img_non(list, cov, len, dst, image, u, v, fa, fb);
- break;
- }
- }
- else
- {
- assert(image->n == 1);
- assert(image->n == pix->n);
- fz_img_1o1(list, cov, len, dst, image, u, v, fa, fb);
- }
- }
+ if (color)
+ fz_blendwithcolormask(dp, color, mp, dest->n, w);
else
- {
- if (color)
- {
- switch (pix->n)
- {
- case 2:
- fz_path_w2i1o2(color, list, cov, len, dst);
- break;
- case 4:
- fz_path_w4i1o4(color, list, cov, len, dst);
- break;
- default:
- assert("Write fz_path_wni1on" != NULL);
- //fz_path_wni1on(color, list, cov, len, dst);
- break;
- }
- }
- else
- fz_path_1o1(list, cov, len, dst);
- }
+ fz_blendmasks(dp, mp, w);
}
fz_error
fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, fz_bbox clip,
- fz_pixmap *dest, unsigned char *color, fz_pixmap *image, fz_matrix *invmat)
+ fz_pixmap *dest, unsigned char *color)
{
fz_error error;
unsigned char *deltas;
@@ -593,7 +519,9 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, fz_bbox clip,
{
if (yd >= clip.y0 && yd < clip.y1)
{
- blit(dest, xmin + skipx, yd, deltas, skipx, clipn, color, image, invmat);
+ undelta(deltas, skipx + clipn);
+ blit(dest, xmin + skipx, yd, deltas + skipx, clipn, color);
+ memset(deltas, 0, skipx + clipn);
}
}
yd = yc;
@@ -622,7 +550,8 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, fz_bbox clip,
if (yd >= clip.y0 && yd < clip.y1)
{
- blit(dest, xmin + skipx, yd, deltas, skipx, clipn, color, image, invmat);
+ undelta(deltas, skipx + clipn);
+ blit(dest, xmin + skipx, yd, deltas + skipx, clipn, color);
}
fz_free(deltas);
diff --git a/draw/porterduff.c b/draw/porterduff.c
index 3596616d..e5070a5d 100644
--- a/draw/porterduff.c
+++ b/draw/porterduff.c
@@ -72,64 +72,6 @@ and stick to using the premultiplied form.
typedef unsigned char byte;
-/*
- * Path drawing (the source colors are not premultiplied)
- */
-
-static void
-path_1o1(byte * restrict src, byte cov, int len, byte * restrict dst)
-{
- while (len--)
- {
- int c;
- cov += *src; *src = 0; src++;
- c = FZ_EXPAND(cov);
- dst[0] = FZ_BLEND(255, dst[0], c);
- dst++;
- }
-}
-
-static void
-path_w2i1o2(byte *ga, byte * restrict src, byte cov, int len, byte * restrict dst)
-{
- byte g = ga[0];
- int a = FZ_EXPAND(ga[1]);
-
- while (len--)
- {
- int ca;
- cov += *src; *src = 0; src++;
- ca = FZ_COMBINE(FZ_EXPAND(cov), a);
- dst[0] = FZ_BLEND(g, dst[0], ca);
- dst[1] = FZ_BLEND(255, dst[1], ca);
- dst += 2;
- }
-}
-
-static void
-path_w4i1o4(byte *rgba, byte * restrict src, byte cov, int len, byte * restrict dst)
-{
- byte r = rgba[0];
- byte g = rgba[1];
- byte b = rgba[2];
- int a = FZ_EXPAND(rgba[3]);
- while (len--)
- {
- int ca;
- cov += *src; *src = 0; src++;
- ca = FZ_COMBINE(FZ_EXPAND(cov), a);
- dst[0] = FZ_BLEND(r, dst[0], ca);
- dst[1] = FZ_BLEND(g, dst[1], ca);
- dst[2] = FZ_BLEND(b, dst[2], ca);
- dst[3] = FZ_BLEND(255, dst[3], ca);
- dst += 4;
- }
-}
-
-void (*fz_path_1o1)(byte*restrict,byte,int,byte*restrict) = path_1o1;
-void (*fz_path_w2i1o2)(byte*,byte*restrict,byte,int,byte*restrict) = path_w2i1o2;
-void (*fz_path_w4i1o4)(byte*,byte*restrict,byte,int,byte*restrict) = path_w4i1o4;
-
/* Blend source alpha over destination alpha */
void
@@ -288,6 +230,9 @@ fz_blendpixmapswithmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
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));
@@ -302,9 +247,6 @@ fz_blendpixmapswithmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk)
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;
- assert(dst->n == src->n);
- assert(msk->n == 1);
-
while (h--)
{
fz_blendwithmask(dp, sp, mp, n, w);
@@ -321,6 +263,8 @@ fz_blendpixmapswithalpha(fz_pixmap *dst, fz_pixmap *src, float alpha)
fz_bbox bbox;
int x, y, w, h, n, a;
+ assert(dst->n == src->n);
+
bbox = fz_boundpixmap(dst);
bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
@@ -334,8 +278,6 @@ fz_blendpixmapswithalpha(fz_pixmap *dst, fz_pixmap *src, float alpha)
sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;
dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
- assert(dst->n == src->n);
-
while (h--)
{
if (a == 255)
diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c
index 36423051..f707b968 100644
--- a/fitz/dev_draw.c
+++ b/fitz/dev_draw.c
@@ -57,11 +57,11 @@ fz_drawfillpath(void *user, fz_path *path, int evenodd, fz_matrix ctm,
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, nil, nil);
+ fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, colorbv);
}
else
{
- fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, nil, nil, nil);
+ fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, dev->dest, nil);
}
}
@@ -101,11 +101,11 @@ fz_drawstrokepath(void *user, fz_path *path, fz_strokestate *stroke, fz_matrix c
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, nil, nil);
+ fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, colorbv);
}
else
{
- fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil, nil, nil);
+ fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil);
}
}
@@ -148,7 +148,7 @@ fz_drawclippath(void *user, fz_path *path, int evenodd, fz_matrix ctm)
fz_clearpixmap(mask, 0);
fz_clearpixmap(dest, 0);
- fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, mask, nil, nil, nil);
+ fz_scanconvert(dev->gel, dev->ael, evenodd, bbox, mask, nil);
dev->stack[dev->top].scissor = dev->scissor;
dev->stack[dev->top].mask = mask;
@@ -195,7 +195,7 @@ fz_drawclipstrokepath(void *user, fz_path *path, fz_strokestate *stroke, fz_matr
fz_clearpixmap(dest, 0);
if (!fz_isemptyrect(bbox))
- fz_scanconvert(dev->gel, dev->ael, 0, bbox, mask, nil, nil, nil);
+ fz_scanconvert(dev->gel, dev->ael, 0, bbox, mask, nil);
dev->stack[dev->top].scissor = dev->scissor;
dev->stack[dev->top].mask = mask;
@@ -539,56 +539,14 @@ fz_drawfillshade(void *user, fz_shade *shade, fz_matrix ctm)
fz_rendershade(shade, ctm, dev->dest, bbox);
}
-static inline void
-calcimagestate(fz_drawdevice *dev, fz_pixmap *image, fz_matrix ctm,
- fz_bbox *bbox, fz_matrix *invmat, int *dx, int *dy)
+static int
+fz_calcimagescale(fz_pixmap *image, fz_matrix ctm, int *dx, int *dy)
{
- float sx, sy;
- fz_path *path;
- fz_matrix mat;
- int w, h;
-
- sx = image->w / sqrtf(ctm.a * ctm.a + ctm.b * ctm.b);
- sy = image->h / sqrtf(ctm.c * ctm.c + ctm.d * ctm.d);
-
- if (sx < 1)
- *dx = 1;
- else
- *dx = sx;
-
- if (sy < 1)
- *dy = 1;
- else
- *dy = sy;
-
- w = (image->w + *dx - 1) / *dx;
- h = (image->h + *dy - 1) / *dy;
-
- path = fz_newpath();
- fz_moveto(path, 0, 0);
- fz_lineto(path, 1, 0);
- fz_lineto(path, 1, 1);
- fz_lineto(path, 0, 1);
- fz_closepath(path);
-
- fz_resetgel(dev->gel, dev->scissor);
- fz_fillpath(dev->gel, path, ctm, 1);
- fz_sortgel(dev->gel);
-
- fz_freepath(path);
-
- *bbox = fz_boundgel(dev->gel);
- *bbox = fz_intersectbbox(*bbox, dev->scissor);
-
- mat.a = 1.0f / w;
- mat.b = 0;
- mat.c = 0;
- mat.d = -1.0f / h;
- mat.e = 0;
- mat.f = 1;
- *invmat = fz_invertmatrix(fz_concat(mat, ctm));
- invmat->e -= 0.5f;
- invmat->f -= 0.5f;
+ float sx = image->w / sqrtf(ctm.a * ctm.a + ctm.b * ctm.b);
+ float sy = image->h / sqrtf(ctm.c * ctm.c + ctm.d * ctm.d);
+ *dx = sx > 1 ? sx : 1;
+ *dy = sy > 1 ? sy : 1;
+ return *dx > 1 || *dy > 1;
}
static void
@@ -596,11 +554,9 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm)
{
fz_drawdevice *dev = user;
fz_colorspace *model = dev->dest->colorspace;
- fz_bbox bbox;
- int dx, dy;
- fz_pixmap *scaled = nil;
fz_pixmap *converted = nil;
- fz_matrix invmat;
+ fz_pixmap *scaled = nil;
+ int dx, dy;
if (!model)
{
@@ -608,17 +564,9 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm)
return;
}
- calcimagestate(dev, image, ctm, &bbox, &invmat, &dx, &dy);
-
- if (fz_isemptyrect(bbox) || image->w == 0 || image->h == 0)
+ if (image->w == 0 || image->h == 0)
return;
- if (dx != 1 || dy != 1)
- {
- scaled = fz_scalepixmap(image, dx, dy);
- image = scaled;
- }
-
if (image->colorspace != model)
{
converted = fz_newpixmap(model, image->x, image->y, image->w, image->h);
@@ -626,7 +574,13 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm)
image = converted;
}
- fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil, image, &invmat);
+ if (fz_calcimagescale(image, ctm, &dx, &dy))
+ {
+ scaled = fz_scalepixmap(image, dx, dy);
+ image = scaled;
+ }
+
+ fz_blendimage(dev->dest, dev->scissor, image, ctm);
if (scaled)
fz_droppixmap(scaled);
@@ -642,18 +596,14 @@ fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm,
fz_colorspace *model = dev->dest->colorspace;
unsigned char colorbv[FZ_MAXCOLORS + 1];
float colorfv[FZ_MAXCOLORS];
- fz_bbox bbox;
- int dx, dy;
fz_pixmap *scaled = nil;
- fz_matrix invmat;
+ int dx, dy;
int i;
- calcimagestate(dev, image, ctm, &bbox, &invmat, &dx, &dy);
-
- if (fz_isemptyrect(bbox) || image->w == 0 || image->h == 0)
+ if (image->w == 0 || image->h == 0)
return;
- if (dx != 1 || dy != 1)
+ if (fz_calcimagescale(image, ctm, &dx, &dy))
{
scaled = fz_scalepixmap(image, dx, dy);
image = scaled;
@@ -665,11 +615,11 @@ fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm,
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, image, &invmat);
+ fz_blendimagewithcolor(dev->dest, dev->scissor, image, ctm, colorbv);
}
else
{
- fz_scanconvert(dev->gel, dev->ael, 0, bbox, dev->dest, nil, image, &invmat);
+ fz_blendimage(dev->dest, dev->scissor, image, ctm);
}
if (scaled)
@@ -683,9 +633,8 @@ fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm)
fz_colorspace *model = dev->dest->colorspace;
fz_bbox bbox;
fz_pixmap *mask, *dest;
- int dx, dy;
fz_pixmap *scaled = nil;
- fz_matrix invmat;
+ int dx, dy;
if (dev->top == STACKSIZE)
{
@@ -693,23 +642,18 @@ fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm)
return;
}
- calcimagestate(dev, image, ctm, &bbox, &invmat, &dx, &dy);
-
- if (fz_isemptyrect(bbox) || image->w == 0 || image->h == 0)
+ if (image->w == 0 || image->h == 0)
{
dev->stack[dev->top].scissor = dev->scissor;
dev->stack[dev->top].mask = nil;
dev->stack[dev->top].dest = nil;
- dev->scissor = bbox;
+ dev->scissor = fz_emptybbox;
dev->top++;
return;
}
- if (dx != 1 || dy != 1)
- {
- scaled = fz_scalepixmap(image, dx, dy);
- image = scaled;
- }
+ bbox = fz_roundrect(fz_transformrect(ctm, fz_unitrect));
+ bbox = fz_intersectbbox(bbox, dev->scissor);
mask = fz_newpixmapwithrect(nil, bbox);
dest = fz_newpixmapwithrect(model, bbox);
@@ -717,7 +661,16 @@ fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm)
fz_clearpixmap(mask, 0);
fz_clearpixmap(dest, 0);
- fz_scanconvert(dev->gel, dev->ael, 0, bbox, mask, nil, image, &invmat);
+ if (fz_calcimagescale(image, ctm, &dx, &dy))
+ {
+ scaled = fz_scalepixmap(image, dx, dy);
+ image = scaled;
+ }
+
+ fz_blendimage(mask, bbox, image, ctm);
+
+ if (scaled)
+ fz_droppixmap(scaled);
dev->stack[dev->top].scissor = dev->scissor;
dev->stack[dev->top].mask = mask;
@@ -725,9 +678,6 @@ fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm)
dev->scissor = bbox;
dev->dest = dest;
dev->top++;
-
- if (scaled)
- fz_droppixmap(scaled);
}
static void
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 1465e8b9..12a273a5 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -977,7 +977,7 @@ fz_ael * fz_newael(void);
void fz_freeael(fz_ael *ael);
fz_error fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill,
- fz_bbox clip, fz_pixmap *pix, unsigned char *colorbv, fz_pixmap *image, fz_matrix *invmat);
+ fz_bbox clip, fz_pixmap *pix, unsigned char *colorbv);
void fz_fillpath(fz_gel *gel, fz_path *path, fz_matrix ctm, float flatness);
void fz_strokepath(fz_gel *gel, fz_path *path, fz_strokestate *stroke, fz_matrix ctm, float flatness, float linewidth);
@@ -1147,16 +1147,8 @@ void fz_blendwithcolormask(unsigned char * restrict dp, unsigned char * restrict
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);
-extern void (*fz_path_1o1)(unsigned char*restrict,unsigned char,int,unsigned char*restrict);
-extern void (*fz_path_w2i1o2)(unsigned char*,unsigned char*restrict,unsigned char,int,unsigned char*restrict);
-extern void (*fz_path_w4i1o4)(unsigned char*,unsigned char*restrict,unsigned char,int,unsigned char*restrict);
-
-extern void (*fz_img_non)(unsigned char*restrict,unsigned char,int,unsigned char*restrict,fz_pixmap*,fz_matrix*);
-extern void (*fz_img_1o1)(unsigned char*restrict,unsigned char,int,unsigned char*restrict,fz_pixmap*,int u, int v, int fa, int fb);
-extern void (*fz_img_4o4)(unsigned char*restrict,unsigned char,int,unsigned char*restrict,fz_pixmap*,int u, int v, int fa, int fb);
-extern void (*fz_img_2o2)(unsigned char*restrict,unsigned char,int,unsigned char*restrict,fz_pixmap*,int u, int v, int fa, int fb);
-extern void (*fz_img_w2i1o2)(unsigned char*,unsigned char*restrict,unsigned char,int,unsigned char*restrict,fz_pixmap*,int u, int v, int fa, int fb);
-extern void (*fz_img_w4i1o4)(unsigned char*,unsigned char*restrict,unsigned char,int,unsigned char*restrict,fz_pixmap*,int u, int v, int fa, int fb);
+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);
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);