diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-11-24 03:47:04 +0100 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-11-24 03:47:04 +0100 |
commit | b48de7618e25bc2cef9d9db4f9b49e1d546e438a (patch) | |
tree | 5f365a90a0bd355073e7d5d1f69e66d2f82b4446 /render | |
parent | e092458f4403f1424d8fd1f5ec194880a05c3362 (diff) | |
download | mupdf-b48de7618e25bc2cef9d9db4f9b49e1d546e438a.tar.xz |
rewrite of render loop part 3
Diffstat (limited to 'render')
-rw-r--r-- | render/pixmap.c | 117 | ||||
-rw-r--r-- | render/rastnone.c | 385 | ||||
-rw-r--r-- | render/rastport.c | 448 | ||||
-rw-r--r-- | render/render.c | 427 |
4 files changed, 729 insertions, 648 deletions
diff --git a/render/pixmap.c b/render/pixmap.c index 21f36ee0..c024a025 100644 --- a/render/pixmap.c +++ b/render/pixmap.c @@ -33,6 +33,17 @@ fz_newpixmapwithrect(fz_pixmap **pixp, fz_irect r, int n) r.max.y - r.min.y, n); } +fz_error * +fz_newpixmapcopy(fz_pixmap **pixp, fz_pixmap *old) +{ + fz_error *error; + error = fz_newpixmap(pixp, old->x, old->y, old->w, old->h, old->n); + if (error) + return error; + memcpy((*pixp)->samples, old->samples, old->w * old->h * old->n); + return nil; +} + void fz_droppixmap(fz_pixmap *pix) { @@ -47,112 +58,6 @@ fz_clearpixmap(fz_pixmap *pix) } void -fz_blendover(fz_pixmap *src, fz_pixmap *dst) -{ - int x, y, k; - fz_irect sr, dr, rect; - unsigned char *s; - unsigned char *d; - - assert(dst->n == src->n || src->n == 1); - - sr.min.x = src->x; - sr.min.y = src->y; - sr.max.x = src->x + src->w; - sr.max.y = src->y + src->h; - - dr.min.x = dst->x; - dr.min.y = dst->y; - dr.max.x = dst->x + dst->w; - dr.max.y = dst->y + dst->h; - - rect = fz_intersectirects(sr, dr); - - if (dst->n == src->n) - { - for (y = rect.min.y; y < rect.max.y; y++) - { - s = src->samples + ((rect.min.x - src->x) + (y - src->y) * src->w) * src->n; - d = dst->samples + ((rect.min.x - dst->x) + (y - dst->y) * dst->w) * dst->n; - for (x = rect.min.x; x < rect.max.x; x++) - { - int sa = s[0]; - int ssa = 255 - sa; - - for (k = 0; k < dst->n; k++) - d[k] = s[k] + fz_mul255(d[k], ssa); - - s += src->n; - d += dst->n; - } - } - } - else if (src->n == 1) - { - for (y = rect.min.y; y < rect.max.y; y++) - { - s = src->samples + ((rect.min.x - src->x) + (y - src->y) * src->w) * src->n; - d = dst->samples + ((rect.min.x - dst->x) + (y - dst->y) * dst->w) * dst->n; - for (x = rect.min.x; x < rect.max.x; x++) - { - int sa = s[0]; - int ssa = 255 - sa; - - d[0] = s[0] + fz_mul255(d[0], ssa); - for (k = 1; k < dst->n; k++) - d[k] = 0 + fz_mul255(d[k], ssa); - - s += src->n; - d += dst->n; - } - } - } -} - -void -fz_blendmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk) -{ - unsigned char *d; - unsigned char *s; - unsigned char *m; - fz_irect sr, dr, mr, rect; - int x, y, k; - - assert(src->n == dst->n); - - sr.min.x = src->x; - sr.min.y = src->y; - sr.max.x = src->x + src->w; - sr.max.y = src->y + src->h; - - dr.min.x = dst->x; - dr.min.y = dst->y; - dr.max.x = dst->x + dst->w; - dr.max.y = dst->y + dst->h; - - mr.min.x = msk->x; - mr.min.y = msk->y; - mr.max.x = msk->x + msk->w; - mr.max.y = msk->y + msk->h; - - rect = fz_intersectirects(sr, dr); - rect = fz_intersectirects(rect, mr); - - for (y = rect.min.y; y < rect.max.y; y++) - { - s = src->samples + ((rect.min.x - src->x) + (y - src->y) * src->w) * src->n; - d = dst->samples + ((rect.min.x - dst->x) + (y - dst->y) * dst->w) * dst->n; - m = msk->samples + ((rect.min.x - msk->x) + (y - msk->y) * msk->w) * msk->n; - for (x = rect.min.x; x < rect.max.x; x++) - { - for (k = 0; k < dst->n; k++) - *d++ = fz_mul255(*s++, *m); - m += msk->n; - } - } -} - -void fz_gammapixmap(fz_pixmap *pix, float gamma) { unsigned char table[255]; diff --git a/render/rastnone.c b/render/rastnone.c deleted file mode 100644 index 2af45882..00000000 --- a/render/rastnone.c +++ /dev/null @@ -1,385 +0,0 @@ -#include <fitz.h> - -/* XXX: half of these funcs are totally wrong. fix! */ - -typedef unsigned char byte; - -/* - * Mask -- blit one span (clipped and adjusted) - * - * mask_g - * mask_i1 - * mask_o1 - * mask_i1o1 - * mask_o4w3 - * mask_i1o4w3 - */ - -static void mask_g(int n, byte *src, byte *pix) -{ - memcpy(pix, src, n); -} - -static void mask_i1(int n, byte *src, byte *dst) -{ - while (n--) - { - dst[0] = fz_mul255(src[0], dst[0]); - src++; - dst++; - } -} - -static void mask_o1(int n, byte *src, byte *dst) -{ - while (n--) - { - dst[0] = src[0] + fz_mul255(dst[0], 255 - src[0]); - src++; - dst++; - } -} - -static void mask_i1o1(int n, byte *src, byte *msk, byte *dst) -{ - while (n--) - { - byte sa = fz_mul255(src[0], msk[0]); - dst[0] = sa + fz_mul255(dst[0], 255 - sa); - src++; - msk++; - dst++; - } -} - -static void mask_o4w3(int n, byte *src, byte *dst, byte *rgb) -{ - byte sa, ssa; - while (n--) - { - sa = src[0]; - ssa = 255 - sa; - dst[0] = sa + fz_mul255(dst[0], ssa); - dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa); - dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa); - dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa); - src ++; - dst += 4; - } -} - -static void mask_i1o4w3(int n, byte *src, byte *msk, byte *dst, byte *rgb) -{ - byte sa, ssa; - while (n--) - { - sa = fz_mul255(src[0], msk[0]); - ssa = 255 - sa; - dst[0] = sa + fz_mul255(dst[0], ssa); - dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa); - dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa); - dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa); - src ++; - msk ++; - dst += 4; - } -} - -/* - * Image -- blit entire image - * - * img1_g - * img1_i1 - * img1_o1 - * img1_i1o1 - * img1_o4w3 - * img1_i1o4w3 - * - * img4_g - * img4_o4 - * img4_i1o4 - */ - -#define lerpmsk(a,b,t) (a + (((b - a) * t) >> 16)) - -static inline byte getmsk(byte *s, int w, int h, int u, int v) -{ - if (u < 0 || u >= w) return 0; - if (v < 0 || v >= h) return 0; - return s[w * v + u]; -} - -static inline int samplemsk(byte *s, int w, int h, int u, int v) -{ - int ui = u >> 16; - int vi = v >> 16; - int ud = u & 0xFFFF; - int vd = v & 0xFFFF; - int a = getmsk(s, w, h, ui, vi); - int b = getmsk(s, w, h, ui+1, vi); - int c = getmsk(s, w, h, ui, vi+1); - int d = getmsk(s, w, h, ui+1, vi+1); - int ab = lerpmsk(a, b, ud); - int cd = lerpmsk(c, d, ud); - return lerpmsk(ab, cd, vd); -} - -static inline void lerpargb(byte *dst, byte *a, byte *b, int t) -{ - dst[0] = lerpmsk(a[0], b[0], t); - dst[1] = lerpmsk(a[1], b[1], t); - dst[2] = lerpmsk(a[2], b[2], t); - dst[3] = lerpmsk(a[3], b[3], t); -} - -static inline byte *getargb(byte *s, int w, int h, int u, int v) -{ - static byte zero[4] = { 0, 0, 0, 0 }; - if (u < 0 || u >= w) return zero; - if (v < 0 || v >= h) return zero; - return s + ((w * v + u) << 2); -} - -static inline void sampleargb(byte *s, int w, int h, int u, int v, byte *abcd) -{ - byte ab[4]; - byte cd[4]; - int ui = u >> 16; - int vi = v >> 16; - int ud = u & 0xFFFF; - int vd = v & 0xFFFF; - byte *a = getargb(s, w, h, ui, vi); - byte *b = getargb(s, w, h, ui+1, vi); - byte *c = getargb(s, w, h, ui, vi+1); - byte *d = getargb(s, w, h, ui+1, vi+1); - lerpargb(ab, a, b, ud); - lerpargb(cd, c, d, ud); - lerpargb(abcd, ab, cd, vd); -} - -#define PSRC byte *src, int w, int h, int nx0, int ny -#define PDST byte *dst0, int dstw -#define PMSK byte *msk0, int mskw -#define PCTM int u0, int v0, int fa, int fb, int fc, int fd - -#if 0 -static void example(PSRC, PDST, PMSK, PCTM) -{ - while (ny--) - { - byte *dst = dst0; - byte *msk = msk0; - int u = u0; - int v = v0; - int nx = nx0; - while (nx--) - { - // dst[0] = ... msk[0] ... sample(s, w, h, u, v); - dst ++; - msk ++; - u += fa; - v += fb; - } - u0 += fc; - v0 += fd; - dst0 += dstw; - msk0 += mskw; - } -} -#endif - -#define BEGLOOP \ - while (ny--) \ - { \ - byte *dst = dst0; \ - int u = u0; \ - int v = v0; \ - int nx = nx0; \ - while (nx--) - -#define ENDLOOP \ - u0 += fc; \ - v0 += fd; \ - dst0 += dstw; \ - } - -#define BEGLOOPM \ - while (ny--) \ - { \ - byte *dst = dst0; \ - byte *msk = msk0; \ - int u = u0; \ - int v = v0; \ - int nx = nx0; \ - while (nx--) - -#define ENDLOOPM \ - u0 += fc; \ - v0 += fd; \ - dst0 += dstw; \ - msk0 += mskw; \ - } - -static void img1_g(PSRC, PDST, PCTM) -{ - BEGLOOP - { - dst[0] = samplemsk(src, w, h, u, v); - dst ++; - u += fa; - v += fb; - } - ENDLOOP -} - -static void img1_i1(PSRC, PDST, PCTM) -{ - BEGLOOP - { - dst[0] = fz_mul255(dst[0], samplemsk(src, w, h, u, v)); - dst ++; - u += fa; - v += fb; - } - ENDLOOP -} - -static void img1_o1(PSRC, PDST, PCTM) -{ - BEGLOOP - { - byte sa = samplemsk(src, w, h, u, v); - dst[0] = sa + fz_mul255(dst[0], 255 - sa); - dst ++; - u += fa; - v += fb; - } - ENDLOOP -} - -static void img1_i1o1(PSRC, PDST, PMSK, PCTM) -{ - BEGLOOPM - { - byte sa = fz_mul255(msk[0], samplemsk(src, w, h, u, v)); - dst[0] = sa + fz_mul255(dst[0], 255 - sa); - dst ++; - msk ++; - u += fa; - v += fb; - } - ENDLOOPM -} - -static void img1_o4w3(PSRC, PDST, PCTM, byte *rgb) -{ - BEGLOOP - { - byte sa = samplemsk(src, w, h, u, v); - byte ssa = 255 - sa; - dst[0] = sa + fz_mul255(dst[0], ssa); - dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa); - dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa); - dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa); - dst += 4; - u += fa; - v += fb; - } - ENDLOOP -} - -static void img1_i1o4w3(PSRC, PDST, PMSK, PCTM, byte *rgb) -{ - BEGLOOPM - { - byte sa = fz_mul255(msk[0], samplemsk(src, w, h, u, v)); - byte ssa = 255 - sa; - dst[0] = sa + fz_mul255(dst[0], ssa); - dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa); - dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa); - dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa); - dst += 4; - msk ++; - u += fa; - v += fb; - } - ENDLOOPM -} - -static void img4_g(PSRC, PDST, PCTM) -{ - BEGLOOP - { - sampleargb(src, w, h, u, v, dst); - dst += 4; - u += fa; - v += fb; - } - ENDLOOP -} - -static void img4_o4(PSRC, PDST, PCTM) -{ - byte argb[4]; - BEGLOOP - { - sampleargb(src, w, h, u, v, argb); - byte sa = argb[0]; - byte ssa = 255 - sa; - dst[0] = sa + fz_mul255(dst[0], ssa); - dst[1] = argb[1] + fz_mul255(dst[1], ssa); - dst[2] = argb[2] + fz_mul255(dst[2], ssa); - dst[3] = argb[3] + fz_mul255(dst[3], ssa); - dst += 4; - u += fa; - v += fb; - } - ENDLOOP -} - -static void img4_i1o4(PSRC, PDST, PMSK, PCTM) -{ - byte argb[4]; - BEGLOOPM - { - sampleargb(src, w, h, u, v, argb); - byte sa = fz_mul255(msk[0], argb[0]); - byte ssa = 255 - sa; - dst[0] = argb[0] + fz_mul255(dst[0], ssa); - dst[1] = argb[1] + fz_mul255((short)dst[1] - argb[1], ssa); - dst[2] = argb[2] + fz_mul255((short)dst[2] - argb[2], ssa); - dst[3] = argb[3] + fz_mul255((short)dst[3] - argb[3], ssa); - dst += 4; - msk ++; - u += fa; - v += fb; - } - ENDLOOPM -} - -/* - * - */ - -void -fz_defaultrastfuncs(fz_rastfuncs *tab) -{ - tab->mask_g = mask_g; - tab->mask_i1 = mask_i1; - tab->mask_o1 = mask_o1; - tab->mask_i1o1 = mask_i1o1; - tab->mask_o4w3 = mask_o4w3; - tab->mask_i1o4w3 = mask_i1o4w3; - - tab->img1_g = img1_g; - tab->img1_i1 = img1_i1; - tab->img1_o1 = img1_o1; - tab->img1_i1o1 = img1_i1o1; - tab->img1_o4w3 = img1_o4w3; - tab->img1_i1o4w3 = img1_i1o4w3; - - tab->img4_g = img4_g; - tab->img4_o4 = img4_o4; - tab->img4_i1o4 = img4_i1o4; -} - diff --git a/render/rastport.c b/render/rastport.c new file mode 100644 index 00000000..0daf3458 --- /dev/null +++ b/render/rastport.c @@ -0,0 +1,448 @@ +#include <fitz.h> + +/* XXX: half of these funcs are totally wrong. fix! */ + +typedef unsigned char byte; + +/* + * General Porter-Duff compositing -- blit image regions + * + * duff_NoN + * duff_NiM + * duff_NiMoN + */ + +/* dst = src over dst */ +static void +duff_NoN(byte *sp0, int sw, int sn, byte *dp0, int dw, int w0, int h) +{ + int k; + while (h--) + { + byte *sp = sp0; + byte *dp = dp0; + int w = w0; + while (w--) + { + byte sa = sp[0]; + byte ssa = 255 - sa; + for (k = 0; k < sn; k++) + { + dp[k] = sp[k] + fz_mul255(dp[k], ssa); + } + sp += sn; + dp += sn; + } + sp0 += sw; + dp0 += dw; + } +} + +/* dst = src in msk */ +static void +duff_NiMcN(byte *sp0, int sw, int sn, byte *mp0, int mw, int mn, byte *dp0, int dw, int w0, int h) +{ + int k; + while (h--) + { + byte *sp = sp0; + byte *mp = mp0; + byte *dp = dp0; + int w = w0; + while (w--) + { + byte ma = mp[0]; + for (k = 0; k < sn; k++) + dp[k] = fz_mul255(sp[k], ma); + sp += sn; + mp += mn; + dp += sn; + } + sp0 += sw; + mp0 += mw; + dp0 += dw; + } +} + +/* dst = src in msk over dst */ +static void +duff_NiMoN(byte *sp0, int sw, int sn, byte *mp0, int mw, int mn, byte *dp0, int dw, int w0, int h) +{ + int k; + while (h--) + { + byte *sp = sp0; + byte *mp = mp0; + byte *dp = dp0; + int w = w0; + while (w--) + { + byte ma = mp[0]; + byte sa = fz_mul255(sp[0], ma); + byte ssa = 255 - sa; + for (k = 0; k < sn; k++) + { + dp[k] = fz_mul255(sp[k], ma) + fz_mul255(dp[k], ssa); + } + sp += sn; + mp += mn; + dp += sn; + } + sp0 += sw; + mp0 += mw; + dp0 += dw; + } +} + +static void duff_1o1(byte *sp0, int sw, byte *dp0, int dw, int w0, int h) +{ + duff_NoN(sp0, sw, 1, dp0, dw, w0, h); +} + +static void duff_4o4(byte *sp0, int sw, byte *dp0, int dw, int w0, int h) +{ + duff_NoN(sp0, sw, 4, dp0, dw, w0, h); +} + +static void duff_1i1c1(byte *sp0, int sw, byte *mp0, int mw, byte *dp0, int dw, int w0, int h) +{ + duff_NiMcN(sp0, sw, 1, mp0, mw, 1, dp0, dw, w0, h); +} + +static void duff_4i1c4(byte *sp0, int sw, byte *mp0, int mw, byte *dp0, int dw, int w0, int h) +{ + duff_NiMcN(sp0, sw, 4, mp0, mw, 1, dp0, dw, w0, h); +} + +static void duff_1i1o1(byte *sp0, int sw, byte *mp0, int mw, byte *dp0, int dw, int w0, int h) +{ + duff_NiMoN(sp0, sw, 1, mp0, mw, 1, dp0, dw, w0, h); +} + +static void duff_4i1o4(byte *sp0, int sw, byte *mp0, int mw, byte *dp0, int dw, int w0, int h) +{ + duff_NiMoN(sp0, sw, 4, mp0, mw, 1, dp0, dw, w0, h); +} + +/* + * Mask -- blit one scanline of mask + * + * msk_1c1 + * msk_1o1 + * msk_1i1c1 + * msk_1i1o1 + * msk_w3i1o4 + * msk_w3i1i1o4 + */ + +static void msk_1c1(byte *src, byte *dst, int w) +{ + memcpy(dst, src, w); +} + +static void msk_1o1(byte *src, byte *dst, int w) +{ + while (w--) + { + dst[0] = src[0] + fz_mul255(dst[0], 255 - src[0]); + src++; + dst++; + } +} + +static void msk_w3i1o4(byte *rgb, byte *src, byte *dst, int n) +{ + byte sa, ssa; + while (n--) + { + sa = src[0]; + ssa = 255 - sa; + dst[0] = sa + fz_mul255(dst[0], ssa); + dst[1] = rgb[0] + fz_mul255((short)dst[1] - rgb[0], ssa); + dst[2] = rgb[1] + fz_mul255((short)dst[2] - rgb[1], ssa); + dst[3] = rgb[2] + fz_mul255((short)dst[3] - rgb[2], ssa); + src ++; + dst += 4; + } +} + +/* + * Image -- draw transformed image + * + */ + +#define lerp(a,b,t) (a + (((b - a) * t) >> 16)) + +static inline byte getcomp(byte *s, int w, int h, int u, int v, int n, int k) +{ + if (u < 0 || u >= w) return 0; + if (v < 0 || v >= h) return 0; + return s[(w * v + u) * n + k]; +} + +static inline int samplecomp(byte *s, int w, int h, int u, int v, int n, int k) +{ + int ui = u >> 16; + int vi = v >> 16; + int ud = u & 0xFFFF; + int vd = v & 0xFFFF; + int a = getcomp(s, w, h, ui, vi, n, k); + int b = getcomp(s, w, h, ui+1, vi, n, k); + int c = getcomp(s, w, h, ui, vi+1, n, k); + int d = getcomp(s, w, h, ui+1, vi+1, n, k); + int ab = lerp(a, b, ud); + int cd = lerp(c, d, ud); + return lerp(ab, cd, vd); +} + +static inline byte getmask(byte *s, int w, int h, int u, int v) +{ + if (u < 0 || u >= w) return 0; + if (v < 0 || v >= h) return 0; + return s[w * v + u]; +} + +static inline int samplemask(byte *s, int w, int h, int u, int v) +{ + 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); +} + +static inline void lerpargb(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 byte *getargb(byte *s, int w, int h, int u, int v) +{ + static byte zero[4] = { 0, 0, 0, 0 }; + if (u < 0 || u >= w) return zero; + if (v < 0 || v >= h) return zero; + return s + ((w * v + u) << 2); +} + +static inline void sampleargb(byte *s, int w, int h, int u, int v, byte *abcd) +{ + byte ab[4]; + byte cd[4]; + int ui = u >> 16; + int vi = v >> 16; + int ud = u & 0xFFFF; + int vd = v & 0xFFFF; + byte *a = getargb(s, w, h, ui, vi); + byte *b = getargb(s, w, h, ui+1, vi); + byte *c = getargb(s, w, h, ui, vi+1); + byte *d = getargb(s, w, h, ui+1, vi+1); + lerpargb(ab, a, b, ud); + lerpargb(cd, c, d, ud); + lerpargb(abcd, ab, cd, vd); +} + +/* + * img_NcN + * img_1c1 + * img_4c4 + * img_1o1 + * img_4o4 + * img_1i1c1 + * img_1i1o1 + * img_4i1c4 + * img_4i1o4 + * img_w3i1o4 + * img_w3i1i1o4 + */ + +static void img_NcN(FZ_PSRC, int srcn, FZ_PDST, FZ_PCTM) +{ + int k; + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + for (k = 0; k < srcn; k++) + { + dstp[k] = samplecomp(src, srcw, srch, u, v, srcn, k); + dstp += srcn; + u += fa; + v += fb; + } + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_1c1(FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + dstp[0] = samplemask(src, srcw, srch, u, v); + dstp ++; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_4c4(FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + sampleargb(src, srcw, srch, u, v, dstp); + dstp += 4; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_1o1(FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + byte srca; + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + srca = samplemask(src, srcw, srch, u, v); + dstp[0] = srca + fz_mul255(dstp[0], 255 - srca); + dstp ++; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_4o4(FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + byte argb[4]; + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + sampleargb(src, srcw, srch, u, v, argb); + byte ssa = 255 - argb[0]; + dstp[0] = argb[0] + fz_mul255(dstp[0], ssa); + dstp[1] = argb[1] + fz_mul255((short)dstp[1] - argb[1], ssa); + dstp[2] = argb[2] + fz_mul255((short)dstp[2] - argb[2], ssa); + dstp[3] = argb[3] + fz_mul255((short)dstp[3] - argb[3], ssa); + dstp += 4; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +static void img_w3i1o4(byte *rgb, FZ_PSRC, FZ_PDST, FZ_PCTM) +{ + byte sa, ssa; + while (h--) + { + byte *dstp = dst0; + int u = u0; + int v = v0; + int w = w0; + while (w--) + { + sa = samplemask(src, srcw, srch, u, v); + ssa = 255 - sa; + dstp[0] = sa + fz_mul255(dstp[0], ssa); + dstp[1] = rgb[0] + fz_mul255((short)dstp[1] - rgb[0], ssa); + dstp[2] = rgb[1] + fz_mul255((short)dstp[2] - rgb[1], ssa); + dstp[3] = rgb[2] + fz_mul255((short)dstp[3] - rgb[2], ssa); + dstp += 4; + u += fa; + v += fb; + } + dst0 += dstw; + u0 += fc; + v0 += fd; + } +} + +/* + * Fill in the big fat vtable + */ + +static fz_rastfuncs deftab = +{ + duff_NoN, + duff_NiMcN, + duff_NiMoN, + duff_1o1, + duff_4o4, + duff_1i1c1, + duff_4i1c4, + duff_1i1o1, + duff_4i1o4, + + msk_1c1, + msk_1o1, + msk_w3i1o4, + + nil, + nil, + nil, + + img_NcN, + img_1c1, + img_4c4, + img_1o1, + img_4o4, + img_w3i1o4 +}; + +void +fz_defaultrastfuncs(fz_rastfuncs *tab) +{ + *tab = deftab; +} + diff --git a/render/render.c b/render/render.c index 6aee9c8a..b92c8fe0 100644 --- a/render/render.c +++ b/render/render.c @@ -1,8 +1,9 @@ #include <fitz.h> +#define DEBUG(args...) printf(args) + #define FNONE 0 #define FOVER 1 -#define FMASK 2 #define FRGB 4 static fz_error *rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm); @@ -38,7 +39,6 @@ fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int maskonly, int gcmem) fz_defaultrastfuncs(&gc->rast); gc->dest = nil; - gc->mask = nil; gc->over = nil; gc->rgb[0] = 0; gc->rgb[1] = 0; @@ -61,7 +61,6 @@ void fz_droprenderer(fz_renderer *gc) { if (gc->dest) fz_droppixmap(gc->dest); - if (gc->mask) fz_droppixmap(gc->mask); if (gc->over) fz_droppixmap(gc->over); if (gc->model) fz_dropcolorspace(gc->model); @@ -79,14 +78,14 @@ static fz_error * rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm) { fz_error *error; -//printf("transform [%g %g %g %g %g %g]\n", -//transform->m.a, transform->m.b, -//transform->m.c, transform->m.d, -//transform->m.e, transform->m.f); -//puts("{"); +DEBUG("transform [%g %g %g %g %g %g]\n", +transform->m.a, transform->m.b, +transform->m.c, transform->m.d, +transform->m.e, transform->m.f); +DEBUG("{\n"); ctm = fz_concat(transform->m, ctm); error = rendernode(gc, transform->super.first, ctm); -//puts("}"); +DEBUG("}\n"); return error; } @@ -112,14 +111,21 @@ rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm) gc->rgb[1] = rgb[1] * 255; gc->rgb[2] = rgb[2] * 255; -printf("color %s [%d %d %d]\n", color->cs->name, gc->rgb[0], gc->rgb[1], gc->rgb[2]); - - error = fz_newpixmapwithrect(&gc->dest, gc->clip, 4); - if (error) - return error; +DEBUG("color %s [%d %d %d];\n", color->cs->name, gc->rgb[0], gc->rgb[1], gc->rgb[2]); - p = gc->dest->samples; - n = gc->dest->w * gc->dest->h; + if (gc->flag == FOVER) + { + p = gc->over->samples; + n = gc->over->w * gc->over->h; + } + else + { + error = fz_newpixmapwithrect(&gc->dest, gc->clip, 4); + if (error) + return error; + p = gc->dest->samples; + n = gc->dest->w * gc->dest->h; + } while (n--) { @@ -144,7 +150,6 @@ struct spandata fz_rastfuncs *rast; int x, n; fz_pixmap *dst; - fz_pixmap *msk; unsigned char *rgb; int flag; }; @@ -154,28 +159,24 @@ static void spanfunc(int y, int x, int n, unsigned char *path, void *userdata) struct spandata *user = userdata; fz_rastfuncs *rast = user->rast; fz_pixmap *dst = user->dst; - fz_pixmap *msk = user->msk; - unsigned char *d; - unsigned char *m = nil; + unsigned char *dstp; path += user->x; + x += user->x; - d = dst->samples + ( (y - dst->y) * dst->w + (x - dst->x) ) * dst->n; - if (msk) - m = msk->samples + ( (y - msk->y) * msk->w + (x - msk->x) ) * msk->n; + dstp = dst->samples + ( (y - dst->y) * dst->w + (x - dst->x) ) * dst->n; switch (user->flag) { case FNONE: - rast->mask_g(user->n, path, d); break; + assert(dst->n == 1); + rast->msk_1c1(path, dstp, user->n); break; case FOVER: - rast->mask_o1(user->n, path, d); break; - case FOVER | FMASK: - rast->mask_i1o1(user->n, path, m, d); break; + assert(dst->n == 1); + rast->msk_1o1(path, dstp, user->n); break; case FOVER | FRGB: - rast->mask_o4w3(user->n, path, d, user->rgb); break; - case FOVER | FMASK | FRGB: - rast->mask_i1o4w3(user->n, path, m, d, user->rgb); break; + assert(dst->n == 4); + rast->msk_w3i1o4(user->rgb, path, dstp, user->n); break; default: assert(!"impossible flag in path span function"); } @@ -213,33 +214,28 @@ renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm) gbox = fz_boundgel(gc->gel); clip = fz_intersectirects(gc->clip, gbox); - if (clip.max.x <= clip.min.x) - return nil; - if (clip.max.y <= clip.min.y) + if (fz_isemptyrect(clip)) return nil; -//printf("path clip[%d %d %d %d]\n", clip.min.x, clip.min.y, clip.max.x, clip.max.y); +DEBUG("path %s;\n", path->paint == FZ_STROKE ? "stroke" : "fill"); user.rast = &gc->rast; user.x = clip.min.x - gbox.min.x; user.n = clip.max.x - clip.min.x; user.flag = gc->flag; + user.rgb = gc->rgb; - if (gc->flag == FNONE) + if (gc->flag & FOVER) + { + user.dst = gc->over; + } + else { error = fz_newpixmapwithrect(&gc->dest, clip, 1); if (error) return error; fz_clearpixmap(gc->dest); user.dst = gc->dest; - user.msk = nil; - user.rgb = gc->rgb; - } - else - { - user.dst = gc->over; - user.msk = gc->mask; - user.rgb = gc->rgb; } error = fz_scanconvert(gc->gel, gc->ael, path->paint == FZ_EOFILL, @@ -259,6 +255,8 @@ static void drawglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig, unsigned char *dp, *sp; int w, h; + int dx0 = dst->x; + int dy0 = dst->y; int dx1 = dst->x + dst->w; int dy1 = dst->y + dst->h; @@ -272,14 +270,12 @@ static void drawglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig, int sx1 = src->w; int sy1 = src->h; - if (x1 < dst->x || x0 >= dx1) return; - if (y1 < dst->y || y0 >= dy1) return; - - if (x0 < dst->x) { sx0 += dst->x - x0; x0 = dst->x; } - if (y0 < dst->y) { sy0 += dst->y - y0; y0 = dst->y; } - - if (x1 >= dx1) { sx1 -= dx1 - x1; x1 = dx1; } - if (y1 >= dy1) { sy1 -= dy1 - y1; y1 = dy1; } + if (x1 < dx0 || x0 >= dx1) return; + if (y1 < dy0 || y0 >= dy1) return; + if (x0 < dx0) { sx0 += dx0 - x0; x0 = dx0; } + if (y0 < dy0) { sy0 += dy0 - y0; y0 = dy0; } + if (x1 >= dx1) { sx1 += dx1 - x1; x1 = dx1; } + if (y1 >= dy1) { sy1 += dy1 - y1; y1 = dy1; } sp = src->samples + (sy0 * src->w + sx0); dp = dst->samples + ((y0 - dst->y) * dst->w + (x0 - dst->x)) * dst->n; @@ -290,29 +286,32 @@ static void drawglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig, switch (gc->flag) { case FNONE: + assert(dst->n == 1); while (h--) { - gc->rast.mask_g(w, sp, dp); + gc->rast.msk_1c1(sp, dp, w); sp += src->w; - dp += dst->w * dst->n; + dp += dst->w; } break; case FOVER: + assert(dst->n == 1); while (h--) { - gc->rast.mask_o1(w, sp, dp); + gc->rast.msk_1o1(sp, dp, w); sp += src->w; - dp += dst->w * dst->n; + dp += dst->w; } break; case FOVER | FRGB: + assert(dst->n == 4); while (h--) { - gc->rast.mask_o4w3(w, sp, dp, gc->rgb); + gc->rast.msk_w3i1o4(gc->rgb, sp, dp, w); sp += src->w; - dp += dst->w * dst->n; + dp += dst->w * 4; } break; @@ -334,14 +333,11 @@ rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm) tbox = fz_roundrect(fz_boundnode((fz_node*)text, ctm)); clip = fz_intersectirects(gc->clip, tbox); -//printf("text %s n=%d [%g %g %g %g] clip[%d %d %d %d]\n", -//text->font->name, text->len, -//text->trm.a, text->trm.b, text->trm.c, text->trm.d, -//clip.min.x, clip.min.y, clip.max.x, clip.max.y); +DEBUG("text %s n=%d [%g %g %g %g];\n", +text->font->name, text->len, +text->trm.a, text->trm.b, text->trm.c, text->trm.d); - if (clip.max.x <= clip.min.x) - return nil; - if (clip.max.y <= clip.min.y) + if (fz_isemptyrect(clip)) return nil; clip.min.x ++; @@ -349,7 +345,7 @@ rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm) clip.max.x ++; clip.max.y ++; - if (gc->flag == FNONE) + if (!(gc->flag & FOVER)) { error = fz_newpixmapwithrect(&gc->dest, clip, 1); if (error) @@ -374,7 +370,7 @@ rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm) if (error) return error; - if (gc->flag == FNONE) + if (!(gc->flag & FOVER)) drawglyph(gc, gc->dest, &glyph, x, y); else drawglyph(gc, gc->over, &glyph, x, y); @@ -423,19 +419,17 @@ renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm) int x0, y0; int w, h; -printf("renderimage %dx%d %d+%d %s\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)"); +DEBUG("image %dx%d %d+%d %s\n{\n", image->w, image->h, image->n, image->a, image->cs?image->cs->name:"(nil)"); bbox = fz_roundrect(fz_boundnode((fz_node*)node, ctm)); clip = fz_intersectirects(gc->clip, bbox); - if (clip.max.x <= clip.min.x) - return nil; - if (clip.max.y <= clip.min.y) + if (fz_isemptyrect(clip)) return nil; calcimagescale(ctm, image->w, image->h, &dx, &dy); -printf(" load image\n"); +DEBUG(" load image\n"); error = fz_newpixmap(&tile, 0, 0, image->w, image->h, image->n + 1); if (error) return error; @@ -446,7 +440,7 @@ printf(" load image\n"); if (dx != 1 || dy != 1) { -printf(" scale image 1/%d 1/%d\n", dx, dy); +DEBUG(" scale image 1/%d 1/%d\n", dx, dy); fz_pixmap *temp; error = fz_scalepixmap(&temp, tile, dx, dy); if (error) @@ -458,7 +452,7 @@ printf(" scale image 1/%d 1/%d\n", dx, dy); if (image->cs && image->cs != gc->model) { fz_pixmap *temp; -printf(" convert from %s to %s\n", image->cs->name, gc->model->name); +DEBUG(" convert from %s to %s\n", image->cs->name, gc->model->name); error = fz_newpixmap(&temp, tile->x, tile->y, tile->w, tile->h, gc->model->n + 1); if (error) goto cleanup; @@ -486,11 +480,15 @@ printf(" convert from %s to %s\n", image->cs->name, gc->model->name); fc = invmat.c * 65536; fd = invmat.d * 65536; +#define PSRC tile->samples, tile->w, tile->h +#define PDST(p) p->samples + ((y0-p->y) * p->w + (x0-p->x)) * p->n, p->w * p->n +#define PCTM u0, v0, fa, fb, fc, fd, w, h + switch (gc->flag) { case FNONE: { -printf(" fnone %d x %d\n", w, h); +DEBUG(" fnone %d x %d\n", w, h); if (image->cs) error = fz_newpixmapwithrect(&gc->dest, clip, gc->model->n + 1); else @@ -499,50 +497,33 @@ printf(" fnone %d x %d\n", w, h); goto cleanup; if (image->cs) - gc->rast.img4_g( - tile->samples, tile->w, tile->h, w, h, - gc->dest->samples, gc->dest->w * gc->dest->n, - u0, v0, fa, fb, fc, fd); + gc->rast.img_4c4(PSRC, PDST(gc->dest), PCTM); else - gc->rast.img1_g( - tile->samples, tile->w, tile->h, w, h, - gc->dest->samples, gc->dest->w * gc->dest->n, - u0, v0, fa, fb, fc, fd); + gc->rast.img_1c1(PSRC, PDST(gc->dest), PCTM); } break; case FOVER: { -printf(" fover %d x %d\n", w, h); +DEBUG(" fover %d x %d\n", w, h); if (image->cs) - gc->rast.img4_o4( - tile->samples, tile->w, tile->h, w, h, - gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)) * 4, - gc->over->w * gc->over->n, - u0, v0, fa, fb, fc, fd); + gc->rast.img_4o4(PSRC, PDST(gc->over), PCTM); else - gc->rast.img1_o1( - tile->samples, tile->w, tile->h, w, h, - gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)), - gc->over->w * gc->over->n, - u0, v0, fa, fb, fc, fd); + gc->rast.img_1o1(PSRC, PDST(gc->over), PCTM); } break; case FOVER | FRGB: - { -printf(" fover+rgb %d x %d\n", w, h); - gc->rast.img1_o4w3( - tile->samples, tile->w, tile->h, w, h, - gc->over->samples + ((y0 - gc->over->y) * gc->over->w + (x0 - gc->over->x)) * 4, - gc->over->w * gc->over->n, - u0, v0, fa, fb, fc, fd, gc->rgb); - } +DEBUG(" fover+rgb %d x %d\n", w, h); + gc->rast.img_w3i1o4(gc->rgb, PSRC, PDST(gc->over), PCTM); break; + default: assert(!"impossible flag in image span function"); } +DEBUG("}\n"); + fz_droppixmap(tile); return nil; @@ -555,24 +536,119 @@ cleanup: * Over, Mask and Blend */ +static void +blendover(fz_renderer *gc, fz_pixmap *src, fz_pixmap *dst) +{ + unsigned char *sp, *dp; + fz_irect sr, dr; + int x, y, w, h; + + sr.min.x = src->x; + sr.min.y = src->y; + sr.max.x = src->x + src->w; + sr.max.y = src->y + src->h; + + dr.min.x = dst->x; + dr.min.y = dst->y; + dr.max.x = dst->x + dst->w; + dr.max.y = dst->y + dst->h; + + dr = fz_intersectirects(sr, dr); + x = dr.min.x; + y = dr.min.y; + w = dr.max.x - dr.min.x; + h = dr.max.y - dr.min.y; + + 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; + + if (src->n == 1 && dst->n == 1) + gc->rast.duff_1o1(sp, src->w, dp, dst->w, w, h); + else if (src->n == 4 && dst->n == 4) + gc->rast.duff_4o4(sp, src->w * 4, dp, dst->w * 4, w, h); + else if (src->n == dst->n) + gc->rast.duff_NoN(sp, src->w * src->n, src->n, dp, dst->w * dst->n, w, h); + else + assert(!"blendover src and dst mismatch"); +} + +static void +blendmask(fz_renderer *gc, fz_pixmap *src, fz_pixmap *msk, fz_pixmap *dst, int over) +{ + unsigned char *sp, *dp, *mp; + fz_irect sr, dr, mr; + int x, y, w, h; + + sr.min.x = src->x; + sr.min.y = src->y; + sr.max.x = src->x + src->w; + sr.max.y = src->y + src->h; + + dr.min.x = dst->x; + dr.min.y = dst->y; + dr.max.x = dst->x + dst->w; + dr.max.y = dst->y + dst->h; + + mr.min.x = msk->x; + mr.min.y = msk->y; + mr.max.x = msk->x + msk->w; + mr.max.y = msk->y + msk->h; + + dr = fz_intersectirects(sr, dr); + dr = fz_intersectirects(dr, mr); + x = dr.min.x; + y = dr.min.y; + w = dr.max.x - dr.min.x; + h = dr.max.y - dr.min.y; + + 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; + + if (over) + { + if (src->n == 1 && msk->n == 1 && dst->n == 1) + gc->rast.duff_1i1o1(sp, src->w, mp, msk->w, dp, dst->w, w, h); + else if (src->n == 4 && msk->n == 1 && dst->n == 4) + gc->rast.duff_4i1o4(sp, src->w * 4, mp, msk->w, dp, dst->w * 4, w, h); + else if (src->n == dst->n) + gc->rast.duff_NiMoN(sp, src->w * src->n, src->n, mp, msk->w * msk->n, msk->n, dp, dst->w * dst->n, w, h); + else + assert(!"blendmaskover src and msk and dst mismatch"); + } + else + { + if (src->n == 1 && msk->n == 1 && dst->n == 1) + gc->rast.duff_1i1c1(sp, src->w, mp, msk->w, dp, dst->w, w, h); + else if (src->n == 4 && msk->n == 1 && dst->n == 4) + gc->rast.duff_4i1c4(sp, src->w * 4, mp, msk->w, dp, dst->w * 4, w, h); + else if (src->n == dst->n) + gc->rast.duff_NiMcN(sp, src->w * src->n, src->n, mp, msk->w * msk->n, msk->n, dp, dst->w * dst->n, w, h); + else + assert(!"blendmask src and msk and dst mismatch"); + } +} + static fz_error * renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) { fz_error *error; fz_node *child; - int cluster = 0;; - -//printf("over\n{\n"); + int cluster = 0; if (!gc->over) { -//printf(" alloc dest!\n"); - error = fz_newpixmapwithrect(&gc->over, gc->clip, gc->maskonly ? 1 : 4); +DEBUG("over cluster %d\n{\n", gc->maskonly ? 1 : 4); + cluster = 1; + if (gc->maskonly) + error = fz_newpixmapwithrect(&gc->over, gc->clip, 1); + else + error = fz_newpixmapwithrect(&gc->over, gc->clip, 4); if (error) return error; fz_clearpixmap(gc->over); - cluster = 1; } +else DEBUG("over\n{\n"); for (child = over->super.first; child; child = child->next) { @@ -581,7 +657,7 @@ renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) return error; if (gc->dest) { - fz_blendover(gc->dest, gc->over); + blendover(gc, gc->dest, gc->over); fz_droppixmap(gc->dest); gc->dest = nil; } @@ -593,7 +669,7 @@ renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) gc->over = nil; } -//printf("}\n"); +DEBUG("}\n"); return nil; } @@ -602,12 +678,13 @@ static fz_error * rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm) { fz_error *error; + int oldmaskonly; fz_pixmap *oldover; - fz_pixmap *oldmask; fz_irect oldclip; - fz_irect newclip; - fz_pixmap *shapepix; - fz_pixmap *colorpix; + fz_irect bbox; + fz_irect clip; + fz_pixmap *shapepix = nil; + fz_pixmap *colorpix = nil; fz_node *shape; fz_node *color; float rgb[3]; @@ -628,7 +705,7 @@ rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm) gc->rgb[2] = rgb[2] * 255; gc->flag |= FRGB; - /* we know these handle FOVER | FRGB */ + /* we know these can handle the FRGB shortcut */ if (fz_ispathnode(shape)) return renderpath(gc, (fz_pathnode*)shape, ctm); if (fz_istextnode(shape)) @@ -640,50 +717,77 @@ rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm) oldclip = gc->clip; oldover = gc->over; - oldmask = gc->mask; - newclip = fz_roundrect(fz_boundnode(shape, ctm)); - newclip = fz_intersectirects(newclip, gc->clip); + bbox = fz_roundrect(fz_boundnode(shape, ctm)); + clip = fz_intersectirects(bbox, gc->clip); + bbox = fz_roundrect(fz_boundnode(color, ctm)); + clip = fz_intersectirects(bbox, clip); - gc->clip = newclip; - gc->over = nil; - gc->mask = nil; + if (fz_isemptyrect(clip)) + return nil; -printf("mask\n{\n"); +DEBUG("mask [%d %d %d %d]\n{\n", clip.min.x, clip.min.y, clip.max.x, clip.max.y); - error = rendernode(gc, color, ctm); - if (error) - return error; - colorpix = gc->dest; - gc->dest = nil; +{ +fz_irect sbox = fz_roundrect(fz_boundnode(shape, ctm)); +fz_irect cbox = fz_roundrect(fz_boundnode(color, ctm)); +if (cbox.min.x >= sbox.min.x && cbox.max.x <= sbox.max.x) +if (cbox.min.y >= sbox.min.y && cbox.max.y <= sbox.max.y) +DEBUG("potentially useless mask\n"); +} + + gc->clip = clip; + gc->over = nil; + + oldmaskonly = gc->maskonly; + gc->maskonly = 1; error = rendernode(gc, shape, ctm); if (error) - return error; + goto cleanup; shapepix = gc->dest; gc->dest = nil; - if (colorpix && shapepix) - { - error = fz_newpixmapwithrect(&gc->dest, gc->clip, colorpix->n); - if (error) - return error; + gc->maskonly = oldmaskonly; - fz_clearpixmap(gc->dest); + error = rendernode(gc, color, ctm); + if (error) + goto cleanup; + colorpix = gc->dest; + gc->dest = nil; - fz_blendmask(gc->dest, colorpix, shapepix); + gc->clip = oldclip; + gc->over = oldover; + + if (shapepix && colorpix) + { + if (gc->over) + { + blendmask(gc, colorpix, shapepix, gc->over, 1); + } + else + { + clip.min.x = MAX(colorpix->x, shapepix->x); + clip.min.y = MAX(colorpix->y, shapepix->y); + clip.max.x = MIN(colorpix->x+colorpix->w, shapepix->x+shapepix->w); + clip.max.y = MIN(colorpix->y+colorpix->h, shapepix->y+shapepix->h); + error = fz_newpixmapwithrect(&gc->dest, clip, colorpix->n); + if (error) + goto cleanup; + blendmask(gc, colorpix, shapepix, gc->dest, 0); + } } +DEBUG("}\n"); + if (shapepix) fz_droppixmap(shapepix); if (colorpix) fz_droppixmap(colorpix); - - gc->over = oldover; - gc->mask = oldmask; - gc->clip = oldclip; - -printf("}\n"); - return nil; + +cleanup: + if (shapepix) fz_droppixmap(shapepix); + if (colorpix) fz_droppixmap(colorpix); + return error; } /* @@ -697,8 +801,8 @@ rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm) return nil; gc->flag = FNONE; - if (gc->over) gc->flag |= FOVER; - if (gc->mask) gc->flag |= FMASK; + if (gc->over) + gc->flag |= FOVER; switch (node->kind) { @@ -718,6 +822,8 @@ rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm) return renderimage(gc, (fz_imagenode*)node, ctm); case FZ_NLINK: return rendernode(gc, ((fz_linknode*)node)->tree->root, ctm); + case FZ_NMETA: + return rendernode(gc, node->first, ctm); } return nil; @@ -731,33 +837,40 @@ fz_rendertree(fz_pixmap **outp, fz_error *error; gc->clip = bbox; + gc->over = nil; - if (white) - { - assert(gc->maskonly == 0); - + if (gc->maskonly) + error = fz_newpixmapwithrect(&gc->over, bbox, 1); + else error = fz_newpixmapwithrect(&gc->over, bbox, 4); - if (error) - return error; + if (error) + return error; + if (white) memset(gc->over->samples, 0xff, gc->over->w * gc->over->h * gc->over->n); - } + else + memset(gc->over->samples, 0x00, gc->over->w * gc->over->h * gc->over->n); + +DEBUG("tree %d [%d %d %d %d]\n{\n", +gc->maskonly ? 1 : 4, +bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); error = rendernode(gc, tree->root, ctm); if (error) return error; - if (white) - { - *outp = gc->over; - gc->over = nil; - } - else +DEBUG("}\n"); + + if (gc->dest) { - *outp = gc->dest; + blendover(gc, gc->dest, gc->over); + fz_droppixmap(gc->dest); gc->dest = nil; } + *outp = gc->over; + gc->over = nil; + return nil; } |