diff options
author | Tor Andersson <tor@ghostscript.com> | 2010-04-08 19:54:33 +0200 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2010-04-08 19:54:33 +0200 |
commit | 28bb08951bea16b4baf3b05365d606fde0a099b6 (patch) | |
tree | 1b33a686f5e6d099d58fad96da808ebc2541bc58 | |
parent | e32122e047e5882f3ca64d86cc0562473360b329 (diff) | |
download | mupdf-28bb08951bea16b4baf3b05365d606fde0a099b6.tar.xz |
Add display list device.
-rw-r--r-- | Makefile | 9 | ||||
-rw-r--r-- | apps/pdfapp.c | 39 | ||||
-rw-r--r-- | apps/pdfapp.h | 2 | ||||
-rw-r--r-- | apps/pdfdraw.c | 14 | ||||
-rw-r--r-- | draw/meshdraw.c | 4 | ||||
-rw-r--r-- | draw/pixmap.c | 21 | ||||
-rw-r--r-- | fitz/dev_draw.c | 110 | ||||
-rw-r--r-- | fitz/dev_list.c | 285 | ||||
-rw-r--r-- | fitz/dev_null.c | 43 | ||||
-rw-r--r-- | fitz/dev_text.c | 61 | ||||
-rw-r--r-- | fitz/dev_trace.c | 60 | ||||
-rw-r--r-- | fitz/fitz_base.h | 35 | ||||
-rw-r--r-- | fitz/fitz_res.h | 214 | ||||
-rw-r--r-- | fitz/res_font.c | 4 | ||||
-rw-r--r-- | fitz/res_path.c | 32 | ||||
-rw-r--r-- | fitz/res_text.c | 17 | ||||
-rw-r--r-- | mupdf/pdf_build.c | 39 | ||||
-rw-r--r-- | mupdf/pdf_image.c | 2 |
18 files changed, 698 insertions, 293 deletions
@@ -96,8 +96,7 @@ FITZ_SRC=$(addprefix fitz/, \ crypt_aes.c crypt_arc4.c crypt_crc32.c crypt_md5.c \ filt_aesd.c filt_arc4.c filt_basic.c filt_dctd.c filt_faxd.c filt_faxdtab.c filt_flate.c \ filt_jbig2d.c filt_jpxd.c filt_lzwd.c filt_pipeline.c filt_predict.c \ - node_path.c node_text.c \ - dev_null.c dev_text.c dev_draw.c dev_trace.c \ + dev_null.c dev_text.c dev_draw.c dev_list.c dev_trace.c \ obj_array.c obj_dict.c obj_parse.c obj_print.c obj_simple.c \ res_colorspace.c res_font.c res_shade.c res_path.c res_text.c \ stm_buffer.c stm_filter.c stm_misc.c stm_open.c stm_read.c \ @@ -254,6 +253,7 @@ CMAP_SRC=\ CMAP_OBJ=$(CMAP_SRC:$(GENDIR)/%.c=$(OBJDIR)/%.o) CMAP_LIB=$(OBJDIR)/libcmaps.a +$(CMAP_OBJ): $(MUPDF_HDR) $(CMAP_LIB): $(CMAP_OBJ) $(AR_CMD) @@ -270,6 +270,7 @@ PDFSHOW_SRC=apps/pdfshow.c apps/pdftool.c PDFSHOW_OBJ=$(PDFSHOW_SRC:apps/%.c=$(OBJDIR)/%.o) PDFSHOW_EXE=$(OBJDIR)/pdfshow +$(PDFSHOW_OBJ): $(MUPDF_HDR) $(PDFSHOW_EXE): $(PDFSHOW_OBJ) $(MUPDF_LIB) $(FITZ_LIB) $(LD_CMD) @@ -277,6 +278,7 @@ PDFCLEAN_SRC=apps/pdfclean.c apps/pdftool.c PDFCLEAN_OBJ=$(PDFCLEAN_SRC:apps/%.c=$(OBJDIR)/%.o) PDFCLEAN_EXE=$(OBJDIR)/pdfclean +$(PDFCLEAN_OBJ): $(MUPDF_HDR) $(PDFCLEAN_EXE): $(PDFCLEAN_OBJ) $(MUPDF_LIB) $(FITZ_LIB) $(LD_CMD) @@ -284,6 +286,7 @@ PDFDRAW_SRC=apps/pdfdraw.c apps/pdftool.c PDFDRAW_OBJ=$(PDFDRAW_SRC:apps/%.c=$(OBJDIR)/%.o) PDFDRAW_EXE=$(OBJDIR)/pdfdraw +$(PDFDRAW_OBJ): $(MUPDF_HDR) $(PDFDRAW_EXE): $(PDFDRAW_OBJ) $(MUPDF_LIB) $(FONT_LIB) $(CMAP_LIB) $(FITZ_LIB) $(DRAW_LIB) $(LD_CMD) @@ -291,6 +294,7 @@ X11VIEW_SRC=apps/x11_main.c apps/x11_image.c apps/pdfapp.c X11VIEW_OBJ=$(X11VIEW_SRC:apps/%.c=$(OBJDIR)/%.o) X11VIEW_EXE=$(OBJDIR)/mupdf +$(X11VIEW_OBJ): $(MUPDF_HDR) $(X11VIEW_EXE): $(X11VIEW_OBJ) $(MUPDF_LIB) $(FONT_LIB) $(CMAP_LIB) $(FITZ_LIB) $(DRAW_LIB) $(LD_CMD) $(X11LIBS) @@ -302,6 +306,7 @@ WINVIEW_EXE=$(OBJDIR)/mupdf.exe $(OBJDIR)/%.o: apps/%.rc windres -i $< -o $@ --include-dir=apps +$(WINVIEW_OBJ): $(MUPDF_HDR) $(WINVIEW_EXE): $(WINVIEW_OBJ) $(MUPDF_LIB) $(FONT_LIB) $(CMAP_LIB) $(FITZ_LIB) $(DRAW_LIB) $(LD_CMD) $(W32LIBS) diff --git a/apps/pdfapp.c b/apps/pdfapp.c index 0b39f134..1f78c4e1 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -164,11 +164,11 @@ void pdfapp_close(pdfapp_t *app) app->page = nil; if (app->image) - fz_freepixmap(app->image); + fz_droppixmap(app->image); app->image = nil; if (app->text) - fz_freetextline(app->text); + fz_freetextspan(app->text); app->text = nil; if (app->outline) @@ -222,6 +222,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage) char buf[256]; fz_error error; fz_device *idev, *tdev, *mdev; + fz_displaylist *list; fz_matrix ctm; fz_irect bbox; fz_obj *obj; @@ -253,29 +254,31 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage) ctm = pdfapp_viewctm(app); bbox = fz_roundrect(fz_transformaabb(ctm, app->page->mediabox)); + list = fz_newdisplaylist(); + + mdev = fz_newlistdevice(list); + app->page->contents->rp = app->page->contents->bp; + error = pdf_runcontentstream(mdev, fz_identity(), app->xref, app->page->resources, app->page->contents); + if (error) + pdfapp_error(app, error); + fz_freedevice(mdev); + if (app->image) - fz_freepixmap(app->image); + fz_droppixmap(app->image); app->image = fz_newpixmapwithrect(pdf_devicergb, bbox); fz_clearpixmap(app->image, 0xFF); idev = fz_newdrawdevice(app->image); + fz_executedisplaylist(list, idev, ctm); + fz_freedevice(idev); if (app->text) - fz_freetextline(app->text); - app->text = fz_newtextline(); + fz_freetextspan(app->text); + app->text = fz_newtextspan(); tdev = fz_newtextdevice(app->text); + fz_executedisplaylist(list, tdev, ctm); + fz_freedevice(tdev); - app->page->contents->rp = app->page->contents->bp; - error = pdf_runcontentstream(idev, ctm, app->xref, app->page->resources, app->page->contents); - if (error) - pdfapp_error(app, error); - - app->page->contents->rp = app->page->contents->bp; - error = pdf_runcontentstream(tdev, ctm, app->xref, app->page->resources, app->page->contents); - if (error) - pdfapp_error(app, error); - - fz_freedrawdevice(idev); - fz_freetextdevice(tdev); + fz_freedisplaylist(list); winconvert(app, app->image); } @@ -641,7 +644,7 @@ void pdfapp_oncopy(pdfapp_t *app, unsigned short *ucsbuf, int ucslen) { ucsbuf[0] = 0; fz_error error; - fz_textline *ln; + fz_textspan *ln; int x, y, c; int i, p; diff --git a/apps/pdfapp.h b/apps/pdfapp.h index ce43d5b4..9df3c46b 100644 --- a/apps/pdfapp.h +++ b/apps/pdfapp.h @@ -32,7 +32,7 @@ struct pdfapp_s float zoom; int rotate; fz_pixmap *image; - fz_textline *text; + fz_textspan *text; /* current page params */ int pageno; diff --git a/apps/pdfdraw.c b/apps/pdfdraw.c index 2e8c8472..203919cf 100644 --- a/apps/pdfdraw.c +++ b/apps/pdfdraw.c @@ -236,7 +236,7 @@ static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark * error = pdf_runcontentstream(dev, ctm, xref, drawpage->resources, drawpage->contents); if (error) die(error); - fz_freedrawdevice(dev); + fz_freedevice(dev); if (drawpattern) { @@ -264,7 +264,7 @@ static void drawpnm(int pagenum, struct benchmark *loadtimes, struct benchmark * pix->h = bbox.y1 - pix->y; } - fz_freepixmap(pix); + fz_droppixmap(pix); if (!drawpattern) { unsigned char buf[16]; @@ -308,7 +308,7 @@ static void drawtxt(int pagenum) fz_error error; fz_matrix ctm; fz_obj *pageobj; - fz_textline *text; + fz_textspan *text; fz_device *dev; pageobj = pdf_getpageobject(xref, pagenum); @@ -318,7 +318,7 @@ static void drawtxt(int pagenum) ctm = fz_identity(); - text = fz_newtextline(); + text = fz_newtextspan(); dev = fz_newtextdevice(text); drawpage->contents->rp = drawpage->contents->bp; @@ -327,11 +327,11 @@ static void drawtxt(int pagenum) die(error); printf("[Page %d]\n", pagenum); - fz_debugtextline(text); + fz_debugtextspan(text); printf("\n"); - fz_freetextdevice(dev); - fz_freetextline(text); + fz_freedevice(dev); + fz_freetextspan(text); } static void drawpages(char *pagelist) diff --git a/draw/meshdraw.c b/draw/meshdraw.c index d756db12..fd7f2565 100644 --- a/draw/meshdraw.c +++ b/draw/meshdraw.c @@ -386,13 +386,13 @@ baddata: d += 4; } - fz_freepixmap(temp); + fz_droppixmap(temp); } else if (shade->cs != destcs) { fz_convertpixmap(shade->cs, temp, destcs, dest); - fz_freepixmap(temp); + fz_droppixmap(temp); } } diff --git a/draw/pixmap.c b/draw/pixmap.c index 539234f6..dd42fb31 100644 --- a/draw/pixmap.c +++ b/draw/pixmap.c @@ -6,6 +6,7 @@ fz_newpixmap(fz_colorspace *colorspace, int x, int y, int w, int h) fz_pixmap *pix; pix = fz_malloc(sizeof(fz_pixmap)); + pix->refs = 1; pix->x = x; pix->y = y; pix->w = w; @@ -30,13 +31,23 @@ fz_newpixmapwithrect(fz_colorspace *colorspace, fz_irect r) return fz_newpixmap(colorspace, r.x0, r.y0, r.x1 - r.x0, r.y1 - r.y0); } +fz_pixmap * +fz_keeppixmap(fz_pixmap *pix) +{ + pix->refs++; + return pix; +} + void -fz_freepixmap(fz_pixmap *pix) +fz_droppixmap(fz_pixmap *pix) { - if (pix->colorspace) - fz_dropcolorspace(pix->colorspace); - fz_free(pix->samples); - fz_free(pix); + if (pix && --pix->refs == 0) + { + if (pix->colorspace) + fz_dropcolorspace(pix->colorspace); + fz_free(pix->samples); + fz_free(pix); + } } void diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c index b8223ce4..f4889aeb 100644 --- a/fitz/dev_draw.c +++ b/fitz/dev_draw.c @@ -97,15 +97,19 @@ blendmaskover(fz_pixmap *src, fz_pixmap *msk, fz_pixmap *dst) else if (src->n == 4 && msk->n == 1 && dst->n == 4) fz_duff_4i1o4(sp, src->w * 4, mp, msk->w, dp, dst->w * 4, w, h); else if (src->n == dst->n) - fz_duff_nimon(sp, src->w * src->n, src->n, mp, msk->w * msk->n, msk->n, dp, dst->w * dst->n, w, h); + fz_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"); } -void fz_drawfillpath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_drawfillpath(void *user, fz_path *path, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { fz_drawdevice *dev = user; - float expansion = fz_matrixexpansion(path->ctm); + float expansion = fz_matrixexpansion(ctm); float flatness = 0.3 / expansion; fz_irect bbox; fz_irect clip; @@ -116,7 +120,7 @@ void fz_drawfillpath(void *user, fz_path *path, fz_colorspace *colorspace, float clip.y1 = dev->dest->y + dev->dest->h; fz_resetgel(dev->gel, clip); - fz_fillpath(dev->gel, path, path->ctm, flatness); + fz_fillpath(dev->gel, path, ctm, flatness); fz_sortgel(dev->gel); bbox = fz_boundgel(dev->gel); @@ -136,18 +140,20 @@ void fz_drawfillpath(void *user, fz_path *path, fz_colorspace *colorspace, float argb[4] = rgb[0] * 255; argb[5] = rgb[1] * 255; argb[6] = rgb[2] * 255; - fz_scanconvert(dev->gel, dev->ael, path->winding == FZ_EVENODD, bbox, dev->dest, argb, 1); + fz_scanconvert(dev->gel, dev->ael, path->evenodd, bbox, dev->dest, argb, 1); } else { - fz_scanconvert(dev->gel, dev->ael, path->winding == FZ_EVENODD, bbox, dev->dest, nil, 1); + fz_scanconvert(dev->gel, dev->ael, path->evenodd, bbox, dev->dest, nil, 1); } } -void fz_drawstrokepath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_drawstrokepath(void *user, fz_path *path, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { fz_drawdevice *dev = user; - float expansion = fz_matrixexpansion(path->ctm); + float expansion = fz_matrixexpansion(ctm); float flatness = 0.3 / expansion; float linewidth = path->linewidth; fz_irect bbox; @@ -163,9 +169,9 @@ void fz_drawstrokepath(void *user, fz_path *path, fz_colorspace *colorspace, flo fz_resetgel(dev->gel, clip); if (path->dashlen > 0) - fz_dashpath(dev->gel, path, path->ctm, flatness, linewidth); + fz_dashpath(dev->gel, path, ctm, flatness, linewidth); else - fz_strokepath(dev->gel, path, path->ctm, flatness, linewidth); + fz_strokepath(dev->gel, path, ctm, flatness, linewidth); fz_sortgel(dev->gel); bbox = fz_boundgel(dev->gel); @@ -193,10 +199,11 @@ void fz_drawstrokepath(void *user, fz_path *path, fz_colorspace *colorspace, flo } } -void fz_drawclippath(void *user, fz_path *path) +static void +fz_drawclippath(void *user, fz_path *path, fz_matrix ctm) { fz_drawdevice *dev = user; - float expansion = fz_matrixexpansion(path->ctm); + float expansion = fz_matrixexpansion(ctm); float flatness = 0.3 / expansion; fz_irect clip, bbox; fz_pixmap *mask, *dest; @@ -213,7 +220,7 @@ void fz_drawclippath(void *user, fz_path *path) clip.y1 = dev->dest->y + dev->dest->h; fz_resetgel(dev->gel, clip); - fz_fillpath(dev->gel, path, path->ctm, flatness); + fz_fillpath(dev->gel, path, ctm, flatness); fz_sortgel(dev->gel); bbox = fz_boundgel(dev->gel); @@ -226,7 +233,7 @@ void fz_drawclippath(void *user, fz_path *path) memset(dest->samples, 0, dest->w * dest->h * dest->n); if (!fz_isemptyrect(bbox)) - fz_scanconvert(dev->gel, dev->ael, path->winding == FZ_EVENODD, bbox, mask, nil, 1); + fz_scanconvert(dev->gel, dev->ael, path->evenodd, bbox, mask, nil, 1); dev->clipstack[dev->cliptop].mask = mask; dev->clipstack[dev->cliptop].dest = dev->dest; @@ -234,7 +241,8 @@ void fz_drawclippath(void *user, fz_path *path) dev->cliptop++; } -static void drawglyph(unsigned char *argb, fz_pixmap *dst, fz_glyph *src, int xorig, int yorig) +static void +drawglyph(unsigned char *argb, fz_pixmap *dst, fz_glyph *src, int xorig, int yorig) { unsigned char *dp, *sp; int w, h; @@ -273,7 +281,9 @@ static void drawglyph(unsigned char *argb, fz_pixmap *dst, fz_glyph *src, int xo fz_text_1o1(sp, src->w, dp, dst->w, w, h); } -void fz_drawfilltext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_drawfilltext(void *user, fz_text *text, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { fz_drawdevice *dev = user; fz_irect clip; @@ -313,7 +323,7 @@ void fz_drawfilltext(void *user, fz_text *text, fz_colorspace *colorspace, float gid = text->els[i].gid; tm.e = text->els[i].x; tm.f = text->els[i].y; - trm = fz_concat(tm, text->ctm); + trm = fz_concat(tm, ctm); x = fz_floor(trm.e); y = fz_floor(trm.f); trm.e = QUANT(trm.e - fz_floor(trm.e), HSUBPIX); @@ -324,15 +334,17 @@ void fz_drawfilltext(void *user, fz_text *text, fz_colorspace *colorspace, float } } -void fz_drawstroketext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_drawstroketext(void *user, fz_text *text, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { - fz_drawdevice *dev = user; fz_warn("/%s setfont", text->font->name); fz_debugtext(text, 0); fz_warn("charpath stroke"); } -void fz_drawcliptext(void *user, fz_text *text) +static void +fz_drawcliptext(void *user, fz_text *text, fz_matrix ctm) { fz_warn("gsave"); fz_warn("/%s setfont", text->font->name); @@ -340,11 +352,13 @@ void fz_drawcliptext(void *user, fz_text *text) fz_warn("charpath clip"); } -void fz_drawignoretext(void *user, fz_text *text) +static void +fz_drawignoretext(void *user, fz_text *text, fz_matrix ctm) { } -void fz_drawpopclip(void *user) +static void +fz_drawpopclip(void *user) { fz_drawdevice *dev = user; if (dev->cliptop > 0) @@ -353,14 +367,15 @@ void fz_drawpopclip(void *user) fz_pixmap *dest = dev->clipstack[dev->cliptop-1].dest; fz_pixmap *scratch = dev->dest; blendmaskover(scratch, mask, dest); - fz_freepixmap(mask); - fz_freepixmap(scratch); + fz_droppixmap(mask); + fz_droppixmap(scratch); dev->cliptop--; dev->dest = dest; } } -void fz_drawdrawshade(void *user, fz_shade *shade, fz_matrix ctm) +static void +fz_drawfillshade(void *user, fz_shade *shade, fz_matrix ctm) { fz_drawdevice *dev = user; fz_rect bounds; @@ -413,7 +428,7 @@ void fz_drawdrawshade(void *user, fz_shade *shade, fz_matrix ctm) fz_rendershade(shade, ctm, dev->model, temp); blendover(temp, dev->dest); - fz_freepixmap(temp); + fz_droppixmap(temp); } static inline void @@ -436,7 +451,8 @@ calcimagescale(fz_matrix ctm, int w, int h, int *odx, int *ody) *ody = dy; } -void fz_drawdrawimage(void *user, fz_pixmap *image, fz_matrix ctm) +static void +fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm) { fz_drawdevice *dev = user; fz_rect bounds; @@ -522,7 +538,9 @@ void fz_drawdrawimage(void *user, fz_pixmap *image, fz_matrix ctm) u0, v0, fa, fb, fc, fd, w, h); } -void fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { fz_drawdevice *dev = user; fz_rect bounds; @@ -609,7 +627,8 @@ void fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, fz_colors } } -void fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) +static void +fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) { fz_drawdevice *dev = user; fz_rect bounds; @@ -690,7 +709,20 @@ void fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) dev->cliptop++; } -fz_device *fz_newdrawdevice(fz_pixmap *dest) +static void +fz_drawfreeuser(void *user) +{ + fz_drawdevice *dev = user; + if (dev->model) + fz_dropcolorspace(dev->model); + fz_freeglyphcache(dev->cache); + fz_freegel(dev->gel); + fz_freeael(dev->ael); + fz_free(dev); +} + +fz_device * +fz_newdrawdevice(fz_pixmap *dest) { fz_drawdevice *ddev = fz_malloc(sizeof(fz_drawdevice)); if (dest->colorspace) @@ -704,6 +736,8 @@ fz_device *fz_newdrawdevice(fz_pixmap *dest) ddev->cliptop = 0; fz_device *dev = fz_newdevice(ddev); + dev->freeuser = fz_drawfreeuser; + dev->fillpath = fz_drawfillpath; dev->strokepath = fz_drawstrokepath; dev->clippath = fz_drawclippath; @@ -715,23 +749,11 @@ fz_device *fz_newdrawdevice(fz_pixmap *dest) dev->fillimagemask = fz_drawfillimagemask; dev->clipimagemask = fz_drawclipimagemask; - dev->drawimage = fz_drawdrawimage; - dev->drawshade = fz_drawdrawshade; + dev->fillimage = fz_drawfillimage; + dev->fillshade = fz_drawfillshade; dev->popclip = fz_drawpopclip; return dev; } -void -fz_freedrawdevice(fz_device *dev) -{ - fz_drawdevice *ddev = dev->user; - if (ddev->model) - fz_dropcolorspace(ddev->model); - fz_freeglyphcache(ddev->cache); - fz_freegel(ddev->gel); - fz_freeael(ddev->ael); - fz_free(ddev); - fz_free(dev); -} diff --git a/fitz/dev_list.c b/fitz/dev_list.c new file mode 100644 index 00000000..22982508 --- /dev/null +++ b/fitz/dev_list.c @@ -0,0 +1,285 @@ +#include "fitz.h" + +static fz_displaynode * +fz_newdisplaynode(fz_displaycommand cmd, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) +{ + fz_displaynode *node; + int i; + + node = fz_malloc(sizeof(fz_displaynode)); + node->cmd = cmd; + node->next = nil; + node->ctm = ctm; + if (colorspace) + { + node->colorspace = fz_keepcolorspace(colorspace); + for (i = 0; i < node->colorspace->n; i++) + node->color[i] = color[i]; + } + else + { + node->colorspace = nil; + } + node->alpha = alpha; + + return node; +} + +static void +fz_appenddisplaynode(fz_displaylist *list, fz_displaynode *node) +{ + if (!list->first) + { + list->first = node; + list->last = node; + } + else + { + list->last->next = node; + list->last = node; + } +} + +static void +fz_freedisplaynode(fz_displaynode *node) +{ + switch (node->cmd) + { + case FZ_CMDFILLPATH: + case FZ_CMDSTROKEPATH: + case FZ_CMDCLIPPATH: + fz_freepath(node->item.path); + break; + case FZ_CMDFILLTEXT: + case FZ_CMDSTROKETEXT: + case FZ_CMDCLIPTEXT: + case FZ_CMDIGNORETEXT: + fz_freetext(node->item.text); + break; + case FZ_CMDFILLSHADE: + fz_dropshade(node->item.shade); + break; + case FZ_CMDFILLIMAGE: + case FZ_CMDFILLIMAGEMASK: + case FZ_CMDCLIPIMAGEMASK: + fz_droppixmap(node->item.image); + break; + case FZ_CMDPOPCLIP: + break; + } + if (node->colorspace) + fz_dropcolorspace(node->colorspace); + fz_free(node); +} + +static void +fz_listfillpath(void *user, fz_path *path, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDFILLPATH, ctm, colorspace, color, alpha); + node->item.path = fz_clonepath(path); + fz_appenddisplaynode(user, node); +} + +static void +fz_liststrokepath(void *user, fz_path *path, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDSTROKEPATH, ctm, colorspace, color, alpha); + node->item.path = fz_clonepath(path); + fz_appenddisplaynode(user, node); +} + +static void +fz_listclippath(void *user, fz_path *path, fz_matrix ctm) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDCLIPPATH, ctm, nil, nil, 0.0); + node->item.path = fz_clonepath(path); + fz_appenddisplaynode(user, node); +} + +static void +fz_listfilltext(void *user, fz_text *text, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDFILLTEXT, ctm, colorspace, color, alpha); + node->item.text = fz_clonetext(text); + fz_appenddisplaynode(user, node); +} + +static void +fz_liststroketext(void *user, fz_text *text, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDSTROKETEXT, ctm, colorspace, color, alpha); + node->item.text = fz_clonetext(text); + fz_appenddisplaynode(user, node); +} + +static void +fz_listcliptext(void *user, fz_text *text, fz_matrix ctm) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDCLIPPATH, ctm, nil, nil, 0.0); + node->item.text = fz_clonetext(text); + fz_appenddisplaynode(user, node); +} + +static void +fz_listignoretext(void *user, fz_text *text, fz_matrix ctm) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDCLIPPATH, ctm, nil, nil, 0.0); + node->item.text = fz_clonetext(text); + fz_appenddisplaynode(user, node); +} + +static void +fz_listpopclip(void *user) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDPOPCLIP, fz_identity(), nil, nil, 0.0); + fz_appenddisplaynode(user, node); +} + +static void +fz_listfillshade(void *user, fz_shade *shade, fz_matrix ctm) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDFILLSHADE, ctm, nil, nil, 0.0); + node->item.shade = fz_keepshade(shade); + fz_appenddisplaynode(user, node); +} + +static void +fz_listfillimage(void *user, fz_pixmap *image, fz_matrix ctm) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDFILLIMAGE, ctm, nil, nil, 0.0); + node->item.image = fz_keeppixmap(image); + fz_appenddisplaynode(user, node); +} + +static void +fz_listfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDFILLIMAGEMASK, ctm, colorspace, color, alpha); + node->item.image = fz_keeppixmap(image); + fz_appenddisplaynode(user, node); +} + +static void +fz_listclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDCLIPIMAGEMASK, ctm, nil, nil, 0.0); + node->item.image = fz_keeppixmap(image); + fz_appenddisplaynode(user, node); +} + +fz_device * +fz_newlistdevice(fz_displaylist *list) +{ + fz_device *dev = fz_newdevice(list); + + dev->fillpath = fz_listfillpath; + dev->strokepath = fz_liststrokepath; + dev->clippath = fz_listclippath; + + dev->filltext = fz_listfilltext; + dev->stroketext = fz_liststroketext; + dev->cliptext = fz_listcliptext; + dev->ignoretext = fz_listignoretext; + + dev->fillshade = fz_listfillshade; + dev->fillimage = fz_listfillimage; + dev->fillimagemask = fz_listfillimagemask; + dev->clipimagemask = fz_listclipimagemask; + + dev->popclip = fz_listpopclip; + + return dev; +} + +fz_displaylist * +fz_newdisplaylist(void) +{ + fz_displaylist *list = fz_malloc(sizeof(fz_displaylist)); + list->first = nil; + list->last = nil; + return list; +} + +void +fz_freedisplaylist(fz_displaylist *list) +{ + fz_displaynode *node = list->first; + while (node) + { + fz_displaynode *next = node->next; + fz_freedisplaynode(node); + node = next; + } +} + +void +fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm) +{ + fz_displaynode *node; + for (node = list->first; node; node = node->next) + { + fz_matrix ctm = fz_concat(node->ctm, topctm); + switch (node->cmd) + { + case FZ_CMDFILLPATH: + dev->fillpath(dev->user, node->item.path, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMDSTROKEPATH: + dev->strokepath(dev->user, node->item.path, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMDCLIPPATH: + dev->clippath(dev->user, node->item.path, ctm); + break; + case FZ_CMDFILLTEXT: + dev->filltext(dev->user, node->item.text, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMDSTROKETEXT: + dev->stroketext(dev->user, node->item.text, ctm, + node->colorspace, node->color, node->alpha); + break; + case FZ_CMDCLIPTEXT: + dev->cliptext(dev->user, node->item.text, ctm); + break; + case FZ_CMDIGNORETEXT: + dev->ignoretext(dev->user, node->item.text, ctm); + break; + case FZ_CMDFILLSHADE: + dev->fillshade(dev->user, node->item.shade, ctm); + break; + case FZ_CMDFILLIMAGE: + dev->fillimage(dev->user, node->item.image, ctm); + break; + case FZ_CMDFILLIMAGEMASK: + dev->fillimagemask(dev->user, node->item.image, ctm, + node->colorspace, node->color, node->alpha); + case FZ_CMDCLIPIMAGEMASK: + dev->clipimagemask(dev->user, node->item.image, ctm); + break; + case FZ_CMDPOPCLIP: + dev->popclip(dev->user); + break; + } + } +} + diff --git a/fitz/dev_null.c b/fitz/dev_null.c index 4ad2e815..06d149ac 100644 --- a/fitz/dev_null.c +++ b/fitz/dev_null.c @@ -1,24 +1,27 @@ #include "fitz.h" -void fz_nullfillpath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha) {} -void fz_nullstrokepath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha) {} -void fz_nullclippath(void *user, fz_path *path) {} -void fz_nullfilltext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha) {} -void fz_nullstroketext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha) {} -void fz_nullcliptext(void *user, fz_text *text) {} -void fz_nullignoretext(void *user, fz_text *text) {} -void fz_nullpopclip(void *user) {} -void fz_nulldrawshade(void *user, fz_shade *shade, fz_matrix ctm) {} -void fz_nulldrawimage(void *user, fz_pixmap *image, fz_matrix ctm) {} -void fz_nullfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} -void fz_nullclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) {} - -fz_device *fz_newdevice(void *user) +static void fz_nullfreeuser(void *user) {} +static void fz_nullfillpath(void *user, fz_path *path, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} +static void fz_nullstrokepath(void *user, fz_path *path, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} +static void fz_nullclippath(void *user, fz_path *path, fz_matrix ctm) {} +static void fz_nullfilltext(void *user, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} +static void fz_nullstroketext(void *user, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} +static void fz_nullcliptext(void *user, fz_text *text, fz_matrix ctm) {} +static void fz_nullignoretext(void *user, fz_text *text, fz_matrix ctm) {} +static void fz_nullpopclip(void *user) {} +static void fz_nullfillshade(void *user, fz_shade *shade, fz_matrix ctm) {} +static void fz_nullfillimage(void *user, fz_pixmap *image, fz_matrix ctm) {} +static void fz_nullfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} +static void fz_nullclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) {} + +fz_device * +fz_newdevice(void *user) { fz_device *dev = fz_malloc(sizeof(fz_device)); memset(dev, 0, sizeof(fz_device)); dev->user = user; + dev->freeuser = fz_nullfreeuser; dev->fillpath = fz_nullfillpath; dev->strokepath = fz_nullstrokepath; @@ -29,12 +32,20 @@ fz_device *fz_newdevice(void *user) dev->cliptext = fz_nullcliptext; dev->ignoretext = fz_nullignoretext; + dev->fillshade = fz_nullfillshade; + dev->fillimage = fz_nullfillimage; dev->fillimagemask = fz_nullfillimagemask; dev->clipimagemask = fz_nullclipimagemask; - dev->drawimage = fz_nulldrawimage; - dev->drawshade = fz_nulldrawshade; dev->popclip = fz_nullpopclip; return dev; } + +void +fz_freedevice(fz_device *dev) +{ + if (dev->freeuser) + dev->freeuser(dev->user); + fz_free(dev); +}
\ No newline at end of file diff --git a/fitz/dev_text.c b/fitz/dev_text.c index 8bcdea7f..a3b01d46 100644 --- a/fitz/dev_text.c +++ b/fitz/dev_text.c @@ -7,7 +7,8 @@ ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 2)) || \ ((FREETYPE_MAJOR == 2) && (FREETYPE_MINOR == 3) && (FREETYPE_PATCH < 8)) -int FT_Get_Advance(FT_Face face, int gid, int masks, FT_Fixed *out) +int +FT_Get_Advance(FT_Face face, int gid, int masks, FT_Fixed *out) { int fterr; fterr = FT_Load_Glyph(face, gid, masks | FT_LOAD_IGNORE_TRANSFORM); @@ -28,14 +29,14 @@ typedef struct fz_textdevice_s fz_textdevice; struct fz_textdevice_s { fz_point point; - fz_textline *line; + fz_textspan *line; }; -fz_textline * -fz_newtextline(void) +fz_textspan * +fz_newtextspan(void) { - fz_textline *line; - line = fz_malloc(sizeof(fz_textline)); + fz_textspan *line; + line = fz_malloc(sizeof(fz_textspan)); line->len = 0; line->cap = 0; line->text = nil; @@ -44,16 +45,16 @@ fz_newtextline(void) } void -fz_freetextline(fz_textline *line) +fz_freetextspan(fz_textspan *line) { if (line->next) - fz_freetextline(line->next); + fz_freetextspan(line->next); fz_free(line->text); fz_free(line); } static void -fz_addtextchar(fz_textline *line, int x, int y, int c) +fz_addtextchar(fz_textspan *line, int x, int y, int c) { if (line->len + 1 >= line->cap) { @@ -67,7 +68,7 @@ fz_addtextchar(fz_textline *line, int x, int y, int c) } void -fz_debugtextline(fz_textline *line) +fz_debugtextspan(fz_textspan *line) { char buf[10]; int c, n, k, i; @@ -87,14 +88,13 @@ fz_debugtextline(fz_textline *line) putchar('\n'); if (line->next) - fz_debugtextline(line->next); + fz_debugtextspan(line->next); } static void -fz_textextractline(fz_textline **line, fz_text *text, fz_point *oldpt) +fz_textextractline(fz_textspan **line, fz_text *text, fz_matrix ctm, fz_point *oldpt) { fz_font *font = text->font; - fz_matrix ctm = text->ctm; fz_matrix tm = text->trm; fz_matrix inv = fz_invertmatrix(text->trm); fz_matrix trm; @@ -149,8 +149,8 @@ fz_textextractline(fz_textline **line, fz_text *text, fz_point *oldpt) if (fabs(dy) > 0.2) { - fz_textline *newline; - newline = fz_newtextline(); + fz_textspan *newline; + newline = fz_newtextspan(); (*line)->next = newline; *line = newline; } @@ -163,19 +163,30 @@ fz_textextractline(fz_textline **line, fz_text *text, fz_point *oldpt) } } -void fz_textfilltext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_textfilltext(void *user, fz_text *text, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { fz_textdevice *tdev = user; - fz_textextractline(&tdev->line, text, &tdev->point); + fz_textextractline(&tdev->line, text, ctm, &tdev->point); } -void fz_textignoretext(void *user, fz_text *text) +static void +fz_textignoretext(void *user, fz_text *text, fz_matrix ctm) { fz_textdevice *tdev = user; - fz_textextractline(&tdev->line, text, &tdev->point); + fz_textextractline(&tdev->line, text, ctm, &tdev->point); } -fz_device *fz_newtextdevice(fz_textline *root) +static void +fz_textfreeuser(void *user) +{ + fz_textdevice *tdev = user; + fz_free(tdev); +} + +fz_device * +fz_newtextdevice(fz_textspan *root) { fz_textdevice *tdev = fz_malloc(sizeof(fz_textdevice)); tdev->line = root; @@ -183,16 +194,8 @@ fz_device *fz_newtextdevice(fz_textline *root) tdev->point.y = -1; fz_device *dev = fz_newdevice(tdev); - + dev->freeuser = fz_textfreeuser; dev->filltext = fz_textfilltext; dev->ignoretext = fz_textignoretext; - return dev; } - -void fz_freetextdevice(fz_device *dev) -{ - fz_textdevice *tdev = dev->user; - fz_free(tdev); - fz_free(dev); -}
\ No newline at end of file diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c index f02aa035..834aee5c 100644 --- a/fitz/dev_trace.c +++ b/fitz/dev_trace.c @@ -1,12 +1,14 @@ #include "fitz.h" -static void fz_tracematrix(fz_matrix ctm) +static void +fz_tracematrix(fz_matrix ctm) { printf("%g %g %g %g %g %g setmatrix\n", ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f); } -static void fz_tracecolor(fz_colorspace *colorspace, float *color, float alpha) +static void +fz_tracecolor(fz_colorspace *colorspace, float *color, float alpha) { int i; printf("/%s setcolorspace\n", colorspace->name); @@ -16,22 +18,24 @@ static void fz_tracecolor(fz_colorspace *colorspace, float *color, float alpha) printf("%g setalpha\n", alpha); } -void fz_tracefillpath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_tracefillpath(void *user, fz_path *path, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { - fz_tracematrix(path->ctm); fz_printpath(path, 0); - if (path->winding == FZ_EVENODD) + if (path->evenodd) printf("eofill\n"); else printf("fill\n"); } -void fz_tracestrokepath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_tracestrokepath(void *user, fz_path *path, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { int i; fz_tracecolor(colorspace, color, alpha); - fz_tracematrix(path->ctm); printf("%g setlinewidth\n", path->linewidth); printf("%g setmiterlimit\n", path->miterlimit); @@ -51,18 +55,20 @@ void fz_tracestrokepath(void *user, fz_path *path, fz_colorspace *colorspace, fl printf("stroke\n"); } -void fz_traceclippath(void *user, fz_path *path) +static void +fz_traceclippath(void *user, fz_path *path, fz_matrix ctm) { printf("gsave\n"); - fz_tracematrix(path->ctm); fz_printpath(path, 0); - if (path->winding == FZ_EVENODD) + if (path->evenodd) printf("eoclip\n"); else printf("clip\n"); } -void fz_tracefilltext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_tracefilltext(void *user, fz_text *text, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { printf("/%s setfont\n", text->font->name); fz_tracematrix(text->trm); @@ -70,7 +76,9 @@ void fz_tracefilltext(void *user, fz_text *text, fz_colorspace *colorspace, floa printf("show\n"); } -void fz_tracestroketext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha) +static void +fz_tracestroketext(void *user, fz_text *text, fz_matrix ctm, + fz_colorspace *colorspace, float *color, float alpha) { printf("/%s setfont\n", text->font->name); fz_tracematrix(text->trm); @@ -78,7 +86,8 @@ void fz_tracestroketext(void *user, fz_text *text, fz_colorspace *colorspace, fl printf("charpath stroke\n"); } -void fz_tracecliptext(void *user, fz_text *text) +static void +fz_tracecliptext(void *user, fz_text *text, fz_matrix ctm) { printf("gsave\n"); printf("/%s setfont\n", text->font->name); @@ -87,7 +96,8 @@ void fz_tracecliptext(void *user, fz_text *text) printf("charpath clip\n"); } -void fz_traceignoretext(void *user, fz_text *text) +static void +fz_traceignoretext(void *user, fz_text *text, fz_matrix ctm) { printf("/%s setfont\n", text->font->name); fz_tracematrix(text->trm); @@ -95,29 +105,29 @@ void fz_traceignoretext(void *user, fz_text *text) printf("invisibletext\n"); } -void fz_tracedrawimage(void *user, fz_pixmap *image, fz_matrix ctm) +static void +fz_tracefillimage(void *user, fz_pixmap *image, fz_matrix ctm) { fz_tracematrix(ctm); - printf("drawimage\n"); + printf("fillimage\n"); } -void fz_tracedrawshade(void *user, fz_shade *shade, fz_matrix ctm) +static void +fz_tracefillshade(void *user, fz_shade *shade, fz_matrix ctm) { fz_tracematrix(ctm); - printf("drawshade\n"); + printf("fillshade\n"); } -void fz_tracepopclip(void *user) +static void +fz_tracepopclip(void *user) { printf("grestore\n"); } fz_device *fz_newtracedevice(void) { - fz_device *dev = fz_malloc(sizeof(fz_device)); - memset(dev, 0, sizeof(dev)); - - dev->user = nil; + fz_device *dev = fz_newdevice(nil); dev->fillpath = fz_tracefillpath; dev->strokepath = fz_tracestrokepath; @@ -128,8 +138,8 @@ fz_device *fz_newtracedevice(void) dev->cliptext = fz_tracecliptext; dev->ignoretext = fz_traceignoretext; - dev->drawimage = fz_tracedrawimage; - dev->drawshade = fz_tracedrawshade; + dev->fillshade = fz_tracefillshade; + dev->fillimage = fz_tracefillimage; dev->popclip = fz_tracepopclip; diff --git a/fitz/fitz_base.h b/fitz/fitz_base.h index edecefd1..52a93f0c 100644 --- a/fitz/fitz_base.h +++ b/fitz/fitz_base.h @@ -288,40 +288,5 @@ fz_irect fz_mergeirects(fz_irect a, fz_irect b); fz_point fz_transformpoint(fz_matrix m, fz_point p); fz_rect fz_transformaabb(fz_matrix m, fz_rect r); -/* - *TODO: move this into draw module - */ - -/* -pixmaps have n components per pixel. the first is always alpha. -premultiplied alpha when rendering, but non-premultiplied for colorspace -conversions and rescaling. -*/ - -typedef struct fz_pixmap_s fz_pixmap; -typedef struct fz_colorspace_s fz_colorspace; - -extern fz_colorspace *pdf_devicegray; -extern fz_colorspace *pdf_devicergb; -extern fz_colorspace *pdf_devicecmyk; -extern fz_colorspace *pdf_devicelab; -extern fz_colorspace *pdf_devicepattern; - -struct fz_pixmap_s -{ - int x, y, w, h, n; - fz_colorspace *colorspace; - unsigned char *samples; -}; - -fz_pixmap * fz_newpixmapwithrect(fz_colorspace *, fz_irect bbox); -fz_pixmap * fz_newpixmap(fz_colorspace *, int x, int y, int w, int h); - -void fz_debugpixmap(fz_pixmap *map, char *prefix); -void fz_clearpixmap(fz_pixmap *map, unsigned char value); -void fz_freepixmap(fz_pixmap *map); - -fz_pixmap * fz_scalepixmap(fz_pixmap *src, int xdenom, int ydenom); - #endif diff --git a/fitz/fitz_res.h b/fitz/fitz_res.h index 35416fda..2faf883a 100644 --- a/fitz/fitz_res.h +++ b/fitz/fitz_res.h @@ -1,121 +1,188 @@ /* - * + * Resources and other graphics related objects. */ +typedef struct fz_pixmap_s fz_pixmap; +typedef struct fz_colorspace_s fz_colorspace; typedef struct fz_path_s fz_path; typedef struct fz_text_s fz_text; typedef struct fz_font_s fz_font; typedef struct fz_shade_s fz_shade; +enum { FZ_MAXCOLORS = 32 }; + +typedef enum fz_blendkind_e +{ + /* PDF 1.4 -- standard separable */ + FZ_BNORMAL, + FZ_BMULTIPLY, + FZ_BSCREEN, + FZ_BOVERLAY, + FZ_BDARKEN, + FZ_BLIGHTEN, + FZ_BCOLORDODGE, + FZ_BCOLORBURN, + FZ_BHARDLIGHT, + FZ_BSOFTLIGHT, + FZ_BDIFFERENCE, + FZ_BEXCLUSION, + + /* PDF 1.4 -- standard non-separable */ + FZ_BHUE, + FZ_BSATURATION, + FZ_BCOLOR, + FZ_BLUMINOSITY +} fz_blendkind; + +/* +pixmaps have n components per pixel. the first is always alpha. +premultiplied alpha when rendering, but non-premultiplied for colorspace +conversions and rescaling. +*/ + +extern fz_colorspace *pdf_devicegray; +extern fz_colorspace *pdf_devicergb; +extern fz_colorspace *pdf_devicecmyk; +extern fz_colorspace *pdf_devicelab; +extern fz_colorspace *pdf_devicepattern; + +struct fz_pixmap_s +{ + int refs; + int x, y, w, h, n; + fz_colorspace *colorspace; + unsigned char *samples; +}; + +fz_pixmap * fz_newpixmapwithrect(fz_colorspace *, fz_irect bbox); +fz_pixmap * fz_newpixmap(fz_colorspace *, int x, int y, int w, int h); +fz_pixmap *fz_keeppixmap(fz_pixmap *map); +void fz_droppixmap(fz_pixmap *map); + +void fz_debugpixmap(fz_pixmap *map, char *prefix); +void fz_clearpixmap(fz_pixmap *map, unsigned char value); + +fz_pixmap * fz_scalepixmap(fz_pixmap *src, int xdenom, int ydenom); + +/* + * The device interface. + */ + typedef struct fz_device_s fz_device; struct fz_device_s { void *user; + void (*freeuser)(void *); - void (*fillpath)(void *, fz_path *, fz_colorspace *, float *color, float alpha); - void (*strokepath)(void *, fz_path *, fz_colorspace *, float *color, float alpha); - void (*clippath)(void *, fz_path *); + void (*fillpath)(void *, fz_path *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*strokepath)(void *, fz_path *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*clippath)(void *, fz_path *, fz_matrix); - void (*filltext)(void *, fz_text *, fz_colorspace *, float *color, float alpha); - void (*stroketext)(void *, fz_text *, fz_colorspace *, float *color, float alpha); - void (*cliptext)(void *, fz_text *); - void (*ignoretext)(void *, fz_text *); + void (*filltext)(void *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*stroketext)(void *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); + void (*cliptext)(void *, fz_text *, fz_matrix); + void (*ignoretext)(void *, fz_text *, fz_matrix); + void (*fillshade)(void *, fz_shade *shd, fz_matrix ctm); + void (*fillimage)(void *, fz_pixmap *img, fz_matrix ctm); void (*fillimagemask)(void *, fz_pixmap *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); void (*clipimagemask)(void *, fz_pixmap *img, fz_matrix ctm); - void (*drawimage)(void *, fz_pixmap *img, fz_matrix ctm); - void (*drawshade)(void *, fz_shade *shd, fz_matrix ctm); void (*popclip)(void *); }; -/* no-op device functions */ fz_device *fz_newdevice(void *user); -void fz_initnulldevice(fz_device *dev); -void fz_nullfillpath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha); -void fz_nullstrokepath(void *user, fz_path *path, fz_colorspace *colorspace, float *color, float alpha); -void fz_nullclippath(void *user, fz_path *path); -void fz_nullfilltext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha); -void fz_nullstroketext(void *user, fz_text *text, fz_colorspace *colorspace, float *color, float alpha); -void fz_nullcliptext(void *user, fz_text *text); -void fz_nullignoretext(void *user, fz_text *text); -void fz_nullpopclip(void *user); -void fz_nulldrawshade(void *user, fz_shade *shade, fz_matrix ctm); -void fz_nulldrawimage(void *user, fz_pixmap *image, fz_matrix ctm); -void fz_nullfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); -void fz_nullclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm); +void fz_freedevice(fz_device *dev); fz_device *fz_newtracedevice(void); fz_device *fz_newdrawdevice(fz_pixmap *dest); -void fz_freedrawdevice(fz_device *dev); -typedef struct fz_textline_s fz_textline; +/* Text extraction device */ + +typedef struct fz_textspan_s fz_textspan; typedef struct fz_textchar_s fz_textchar; struct fz_textchar_s { - int x, y; - int c; + int c, x, y, w; }; -struct fz_textline_s +struct fz_textspan_s { + int ascender, descender; int len, cap; fz_textchar *text; - fz_textline *next; + fz_textspan *next; }; -fz_textline * fz_newtextline(void); -void fz_freetextline(fz_textline *line); -void fz_debugtextline(fz_textline *line); +fz_textspan * fz_newtextspan(void); +void fz_freetextspan(fz_textspan *line); +void fz_debugtextspan(fz_textspan *line); -fz_device *fz_newtextdevice(fz_textline *text); -void fz_freetextdevice(fz_device *dev); +fz_device *fz_newtextdevice(fz_textspan *text); -typedef enum fz_blendkind_e +/* Display list device -- record and play back device commands. */ + +typedef struct fz_displaylist_s fz_displaylist; +typedef struct fz_displaynode_s fz_displaynode; + +typedef enum fz_displaycommand_e { - /* PDF 1.4 -- standard separable */ - FZ_BNORMAL, - FZ_BMULTIPLY, - FZ_BSCREEN, - FZ_BOVERLAY, - FZ_BDARKEN, - FZ_BLIGHTEN, - FZ_BCOLORDODGE, - FZ_BCOLORBURN, - FZ_BHARDLIGHT, - FZ_BSOFTLIGHT, - FZ_BDIFFERENCE, - FZ_BEXCLUSION, + FZ_CMDFILLPATH, + FZ_CMDSTROKEPATH, + FZ_CMDCLIPPATH, + FZ_CMDFILLTEXT, + FZ_CMDSTROKETEXT, + FZ_CMDCLIPTEXT, + FZ_CMDIGNORETEXT, + FZ_CMDFILLSHADE, + FZ_CMDFILLIMAGE, + FZ_CMDFILLIMAGEMASK, + FZ_CMDCLIPIMAGEMASK, + FZ_CMDPOPCLIP, +} fz_displaycommand; + +struct fz_displaylist_s +{ + fz_displaynode *first; + fz_displaynode *last; +}; - /* PDF 1.4 -- standard non-separable */ - FZ_BHUE, - FZ_BSATURATION, - FZ_BCOLOR, - FZ_BLUMINOSITY -} fz_blendkind; +struct fz_displaynode_s +{ + fz_displaycommand cmd; + fz_displaynode *next; + union { + fz_path *path; + fz_text *text; + fz_shade *shade; + fz_pixmap *image; + } item; + fz_matrix ctm; + fz_colorspace *colorspace; + float alpha; + float color[FZ_MAXCOLORS]; +}; + +fz_displaylist *fz_newdisplaylist(void); +void fz_freedisplaylist(fz_displaylist *list); +fz_device *fz_newlistdevice(fz_displaylist *list); +void fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix ctm); /* - * Vector paths. - * They can be stroked and dashed, or be filled. - * They have a fill rule (nonzero or evenodd). + * Vector path buffer. + * It can be stroked and dashed, or be filled. + * It has a fill rule (nonzero or evenodd). * * When rendering, they are flattened, stroked and dashed straight * into the Global Edge List. */ typedef struct fz_stroke_s fz_stroke; -typedef struct fz_dash_s fz_dash; typedef union fz_pathel_s fz_pathel; -typedef enum fz_pathwinding_e -{ - FZ_EVENODD, - FZ_NONZERO, -} fz_pathwinding; - typedef enum fz_pathelkind_e { FZ_MOVETO, @@ -132,8 +199,7 @@ union fz_pathel_s struct fz_path_s { - fz_matrix ctm; - fz_pathwinding winding; + int evenodd; int linecap; int linejoin; float linewidth; @@ -155,13 +221,12 @@ void fz_closepath(fz_path*); void fz_resetpath(fz_path *path); void fz_freepath(fz_path *path); -fz_rect fz_boundpath(fz_path *, int dostroke); +fz_path *fz_clonepath(fz_path *old); + +fz_rect fz_boundpath(fz_path *path, fz_matrix ctm, int dostroke); void fz_debugpath(fz_path *, int indent); void fz_printpath(fz_path *, int indent); -fz_dash *fz_newdash(float phase, int len, float *array); -void fz_freedash(fz_dash *dash); - /* * Text buffer. * @@ -187,7 +252,6 @@ struct fz_text_s { fz_font *font; fz_matrix trm; - fz_matrix ctm; int len, cap; fz_textel *els; }; @@ -199,14 +263,14 @@ void fz_resettext(fz_text *text); void fz_freetext(fz_text *text); void fz_debugtext(fz_text*, int indent); +fz_text *fz_clonetext(fz_text *old); + /* * Colorspace resources. * * TODO: use lcms */ -enum { FZ_MAXCOLORS = 32 }; - struct fz_colorspace_s { int refs; @@ -254,7 +318,7 @@ struct fz_font_s float *t3widths; /* has 256 entries if used */ void *t3xref; /* a pdf_xref for the callback */ fz_error (*t3runcontentstream)(fz_device *dev, fz_matrix ctm, - void *xref, fz_obj *resources, fz_buffer *contents); + struct pdf_xref_s *xref, fz_obj *resources, fz_buffer *contents); fz_rect bbox; }; diff --git a/fitz/res_font.c b/fitz/res_font.c index 817bc3eb..ea8eec98 100644 --- a/fitz/res_font.c +++ b/fitz/res_font.c @@ -372,7 +372,7 @@ fz_rendert3glyph(fz_glyph *glyph, fz_font *font, int gid, fz_matrix trm) static fz_pixmap *pixmap = nil; if (pixmap) { - fz_freepixmap(pixmap); + fz_droppixmap(pixmap); pixmap = nil; } @@ -393,7 +393,7 @@ fz_rendert3glyph(fz_glyph *glyph, fz_font *font, int gid, fz_matrix trm) error = font->t3runcontentstream(dev, ctm, font->t3xref, font->t3resources, contents); if (error) fz_catch(error, "cannot draw type3 glyph"); - fz_freedrawdevice(dev); + fz_freedevice(dev); glyph->x = pixmap->x; glyph->y = pixmap->y; diff --git a/fitz/res_path.c b/fitz/res_path.c index f096f4ef..a7de4da9 100644 --- a/fitz/res_path.c +++ b/fitz/res_path.c @@ -6,10 +6,9 @@ fz_newpath(void) fz_path *path; path = fz_malloc(sizeof(fz_path)); - path->ctm = fz_identity(); path->dashlen = 0; path->dashphase = 0; - path->winding = FZ_NONZERO; + path->evenodd = 0; path->linecap = 0; path->linejoin = 0; path->linewidth = 1.0; @@ -21,6 +20,22 @@ fz_newpath(void) return path; } +fz_path * +fz_clonepath(fz_path *old) +{ + fz_path *path; + + path = fz_malloc(sizeof(fz_path)); + memcpy(path, old, sizeof(fz_path)); + + path->len = old->len; + path->cap = path->len; + path->els = fz_malloc(path->cap * sizeof(fz_pathel)); + memcpy(path->els, old->els, sizeof(fz_pathel) * path->len); + + return path; +} + void fz_freepath(fz_path *path) { @@ -31,10 +46,9 @@ fz_freepath(fz_path *path) void fz_resetpath(fz_path *path) { - path->ctm = fz_identity(); path->dashlen = 0; path->dashphase = 0; - path->winding = FZ_NONZERO; + path->evenodd = 0; path->linecap = 0; path->linejoin = 0; path->linewidth = 1.0; @@ -123,7 +137,7 @@ static inline fz_rect boundexpand(fz_rect r, fz_point p) } fz_rect -fz_boundpath(fz_path *path, int dostroke) +fz_boundpath(fz_path *path, fz_matrix ctm, int dostroke) { fz_point p; fz_rect r = fz_emptyrect; @@ -133,7 +147,7 @@ fz_boundpath(fz_path *path, int dostroke) { p.x = path->els[1].v; p.y = path->els[2].v; - p = fz_transformpoint(path->ctm, p); + p = fz_transformpoint(ctm, p); r.x0 = r.x1 = p.x; r.y0 = r.y1 = p.y; } @@ -145,15 +159,15 @@ fz_boundpath(fz_path *path, int dostroke) case FZ_CURVETO: p.x = path->els[i++].v; p.y = path->els[i++].v; - r = boundexpand(r, fz_transformpoint(path->ctm, p)); + r = boundexpand(r, fz_transformpoint(ctm, p)); p.x = path->els[i++].v; p.y = path->els[i++].v; - r = boundexpand(r, fz_transformpoint(path->ctm, p)); + r = boundexpand(r, fz_transformpoint(ctm, p)); case FZ_MOVETO: case FZ_LINETO: p.x = path->els[i++].v; p.y = path->els[i++].v; - r = boundexpand(r, fz_transformpoint(path->ctm, p)); + r = boundexpand(r, fz_transformpoint(ctm, p)); break; case FZ_CLOSEPATH: break; diff --git a/fitz/res_text.c b/fitz/res_text.c index a21cb3fc..798bd8a5 100644 --- a/fitz/res_text.c +++ b/fitz/res_text.c @@ -8,7 +8,6 @@ fz_newtext(fz_font *font) text = fz_malloc(sizeof(fz_text)); text->font = fz_keepfont(font); text->trm = fz_identity(); - text->ctm = fz_identity(); text->len = 0; text->cap = 0; text->els = nil; @@ -24,6 +23,22 @@ fz_freetext(fz_text *text) fz_free(text); } +fz_text * +fz_clonetext(fz_text *old) +{ + fz_text *text; + + text = fz_malloc(sizeof(fz_text)); + text->font = fz_keepfont(old->font); + text->trm = old->trm; + text->len = old->len; + text->cap = text->len; + text->els = fz_malloc(text->len * sizeof(fz_textel)); + memcpy(text->els, old->els, text->len * sizeof(fz_textel)); + + return text; +} + fz_rect fz_boundtext(fz_text *text, fz_matrix ctm) { diff --git a/mupdf/pdf_build.c b/mupdf/pdf_build.c index 445541dd..c3013855 100644 --- a/mupdf/pdf_build.c +++ b/mupdf/pdf_build.c @@ -250,7 +250,7 @@ void pdf_showshade(pdf_csi *csi, fz_shade *shd) { pdf_gstate *gstate = csi->gstate + csi->gtop; - csi->dev->drawshade(csi->dev->user, shd, gstate->ctm); + csi->dev->fillshade(csi->dev->user, shd, gstate->ctm); } void @@ -261,7 +261,7 @@ pdf_showimage(pdf_csi *csi, pdf_xref *xref, pdf_image *image) fz_error error = pdf_loadtile(image, tile); if (error) { - fz_freepixmap(tile); + fz_droppixmap(tile); fz_catch(error, "cannot load image data"); return; } @@ -273,7 +273,7 @@ pdf_showimage(pdf_csi *csi, pdf_xref *xref, pdf_image *image) if (error) fz_catch(error, "cannot load image mask data"); csi->dev->clipimagemask(csi->dev->user, mask, gstate->ctm); - fz_freepixmap(mask); + fz_droppixmap(mask); } if (image->n == 0 && image->a == 1) @@ -302,20 +302,20 @@ pdf_showimage(pdf_csi *csi, pdf_xref *xref, pdf_image *image) break; case PDF_MSHADE: csi->dev->clipimagemask(csi->dev->user, tile, gstate->ctm); - csi->dev->drawshade(csi->dev->user, gstate->fill.shade, gstate->ctm); + csi->dev->fillshade(csi->dev->user, gstate->fill.shade, gstate->ctm); csi->dev->popclip(csi->dev->user); break; } } else { - csi->dev->drawimage(csi->dev->user, tile, gstate->ctm); + csi->dev->fillimage(csi->dev->user, tile, gstate->ctm); } if (image->mask) csi->dev->popclip(csi->dev->user); - fz_freepixmap(tile); + fz_droppixmap(tile); } void @@ -328,8 +328,7 @@ pdf_showpath(pdf_csi *csi, pdf_xref *xref, int doclose, int dofill, int dostroke if (doclose) fz_closepath(csi->path); - csi->path->ctm = gstate->ctm; - csi->path->winding = evenodd ? FZ_EVENODD : FZ_NONZERO; + csi->path->evenodd = evenodd; csi->path->linewidth = gstate->linewidth; csi->path->linecap = gstate->linecap; csi->path->linejoin = gstate->linejoin; @@ -342,7 +341,7 @@ pdf_showpath(pdf_csi *csi, pdf_xref *xref, int doclose, int dofill, int dostroke if (csi->clip) { gstate->clipdepth++; - csi->dev->clippath(csi->dev->user, csi->path); + csi->dev->clippath(csi->dev->user, csi->path, gstate->ctm); csi->clip = 0; } @@ -355,18 +354,18 @@ pdf_showpath(pdf_csi *csi, pdf_xref *xref, int doclose, int dofill, int dostroke case PDF_MCOLOR: case PDF_MINDEXED: case PDF_MLAB: - csi->dev->fillpath(csi->dev->user, csi->path, + csi->dev->fillpath(csi->dev->user, csi->path, gstate->ctm, gstate->fill.cs, gstate->fill.v, gstate->fill.alpha); break; case PDF_MPATTERN: - bbox = fz_boundpath(csi->path, 0); - csi->dev->clippath(csi->dev->user, csi->path); + bbox = fz_boundpath(csi->path, gstate->ctm, 0); + csi->dev->clippath(csi->dev->user, csi->path, gstate->ctm); pdf_showpattern(csi, gstate->fill.pattern, xref, bbox, PDF_MFILL); csi->dev->popclip(csi->dev->user); break; case PDF_MSHADE: - csi->dev->clippath(csi->dev->user, csi->path); - csi->dev->drawshade(csi->dev->user, gstate->fill.shade, gstate->ctm); + csi->dev->clippath(csi->dev->user, csi->path, gstate->ctm); + csi->dev->fillshade(csi->dev->user, gstate->fill.shade, gstate->ctm); csi->dev->popclip(csi->dev->user); break; } @@ -381,7 +380,7 @@ pdf_showpath(pdf_csi *csi, pdf_xref *xref, int doclose, int dofill, int dostroke case PDF_MCOLOR: case PDF_MINDEXED: case PDF_MLAB: - csi->dev->strokepath(csi->dev->user, csi->path, + csi->dev->strokepath(csi->dev->user, csi->path, gstate->ctm, gstate->stroke.cs, gstate->stroke.v, gstate->stroke.alpha); break; case PDF_MPATTERN: @@ -412,8 +411,6 @@ pdf_flushtext(pdf_csi *csi) if (!csi->text) return; - csi->text->ctm = gstate->ctm; - switch (csi->textmode) { case 0: @@ -448,12 +445,12 @@ pdf_flushtext(pdf_csi *csi) } if (doinvisible) - csi->dev->ignoretext(csi->dev->user, csi->text); + csi->dev->ignoretext(csi->dev->user, csi->text, gstate->ctm); if (doclip) { gstate->clipdepth++; - csi->dev->cliptext(csi->dev->user, csi->text); + csi->dev->cliptext(csi->dev->user, csi->text, gstate->ctm); } if (dofill) @@ -465,7 +462,7 @@ pdf_flushtext(pdf_csi *csi) case PDF_MCOLOR: case PDF_MINDEXED: case PDF_MLAB: - csi->dev->filltext(csi->dev->user, csi->text, + csi->dev->filltext(csi->dev->user, csi->text, gstate->ctm, gstate->fill.cs, gstate->fill.v, gstate->fill.alpha); break; case PDF_MPATTERN: @@ -486,7 +483,7 @@ pdf_flushtext(pdf_csi *csi) case PDF_MCOLOR: case PDF_MINDEXED: case PDF_MLAB: - csi->dev->stroketext(csi->dev->user, csi->text, + csi->dev->stroketext(csi->dev->user, csi->text, gstate->ctm, gstate->stroke.cs, gstate->stroke.v, gstate->stroke.alpha); break; case PDF_MPATTERN: diff --git a/mupdf/pdf_image.c b/mupdf/pdf_image.c index 00a9ee30..0b1dca7e 100644 --- a/mupdf/pdf_image.c +++ b/mupdf/pdf_image.c @@ -553,7 +553,7 @@ pdf_loadtile(pdf_image *src, fz_pixmap *tile) if (src->usecolorkey) maskcolorkeyindexed(tmp, tile, src->colorkey); - fz_freepixmap(tmp); + fz_droppixmap(tmp); } else |