diff options
-rw-r--r-- | Jamfile | 4 | ||||
-rw-r--r-- | include/fitz.h | 4 | ||||
-rw-r--r-- | include/fitz/image.h | 10 | ||||
-rw-r--r-- | include/fitz/scanconv.h | 2 | ||||
-rw-r--r-- | include/fitz/tree.h | 11 | ||||
-rw-r--r-- | mupdf/build.c | 58 | ||||
-rw-r--r-- | mupdf/colorspace.c | 6 | ||||
-rw-r--r-- | mupdf/font.c | 1 | ||||
-rw-r--r-- | mupdf/image.c | 54 | ||||
-rw-r--r-- | mupdf/interpret.c | 131 | ||||
-rw-r--r-- | mupdf/open.c | 3 | ||||
-rw-r--r-- | mupdf/page.c | 22 | ||||
-rw-r--r-- | mupdf/repair.c | 3 | ||||
-rw-r--r-- | mupdf/resources.c | 376 | ||||
-rw-r--r-- | mupdf/xref.c | 3 | ||||
-rw-r--r-- | render/render.c | 14 | ||||
-rw-r--r-- | render/renderimage.c | 59 | ||||
-rw-r--r-- | render/renderpath.c | 53 | ||||
-rw-r--r-- | render/rendertext.c | 8 | ||||
-rw-r--r-- | render/scanconv.c | 30 | ||||
-rw-r--r-- | test/pdfrip.c | 15 | ||||
-rw-r--r-- | tree/debug.c | 5 | ||||
-rw-r--r-- | tree/font.c | 1 | ||||
-rw-r--r-- | tree/node2.c | 24 | ||||
-rw-r--r-- | tree/text.c | 64 |
25 files changed, 740 insertions, 221 deletions
@@ -82,8 +82,9 @@ Library libfitz : render/fill.c render/stroke.c render/render.c - render/renderpath.c render/rendertext.c + render/renderpath.c + render/renderimage.c ; Library libmupdf : @@ -103,6 +104,7 @@ Library libmupdf : mupdf/font.c mupdf/fontfile.c mupdf/colorspace.c + mupdf/image.c mupdf/resources.c mupdf/page.c mupdf/pagetree.c diff --git a/include/fitz.h b/include/fitz.h index 85ac8118..48754391 100644 --- a/include/fitz.h +++ b/include/fitz.h @@ -18,13 +18,15 @@ #include "fitz/cmap.h" #include "fitz/font.h" + #include "fitz/colorspace.h" +#include "fitz/pixmap.h" +#include "fitz/image.h" #include "fitz/tree.h" #include "fitz/path.h" #include "fitz/text.h" -#include "fitz/pixmap.h" #include "fitz/scanconv.h" #include "fitz/render.h" diff --git a/include/fitz/image.h b/include/fitz/image.h new file mode 100644 index 00000000..0ff954c5 --- /dev/null +++ b/include/fitz/image.h @@ -0,0 +1,10 @@ +typedef struct fz_image_s fz_image; + +struct fz_image_s +{ + fz_error* (*loadtile)(fz_image*,fz_pixmap*); + void (*free)(fz_image*); + fz_colorspace *cs; + int w, h, n, a; +}; + diff --git a/include/fitz/scanconv.h b/include/fitz/scanconv.h index 794b9ba2..057153c4 100644 --- a/include/fitz/scanconv.h +++ b/include/fitz/scanconv.h @@ -39,7 +39,7 @@ void fz_advanceael(fz_ael *ael); void fz_freeael(fz_ael *ael); fz_error *fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, int y0, int y1, - void (*blitfunc)(int,int,int,short*,void*), void *blitdata); + void (*blitfunc)(int,int,int,unsigned char*,void*), void *blitdata); fz_error *fz_fillpath(fz_gel *gel, fz_pathnode *path, fz_matrix ctm, float flatness); fz_error *fz_strokepath(fz_gel *gel, fz_pathnode *path, fz_matrix ctm, float flatness); diff --git a/include/fitz/tree.h b/include/fitz/tree.h index 6578ab51..7181ac9b 100644 --- a/include/fitz/tree.h +++ b/include/fitz/tree.h @@ -125,15 +125,14 @@ struct fz_linknode_s struct fz_metanode_s { fz_node super; - fz_obj *info; + fz_obj *name; + fz_obj *dict; }; struct fz_imagenode_s { fz_node super; - fz_colorspace *cs; - int w, h, n, a; - // XXX fz_image *image; + fz_image *image; }; /* common to all nodes */ @@ -142,7 +141,7 @@ fz_rect fz_boundnode(fz_node *node, fz_matrix ctm); void fz_freenode(fz_node *node); /* branch nodes */ -fz_error *fz_newmetanode(fz_node **nodep, fz_obj *info); +fz_error *fz_newmetanode(fz_node **nodep, fz_obj *name, fz_obj *dict); fz_error *fz_newovernode(fz_node **nodep); fz_error *fz_newmasknode(fz_node **nodep); fz_error *fz_newblendnode(fz_node **nodep, fz_colorspace *cs, fz_blendkind b, int k, int i); @@ -157,7 +156,7 @@ int fz_ismetanode(fz_node *node); /* leaf nodes */ fz_error *fz_newlinknode(fz_node **nodep, fz_tree *subtree); fz_error *fz_newcolornode(fz_node **nodep, fz_colorspace *cs, int n, float *v); -fz_error *fz_newimagenode(fz_node **nodep, fz_colorspace *cs, int w, int h, int n, int a); +fz_error *fz_newimagenode(fz_node **nodep, fz_image *image); int fz_islinknode(fz_node *node); int fz_iscolornode(fz_node *node); diff --git a/mupdf/build.c b/mupdf/build.c index 5747b962..d235c9bc 100644 --- a/mupdf/build.c +++ b/mupdf/build.c @@ -1,8 +1,6 @@ #include <fitz.h> #include <mupdf.h> -extern int FT_Get_Char_Index(void*, int); - void pdf_initgstate(pdf_gstate *gs) { @@ -137,6 +135,62 @@ pdf_addtransform(pdf_gstate *gs, fz_node *transform) return nil; } +#if 0 + +BMC ... EMC object nesting can be completely fucked up +and out of sync with graphics object nesting. + +fz_error * +pdf_beginmarkedcontent(pdf_gstate *gs, fz_node *meta) +{ + fz_error *error; + fz_node *over; + + error = fz_newovernode(&over); + if (error) return error; + + fz_insertnode(gs->head, meta); + fz_insertnode(meta, over); + gs->head = over; + +printf("begin mc meta=%p over=%p\n", meta, over); +{ +fz_node *node = gs->head; + while (node) + { +printf(" node=%p ismeta=%d\n", node, fz_ismetanode(node)); + node = node->parent; + } +printf("okay.\n"); +} + + return nil; +} + +fz_error * +pdf_endmarkedcontent(pdf_gstate *gs) +{ + fz_node *node = gs->head; + +printf("end mc\n"); +printf(" node=%p ismeta=%d\n", node, fz_ismetanode(node)); + + while (node && !fz_ismetanode(node)) + { +printf(" node=%p ismeta=%d\n", node, fz_ismetanode(node)); + node = node->parent; + } + + if (node == nil) + return fz_throw("syntaxerror: unbalanced marked content"); + + gs->head = node->parent; + + return nil; +} + +#endif + fz_error * pdf_showpath(pdf_csi *csi, int doclose, int dofill, int dostroke, int evenodd) diff --git a/mupdf/colorspace.c b/mupdf/colorspace.c index 05a4535c..3511dc91 100644 --- a/mupdf/colorspace.c +++ b/mupdf/colorspace.c @@ -530,6 +530,12 @@ printf("\n"); { return loadiccbased(csp, xref, fz_arrayget(obj, 1)); } + + if (!strcmp(fz_toname(name), "Separation")) + { + *csp = pdf_devicegray; + return nil; + } } } diff --git a/mupdf/font.c b/mupdf/font.c index c7ff3eb9..562eb5ba 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -94,6 +94,7 @@ ftrender(fz_glyph *glyph, fz_font *fzfont, int cid, fz_matrix trm) FT_Set_Transform(face, &m, &v); fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); + //fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP); if (fterr) return fz_throw("freetype failed to load glyph: 0x%x", fterr); diff --git a/mupdf/image.c b/mupdf/image.c new file mode 100644 index 00000000..00e6171b --- /dev/null +++ b/mupdf/image.c @@ -0,0 +1,54 @@ +#include <fitz.h> +#include <mupdf.h> + +static fz_error *loadtile(fz_image *fzimg, fz_pixmap *tile) +{ + return nil; +} + +fz_error * +pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict) +{ + fz_error *error; + pdf_image *img; + fz_colorspace *cs; + int ismask; + fz_obj *obj; + + img = fz_malloc(sizeof(pdf_image)); + if (!img) + return fz_outofmem; + + img->super.loadtile = loadtile; + img->super.free = nil; + img->super.cs = nil; + + img->super.w = fz_toint(fz_dictgets(dict, "Width")); + img->super.h = fz_toint(fz_dictgets(dict, "Height")); + img->bpc = fz_toint(fz_dictgets(dict, "BitsPerComponent")); + + cs = nil; + obj = fz_dictgets(dict, "ColorSpace"); + if (obj) + error = pdf_loadcolorspace(&cs, xref, obj); + + ismask = fz_tobool(fz_dictgets(dict, "ImageMask")); + + if (!ismask) + { + img->super.cs = cs; + img->super.n = cs->n; + img->super.a = 0; + } + else + { + img->super.cs = nil; + img->super.n = 0; + img->super.a = 1; + } + + *imgp = img; + + return nil; +} + diff --git a/mupdf/interpret.c b/mupdf/interpret.c index fdf367b5..f9179792 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -1,20 +1,6 @@ #include <fitz.h> #include <mupdf.h> -void pdf_initgstate(pdf_gstate *gs); - -fz_error *pdf_buildstrokepath(pdf_gstate *gs, fz_pathnode *path); -fz_error *pdf_buildfillpath(pdf_gstate *gs, fz_pathnode *path, int evenodd); - -fz_error *pdf_addfillshape(pdf_gstate *gs, fz_node *shape); -fz_error *pdf_addstrokeshape(pdf_gstate *gs, fz_node *shape); -fz_error *pdf_addclipmask(pdf_gstate *gs, fz_node *shape); -fz_error *pdf_addtransform(pdf_gstate *gs, fz_node *transform); - -fz_error *pdf_showpath(pdf_csi *, int doclose, int dofill, int dostroke, int evenodd); -fz_error *pdf_showtext(pdf_csi *, fz_obj *text); -fz_error *pdf_flushtext(pdf_csi *); - fz_error * pdf_newcsi(pdf_csi **csip) { @@ -51,8 +37,8 @@ pdf_newcsi(pdf_csi **csip) csi->tree->root = node; csi->gstate[0].head = node; - error = fz_newcolornode(&node, pdf_devicegray, 1, &white); - fz_insertnode(csi->tree->root, node); +// error = fz_newcolornode(&node, pdf_devicegray, 1, &white); +// fz_insertnode(csi->tree->root, node); csi->clip = nil; @@ -83,9 +69,8 @@ pdf_freecsi(pdf_csi *csi) } static fz_error * -runextgstate(pdf_gstate *gstate, pdf_resources *rdb, fz_obj *extgstate) +runextgstate(pdf_gstate *gstate, pdf_xref *xref, fz_obj *extgstate) { - char name[64]; int i, k; for (i = 0; i < fz_dictlen(extgstate); i++) @@ -98,13 +83,9 @@ runextgstate(pdf_gstate *gstate, pdf_resources *rdb, fz_obj *extgstate) { if (fz_isarray(val) && fz_arraylen(val) == 2) { - fz_obj *ref, *obj; - ref = fz_arrayget(val, 0); - sprintf(name, "$f.%d.%d", fz_tonum(ref), fz_togen(ref)); - obj = fz_dictgets(rdb->font, name); - if (!obj) - return fz_throw("syntaxerror: missing resource"); - gstate->font = fz_topointer(obj); + gstate->font = pdf_findresource(xref->rfont, fz_arrayget(val, 0)); + if (!gstate->font) + return fz_throw("syntaxerror: missing font resource"); gstate->size = fz_toreal(fz_arrayget(val, 1)); } else @@ -139,7 +120,7 @@ runextgstate(pdf_gstate *gstate, pdf_resources *rdb, fz_obj *extgstate) } static fz_error * -runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) +runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) { pdf_gstate *gstate = csi->gstate + csi->gtop; fz_error *error; @@ -169,7 +150,7 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) fz_node *meta; if (csi->top != 1) goto syntaxerror; - error = fz_newmetanode(&meta, csi->stack[0]); + error = fz_newmetanode(&meta, csi->stack[0], nil); if (error) return error; fz_insertnode(gstate->head, meta); } @@ -177,18 +158,43 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) else if (!strcmp(buf, "DP")) { fz_node *meta; - fz_obj *info; if (csi->top != 2) goto syntaxerror; - error = fz_packobj(&info, "<< %o %o >>", - csi->stack[0], csi->stack[1]); + error = fz_newmetanode(&meta, csi->stack[0], csi->stack[1]); if (error) return error; - error = fz_newmetanode(&meta, info); - fz_dropobj(info); + fz_insertnode(gstate->head, meta); + } + + else if (!strcmp(buf, "BMC")) + { + fz_node *meta; + if (csi->top != 1) + goto syntaxerror; + error = fz_newmetanode(&meta, csi->stack[0], nil); if (error) return error; + // error = pdf_beginmarkedcontent(gstate, meta); + // if (error) { fz_freenode(meta); return error; }; fz_insertnode(gstate->head, meta); } + else if (!strcmp(buf, "BDC")) + { + fz_node *meta; + if (csi->top != 2) + goto syntaxerror; + error = fz_newmetanode(&meta, csi->stack[0], csi->stack[1]); + if (error) return error; + // error = pdf_beginmarkedcontent(gstate, meta); + // if (error) { fz_freenode(meta); return error; }; + fz_insertnode(gstate->head, meta); + } + + else if (!strcmp(buf, "EMC")) + { + // error = pdf_endmarkedcontent(gstate); + // if (error) return error; + } + else if (!strcmp(buf, "cm")) { fz_matrix m; @@ -218,16 +224,21 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) else if (!strcmp(buf, "gs")) { + fz_obj *dict; fz_obj *obj; if (csi->top != 1) goto syntaxerror; - obj = fz_dictget(rdb->extgstate, csi->stack[0]); + dict = fz_dictgets(rdb, "ExtGState"); + if (!dict) + return fz_throw("syntaxerror: missing extgstate resource"); + + obj = fz_dictget(dict, csi->stack[0]); if (!obj) - return fz_throw("syntaxerror: missing resource"); - - runextgstate(gstate, rdb, obj); + return fz_throw("syntaxerror: missing extgstate resource"); + + runextgstate(gstate, xref, obj); } else if (!strcmp(buf, "re")) @@ -286,6 +297,7 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) else if (!strcmp(buf, "cs")) { + fz_obj *dict; fz_obj *obj; if (csi->top != 1) @@ -301,15 +313,24 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) gstate->fillcs = pdf_devicecmyk; else { - obj = fz_dictget(rdb->colorspace, obj); + dict = fz_dictgets(rdb, "ColorSpace"); + if (!dict) + return fz_throw("syntaxerror: missing colorspace resource"); + obj = fz_dictget(dict, obj); if (!obj) - return fz_throw("syntaxerror: missing resource"); - gstate->fillcs = fz_topointer(obj); + return fz_throw("syntaxerror: missing colorspace resource"); + if (fz_isindirect(obj)) + gstate->fillcs = pdf_findresource(xref->rcolorspace, obj); + else + return fz_throw("syntaxerror: inline colorspace in dict"); + if (!gstate->fillcs) + return fz_throw("syntaxerror: missing colorspace resource"); } } else if (!strcmp(buf, "CS")) { + fz_obj *dict; fz_obj *obj; if (csi->top != 1) @@ -325,10 +346,18 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) gstate->strokecs = pdf_devicecmyk; else { - obj = fz_dictget(rdb->colorspace, obj); + dict = fz_dictgets(rdb, "ColorSpace"); + if (!dict) + return fz_throw("syntaxerror: missing colorspace resource"); + obj = fz_dictget(dict, obj); if (!obj) - return fz_throw("syntaxerror: missing resource"); - gstate->strokecs = fz_topointer(obj); + return fz_throw("syntaxerror: missing colorspace resource"); + if (fz_isindirect(obj)) + gstate->strokecs = pdf_findresource(xref->rcolorspace, obj); + else + return fz_throw("syntaxerror: inline colorspace in dict"); + if (!gstate->strokecs) + return fz_throw("syntaxerror: missing colorspace resource"); } } @@ -419,16 +448,24 @@ runkeyword(pdf_csi *csi, pdf_resources *rdb, char *buf) else if (!strcmp(buf, "Tf")) { + fz_obj *dict; fz_obj *obj; if (csi->top != 2) goto syntaxerror; - obj = fz_dictget(rdb->font, csi->stack[0]); + dict = fz_dictgets(rdb, "Font"); + if (!dict) + return fz_throw("syntaxerror: missing font resource"); + + obj = fz_dictget(dict, csi->stack[0]); if (!obj) - return fz_throw("syntaxerror: missing resource"); + return fz_throw("syntaxerror: missing font resource"); + + gstate->font = pdf_findresource(xref->rfont, obj); + if (!gstate->font) + return fz_throw("syntaxerror: missing font resource"); - gstate->font = fz_topointer(obj); gstate->size = fz_toreal(csi->stack[1]); } @@ -754,7 +791,7 @@ syntaxerror: } fz_error * -pdf_runcsi(pdf_csi *csi, pdf_resources *rdb, fz_file *file) +pdf_runcsi(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_file *file) { fz_error *error; unsigned char buf[65536]; @@ -835,7 +872,7 @@ pdf_runcsi(pdf_csi *csi, pdf_resources *rdb, fz_file *file) break; case PDF_TKEYWORD: - error = runkeyword(csi, rdb, buf); + error = runkeyword(csi, xref, rdb, buf); if (error) return error; clearstack(csi); break; diff --git a/mupdf/open.c b/mupdf/open.c index 529872a8..19320d43 100644 --- a/mupdf/open.c +++ b/mupdf/open.c @@ -460,9 +460,10 @@ pdf_openpdf(pdf_xref **xrefp, char *filename) unsigned char buf[65536]; /* yeowch! */ - xref = fz_malloc(sizeof (pdf_xref)); + xref = fz_malloc(sizeof(pdf_xref)); if (!xref) return fz_outofmem; + memset(xref, 0, sizeof(pdf_xref)); xref->file = nil; xref->version = 1.0; diff --git a/mupdf/page.c b/mupdf/page.c index 4450ae8d..48e8af77 100644 --- a/mupdf/page.c +++ b/mupdf/page.c @@ -2,7 +2,7 @@ #include <mupdf.h> static fz_error * -runcsi(pdf_xref *xref, pdf_csi *csi, pdf_resources *rdb, fz_obj *stmref) +runcsi(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_obj *stmref) { fz_error *error; @@ -10,7 +10,7 @@ runcsi(pdf_xref *xref, pdf_csi *csi, pdf_resources *rdb, fz_obj *stmref) if (error) return error; - error = pdf_runcsi(csi, rdb, xref->stream); + error = pdf_runcsi(csi, xref, rdb, xref->stream); pdf_closestream(xref); @@ -18,7 +18,7 @@ runcsi(pdf_xref *xref, pdf_csi *csi, pdf_resources *rdb, fz_obj *stmref) } static fz_error * -loadpagecontents(fz_tree **treep, pdf_xref *xref, pdf_resources *rdb, fz_obj *ref) +loadpagecontents(fz_tree **treep, pdf_xref *xref, fz_obj *rdb, fz_obj *ref) { fz_error *error; fz_obj *obj; @@ -39,7 +39,7 @@ loadpagecontents(fz_tree **treep, pdf_xref *xref, pdf_resources *rdb, fz_obj *re { for (i = 0; i < fz_arraylen(obj); i++) { - error = runcsi(xref, csi, rdb, fz_arrayget(obj, i)); + error = runcsi(csi, xref, rdb, fz_arrayget(obj, i)); if (error) { fz_dropobj(obj); goto cleanup; @@ -48,7 +48,7 @@ loadpagecontents(fz_tree **treep, pdf_xref *xref, pdf_resources *rdb, fz_obj *re } else { - error = runcsi(xref, csi, rdb, ref); + error = runcsi(csi, xref, rdb, ref); if (error) { fz_dropobj(obj); goto cleanup; @@ -62,7 +62,7 @@ loadpagecontents(fz_tree **treep, pdf_xref *xref, pdf_resources *rdb, fz_obj *re { for (i = 0; i < fz_arraylen(ref); i++) { - error = runcsi(xref, csi, rdb, fz_arrayget(ref, i)); + error = runcsi(csi, xref, rdb, fz_arrayget(ref, i)); if (error) goto cleanup; } @@ -83,7 +83,7 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) fz_error *error; fz_obj *obj; pdf_page *page; - pdf_resources *rdb; + fz_obj *rdb; fz_tree *tree; fz_rect bbox; int rotate; @@ -123,7 +123,7 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) error = loadpagecontents(&tree, xref, rdb, obj); if (error) { - pdf_freeresources(rdb); + fz_dropobj(rdb); return error; } @@ -134,7 +134,7 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) page = *pagep = fz_malloc(sizeof(pdf_page)); if (!page) { fz_droptree(tree); - pdf_freeresources(rdb); + fz_dropobj(rdb); return fz_outofmem; } @@ -143,7 +143,7 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) page->mediabox.max.x = MAX(bbox.min.x, bbox.max.x); page->mediabox.max.y = MAX(bbox.min.y, bbox.max.y); page->rotate = rotate; - page->rdb = rdb; + page->resources = rdb; page->tree = tree; return nil; @@ -152,7 +152,7 @@ pdf_loadpage(pdf_page **pagep, pdf_xref *xref, fz_obj *dict) void pdf_freepage(pdf_page *page) { - pdf_freeresources(page->rdb); + fz_dropobj(page->resources); fz_droptree(page->tree); fz_free(page); } diff --git a/mupdf/repair.c b/mupdf/repair.c index 8742d15f..5f4a139e 100644 --- a/mupdf/repair.c +++ b/mupdf/repair.c @@ -124,9 +124,10 @@ pdf_repairpdf(pdf_xref **xrefp, char *filename) int next; int i; - xref = fz_malloc(sizeof (pdf_xref)); + xref = fz_malloc(sizeof(pdf_xref)); if (!xref) return fz_outofmem; + memset(xref, 0, sizeof(pdf_xref)); xref->file = nil; xref->version = 0.0; diff --git a/mupdf/resources.c b/mupdf/resources.c index ef2515a2..f859566f 100644 --- a/mupdf/resources.c +++ b/mupdf/resources.c @@ -1,126 +1,348 @@ #include <fitz.h> #include <mupdf.h> +void * +pdf_findresource(pdf_rsrc *rsrc, fz_obj *ref) +{ + while (rsrc) + { + if (rsrc->oid == fz_tonum(ref) && rsrc->gen == fz_togen(ref)) + return rsrc->val; + rsrc = rsrc->next; + } + return nil; +} + +/* +Load resources: + +Go through resource dictionary and resolve some levels of +indirect references so we end up with a stylized structure: + +<< + /Font << + /F0 1 0 R + /F1 2 0 R + /F2 3 0 R + >> + /ExtGState << + /Gs0 << ... /Font 1 0 R ... >> + /Gs1 << ... >> + >> + /ColorSpace << + /Cs0 5 0 R + /Cs1 [ /ICCBased 5 0 R ] % /Cs1 -1 0 R ??? + /Cs2 [ /CalRGB << ... >> ] % /Cs2 -2 0 R ??? + >> + /XObject << + /Im0 10 0 R + /Fm0 11 0 R + >> +>> + +Then all references to actual resources will get +parsed and inserted into the pdf_xref resource +lists, indexed by their object number. + +TODO: inline colorspaces -> fake objects || refcount ? +TODO: inline images -> fake objects || refcount? + +*/ + static fz_error * -loadextgstatefonts(pdf_resources *rdb, pdf_xref *xref) +preloadcolorspace(pdf_xref *xref, fz_obj *ref) { - fz_error *err; - char name[64]; - pdf_font *font; - fz_obj *extgstate; + fz_error *error; + fz_colorspace *colorspace; + pdf_rsrc *rsrc; fz_obj *obj; - fz_obj *ptr; - fz_obj *ref; - int i; - for (i = 0; i < fz_dictlen(rdb->extgstate); i++) - { - extgstate = fz_dictgetval(rdb->extgstate, i); + if (pdf_findresource(xref->rcolorspace, ref)) + return nil; - obj = fz_dictgets(extgstate, "Font"); - if (obj) - { - font = nil; - ptr = nil; + rsrc = fz_malloc(sizeof(pdf_rsrc)); + if (!rsrc) + return fz_outofmem; + rsrc->oid = fz_tonum(ref); + rsrc->gen = fz_togen(ref); + + error = pdf_loadindirect(&obj, xref, ref); + if (error) + return error; + error = pdf_loadcolorspace(&colorspace, xref, obj); + fz_dropobj(obj); + if (error) { + fz_free(rsrc); + return error; + } - if (!fz_isarray(obj) || fz_arraylen(obj) != 2) - return fz_throw("syntaxerror in ExtGState/Font"); + rsrc->val = colorspace; + rsrc->next = xref->rcolorspace; + xref->rcolorspace = rsrc; + return nil; +} - ref = fz_arrayget(obj, 0); - sprintf(name, "$f.%d.%d", fz_tonum(ref), fz_togen(ref)); +static fz_error * +preloadxobject(pdf_xref *xref, fz_obj *ref) +{ + fz_error *error; + pdf_rsrc *rsrc; + fz_obj *obj; + fz_obj *subtype; - err = pdf_resolve(&ref, xref); - if (err) return err; + if (pdf_findresource(xref->rxobject, ref)) + return nil; + if (pdf_findresource(xref->rimage, ref)) + return nil; - err = pdf_loadfont(&font, xref, ref); - if (err) goto cleanup; + rsrc = fz_malloc(sizeof(pdf_rsrc)); + if (!rsrc) + return fz_outofmem; + rsrc->oid = fz_tonum(ref); + rsrc->gen = fz_togen(ref); - err = fz_newpointer(&ptr, font); - if (err) goto cleanup; + error = pdf_loadindirect(&obj, xref, ref); + if (error) + return error; - err = fz_dictputs(rdb->font, name, ptr); - if (err) goto cleanup; + subtype = fz_dictgets(obj, "Subtype"); - fz_dropobj(ptr); - fz_dropobj(ref); + if (!strcmp(fz_toname(subtype), "Form")) + { +// error = pdf_loadxobject((pdf_xobject**)&rsrc->val, xref, obj); + fz_dropobj(obj); + if (error) { + fz_free(rsrc); + return error; } + rsrc->next = xref->rxobject; + xref->rxobject = rsrc; + return nil; } - return nil; + else if (!strcmp(fz_toname(subtype), "Image")) + { + error = pdf_loadimage((pdf_image**)&rsrc->val, xref, obj); + fz_dropobj(obj); + if (error) { + fz_free(rsrc); + return error; + } + rsrc->next = xref->rimage; + xref->rimage = rsrc; + return nil; + } -cleanup: - if (font) fz_freefont((fz_font*)font); - if (ptr) fz_dropobj(ptr); - fz_dropobj(ref); - return err; + else + { + fz_dropobj(obj); + fz_free(rsrc); + return fz_throw("syntaxerror: unknown XObject subtype"); + } } static fz_error * -loadextgstates(pdf_resources *rdb, pdf_xref *xref, fz_obj *dict) +preloadfont(pdf_xref *xref, fz_obj *ref) { - fz_error *err; - fz_obj *key, *val; - int i; + fz_error *error; + pdf_font *font; + pdf_rsrc *rsrc; + fz_obj *obj; - for (i = 0; i < fz_dictlen(dict); i++) - { - key = fz_dictgetkey(dict, i); - val = fz_dictgetval(dict, i); + if (pdf_findresource(xref->rfont, ref)) + return nil; - err = pdf_resolve(&val, xref); - if (err) return err; + rsrc = fz_malloc(sizeof(pdf_rsrc)); + if (!rsrc) + return fz_outofmem; + rsrc->oid = fz_tonum(ref); + rsrc->gen = fz_togen(ref); + + error = pdf_loadindirect(&obj, xref, ref); + if (error) + return error; + error = pdf_loadfont(&font, xref, obj); + fz_dropobj(obj); + if (error) { + fz_free(rsrc); + return error; + } - err = fz_dictput(rdb->extgstate, key, val); - if (err) { fz_dropobj(val); return err; } + rsrc->val = font; + rsrc->next = xref->rfont; + xref->rfont = rsrc; + return nil; +} - fz_dropobj(val); +static fz_error * +scanfonts(pdf_xref *xref, fz_obj *rdb) +{ + fz_error *error; + fz_obj *dict; + fz_obj *obj; + int i; + + dict = fz_dictgets(rdb, "ExtGState"); + if (dict) + { + for (i = 0; i < fz_dictlen(dict); i++) + { + obj = fz_dictgetval(dict, i); + obj = fz_dictgets(obj, "Font"); + if (obj) + { + error = preloadfont(xref, fz_arrayget(obj, 0)); + if (error) + return error; + } + } + } + + dict = fz_dictgets(rdb, "Font"); + if (dict) + { + for (i = 0; i < fz_dictlen(dict); i++) + { + obj = fz_dictgetval(dict, i); + error = preloadfont(xref, obj); + if (error) + return error; + } } return nil; } static fz_error * -loadfonts(pdf_resources *rdb, pdf_xref *xref, fz_obj *dict) +copyresolved(fz_obj **outp, pdf_xref *xref, fz_obj *dict) { - fz_error *err; - pdf_font *font; - fz_obj *key, *val; - fz_obj *ptr; + fz_error *error; + fz_obj *key, *val, *obj; + fz_obj *copy; int i; + error = fz_newdict(©, fz_dictlen(dict)); + if (error) + return error; + for (i = 0; i < fz_dictlen(dict); i++) { - font = nil; - ptr = nil; - key = fz_dictgetkey(dict, i); val = fz_dictgetval(dict, i); - err = pdf_resolve(&val, xref); - if (err) return err; + if (fz_isindirect(val)) + { + error = pdf_loadindirect(&obj, xref, val); + if (error) + goto cleanup; + error = fz_dictput(copy, key, obj); + fz_dropobj(obj); + if (error) + goto cleanup; + } + else + { + error = fz_dictput(copy, key, val); + if (error) + goto cleanup; + } + } - err = pdf_loadfont(&font, xref, val); - if (err) goto cleanup; + *outp = copy; + return nil; - err = fz_newpointer(&ptr, font); - if (err) goto cleanup; +cleanup: + fz_dropobj(copy); + return error; +} - err = fz_dictput(rdb->font, key, ptr); - if (err) goto cleanup; +fz_error * +pdf_loadresources(fz_obj **rdbp, pdf_xref *xref, fz_obj *orig) +{ + fz_error *error; + fz_obj *copy; + fz_obj *old; + fz_obj *new; + fz_obj *dict; + fz_obj *obj; + int i; - fz_dropobj(ptr); - fz_dropobj(val); + /* + * Resolve indirect objects + */ + + error = copyresolved(©, xref, orig); + if (error) + return error; + + old = fz_dictgets(copy, "ExtGState"); + if (old) + { + error = copyresolved(&new, xref, old); + if (error) + goto cleanup; + error = fz_dictputs(copy, "ExtGState", new); + fz_dropobj(new); + if (error) + goto cleanup; } + /* + * Load ColorSpace objects + */ + + dict = fz_dictgets(copy, "ColorSpace"); + if (dict) + { + for (i = 0; i < fz_dictlen(dict); i++) + { + obj = fz_dictgetval(dict, i); + if (fz_isindirect(obj)) + { + error = preloadcolorspace(xref, obj); + if (error) + return error; + } + } + } + + /* + * Load XObjects and Images + */ + + dict = fz_dictgets(copy, "XObject"); + if (dict) + { + for (i = 0; i < fz_dictlen(dict); i++) + { + obj = fz_dictgetval(dict, i); + if (fz_isindirect(obj)) + { + error = preloadxobject(xref, obj); + if (error) + return error; + } + } + } + + /* + * Load Font objects + */ + + error = scanfonts(xref, copy); + if (error) + goto cleanup; + + *rdbp = copy; return nil; cleanup: - if (font) fz_freefont((fz_font*)font); - if (ptr) fz_dropobj(ptr); - fz_dropobj(val); - return err; + fz_dropobj(copy); + return error; } +#if 0 + static fz_error * loadcolorspaces(pdf_resources *rdb, pdf_xref *xref, fz_obj *dict) { @@ -228,15 +450,5 @@ pdf_loadresources(pdf_resources **rdbp, pdf_xref *xref, fz_obj *topdict) return nil; } -void -pdf_freeresources(pdf_resources *rdb) -{ - /* TODO freefont and freecolorspace */ - if (rdb->extgstate) fz_dropobj(rdb->extgstate); - if (rdb->colorspace) fz_dropobj(rdb->colorspace); - if (rdb->font) fz_dropobj(rdb->font); - if (rdb->ximage) fz_dropobj(rdb->ximage); - if (rdb->xform) fz_dropobj(rdb->xform); - fz_free(rdb); -} +#endif diff --git a/mupdf/xref.c b/mupdf/xref.c index ae11ebb7..5dde5f5f 100644 --- a/mupdf/xref.c +++ b/mupdf/xref.c @@ -10,9 +10,10 @@ pdf_newpdf(pdf_xref **xrefp) { pdf_xref *xref; - xref = fz_malloc(sizeof (pdf_xref)); + xref = fz_malloc(sizeof(pdf_xref)); if (!xref) return fz_outofmem; + memset(xref, 0, sizeof(pdf_xref)); xref->file = nil; xref->version = 1.3; diff --git a/render/render.c b/render/render.c index d46d5b71..29b51480 100644 --- a/render/render.c +++ b/render/render.c @@ -5,6 +5,9 @@ fz_error *fz_rendercolorpath(fz_renderer*, fz_pathnode*, fz_colornode*, fz_matri fz_error *fz_rendertext(fz_renderer*, fz_textnode*, fz_matrix); fz_error *fz_renderpath(fz_renderer*, fz_pathnode*, fz_matrix); +fz_error *fz_renderimageover(fz_renderer*, fz_imagenode*, fz_matrix); +fz_error *fz_renderimage(fz_renderer*, fz_imagenode*, fz_matrix); + fz_error * fz_newrenderer(fz_renderer **gcp, fz_colorspace *processcolormodel) { @@ -131,7 +134,6 @@ fz_renderover(fz_renderer *gc, fz_overnode *over, fz_matrix ctm) fz_error *error; fz_pixmap *oldacc = nil; int oldmode; -int i; /* uh-oh! we have a new over cluster */ if (gc->mode != FZ_ROVER) @@ -209,6 +211,10 @@ fz_rendermask(fz_renderer *gc, fz_masknode *mask, fz_matrix ctm) fz_blendmask(gc->tmp, colorpix, shapepix); +//printf("mask color");fz_debugpixmap(colorpix);getchar(); +//printf("mask shape");fz_debugpixmap(shapepix);getchar(); +//printf("mask blend");fz_debugpixmap(gc->tmp);getchar(); + fz_freepixmap(shapepix); fz_freepixmap(colorpix); @@ -246,6 +252,8 @@ fz_rendernode(fz_renderer *gc, fz_node *node, fz_matrix ctm) return fz_renderpath(gc, (fz_pathnode*)node, ctm); case FZ_NTEXT: return fz_rendertext(gc, (fz_textnode*)node, ctm); + case FZ_NIMAGE: + return fz_renderimage(gc, (fz_imagenode*)node, ctm); default: return nil; } @@ -261,6 +269,10 @@ fz_rendertree(fz_pixmap **outp, fz_renderer *gc, fz_tree *tree, fz_matrix ctm, f gc->w = ceil(bbox.max.x) - floor(bbox.min.x); gc->h = ceil(bbox.max.y) - floor(bbox.min.y); + /* compensate for rounding */ + ctm.e -= bbox.min.x - floor(bbox.min.x); + ctm.f -= bbox.min.y - floor(bbox.min.y); + error = fz_rendernode(gc, tree->root, ctm); if (error) return error; diff --git a/render/renderimage.c b/render/renderimage.c new file mode 100644 index 00000000..4c6ef816 --- /dev/null +++ b/render/renderimage.c @@ -0,0 +1,59 @@ +#include <fitz.h> + +static int cmpy(const void *a, const void *b) +{ + const fz_point *ap = a; + const fz_point *bp = b; + return bp->y - ap->y; +} + +static void +drawtile(fz_pixmap *out, fz_pixmap *tile, fz_matrix ctm) +{ + static const fz_point rect[4] = { {0, 0}, {0, 1}, {1, 1}, {1, 0} }; + fz_point v[4]; + int i; + + for (i = 0; i < 4; i++) + v[i] = fz_transformpoint(ctm, rect[i]); + + qsort(v, 4, sizeof(fz_point), cmpy); + + for (i = 0; i < 4; i++) + printf("%d: %g %g\n", i, v[i].x, v[i].y); + +} + +fz_error * +fz_renderimage(fz_renderer *gc, fz_imagenode *node, fz_matrix ctm) +{ + fz_error *error; + fz_pixmap *tile; + fz_image *image = node->image; + fz_colorspace *cs = image->cs; + int w = image->w; + int h = image->h; + int n = image->n; + + error = fz_newpixmap(&tile, cs, 0, 0, w, h, n, 1); + if (error) + return error; + + error = fz_newpixmap(&gc->tmp, cs, gc->x, gc->y, gc->w, gc->h, n, 1); + if (error) + goto cleanup; + + error = image->loadtile(image, tile); + if (error) + goto cleanup; + + drawtile(gc->tmp, tile, ctm); + + fz_freepixmap(tile); + return nil; + +cleanup: + fz_freepixmap(tile); + return error; +} + diff --git a/render/renderpath.c b/render/renderpath.c index 9e805a53..8d2f875b 100644 --- a/render/renderpath.c +++ b/render/renderpath.c @@ -1,6 +1,8 @@ #include <fitz.h> -enum { HS = 17, VS = 15 }; +// enum { HS = 1, VS = 1, SF = 255 }; +// enum { HS = 5, VS = 3, SF = 17 }; +enum { HS = 17, VS = 15, SF = 1 }; static fz_error *pathtogel(fz_gel *gel, fz_pathnode *path, fz_matrix ctm) { @@ -17,7 +19,7 @@ static fz_error *pathtogel(fz_gel *gel, fz_pathnode *path, fz_matrix ctm) return fz_fillpath(gel, path, ctm, flatness); } -static void blitcolorspan(int y, int x0, int n, short *list, void *userdata) +static void blitcolorspan(int y, int x, int n, unsigned char *alpha, void *userdata) { fz_renderer *gc = userdata; fz_pixmap *pix = gc->acc; @@ -28,23 +30,24 @@ static void blitcolorspan(int y, int x0, int n, short *list, void *userdata) unsigned char g = gc->g; unsigned char b = gc->b; - sa = 0; - - while (x0 < pix->x) + if (x < pix->x) { - sa += *list++; - x0 ++; - n --; + alpha += pix->x - x; + n -= pix->x - x; + x = pix->x; } - if (n > pix->w) - n = pix->w; + if (x + n > pix->x + pix->w) + n = pix->x + pix->w - x; + + if (n < 0) + return; - p = &pix->samples[(y - pix->y) * pix->stride + (x0 - pix->x) * 4]; + p = &pix->samples[(y - pix->y) * pix->stride + (x - pix->x) * 4]; while (n--) { - sa += *list++; + sa = *alpha++ * SF; ssa = 255 - sa; p[0] = fz_mul255(r, sa) + fz_mul255(p[0], ssa); @@ -56,31 +59,27 @@ static void blitcolorspan(int y, int x0, int n, short *list, void *userdata) } } -static void blitalphaspan(int y, int x0, int n, short *list, void *userdata) +static void blitalphaspan(int y, int x, int n, unsigned char *alpha, void *userdata) { fz_pixmap *pix = userdata; - unsigned char a; unsigned char *p; - a = 0; - - while (x0 < pix->x) + if (x < pix->x) { - a += *list++; - x0 ++; - n --; + alpha += pix->x - x; + n -= pix->x - x; + x = pix->x; } - if (n > pix->w) - n = pix->w; + if (x + n > pix->x + pix->w) + n = pix->x + pix->w - x; - p = &pix->samples[(y - pix->y) * pix->stride + (x0 - pix->x) * 4]; + if (n < 0) + return; + p = &pix->samples[(y - pix->y) * pix->stride + (x - pix->x)]; while (n--) - { - a += *list++; - *p++ = a; - } + *p++ = *alpha++ * SF; } fz_error * diff --git a/render/rendertext.c b/render/rendertext.c index cc181657..81afeafa 100644 --- a/render/rendertext.c +++ b/render/rendertext.c @@ -33,13 +33,13 @@ static void blitcolorglyph(fz_pixmap *out, fz_glyph *gl, int xo, int yo, fz_rend { for (sx = 0; sx < gl->w; sx++) { - dx = xo + sx + gl->lsb - out->x; dy = yo - sy + gl->top - out->y; + if (dy < 0) continue; + if (dy >= out->h) break; + dx = xo + sx + gl->lsb - out->x; if (dx < 0) continue; - if (dy < 0) continue; - if (dx >= out->w) continue; - if (dy >= out->h) continue; + if (dx >= out->w) break; sa = gl->bitmap[sx + sy * gl->w]; ssa = 255 - sa; diff --git a/render/scanconv.c b/render/scanconv.c index b2689ae2..db859d1f 100644 --- a/render/scanconv.c +++ b/render/scanconv.c @@ -1,7 +1,7 @@ #include <fitz.h> static inline void -addspan(short *list, int x0, int x1, int xofs, int hs) +addspan(unsigned char *list, int x0, int x1, int xofs, int hs) { int x0pix, x0sub; int x1pix, x1sub; @@ -34,7 +34,7 @@ addspan(short *list, int x0, int x1, int xofs, int hs) } static inline void -nonzerowinding(fz_ael *ael, short *list, int xofs, int hs) +nonzerowinding(fz_ael *ael, unsigned char *list, int xofs, int hs) { int winding = 0; int x = 0; @@ -50,7 +50,7 @@ nonzerowinding(fz_ael *ael, short *list, int xofs, int hs) } static inline void -evenodd(fz_ael *ael, short *list, int xofs, int hs) +evenodd(fz_ael *ael, unsigned char *list, int xofs, int hs) { int even = 0; int x = 0; @@ -65,22 +65,22 @@ evenodd(fz_ael *ael, short *list, int xofs, int hs) } } -/* -void -fz_emitdeltas(short *list, int y, int xofs, int n) +static void toalpha(unsigned char *list, int n) { int d = 0; while (n--) - d += *list++; + { + d += *list; + *list++ = d; + } } -*/ fz_error * fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, int y0, int y1, - void (*blitfunc)(int,int,int,short*,void*), void *blitdata) + void (*blitfunc)(int,int,int,unsigned char*,void*), void *blitdata) { fz_error *error; - short *deltas; + unsigned char *deltas; int y, e; int yd, yc; @@ -96,11 +96,11 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, int y0, int y1, if (gel->len == 0) return nil; - deltas = fz_malloc(sizeof(short) * (xmax - xmin + 1)); + deltas = fz_malloc(xmax - xmin + 1); if (!deltas) return fz_outofmem; - memset(deltas, 0, sizeof(short) * (xmax - xmin + 1)); + memset(deltas, 0, xmax - xmin + 1); e = 0; y = gel->edges[0].y; @@ -113,8 +113,9 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, int y0, int y1, if (yc != yd) { if (yd >= y0 && yd < y1) { + toalpha(deltas, xmax - xmin); blitfunc(yd, xmin, xmax - xmin, deltas, blitdata); - memset(deltas, 0, sizeof(short) * (xmax - xmin + 1)); + memset(deltas, 0, xmax - xmin + 1); } } yd = yc; @@ -142,7 +143,10 @@ fz_scanconvert(fz_gel *gel, fz_ael *ael, int eofill, int y0, int y1, } if (yd >= y0 && yd < y1) + { + toalpha(deltas, xmax - xmin); blitfunc(yd, xmin, xmax - xmin, deltas, blitdata); + } fz_free(deltas); return nil; diff --git a/test/pdfrip.c b/test/pdfrip.c index f7cbc093..e8cd088f 100644 --- a/test/pdfrip.c +++ b/test/pdfrip.c @@ -33,23 +33,20 @@ void showpage(pdf_xref *xref, fz_obj *pageobj) page->mediabox.max.x, page->mediabox.max.y); printf(" rotate %d\n", page->rotate); - printf(" fonts\n"); - fz_debugobj(page->rdb->font); - printf("\n"); - - printf(" colorspaces\n"); - fz_debugobj(page->rdb->colorspace); + printf(" resources\n"); + fz_debugobj(page->resources); printf("\n"); printf("tree\n"); fz_debugtree(page->tree); - printf("endtree"); + printf("endtree\n"); } { fz_pixmap *pix; fz_renderer *gc; fz_matrix ctm; + fz_rect bbox; error = fz_newrenderer(&gc, pdf_devicergb); if (error) fz_abort(error); @@ -58,8 +55,12 @@ void showpage(pdf_xref *xref, fz_obj *pageobj) printf("ctm %g %g %g %g %g %g\n", ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f); +printf("bounding!\n"); + bbox = fz_boundtree(page->tree, ctm); +printf(" [%g %g %g %g]\n", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); printf("rendering!\n"); error = fz_rendertree(&pix, gc, page->tree, ctm, page->mediabox); + //error = fz_rendertree(&pix, gc, page->tree, ctm, bbox); if (error) fz_abort(error); printf("done!\n"); diff --git a/tree/debug.c b/tree/debug.c index 583608f5..e55d56e7 100644 --- a/tree/debug.c +++ b/tree/debug.c @@ -13,7 +13,8 @@ static void lispmeta(fz_metanode *node, int level) fz_node *child; indent(level); printf("(meta "); - fz_debugobj(node->info); + if (node->name) { fz_debugobj(node->name); } + if (node->dict) { printf("\n"); fz_debugobj(node->dict); } printf("\n"); for (child = node->super.child; child; child = child->next) lispnode(child, level + 1); @@ -141,7 +142,7 @@ static void lisptext(fz_textnode *node, int level) static void lispimage(fz_imagenode *node, int level) { indent(level); - printf("(image %d %d %d %d)\n", node->w, node->h, node->n, node->a); + printf("(image)\n"); } static void lispnode(fz_node *node, int level) diff --git a/tree/font.c b/tree/font.c index 5dfaec2e..58c194ae 100644 --- a/tree/font.c +++ b/tree/font.c @@ -39,6 +39,7 @@ fz_setfontwmode(fz_font *font, int wmode) void fz_setfontbbox(fz_font *font, int xmin, int ymin, int xmax, int ymax) { +printf(" bbox [%d %d %d %d]\n", xmin, ymin, xmax, ymax); font->bbox.min.x = xmin; font->bbox.min.y = ymin; font->bbox.max.x = xmax; diff --git a/tree/node2.c b/tree/node2.c index d50936ef..6e28aaac 100644 --- a/tree/node2.c +++ b/tree/node2.c @@ -164,7 +164,7 @@ fz_boundtransformnode(fz_transformnode *node, fz_matrix ctm) */ fz_error * -fz_newmetanode(fz_node **nodep, fz_obj *info) +fz_newmetanode(fz_node **nodep, fz_obj *name, fz_obj *dict) { fz_metanode *node; @@ -174,7 +174,13 @@ fz_newmetanode(fz_node **nodep, fz_obj *info) *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NMETA); - node->info = fz_keepobj(info); + node->name = nil; + node->dict = nil; + + if (name) + node->name = fz_keepobj(name); + if (dict) + node->dict = fz_keepobj(dict); return nil; } @@ -182,8 +188,10 @@ fz_newmetanode(fz_node **nodep, fz_obj *info) void fz_freemetanode(fz_metanode *node) { - if (node->info) - fz_dropobj(node->info); + if (node->name) + fz_dropobj(node->name); + if (node->dict) + fz_dropobj(node->dict); } fz_rect @@ -261,7 +269,7 @@ fz_boundcolornode(fz_colornode *node, fz_matrix ctm) */ fz_error * -fz_newimagenode(fz_node **nodep, fz_colorspace *cs, int w, int h, int n, int a) +fz_newimagenode(fz_node **nodep, fz_image *image) { fz_imagenode *node; @@ -271,11 +279,7 @@ fz_newimagenode(fz_node **nodep, fz_colorspace *cs, int w, int h, int n, int a) *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NIMAGE); - node->cs = cs; - node->w = w; - node->h = h; - node->n = n; - node->a = a; + node->image = image; return nil; } diff --git a/tree/text.c b/tree/text.c index d822ec34..1832df9f 100644 --- a/tree/text.c +++ b/tree/text.c @@ -29,9 +29,67 @@ fz_freetextnode(fz_textnode *text) fz_rect fz_boundtextnode(fz_textnode *text, fz_matrix ctm) { - // FIXME convolve font bbox to all glyph x,y pairs - /* fz_rect bounds = fz_boundglyph(text->font, text->els[0], ctm); */ - return fz_infiniterect(); + fz_matrix trm; + fz_point ul, ur, ll, lr; + fz_rect bbox; + fz_rect fbox; + int i; + + if (text->len == 0) + return fz_infiniterect(); + + /* find bbox of glyph origins in ctm space */ + + bbox.min.x = bbox.max.x = text->els[0].x; + bbox.min.y = bbox.max.y = text->els[0].y; + + for (i = 1; i < text->len; i++) + { + bbox.min.x = MIN(bbox.min.x, text->els[i].x); + bbox.min.y = MIN(bbox.min.y, text->els[i].y); + bbox.max.x = MAX(bbox.max.x, text->els[i].x); + bbox.max.y = MAX(bbox.max.y, text->els[i].y); + } + + ll.x = bbox.min.x; ll.y = bbox.min.y; ll = fz_transformpoint(ctm, ll); + ul.x = bbox.min.x; ul.y = bbox.max.y; ul = fz_transformpoint(ctm, ul); + ur.x = bbox.max.x; ur.y = bbox.max.y; ur = fz_transformpoint(ctm, ur); + lr.x = bbox.max.x; lr.y = bbox.min.y; lr = fz_transformpoint(ctm, lr); + + bbox.min.x = MIN4(ll.x, ul.x, ur.x, lr.x); + bbox.min.y = MIN4(ll.y, ul.y, ur.y, lr.y); + bbox.max.x = MAX4(ll.x, ul.x, ur.x, lr.x); + bbox.max.y = MAX4(ll.y, ul.y, ur.y, lr.y); + + /* find bbox of font in trm * ctm space */ + + trm = fz_concat(text->trm, ctm); + trm.e = 0; + trm.f = 0; + + fbox.min.x = text->font->bbox.min.x * 0.001; + fbox.min.y = text->font->bbox.min.y * 0.001; + fbox.max.x = text->font->bbox.max.x * 0.001; + fbox.max.y = text->font->bbox.max.y * 0.001; + + ll.x = fbox.min.x; ll.y = fbox.min.y; ll = fz_transformpoint(trm, ll); + ul.x = fbox.min.x; ul.y = fbox.max.y; ul = fz_transformpoint(trm, ul); + ur.x = fbox.max.x; ur.y = fbox.max.y; ur = fz_transformpoint(trm, ur); + lr.x = fbox.max.x; lr.y = fbox.min.y; lr = fz_transformpoint(trm, lr); + + fbox.min.x = MIN4(ll.x, ul.x, ur.x, lr.x); + fbox.min.y = MIN4(ll.y, ul.y, ur.y, lr.y); + fbox.max.x = MAX4(ll.x, ul.x, ur.x, lr.x); + fbox.max.y = MAX4(ll.y, ul.y, ur.y, lr.y); + + bbox.min.x += MIN4(ll.x, ul.x, ur.x, lr.x); + bbox.min.y += MIN4(ll.y, ul.y, ur.y, lr.y); + bbox.max.x += MAX4(ll.x, ul.x, ur.x, lr.x); + bbox.max.y += MAX4(ll.y, ul.y, ur.y, lr.y); + +// printf("text [ %g %g %g %g ]\n", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); + + return bbox; } static fz_error * |