diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-11-19 08:49:17 +0100 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-11-19 08:49:17 +0100 |
commit | 4c164469d43cf248e72d384137d59fbd7204afcb (patch) | |
tree | e471da0d278bfe8fca6ac1cc40747c357414bc36 | |
parent | d5a8ffc6e88c7853169b972ee94286702b214c6b (diff) | |
download | mupdf-4c164469d43cf248e72d384137d59fbd7204afcb.tar.xz |
rewrite of render loop part 1
-rw-r--r-- | Jamfile | 4 | ||||
-rw-r--r-- | include/fitz/colorspace.h | 2 | ||||
-rw-r--r-- | include/fitz/font.h | 2 | ||||
-rw-r--r-- | include/fitz/pixmap.h | 1 | ||||
-rw-r--r-- | include/fitz/render.h | 59 | ||||
-rw-r--r-- | mupdf/colorspace1.c | 4 | ||||
-rw-r--r-- | mupdf/font.c | 19 | ||||
-rw-r--r-- | mupdf/image2.c | 2 | ||||
-rw-r--r-- | mupdf/interpret.c | 2 | ||||
-rw-r--r-- | mupdf/type3.c | 19 | ||||
-rw-r--r-- | render/glyphcache.c | 12 | ||||
-rw-r--r-- | render/pixmap.c | 9 | ||||
-rw-r--r-- | render/rastnone.c | 379 | ||||
-rw-r--r-- | render/render.c | 511 | ||||
-rw-r--r-- | render/scale.c | 4 | ||||
-rw-r--r-- | test/pdfrip.c | 2 | ||||
-rw-r--r-- | test/x11pdf.c | 2 | ||||
-rw-r--r-- | tree/colorspace.c | 4 |
18 files changed, 857 insertions, 180 deletions
@@ -87,10 +87,8 @@ Library libfitz : render/fill.c render/stroke.c render/scale.c + render/rastnone.c render/render.c - render/rendertext.c - render/renderpath.c - render/renderimage.c ; Library libmupdf : diff --git a/include/fitz/colorspace.h b/include/fitz/colorspace.h index 1d6c9a64..f6fae48c 100644 --- a/include/fitz/colorspace.h +++ b/include/fitz/colorspace.h @@ -4,6 +4,8 @@ typedef struct fz_colorcube1_s fz_colorcube1; typedef struct fz_colorcube3_s fz_colorcube3; typedef struct fz_colorcube4_s fz_colorcube4; +enum { FZ_MAXCOLORS = 32 }; + struct fz_colorspace_s { int refs; diff --git a/include/fitz/font.h b/include/fitz/font.h index ea1ad692..7e925461 100644 --- a/include/fitz/font.h +++ b/include/fitz/font.h @@ -42,7 +42,7 @@ struct fz_font_s struct fz_glyph_s { - int w, h, lsb, top; + int x, y, w, h; unsigned char *bitmap; }; diff --git a/include/fitz/pixmap.h b/include/fitz/pixmap.h index ecd45270..6d0391fa 100644 --- a/include/fitz/pixmap.h +++ b/include/fitz/pixmap.h @@ -13,6 +13,7 @@ struct fz_pixmap_s fz_sample *samples; }; +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); void fz_debugpixmap(fz_pixmap *map); void fz_clearpixmap(fz_pixmap *map); diff --git a/include/fitz/render.h b/include/fitz/render.h index 6e171a06..807b6227 100644 --- a/include/fitz/render.h +++ b/include/fitz/render.h @@ -1,25 +1,64 @@ 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 + +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 (*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 (*img4_g)(FZ_PID); + void (*img4_o4)(FZ_PID); + void (*img4_i1o4)(FZ_PIM); +}; + +#undef FZ_PIM +#undef FZ_PID +#undef FZ_BYTE struct fz_renderer_s { + int maskonly; fz_colorspace *model; fz_glyphcache *cache; fz_gel *gel; fz_ael *ael; + + fz_rastfuncs rast; + fz_irect clip; - fz_pixmap *tmp; - fz_pixmap *acc; - unsigned char r, g, b; - int hasrgb; + fz_pixmap *dest; + fz_pixmap *over; + fz_pixmap *mask; + unsigned char rgb[3]; + int flag; }; -fz_error *fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int gcmem); +void fz_defaultrastfuncs(fz_rastfuncs *); + +fz_error *fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int maskonly, int gcmem); void fz_droprenderer(fz_renderer *gc); -fz_error *fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm); -fz_error *fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm); -fz_error *fz_rendertransform(fz_renderer *gc, fz_transformnode *xform, fz_matrix ctm); -fz_error *fz_rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm); -fz_error *fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm); fz_error *fz_rendertree(fz_pixmap **out, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, fz_irect bbox, int white); diff --git a/mupdf/colorspace1.c b/mupdf/colorspace1.c index d666904d..5d943fdb 100644 --- a/mupdf/colorspace1.c +++ b/mupdf/colorspace1.c @@ -430,7 +430,7 @@ static void separationtoxyz(fz_colorspace *fzcs, float *sep, float *xyz) { struct separation *cs = (struct separation *)fzcs; fz_error *error; - float alt[32]; + float alt[FZ_MAXCOLORS]; error = pdf_evalfunction(cs->tint, sep, fzcs->n, alt, cs->base->n); if (error) @@ -513,7 +513,7 @@ static void indexedtoxyz(fz_colorspace *fzcs, float *ind, float *xyz) { pdf_indexed *cs = (pdf_indexed *)fzcs; - float alt[32]; + float alt[FZ_MAXCOLORS]; int i, k; i = ind[0] * 255; i = CLAMP(i, 0, cs->high); diff --git a/mupdf/font.c b/mupdf/font.c index 229ef932..e2debc85 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -110,8 +110,8 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) glyph->w = 0; glyph->h = 0; - glyph->lsb = 0; - glyph->top = 0; + glyph->x = 0; + glyph->y = 0; glyph->bitmap = nil; /* freetype mutilates complex glyphs if they are loaded @@ -161,10 +161,21 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) glyph->w = face->glyph->bitmap.width; glyph->h = face->glyph->bitmap.rows; - glyph->lsb = face->glyph->bitmap_left; - glyph->top = face->glyph->bitmap_top; + glyph->x = face->glyph->bitmap_left; + glyph->y = face->glyph->bitmap_top - glyph->h; glyph->bitmap = face->glyph->bitmap.buffer; + int i; + unsigned char tmp[glyph->w * glyph->h]; + memcpy(tmp, glyph->bitmap, glyph->w * glyph->h); + + for (i = 0; i < glyph->h; i++) + { + memcpy( glyph->bitmap + i * glyph->w, + tmp + (glyph->h - i - 1) * glyph->w, + glyph->w ); + } + return nil; } diff --git a/mupdf/image2.c b/mupdf/image2.c index 485766e6..d46bdd0e 100644 --- a/mupdf/image2.c +++ b/mupdf/image2.c @@ -141,7 +141,7 @@ static void loadtile8a(pdf_image *src, fz_pixmap *dst, int n) static void decodetile(fz_pixmap *pix, int bpc, int skip, float *decode) { - unsigned char table[32][256]; + unsigned char table[FZ_MAXCOLORS][256]; float invtwon = 1.0 / ((1 << bpc) - 1); int x, y, k, i; diff --git a/mupdf/interpret.c b/mupdf/interpret.c index 6f6f1aaf..c0a9b882 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -228,7 +228,7 @@ runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) float a, b, c, d, e, f; float x, y, w, h; fz_matrix m; - float v[32]; + float v[FZ_MAXCOLORS]; int what; int i; diff --git a/mupdf/type3.c b/mupdf/type3.c index a2612b82..ee7708c0 100644 --- a/mupdf/type3.c +++ b/mupdf/type3.c @@ -27,7 +27,6 @@ t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) fz_pixmap *pixmap; fz_matrix ctm; fz_irect bbox; - int i; if (cid < 0 || cid > 255) return fz_throw("rangecheck: glyph out of range"); @@ -43,7 +42,7 @@ t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) ctm = fz_concat(font->matrix, trm); bbox = fz_roundrect(fz_boundtree(tree, ctm)); - error = fz_newrenderer(&gc, nil, GCMEM); + error = fz_newrenderer(&gc, pdf_devicegray, 1, GCMEM); if (error) return error; error = fz_rendertree(&pixmap, gc, tree, ctm, bbox, 0); @@ -53,24 +52,12 @@ t3render(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) assert(pixmap->n == 1); - glyph->lsb = pixmap->x; - glyph->top = pixmap->h + pixmap->y; + glyph->x = pixmap->x; + glyph->y = pixmap->y; glyph->w = pixmap->w; glyph->h = pixmap->h; glyph->bitmap = pixmap->samples; - unsigned char tmp[pixmap->w * pixmap->h]; - memcpy(tmp, pixmap->samples, pixmap->w * pixmap->h); - - for (i = 0; i < pixmap->h; i++) - { - memcpy( pixmap->samples + i * pixmap->w, - tmp + (pixmap->h - i - 1) * pixmap->w, - pixmap->w ); - } - - /* XXX flip bitmap in ftrender instead; free pixmap */ - return nil; } diff --git a/render/glyphcache.c b/render/glyphcache.c index 1d3b8117..a5f9f2b6 100644 --- a/render/glyphcache.c +++ b/render/glyphcache.c @@ -37,7 +37,7 @@ struct fz_val_s { fz_hash *ent; unsigned char *data; - short w, h, lsb, top; + short w, h, x, y; int uses; }; @@ -239,7 +239,7 @@ fz_debugglyphcache(fz_glyphcache *arena) k->c / 65536.0, k->d / 65536.0, k->e, k->f, - b->w, b->h, b->lsb, b->top); + b->w, b->h, b->x, b->y); } } @@ -319,8 +319,8 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz val->uses ++; glyph->w = val->w; glyph->h = val->h; - glyph->lsb = val->lsb; - glyph->top = val->top; + glyph->x = val->x; + glyph->y = val->y; glyph->bitmap = val->data; bubble(arena, val - arena->lru); @@ -354,8 +354,8 @@ fz_renderglyph(fz_glyphcache *arena, fz_glyph *glyph, fz_font *font, int cid, fz val->uses = 0; val->w = glyph->w; val->h = glyph->h; - val->lsb = glyph->lsb; - val->top = glyph->top; + val->x = glyph->x; + val->y = glyph->y; val->data = arena->buffer + arena->used; arena->used += size; diff --git a/render/pixmap.c b/render/pixmap.c index 396b8784..21f36ee0 100644 --- a/render/pixmap.c +++ b/render/pixmap.c @@ -24,6 +24,15 @@ fz_newpixmap(fz_pixmap **pixp, int x, int y, int w, int h, int n) return nil; } +fz_error * +fz_newpixmapwithrect(fz_pixmap **pixp, fz_irect r, int n) +{ + return fz_newpixmap(pixp, + r.min.x, r.min.y, + r.max.x - r.min.x, + r.max.y - r.min.y, n); +} + void fz_droppixmap(fz_pixmap *pix) { diff --git a/render/rastnone.c b/render/rastnone.c new file mode 100644 index 00000000..4e4066fa --- /dev/null +++ b/render/rastnone.c @@ -0,0 +1,379 @@ +#include <fitz.h> + +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 & 0xFF; + int vd = v & 0xFF; + 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 & 0xFF; + int vd = v & 0xFF; + 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 nx, 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; + 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 BLOOP \ + while (ny--) \ + { \ + byte *dst = dst0; \ + int u = u0; \ + int v = v0; \ + while (nx--) \ + +#define ELOOP \ + u0 += fc; \ + v0 += fd; \ + dst0 += dstw; \ + } + +#define BLOOPM \ + while (ny--) \ + { \ + byte *dst = dst0; \ + byte *msk = msk0; \ + int u = u0; \ + int v = v0; \ + while (nx--) \ + +#define ELOOPM \ + u0 += fc; \ + v0 += fd; \ + dst0 += dstw; \ + msk0 += mskw; \ + } + +static void img1_g(PSRC, PDST, PCTM) +{ + BLOOP + { + dst[0] = samplemsk(src, w, h, u, v); + dst ++; + u += fa; + v += fb; + } + ELOOP +} + +static void img1_i1(PSRC, PDST, PCTM) +{ + BLOOP + { + dst[0] = fz_mul255(dst[0], samplemsk(src, w, h, u, v)); + dst ++; + u += fa; + v += fb; + } + ELOOP +} + +static void img1_o1(PSRC, PDST, PCTM) +{ + BLOOP + { + byte sa = samplemsk(src, w, h, u, v); + dst[0] = sa + fz_mul255(dst[0], 255 - sa); + dst ++; + u += fa; + v += fb; + } + ELOOP +} + +static void img1_i1o1(PSRC, PDST, PMSK, PCTM) +{ + BLOOPM + { + 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; + } + ELOOPM +} + +static void img1_o4w3(PSRC, PDST, PCTM, byte *rgb) +{ + BLOOP + { + 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; + } + ELOOP +} + +static void img1_i1o4w3(PSRC, PDST, PMSK, PCTM, byte *rgb) +{ + BLOOPM + { + 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; + } + ELOOPM +} + +static void img4_g(PSRC, PDST, PCTM) +{ + BLOOP + { + sampleargb(src, w, h, u, v, dst); + dst += 4; + u += fa; + v += fb; + } + ELOOP +} + +static void img4_o4(PSRC, PDST, PCTM) +{ + byte argb[4]; + BLOOP + { + sampleargb(src, w, h, u, v, argb); + byte ssa = 255 - argb[0]; + 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; + u += fa; + v += fb; + } + ELOOP +} + +static void img4_i1o4(PSRC, PDST, PMSK, PCTM) +{ + byte argb[4]; + BLOOPM + { + 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; + } + ELOOPM +} + +/* + * + */ + +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/render.c b/render/render.c index 62bce18d..672f312f 100644 --- a/render/render.c +++ b/render/render.c @@ -1,30 +1,27 @@ #include <fitz.h> -fz_error *fz_rendercolortext(fz_renderer*, fz_textnode*, fz_colornode*, fz_matrix); -fz_error *fz_rendercolorpath(fz_renderer*, fz_pathnode*, fz_colornode*, fz_matrix); -fz_error *fz_rendertext(fz_renderer*, fz_textnode*, fz_matrix); -fz_error *fz_renderpath(fz_renderer*, fz_pathnode*, fz_matrix); +#define FNONE 0 +#define FOVER 1 +#define FMASK 2 +#define FRGB 4 -fz_error *fz_rendercolorimage(fz_renderer*, fz_imagenode*, fz_colornode*, fz_matrix); -fz_error *fz_renderimage(fz_renderer*, fz_imagenode*, fz_matrix); +static fz_error *rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm); fz_error * -fz_newrenderer(fz_renderer **gcp, fz_colorspace *processcolormodel, int gcmem) +fz_newrenderer(fz_renderer **gcp, fz_colorspace *pcm, int maskonly, int gcmem) { fz_error *error; fz_renderer *gc; - gc = *gcp = fz_malloc(sizeof(fz_renderer)); + gc = fz_malloc(sizeof(fz_renderer)); if (!gc) return fz_outofmem; - gc->model = processcolormodel; + gc->maskonly = maskonly; + gc->model = pcm; gc->cache = nil; gc->gel = nil; gc->ael = nil; - gc->tmp = nil; - gc->acc = nil; - gc->hasrgb = 0; error = fz_newglyphcache(&gc->cache, gcmem / 32, gcmem); if (error) @@ -38,230 +35,483 @@ fz_newrenderer(fz_renderer **gcp, fz_colorspace *processcolormodel, int gcmem) if (error) goto cleanup; + fz_defaultrastfuncs(&gc->rast); + + gc->dest = nil; + gc->mask = nil; + gc->over = nil; + gc->rgb[0] = 0; + gc->rgb[1] = 0; + gc->rgb[2] = 0; + gc->flag = 0; + + *gcp = gc; return nil; cleanup: - if (gc->cache) - fz_dropglyphcache(gc->cache); - if (gc->gel) - fz_dropgel(gc->gel); - if (gc->ael) - fz_dropael(gc->ael); + if (gc->model) fz_dropcolorspace(gc->model); + if (gc->cache) fz_dropglyphcache(gc->cache); + if (gc->gel) fz_dropgel(gc->gel); + if (gc->ael) fz_dropael(gc->ael); fz_free(gc); - return error; } void fz_droprenderer(fz_renderer *gc) { - if (gc->cache) - fz_dropglyphcache(gc->cache); - if (gc->gel) - fz_dropgel(gc->gel); - if (gc->ael) - fz_dropael(gc->ael); - if (gc->tmp) - fz_droppixmap(gc->tmp); - if (gc->acc) - fz_droppixmap(gc->acc); + 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); + if (gc->cache) fz_dropglyphcache(gc->cache); + if (gc->gel) fz_dropgel(gc->gel); + if (gc->ael) fz_dropael(gc->ael); fz_free(gc); } -fz_error * -fz_rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm) +/* + * Transform + */ + +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("{"); + ctm = fz_concat(transform->m, ctm); + error = rendernode(gc, transform->super.first, ctm); +puts("}"); + return error; +} + +/* + * Color + */ + +static fz_error * +rendercolor(fz_renderer *gc, fz_colornode *color, fz_matrix ctm) { fz_error *error; - int x, y, w, h; float rgb[3]; unsigned char *p; + int n; - assert(gc->model); + if (gc->maskonly) + return fz_throw("assert: mask only renderer"); + if (gc->model->n != 3) + return fz_throw("assert: non-rgb renderer"); fz_convertcolor(color->cs, color->samples, gc->model, rgb); - gc->r = rgb[0] * 255; - gc->g = rgb[1] * 255; - gc->b = rgb[2] * 255; + gc->rgb[0] = rgb[0] * 255; + gc->rgb[1] = rgb[1] * 255; + gc->rgb[2] = rgb[2] * 255; - x = gc->clip.min.x; - y = gc->clip.min.y; - w = gc->clip.max.x - gc->clip.min.x; - h = gc->clip.max.y - gc->clip.min.y; +printf("color %s [%d %d %d]\n", color->cs->name, gc->rgb[0], gc->rgb[1], gc->rgb[2]); - error = fz_newpixmap(&gc->tmp, x, y, w, h, 4); + error = fz_newpixmapwithrect(&gc->dest, gc->clip, 4); if (error) return error; - p = gc->tmp->samples; + p = gc->dest->samples; + n = gc->dest->w * gc->dest->h; + + while (n--) + { + p[0] = 255; + p[1] = gc->rgb[0]; + p[2] = gc->rgb[1]; + p[3] = gc->rgb[2]; + p += 4; + } + + return nil; +} + +/* + * Path + */ + +enum { HS = 17, VS = 15, SF = 1 }; + +struct spandata +{ + fz_rastfuncs *rast; + int x, n; + fz_pixmap *dst; + fz_pixmap *msk; + unsigned char *rgb; + int flag; +}; + +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; - for (y = 0; y < gc->tmp->h; y++) + path += 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; + + switch (user->flag) { - for (x = 0; x < gc->tmp->w; x++) + case FNONE: + rast->mask_g(user->n, path, d); break; + case FOVER: + rast->mask_o1(user->n, path, d); break; + case FOVER | FMASK: + rast->mask_i1o1(user->n, path, m, d); 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; + default: + assert(!"impossible flag in path span function"); + } +} + +static fz_error * +renderpath(fz_renderer *gc, fz_pathnode *path, fz_matrix ctm) +{ + struct spandata user; + fz_error *error; + float flatness; + fz_irect gbox; + fz_irect clip; + + flatness = 0.3 / fz_matrixexpansion(ctm); + if (flatness < 0.1) + flatness = 0.1; + + fz_resetgel(gc->gel, HS, VS); + + if (path->paint == FZ_STROKE) + { + if (path->dash) + error = fz_dashpath(gc->gel, path, ctm, flatness); + else + error = fz_strokepath(gc->gel, path, ctm, flatness); + } + else + error = fz_fillpath(gc->gel, path, ctm, flatness); + if (error) + return error; + + fz_sortgel(gc->gel); + + gbox = fz_boundgel(gc->gel); + clip = fz_intersectirects(gc->clip, gbox); + +//printf("path clip[%d %d %d %d]\n", clip.min.x, clip.min.y, clip.max.x, clip.max.y); + + user.rast = &gc->rast; + user.x = clip.min.x - gbox.min.x; + user.n = clip.max.x - clip.min.x; + user.flag = gc->flag; + + if (gc->flag == FNONE) + { + 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, + clip.min.y, clip.max.y, spanfunc, &user); + if (error) + return error; + + return nil; +} + +/* + * Text + */ + +static void copyglyph(fz_renderer *gc, fz_pixmap *dst, fz_glyph *src, int xorig, int yorig) +{ + int x, y; + + xorig += src->x; + yorig += src->y; + + for (y = 0; y < src->h; y++) + for (x = 0; x < src->w; x++) { - *p++ = 255; - *p++ = gc->r; - *p++ = gc->g; - *p++ = gc->b; + int dx = xorig + x - dst->x; + int dy = yorig + y - dst->y; + + if (dx < 0) {puts("dx<0");continue;} + if (dy < 0) {puts("dy<0");continue;} + if (dx >= dst->w) {puts("dx>w");continue;} + if (dy >= dst->h) {puts("dy>h");continue;} + + int a = src->bitmap[x + y * src->w]; + int b = dst->samples[dx + dy * dst->w]; + int c = a + fz_mul255(b, 255 - a); + dst->samples[dx + dy * dst->w] = a; } +} + +static fz_error * +rendertext(fz_renderer *gc, fz_textnode *text, fz_matrix ctm) +{ + fz_error *error; + fz_irect tbox; + fz_irect clip; + fz_matrix tm, trm; + fz_glyph glyph; + int i, x, y, cid; + + 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); +fflush(stdout); + + clip.min.x ++; + clip.min.y ++; + clip.max.x ++; + clip.max.y ++; + + error = fz_newpixmapwithrect(&gc->dest, clip, 1); + if (error) + return error; + + fz_clearpixmap(gc->dest); + + tm = text->trm; + + for (i = 0; i < text->len; i++) + { + cid = text->els[i].cid; + tm.e = text->els[i].x; + tm.f = text->els[i].y; + trm = fz_concat(tm, ctm); + x = fz_floor(trm.e); + y = fz_floor(trm.f); + trm.e = (trm.e - fz_floor(trm.e)); + trm.f = (trm.f - fz_floor(trm.f)); + + error = fz_renderglyph(gc->cache, &glyph, text->font, cid, trm); + if (error) + return error; + + copyglyph(gc, gc->dest, &glyph, x, y); } return nil; } -fz_error * -fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) +/* + * Image + */ + +static fz_error * +renderimage(fz_renderer *gc, fz_imagenode *image, fz_matrix ctm) +{ + return nil; +} + +/* + * Over, Mask and Blend + */ + +static fz_error * +renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) { fz_error *error; fz_node *child; int cluster = 0;; - if (!gc->acc) - { - int x = gc->clip.min.x; - int y = gc->clip.min.y; - int w = gc->clip.max.x - gc->clip.min.x; - int h = gc->clip.max.y - gc->clip.min.y; +printf("over\n{\n"); - error = fz_newpixmap(&gc->acc, x, y, w, h, gc->model ? 4 : 1); + if (!gc->over) + { +printf(" alloc dest!\n"); + error = fz_newpixmapwithrect(&gc->over, gc->clip, gc->maskonly ? 1 : 4); if (error) return error; - - fz_clearpixmap(gc->acc); - + fz_clearpixmap(gc->over); cluster = 1; } for (child = over->super.first; child; child = child->next) { - error = fz_rendernode(gc, child, ctm); + error = rendernode(gc, child, ctm); if (error) return error; - - if (gc->tmp) + if (gc->dest) { - fz_blendover(gc->tmp, gc->acc); - fz_droppixmap(gc->tmp); - gc->tmp = nil; + fz_blendover(gc->dest, gc->over); + fz_droppixmap(gc->dest); + gc->dest = nil; } } if (cluster) { - gc->tmp = gc->acc; - gc->acc = nil; + gc->dest = gc->over; + gc->over = nil; } +printf("}\n"); + return nil; } -fz_error * -fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm) +static fz_error * +rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm) { fz_error *error; - fz_pixmap *oldacc; - fz_pixmap *colorpix; + fz_pixmap *oldover; + fz_pixmap *oldmask; + fz_irect oldclip; + fz_irect newclip; fz_pixmap *shapepix; - fz_node *color; + fz_pixmap *colorpix; fz_node *shape; - fz_irect newclip; - fz_irect oldclip; - int x, y, w, h; + fz_node *color; + float rgb[3]; shape = mask->super.first; color = shape->next; - if (gc->acc) + /* special case black voodo */ + if (gc->flag & FOVER) { - if (fz_ispathnode(shape) && fz_iscolornode(color)) - return fz_rendercolorpath(gc, (fz_pathnode*)shape, (fz_colornode*)color, ctm); - if (fz_istextnode(shape) && fz_iscolornode(color)) - return fz_rendercolortext(gc, (fz_textnode*)shape, (fz_colornode*)color, ctm); - if (fz_isimagenode(shape) && fz_iscolornode(color)) - return fz_rendercolorimage(gc, (fz_imagenode*)shape, (fz_colornode*)color, ctm); + if (fz_iscolornode(color)) + { + fz_colornode *colorn = (fz_colornode*)color; + + fz_convertcolor(colorn->cs, colorn->samples, gc->model, rgb); + gc->rgb[0] = rgb[0] * 255; + gc->rgb[1] = rgb[1] * 255; + gc->rgb[2] = rgb[2] * 255; + gc->flag |= FRGB; + + /* we know these handle FOVER | FRGB */ + if (fz_ispathnode(shape)) + return renderpath(gc, (fz_pathnode*)shape, ctm); + if (fz_istextnode(shape)) + return rendertext(gc, (fz_textnode*)shape, ctm); + if (fz_isimagenode(shape)) + return renderimage(gc, (fz_imagenode*)shape, ctm); + } } - oldacc = gc->acc; oldclip = gc->clip; + oldover = gc->over; + oldmask = gc->mask; + newclip = fz_roundrect(fz_boundnode(shape, ctm)); newclip = fz_intersectirects(newclip, gc->clip); - gc->acc = nil; gc->clip = newclip; + gc->over = nil; + gc->mask = nil; - gc->tmp = nil; - error = fz_rendernode(gc, color, ctm); +printf("mask\n{\n"); + + error = rendernode(gc, color, ctm); if (error) return error; - colorpix = gc->tmp; + colorpix = gc->dest; + gc->dest = nil; - gc->tmp = nil; - error = fz_rendernode(gc, shape, ctm); + error = rendernode(gc, shape, ctm); if (error) return error; - shapepix = gc->tmp; - - x = gc->clip.min.x; - y = gc->clip.min.y; - w = gc->clip.max.x - gc->clip.min.x; - h = gc->clip.max.y - gc->clip.min.y; + shapepix = gc->dest; + gc->dest = nil; - error = fz_newpixmap(&gc->tmp, x, y, w, h, colorpix->n); + error = fz_newpixmapwithrect(&gc->dest, gc->clip, colorpix->n); if (error) return error; - fz_clearpixmap(gc->tmp); + fz_clearpixmap(gc->dest); + + fz_blendmask(gc->dest, colorpix, shapepix); - fz_blendmask(gc->tmp, colorpix, shapepix); +//fz_debugpixmap(gc->dest);getchar(); fz_droppixmap(shapepix); fz_droppixmap(colorpix); - gc->acc = oldacc; + gc->over = oldover; + gc->mask = oldmask; gc->clip = oldclip; +printf("}\n"); + return nil; } -fz_error * -fz_rendertransform(fz_renderer *gc, fz_transformnode *transform, fz_matrix ctm) -{ - ctm = fz_concat(transform->m, ctm); - return fz_rendernode(gc, transform->super.first, ctm); -} +/* + * Dispatch + */ -fz_error * -fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm) +static fz_error * +rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm) { - assert(gc->tmp == nil); - if (!node) return nil; + gc->flag = FNONE; + if (gc->over) gc->flag |= FOVER; + if (gc->mask) gc->flag |= FMASK; + switch (node->kind) { case FZ_NOVER: - return fz_renderover(gc, (fz_overnode*)node, ctm); + return renderover(gc, (fz_overnode*)node, ctm); case FZ_NMASK: - return fz_rendermask(gc, (fz_masknode*)node, ctm); + return rendermask(gc, (fz_masknode*)node, ctm); case FZ_NTRANSFORM: - return fz_rendertransform(gc, (fz_transformnode*)node, ctm); + return rendertransform(gc, (fz_transformnode*)node, ctm); case FZ_NCOLOR: - return fz_rendercolor(gc, (fz_colornode*)node, ctm); + return rendercolor(gc, (fz_colornode*)node, ctm); case FZ_NPATH: - return fz_renderpath(gc, (fz_pathnode*)node, ctm); + return renderpath(gc, (fz_pathnode*)node, ctm); case FZ_NTEXT: - return fz_rendertext(gc, (fz_textnode*)node, ctm); + return rendertext(gc, (fz_textnode*)node, ctm); case FZ_NIMAGE: - return fz_renderimage(gc, (fz_imagenode*)node, ctm); + return renderimage(gc, (fz_imagenode*)node, ctm); case FZ_NLINK: - return fz_rendernode(gc, ((fz_linknode*)node)->tree->root, ctm); - default: - return nil; + return rendernode(gc, ((fz_linknode*)node)->tree->root, ctm); } + + return nil; } fz_error * -fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, fz_irect bbox, int white) +fz_rendertree(fz_pixmap **outp, + fz_renderer *gc, fz_tree *tree, fz_matrix ctm, + fz_irect bbox, int white) { fz_error *error; @@ -269,27 +519,28 @@ fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, f if (white) { - error = fz_newpixmap(&gc->acc, - bbox.min.x, bbox.min.y, - bbox.max.x - bbox.min.x, bbox.max.y - bbox.min.y, 4); + assert(gc->maskonly == 0); + + error = fz_newpixmapwithrect(&gc->over, bbox, 4); if (error) return error; - memset(gc->acc->samples, 0xff, gc->acc->w * gc->acc->h * gc->acc->n); + + memset(gc->over->samples, 0xff, gc->over->w * gc->over->h * gc->over->n); } - error = fz_rendernode(gc, tree->root, ctm); + error = rendernode(gc, tree->root, ctm); if (error) return error; if (white) { - *outp = gc->acc; - gc->acc = nil; + *outp = gc->over; + gc->over = nil; } else { - *outp = gc->tmp; - gc->tmp = nil; + *outp = gc->dest; + gc->dest = nil; } return nil; diff --git a/render/scale.c b/render/scale.c index a07d52a7..6b06dcfa 100644 --- a/render/scale.c +++ b/render/scale.c @@ -4,7 +4,7 @@ static void scalerow(unsigned char *src, unsigned char *dst, int w, int ncomp, int denom) { int x, left, k; - int sum[32]; + int sum[FZ_MAXCOLORS]; left = 0; for (k = 0; k < ncomp; k++) @@ -37,7 +37,7 @@ scalecols(unsigned char *src, unsigned char *dst, int w, int ncomp, int denom) { int x, y, k; unsigned char *s; - int sum[32]; + int sum[FZ_MAXCOLORS]; for (x = 0; x < w; x++) { diff --git a/test/pdfrip.c b/test/pdfrip.c index 877be289..b34dfb11 100644 --- a/test/pdfrip.c +++ b/test/pdfrip.c @@ -49,7 +49,7 @@ void showpage(pdf_xref *xref, fz_obj *pageobj) fz_matrix ctm; fz_rect bbox; - error = fz_newrenderer(&gc, pdf_devicergb, 1024 * 512); + error = fz_newrenderer(&gc, pdf_devicergb, 0, 1024 * 512); if (error) fz_abort(error); ctm = fz_concat(fz_translate(0, -page->mediabox.max.y), fz_scale(zoom, -zoom)); diff --git a/test/x11pdf.c b/test/x11pdf.c index 9b1e94c7..b02b2c58 100644 --- a/test/x11pdf.c +++ b/test/x11pdf.c @@ -231,7 +231,7 @@ static void pdfopen(char *filename, char *password) } } - error = fz_newrenderer(&rast, pdf_devicergb, 1024 * 512); + error = fz_newrenderer(&rast, pdf_devicergb, 0, 1024 * 512); if (error) fz_abort(error); image = nil; diff --git a/tree/colorspace.c b/tree/colorspace.c index f5025468..aabf531b 100644 --- a/tree/colorspace.c +++ b/tree/colorspace.c @@ -55,8 +55,8 @@ fz_stdconvcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *ds void fz_stdconvpixmap(fz_colorspace *srcs, fz_pixmap *src, fz_colorspace *dsts, fz_pixmap *dst) { - float srcv[32]; - float dstv[32]; + float srcv[FZ_MAXCOLORS]; + float dstv[FZ_MAXCOLORS]; int y, x, k; unsigned char *s = src->samples; |