diff options
author | Tor Andersson <tor@ghostscript.com> | 2010-07-21 22:42:11 +0000 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2010-07-21 22:42:11 +0000 |
commit | d5d8d07709f6ad7d76ee1c466faf4d28549299a9 (patch) | |
tree | 4a5a49a4cf4edb527ac757068dfd3c6ec7d504e8 | |
parent | c7f031f2039aa6b8c681e377849208ebea4b6f01 (diff) | |
download | mupdf-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.c | 16 | ||||
-rw-r--r-- | draw/imagedraw.c | 350 | ||||
-rw-r--r-- | draw/pathscan.c | 101 | ||||
-rw-r--r-- | draw/porterduff.c | 68 | ||||
-rw-r--r-- | fitz/dev_draw.c | 136 | ||||
-rw-r--r-- | fitz/fitz.h | 14 |
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); |