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 | |
parent | e092458f4403f1424d8fd1f5ec194880a05c3362 (diff) | |
download | mupdf-b48de7618e25bc2cef9d9db4f9b49e1d546e438a.tar.xz |
rewrite of render loop part 3
-rw-r--r-- | Jamfile | 2 | ||||
-rw-r--r-- | TODO | 8 | ||||
-rw-r--r-- | base/rect.c | 58 | ||||
-rw-r--r-- | include/fitz/geometry.h | 8 | ||||
-rw-r--r-- | include/fitz/pixmap.h | 5 | ||||
-rw-r--r-- | include/fitz/render.h | 56 | ||||
-rw-r--r-- | include/mupdf/rsrc.h | 1 | ||||
-rw-r--r-- | mupdf/type3.c | 18 | ||||
-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 | ||||
-rw-r--r-- | test/ximage.c | 7 | ||||
-rw-r--r-- | tree/debug.c | 14 | ||||
-rw-r--r-- | tree/node1.c | 2 | ||||
-rw-r--r-- | tree/node2.c | 73 | ||||
-rw-r--r-- | tree/path.c | 27 | ||||
-rw-r--r-- | tree/text.c | 2 | ||||
-rw-r--r-- | tree/tree.c | 2 |
19 files changed, 871 insertions, 789 deletions
@@ -87,7 +87,7 @@ Library libfitz : render/fill.c render/stroke.c render/scale.c - render/rastnone.c + render/rastport.c render/render.c ; @@ -16,7 +16,6 @@ shadings rendering - bbox culling (cache bbox in over node?) - - image mask + color case - merge gka optims - optimize inner rendering loops - optimize image load/decode/scale @@ -27,7 +26,12 @@ parser - resource dict generate fake ids - try to clean up colorspace/material handling in interpreter - annotations and destinations (for links and outline) - - BPC 2, 4 + +fz_optimizetree() + - remove rectangular clip nodes whose children fit + - remove white fills at beginning of page + - remove overs with only one child + - concatenate chained transforms clean up - make source ansi c89 / pedantic diff --git a/base/rect.c b/base/rect.c index 6df6749a..2efb11f7 100644 --- a/base/rect.c +++ b/base/rect.c @@ -1,38 +1,43 @@ #include <fitz.h> -static fz_rect none = { { 0, 0}, {0, 0} }; -static fz_irect inone = { { 0, 0}, {0, 0} }; +fz_rect fz_infiniterect = { { 1, 1}, {-1, -1} }; +fz_rect fz_emptyrect = { { 0, 0}, {0, 0} }; -fz_rect -fz_infiniterect(void) +static fz_irect infinite = { { 1, 1}, {-1, -1} }; +static fz_irect empty = { { 0, 0}, {0, 0} }; + +fz_irect +fz_roundrect(fz_rect f) { - fz_rect r; - r.min.x = 1; - r.min.y = 1; - r.max.x = -1; - r.max.y = -1; - return r; + fz_irect i; + i.min.x = fz_floor(f.min.x); + i.min.y = fz_floor(f.min.y); + i.max.x = fz_ceil(f.max.x); + i.max.y = fz_ceil(f.max.y); + return i; } fz_rect fz_intersectrects(fz_rect a, fz_rect b) { fz_rect r; - if (a.max.x < a.min.x) - return (b.max.x < b.min.x) ? none : b; + if (fz_isinfiniterect(a)) return b; + if (fz_isinfiniterect(b)) return a; r.min.x = MAX(a.min.x, b.min.x); r.min.y = MAX(a.min.y, b.min.y); r.max.x = MIN(a.max.x, b.max.x); r.max.y = MIN(a.max.y, b.max.y); - return (r.max.x < r.min.x || r.max.y < r.min.y) ? none : r; + return (r.max.x < r.min.x || r.max.y < r.min.y) ? fz_emptyrect : r; } fz_rect fz_mergerects(fz_rect a, fz_rect b) { fz_rect r; - if (a.max.x < a.min.x) - return (b.max.x < b.min.x) ? none : b; + if (fz_isinfiniterect(a) || fz_isinfiniterect(b)) + return fz_infiniterect; + if (fz_isemptyrect(a)) return b; + if (fz_isemptyrect(b)) return a; r.min.x = MIN(a.min.x, b.min.x); r.min.y = MIN(a.min.y, b.min.y); r.max.x = MAX(a.max.x, b.max.x); @@ -41,35 +46,26 @@ fz_mergerects(fz_rect a, fz_rect b) } fz_irect -fz_roundrect(fz_rect f) -{ - fz_irect i; - i.min.x = fz_floor(f.min.x); - i.min.y = fz_floor(f.min.y); - i.max.x = fz_ceil(f.max.x); - i.max.y = fz_ceil(f.max.y); - return i; -} - -fz_irect fz_intersectirects(fz_irect a, fz_irect b) { fz_irect r; - if (a.max.x < a.min.x) - return (b.max.x < b.min.x) ? inone : b; + if (fz_isinfiniterect(a)) return b; + if (fz_isinfiniterect(b)) return a; r.min.x = MAX(a.min.x, b.min.x); r.min.y = MAX(a.min.y, b.min.y); r.max.x = MIN(a.max.x, b.max.x); r.max.y = MIN(a.max.y, b.max.y); - return (r.max.x < r.min.x || r.max.y < r.min.y) ? inone : r; + return (r.max.x < r.min.x || r.max.y < r.min.y) ? empty : r; } fz_irect fz_mergeirects(fz_irect a, fz_irect b) { fz_irect r; - if (a.max.x < a.min.x) - return (b.max.x < b.min.x) ? inone : b; + if (fz_isinfiniterect(a) || fz_isinfiniterect(b)) + return infinite; + if (fz_isemptyrect(a)) return b; + if (fz_isemptyrect(b)) return a; r.min.x = MIN(a.min.x, b.min.x); r.min.y = MIN(a.min.y, b.min.y); r.max.x = MAX(a.max.x, b.max.x); diff --git a/include/fitz/geometry.h b/include/fitz/geometry.h index 96977cc6..7d2adc98 100644 --- a/include/fitz/geometry.h +++ b/include/fitz/geometry.h @@ -4,6 +4,12 @@ typedef struct fz_rect_s fz_rect; typedef struct fz_ipoint_s fz_ipoint; typedef struct fz_irect_s fz_irect; +extern fz_rect fz_emptyrect; +extern fz_rect fz_infiniterect; + +#define fz_isemptyrect(r) ((r).min.x == (r).max.x) +#define fz_isinfiniterect(r) ((r).min.x > (r).max.x) + /* / a b 0 \ | c d 0 | @@ -38,8 +44,6 @@ struct fz_irect_s void fz_invert3x3(float *dst, float *m); -fz_rect fz_infiniterect(void); - fz_matrix fz_concat(fz_matrix one, fz_matrix two); fz_matrix fz_identity(void); fz_matrix fz_scale(float sx, float sy); diff --git a/include/fitz/pixmap.h b/include/fitz/pixmap.h index 6d0391fa..c369df84 100644 --- a/include/fitz/pixmap.h +++ b/include/fitz/pixmap.h @@ -15,12 +15,11 @@ struct fz_pixmap_s fz_error *fz_newpixmapwithrect(fz_pixmap **mapp, fz_irect bbox, int n); fz_error *fz_newpixmap(fz_pixmap **mapp, int x, int y, int w, int h, int n); +fz_error *fz_newpixmapcopy(fz_pixmap **pixp, fz_pixmap *old); + void fz_debugpixmap(fz_pixmap *map); void fz_clearpixmap(fz_pixmap *map); void fz_droppixmap(fz_pixmap *map); fz_error *fz_scalepixmap(fz_pixmap **dstp, fz_pixmap *src, int xdenom, int ydenom); -void fz_blendover(fz_pixmap *src, fz_pixmap *dst); -void fz_blendmask(fz_pixmap *dst, fz_pixmap *color, fz_pixmap *shape); - diff --git a/include/fitz/render.h b/include/fitz/render.h index 807b6227..e2435382 100644 --- a/include/fitz/render.h +++ b/include/fitz/render.h @@ -2,39 +2,42 @@ typedef struct fz_renderer_s fz_renderer; typedef struct fz_rastfuncs_s fz_rastfuncs; #define FZ_BYTE unsigned char -#define FZ_PID \ - FZ_BYTE *src, int w, int h, int nx, int ny, \ - FZ_BYTE *dst0, int dstw, \ - int u0, int v0, int fa, int fb, int fc, int fd -#define FZ_PIM \ - FZ_BYTE *src, int w, int h, int nx, int ny, \ - FZ_BYTE *dst0, int dstw, \ - FZ_BYTE *msk0, int mskw, \ - int u0, int v0, int fa, int fb, int fc, int fd + +#define FZ_PSRC \ + unsigned char *src, int srcw, int srch +#define FZ_PDST \ + unsigned char *dst0, int dstw +#define FZ_PCTM \ + int u0, int v0, int fa, int fb, int fc, int fd, int w0, int h struct fz_rastfuncs_s { - void (*mask_g)(int, FZ_BYTE*, FZ_BYTE*); - void (*mask_i1)(int, FZ_BYTE*, FZ_BYTE*); - void (*mask_o1)(int, FZ_BYTE*, FZ_BYTE*); - void (*mask_i1o1)(int, FZ_BYTE*, FZ_BYTE*, FZ_BYTE*); - void (*mask_o4w3)(int, FZ_BYTE*, FZ_BYTE*, FZ_BYTE*); - void (*mask_i1o4w3)(int, FZ_BYTE*, FZ_BYTE*, FZ_BYTE*, FZ_BYTE*); + void (*duff_NoN)(FZ_BYTE*,int,int,FZ_BYTE*,int,int,int); + void (*duff_NiMcN)(FZ_BYTE*,int,int,FZ_BYTE*,int,int,FZ_BYTE*,int,int,int); + void (*duff_NiMoN)(FZ_BYTE*,int,int,FZ_BYTE*,int,int,FZ_BYTE*,int,int,int); + void (*duff_1o1)(FZ_BYTE*,int,FZ_BYTE*,int,int,int); + void (*duff_4o4)(FZ_BYTE*,int,FZ_BYTE*,int,int,int); + void (*duff_1i1c1)(FZ_BYTE*,int,FZ_BYTE*,int,FZ_BYTE*,int,int,int); + void (*duff_4i1c4)(FZ_BYTE*,int,FZ_BYTE*,int,FZ_BYTE*,int,int,int); + void (*duff_1i1o1)(FZ_BYTE*,int,FZ_BYTE*,int,FZ_BYTE*,int,int,int); + void (*duff_4i1o4)(FZ_BYTE*,int,FZ_BYTE*,int,FZ_BYTE*,int,int,int); + + void (*msk_1c1)(FZ_BYTE*,FZ_BYTE*,int); + void (*msk_1o1)(FZ_BYTE*,FZ_BYTE*,int); + void (*msk_w3i1o4)(FZ_BYTE*,FZ_BYTE*,FZ_BYTE*,int); - void (*img1_g)(FZ_PID); - void (*img1_i1)(FZ_PID); - void (*img1_o1)(FZ_PID); - void (*img1_i1o1)(FZ_PIM); - void (*img1_o4w3)(FZ_PID, FZ_BYTE*); - void (*img1_i1o4w3)(FZ_PIM, FZ_BYTE*); + void (*glf_1c1)(FZ_BYTE*,int,FZ_BYTE*,int,int,int); + void (*glf_1o1)(FZ_BYTE*,int,FZ_BYTE*,int,int,int); + void (*glf_w3i1o4)(FZ_BYTE*,FZ_BYTE*,int,FZ_BYTE*,int,int,int); - void (*img4_g)(FZ_PID); - void (*img4_o4)(FZ_PID); - void (*img4_i1o4)(FZ_PIM); + void (*img_NcN)(FZ_PSRC, int sn, FZ_PDST, FZ_PCTM); + void (*img_1c1)(FZ_PSRC, FZ_PDST, FZ_PCTM); + void (*img_4c4)(FZ_PSRC, FZ_PDST, FZ_PCTM); + void (*img_1o1)(FZ_PSRC, FZ_PDST, FZ_PCTM); + void (*img_4o4)(FZ_PSRC, FZ_PDST, FZ_PCTM); + void (*img_w3i1o4)(FZ_BYTE*,FZ_PSRC,FZ_PDST,FZ_PCTM); }; -#undef FZ_PIM -#undef FZ_PID #undef FZ_BYTE struct fz_renderer_s @@ -50,7 +53,6 @@ struct fz_renderer_s fz_irect clip; fz_pixmap *dest; fz_pixmap *over; - fz_pixmap *mask; unsigned char rgb[3]; int flag; }; diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index 9139a8e5..91deb38d 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -155,7 +155,6 @@ struct pdf_font_s fz_buffer *fontdata; /* Type3 data */ - fz_rect bbox; fz_matrix matrix; fz_tree *charprocs[256]; }; diff --git a/mupdf/type3.c b/mupdf/type3.c index 64ef9a2c..082f4ce8 100644 --- a/mupdf/type3.c +++ b/mupdf/type3.c @@ -99,6 +99,7 @@ pdf_loadtype3font(pdf_font **fontp, pdf_xref *xref, fz_obj *dict) fz_obj *obj; int first, last; int i, k, n; + fz_rect bbox; obj = fz_dictgets(dict, "Name"); if (obj) @@ -128,13 +129,18 @@ printf(" matrix [%g %g %g %g %g %g]\n", font->matrix.c, font->matrix.d, font->matrix.e, font->matrix.f); - /* TODO: scale bbox by fontmatrix * 1000 */ obj = fz_dictgets(dict, "FontBBox"); - fz_setfontbbox((fz_font*)font, - fz_toreal(fz_arrayget(obj, 0)), - fz_toreal(fz_arrayget(obj, 1)), - fz_toreal(fz_arrayget(obj, 2)), - fz_toreal(fz_arrayget(obj, 3))); + bbox.min.x = fz_toreal(fz_arrayget(obj, 0)); + bbox.min.y = fz_toreal(fz_arrayget(obj, 1)); + bbox.max.x = fz_toreal(fz_arrayget(obj, 2)); + bbox.max.y = fz_toreal(fz_arrayget(obj, 3)); + bbox = fz_transformaabb(font->matrix, bbox); + bbox.min.x = fz_floor(bbox.min.x * 1000); + bbox.min.y = fz_floor(bbox.min.x * 1000); + bbox.max.x = fz_ceil(bbox.max.x * 1000); + bbox.max.y = fz_ceil(bbox.max.x * 1000); + fz_setfontbbox((fz_font*)font, bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); +printf(" bbox [%g %g %g %g]\n", bbox.min.x,bbox.min.y,bbox.max.x,bbox.max.y); /* * Encoding 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; } diff --git a/test/ximage.c b/test/ximage.c index 9c368360..79c6670c 100644 --- a/test/ximage.c +++ b/test/ximage.c @@ -460,10 +460,17 @@ ximage_convert_bgra8888(PARAMS) for (x = 0; x < w; x++) { val = s[x]; d[x] = + (val >> 24) | + ((val >> 8) & 0xff) | + ((val << 8) & 0xff0000) | + (val << 24); +/* + d[x] = (((val >> 24) & 0xff) << 0) | (((val >> 16) & 0xff) << 8) | (((val >> 8) & 0xff) << 16) | (((val >> 0) & 0xff) << 24); +*/ } d += dststride>>2; s += srcstride>>2; diff --git a/tree/debug.c b/tree/debug.c index cbfffc20..0f4edada 100644 --- a/tree/debug.c +++ b/tree/debug.c @@ -6,6 +6,16 @@ static void indent(int level) putchar(' '); } +static void showbbox(void *node0) +{ + fz_node *node = node0; + fz_irect bbox; + bbox = fz_roundrect(fz_boundnode(node, fz_identity())); + printf("[%d %d %d %d]", + bbox.min.x, bbox.min.y, + bbox.max.x, bbox.max.y); +} + static void lispnode(fz_node *node, int level); static void lispmeta(fz_metanode *node, int level) @@ -26,7 +36,7 @@ static void lispover(fz_overnode *node, int level) { fz_node *child; indent(level); - printf("(over\n"); + printf("(over "); showbbox(node); printf("\n"); for (child = node->super.first; child; child = child->next) lispnode(child, level + 1); indent(level); @@ -37,7 +47,7 @@ static void lispmask(fz_masknode *node, int level) { fz_node *child; indent(level); - printf("(mask\n"); + printf("(mask "); showbbox(node); printf("\n"); for (child = node->super.first; child; child = child->next) lispnode(child, level + 1); indent(level); diff --git a/tree/node1.c b/tree/node1.c index 19244721..2587077c 100644 --- a/tree/node1.c +++ b/tree/node1.c @@ -90,7 +90,7 @@ fz_boundnode(fz_node *node, fz_matrix ctm) case FZ_NMETA: return fz_boundmetanode((fz_metanode *) node, ctm); } - return fz_infiniterect(); + return fz_emptyrect; } int diff --git a/tree/node2.c b/tree/node2.c index 1374a30f..5c3e3931 100644 --- a/tree/node2.c +++ b/tree/node2.c @@ -23,20 +23,20 @@ fz_boundovernode(fz_overnode *node, fz_matrix ctm) { fz_node *child; fz_rect bbox; - fz_rect r; + fz_rect temp; - bbox = fz_infiniterect(); + child = node->super.first; + if (!child) + return fz_emptyrect; - for (child = node->super.first; child; child = child->next) + bbox = fz_boundnode(child, ctm); + + child = child->next; + while (child) { - r = fz_boundnode(child, ctm); - if (r.max.x >= r.min.x) - { - if (bbox.max.x >= bbox.min.x) - bbox = fz_mergerects(r, bbox); - else - bbox = r; - } + temp = fz_boundnode(child, ctm); + bbox = fz_mergerects(temp, bbox); + child = child->next; } return bbox; @@ -63,25 +63,16 @@ fz_newmasknode(fz_node **nodep) fz_rect fz_boundmasknode(fz_masknode *node, fz_matrix ctm) { - fz_node *child; - fz_rect bbox; - fz_rect r; - - bbox = fz_infiniterect(); + fz_node *shape; + fz_node *color; + fz_rect one, two; - for (child = node->super.first; child; child = child->next) - { - r = fz_boundnode(child, ctm); - if (r.max.x >= r.min.x) - { - if (bbox.max.x >= bbox.min.x) - bbox = fz_intersectrects(r, bbox); - else - bbox = r; - } - } + shape = node->super.first; + color = shape->next; - return bbox; + one = fz_boundnode(shape, ctm); + two = fz_boundnode(color, ctm); + return fz_intersectrects(one, two); } /* @@ -110,25 +101,7 @@ fz_newblendnode(fz_node **nodep, fz_colorspace *cs, fz_blendkind b, int k, int i fz_rect fz_boundblendnode(fz_blendnode *node, fz_matrix ctm) { - fz_node *child; - fz_rect bbox; - fz_rect r; - - bbox = fz_infiniterect(); - - for (child = node->super.first; child; child = child->next) - { - r = fz_boundnode(child, ctm); - if (r.max.x >= r.min.x) - { - if (bbox.max.x >= bbox.min.x) - bbox = fz_mergerects(r, bbox); - else - bbox = r; - } - } - - return bbox; + return fz_emptyrect; } /* @@ -155,7 +128,7 @@ fz_rect fz_boundtransformnode(fz_transformnode *node, fz_matrix ctm) { if (!node->super.first) - return fz_infiniterect(); + return fz_emptyrect; return fz_boundnode(node->super.first, fz_concat(node->m, ctm)); } @@ -198,7 +171,7 @@ fz_rect fz_boundmetanode(fz_metanode *node, fz_matrix ctm) { if (!node->super.first) - return fz_infiniterect(); + return fz_emptyrect; return fz_boundnode(node->super.first, ctm); } @@ -261,7 +234,7 @@ fz_newcolornode(fz_node **nodep, fz_colorspace *cs, int n, float *v) fz_rect fz_boundcolornode(fz_colornode *node, fz_matrix ctm) { - return fz_infiniterect(); + return fz_infiniterect; } /* diff --git a/tree/path.c b/tree/path.c index 74e29a59..ac070025 100644 --- a/tree/path.c +++ b/tree/path.c @@ -168,18 +168,10 @@ fz_endpath(fz_pathnode *path, fz_pathkind paint, fz_stroke *stroke, fz_dash *das static inline fz_rect boundexpand(fz_rect r, fz_point p) { - if (r.min.x > r.max.x) - { - r.min.x = r.max.x = p.x; - r.min.y = r.max.y = p.y; - } - else - { - if (p.x < r.min.x) r.min.x = p.x; - if (p.y < r.min.y) r.min.y = p.y; - if (p.x > r.max.x) r.max.x = p.x; - if (p.y > r.max.y) r.max.y = p.y; - } + if (p.x < r.min.x) r.min.x = p.x; + if (p.y < r.min.y) r.min.y = p.y; + if (p.x > r.max.x) r.max.x = p.x; + if (p.y > r.max.y) r.max.y = p.y; return r; } @@ -187,9 +179,18 @@ fz_rect fz_boundpathnode(fz_pathnode *path, fz_matrix ctm) { fz_point p; - fz_rect r = fz_infiniterect(); + fz_rect r = fz_emptyrect; int i = 0; + if (path->len) + { + p.x = path->els[1].v; + p.y = path->els[2].v; + p = fz_transformpoint(ctm, p); + r.min.x = r.max.x = p.x; + r.min.y = r.max.y = p.y; + } + while (i < path->len) { switch (path->els[i++].k) diff --git a/tree/text.c b/tree/text.c index a7581cf9..ef77f530 100644 --- a/tree/text.c +++ b/tree/text.c @@ -35,7 +35,7 @@ fz_boundtextnode(fz_textnode *text, fz_matrix ctm) int i; if (text->len == 0) - return fz_infiniterect(); + return fz_emptyrect; /* find bbox of glyph origins in ctm space */ diff --git a/tree/tree.c b/tree/tree.c index 0c7cefb1..f07e564f 100644 --- a/tree/tree.c +++ b/tree/tree.c @@ -39,7 +39,7 @@ fz_boundtree(fz_tree *tree, fz_matrix ctm) { if (tree->root) return fz_boundnode(tree->root, ctm); - return fz_infiniterect(); + return fz_emptyrect; } void |