diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-12-13 09:37:48 +0100 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-12-13 09:37:48 +0100 |
commit | 72976993f5b39d9ee1599dc89961288b297cdc62 (patch) | |
tree | 131098a8e8c2de04766181aeddc8a13aebb2981d | |
parent | 690dabe2db5f440b9bbb4c4eecbeeb77635a22b4 (diff) | |
download | mupdf-72976993f5b39d9ee1599dc89961288b297cdc62.tar.xz |
clean up nametree and outlines
-rw-r--r-- | Jamfile | 6 | ||||
-rw-r--r-- | TODO | 58 | ||||
-rw-r--r-- | base/matrix.c | 2 | ||||
-rw-r--r-- | include/fitz/object.h | 15 | ||||
-rw-r--r-- | include/mupdf/annot.h | 23 | ||||
-rw-r--r-- | include/mupdf/page.h | 42 | ||||
-rw-r--r-- | include/mupdf/rsrc.h | 1 | ||||
-rw-r--r-- | include/mupdf/syntax.h | 1 | ||||
-rw-r--r-- | include/mupdf/xref.h | 28 | ||||
-rw-r--r-- | mupdf/annot.c | 94 | ||||
-rw-r--r-- | mupdf/build.c | 4 | ||||
-rw-r--r-- | mupdf/colorspace1.c | 4 | ||||
-rw-r--r-- | mupdf/crypt.c | 16 | ||||
-rw-r--r-- | mupdf/font.c | 8 | ||||
-rw-r--r-- | mupdf/fontenc.c | 36 | ||||
-rw-r--r-- | mupdf/fontfile.c | 4 | ||||
-rw-r--r-- | mupdf/nametree.c | 147 | ||||
-rw-r--r-- | mupdf/open.c | 46 | ||||
-rw-r--r-- | mupdf/outline.c | 244 | ||||
-rw-r--r-- | mupdf/parse.c | 49 | ||||
-rw-r--r-- | mupdf/repair.c | 36 | ||||
-rw-r--r-- | mupdf/save.c | 4 | ||||
-rw-r--r-- | mupdf/store.c | 2 | ||||
-rw-r--r-- | mupdf/xref.c | 134 | ||||
-rw-r--r-- | object/dict.c | 151 | ||||
-rw-r--r-- | object/simple.c | 26 | ||||
-rw-r--r-- | test/pdfclean.c | 14 | ||||
-rw-r--r-- | test/pdfdebug.c | 26 | ||||
-rw-r--r-- | test/x11pdf.c | 65 |
29 files changed, 647 insertions, 639 deletions
@@ -205,9 +205,9 @@ LINKLIBS on x11pdf = -lX11 -lXext $(LINKLIBS) ; Main pdfclean : test/pdfclean.c ; Main pdfdebug : test/pdfdebug.c ; -Main pdfmerge : test/pdfmerge.c ; -Main pdfrip : test/pdfrip.c ; -Main pdffunction : test/pdffunction.c ; +# Main pdfmerge : test/pdfmerge.c ; +# Main pdfrip : test/pdfrip.c ; +# Main pdffunction : test/pdffunction.c ; Main x11pdf : test/x11pdf.c test/ximage.c ; @@ -1,36 +1,34 @@ immediate plan: - + refactor xref init - + loadlowlevel - + loadhighlevel - - load name trees - - load page tree - - load outline - - - altivec optimize - - design gui for editor - - go through spec and check all features! - - talk to keithp about fontconfig cid-font + cmap support + * design gui for editor + * libfontfocus + * write mupdf hackers guide + * clean up and 'freeze' public api - * page labels + dests + outline + annots + * refactor image loading + * refactor xref loading/repair + * restructure build.c and interpret.c (ftb vs csi) + * fix the colorspace/pattern/shading material mess + * font loading: + - configuration... where to find system files (asian font archive?) + - system fontfile + cmap store + - embedded fontfile store + - split type3 and ftfont malloc (dont waste t3 charprocs on ft fonts) + - make ftfontfile separate struct w/ refcounting + - refactor font loading more. simple/cid/type3 have too much in common. - * libfontfocus + * structure low/high level stuff + - rewrite outline parser + - implement comments - * font and cmap config (where to load cmap and which cid fonts) - - global fontfile/cmap cache - - unify handling of mallocing fonts and images - - split type3 and ftfont malloc (dont waste t3 charprocs on ft fonts) - - make ftfontfile separate struct w/ refcounting - - refactor font loading more. simple/cid/type3 have too much in common. - fix default .fonts.conf for base14 fonts - fix default .fonts.conf for asian fonts - maybe add CMap directory entry to fontconfig? + * clean high-level api - * clean up and 'freeze' public api + - go through spec and check all features! + - altivec optimize --- -std rsrc fmt +std rsrc fmt (v3) transparency (v2) - everything! @@ -47,24 +45,14 @@ image rendering (v2) - better filter than box - lazy decoding -shadings - - ... jeong ... - rendering - fix glyphcache evictlast - bbox culling per glyph - font focus - -parser - - try to clean up colorspace/material handling in interpreter - - annotations and destinations (for links and outline) + - render cache (link-nodes and scaled images and colorspaced shades) fz_optimizetree() - error & memory - concatenate chained transforms - remove identity transforms -cache - global cache for cmaps and fontfiles (emb+sys) - render cache (link-nodes and scaled images and shades) - diff --git a/base/matrix.c b/base/matrix.c index b0513940..7d7097c4 100644 --- a/base/matrix.c +++ b/base/matrix.c @@ -133,8 +133,6 @@ fz_transformaabb(fz_matrix m, fz_rect r) if (fz_isinfiniterect(r)) return r; - if (fz_isemptyrect(r)) - return r; s.x = r.min.x; s.y = r.min.y; t.x = r.min.x; t.y = r.max.y; diff --git a/include/fitz/object.h b/include/fitz/object.h index 015f1e74..34b62f59 100644 --- a/include/fitz/object.h +++ b/include/fitz/object.h @@ -1,4 +1,5 @@ typedef struct fz_obj_s fz_obj; +typedef struct fz_keyval_s fz_keyval; typedef enum fz_objkind_e { @@ -23,7 +24,7 @@ struct fz_keyval_s struct fz_obj_s { unsigned short refs; - unsigned short kind; /* fz_objkind takes 4 bytes :( */ + char kind; /* fz_objkind takes 4 bytes :( */ union { int b; @@ -40,9 +41,10 @@ struct fz_obj_s fz_obj **items; } a; struct { + char sorted; int len; int cap; - struct fz_keyval_s *items; + fz_keyval *items; } d; struct { int oid; @@ -83,19 +85,21 @@ int fz_isdict(fz_obj *obj); int fz_isindirect(fz_obj *obj); int fz_ispointer(fz_obj *obj); -int fz_cmpobj(fz_obj *a, fz_obj *b); +int fz_objcmp(fz_obj *a, fz_obj *b); /* silent failure, no error reporting */ int fz_tobool(fz_obj *obj); int fz_toint(fz_obj *obj); float fz_toreal(fz_obj *obj); char *fz_toname(fz_obj *obj); -char *fz_tostringbuf(fz_obj *obj); -int fz_tostringlen(fz_obj *obj); +char *fz_tostrbuf(fz_obj *obj); +int fz_tostrlen(fz_obj *obj); int fz_tonum(fz_obj *obj); int fz_togen(fz_obj *obj); void *fz_topointer(fz_obj *obj); +fz_error *fz_newnamefromstring(fz_obj **op, fz_obj *str); + int fz_arraylen(fz_obj *array); fz_obj *fz_arrayget(fz_obj *array, int i); fz_error *fz_arrayput(fz_obj *array, int i, fz_obj *obj); @@ -111,6 +115,7 @@ fz_error *fz_dictput(fz_obj *dict, fz_obj *key, fz_obj *val); fz_error *fz_dictputs(fz_obj *dict, char *key, fz_obj *val); fz_error *fz_dictdel(fz_obj *dict, fz_obj *key); fz_error *fz_dictdels(fz_obj *dict, char *key); +void fz_sortdict(fz_obj *dict); int fz_sprintobj(char *s, int n, fz_obj *obj, int tight); void fz_debugobj(fz_obj *obj); diff --git a/include/mupdf/annot.h b/include/mupdf/annot.h index ac017735..47e7a9f8 100644 --- a/include/mupdf/annot.h +++ b/include/mupdf/annot.h @@ -5,6 +5,7 @@ typedef struct pdf_link_s pdf_link; typedef struct pdf_comment_s pdf_comment; typedef struct pdf_widget_s pdf_widget; +typedef struct pdf_outline_s pdf_outline; typedef enum pdf_linkkind_e { @@ -16,9 +17,7 @@ struct pdf_link_s { pdf_linkkind kind; fz_rect rect; - fz_obj *page; - fz_obj *uri; - int ismap; + fz_obj *dest; pdf_link *next; }; @@ -46,8 +45,24 @@ struct pdf_comment_s pdf_comment *next; }; -fz_error * pdf_newlink(pdf_link**, fz_rect rect, int ismap, fz_obj *page, fz_obj *uri); +struct pdf_outline_s +{ + char *title; + pdf_link *link; + pdf_outline *child; + pdf_outline *next; +}; + +fz_error *pdf_loadnametree(fz_obj **dictp, pdf_xref *xref, fz_obj *root); +fz_error *pdf_loadnametrees(pdf_xref *xref); + +fz_error *pdf_newlink(pdf_link**, fz_rect rect, fz_obj *dest); +fz_error *pdf_loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict); void pdf_droplink(pdf_link *link); +fz_error *pdf_loadoutline(pdf_outline **outlinep, pdf_xref *xref); +void pdf_debugoutline(pdf_outline *outline, int level); +void pdf_dropoutline(pdf_outline *outline); + fz_error *pdf_loadannots(pdf_comment **, pdf_link **, pdf_xref *, fz_obj *annots); diff --git a/include/mupdf/page.h b/include/mupdf/page.h index f027ac89..648fe54d 100644 --- a/include/mupdf/page.h +++ b/include/mupdf/page.h @@ -2,40 +2,11 @@ * Page tree, pages and related objects */ -typedef struct pdf_outlinetree_s pdf_outlinetree; -typedef struct pdf_outline_s pdf_outline; -typedef struct pdf_nametree_s pdf_nametree; typedef struct pdf_pagetree_s pdf_pagetree; typedef struct pdf_page_s pdf_page; typedef struct pdf_textline_s pdf_textline; typedef struct pdf_textchar_s pdf_textchar; -struct pdf_outlinetree_s -{ - pdf_outline *first; - int count; -}; - -struct pdf_outline_s -{ - char *title; - pdf_outline *next; - pdf_outline *first; - int count; - fz_obj *dest; - fz_obj *a; - fz_obj *se; - float c[3]; - int f; -}; - -struct pdf_nametree_s -{ - int len; - int cap; - struct fz_keyval_s *items; -}; - struct pdf_pagetree_s { int count; @@ -67,19 +38,6 @@ struct pdf_textline_s pdf_textline *next; }; -/* outline.c */ -fz_error *pdf_loadoutlinetree(pdf_outlinetree **oo, pdf_xref *xref); -void pdf_debugoutlinetree(pdf_outlinetree *outlinetree); -void pdf_dropoutlinetree(pdf_outlinetree *outlinetree); - -/* nametree.c */ -fz_error *pdf_loadnametrees(pdf_xref *xref); -fz_error *pdf_loadnametree(pdf_nametree **treep, pdf_xref *xref, fz_obj *root); -void pdf_dropnametree(pdf_nametree *tree); -void pdf_debugnametree(pdf_nametree *tree); -fz_obj *pdf_lookupname(pdf_nametree *tree, fz_obj *name); -fz_obj *pdf_lookupnames(pdf_nametree *tree, char *name); - /* pagetree.c */ fz_error *pdf_loadpagetree(pdf_pagetree **pp, pdf_xref *xref); int pdf_getpagecount(pdf_pagetree *pages); diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index 29c8fa97..34aefea2 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -150,6 +150,7 @@ extern int pdf_adobeglyphlen; void pdf_loadencoding(char **estrings, char *encoding); int pdf_lookupagl(char *name); +extern unsigned short pdf_docencoding[256]; extern char *pdf_macroman[256]; extern char *pdf_macexpert[256]; extern char *pdf_winansi[256]; diff --git a/include/mupdf/syntax.h b/include/mupdf/syntax.h index 786147bd..c25dcb01 100644 --- a/include/mupdf/syntax.h +++ b/include/mupdf/syntax.h @@ -27,6 +27,7 @@ fz_error *pdf_parseindobj(fz_obj **op, fz_file *f, char *buf, int cap, int *oid, fz_rect pdf_torect(fz_obj *array); fz_matrix pdf_tomatrix(fz_obj *array); +fz_error *pdf_toutf8(char **dstp, fz_obj *src); /* * Encryption diff --git a/include/mupdf/xref.h b/include/mupdf/xref.h index 3721e09a..98f45a39 100644 --- a/include/mupdf/xref.h +++ b/include/mupdf/xref.h @@ -11,15 +11,20 @@ struct pdf_xref_s fz_file *stream; float version; int startxref; - fz_obj *trailer; /* TODO split this into root/info/encrypt/id */ pdf_crypt *crypt; + fz_obj *trailer; /* TODO split this into root/info/encrypt/id */ + fz_obj *root; /* resolved catalog dict */ + fz_obj *info; /* resolved info dict */ + fz_obj *dests; /* flattened dests nametree */ + int len; int cap; pdf_xrefentry *table; - struct pdf_nametree_s *dests; struct pdf_store_s *store; + struct pdf_pagetree_s *pages; + struct pdf_outline_s *outlines; }; struct pdf_xrefentry_s @@ -33,16 +38,17 @@ struct pdf_xrefentry_s fz_obj *obj; /* stored/cached object */ }; -fz_error *pdf_repairpdf(pdf_xref **, char *filename); -fz_error *pdf_openpdf(pdf_xref **, char *filename); -fz_error *pdf_newpdf(pdf_xref **); +fz_error *pdf_newxref(pdf_xref **); +fz_error *pdf_repairxref(pdf_xref *, char *filename); +fz_error *pdf_loadxref(pdf_xref *, char *filename); -fz_error *pdf_updatepdf(pdf_xref *, char *filename); -fz_error *pdf_savepdf(pdf_xref *, char *filename, pdf_crypt *encrypt); +fz_error *pdf_openpdf(pdf_xref **, char *filename); +fz_error *pdf_updatexref(pdf_xref *, char *filename); +fz_error *pdf_savexref(pdf_xref *, char *filename, pdf_crypt *encrypt); -void pdf_debugpdf(pdf_xref *); -void pdf_flushpdf(pdf_xref *, int force); -void pdf_closepdf(pdf_xref *); +void pdf_debugxref(pdf_xref *); +void pdf_flushxref(pdf_xref *, int force); +void pdf_closexref(pdf_xref *); fz_error *pdf_allocobject(pdf_xref *, int *oidp, int *genp); fz_error *pdf_deleteobject(pdf_xref *, int oid, int gen); @@ -67,5 +73,5 @@ fz_error *pdf_transplant(pdf_xref *dst, pdf_xref *src, fz_obj **newp, fz_obj *ol /* private */ fz_error *pdf_loadobjstm(pdf_xref *xref, int oid, int gen, char *buf, int cap); -fz_error *pdf_decryptpdf(pdf_xref *xref); +fz_error *pdf_decryptxref(pdf_xref *xref); diff --git a/mupdf/annot.c b/mupdf/annot.c index 0f8acf6f..055dae75 100644 --- a/mupdf/annot.c +++ b/mupdf/annot.c @@ -8,7 +8,7 @@ loadcomment(pdf_comment **commentp, pdf_xref *xref, fz_obj *dict) } fz_error * -pdf_newlink(pdf_link **linkp, fz_rect bbox, int ismap, fz_obj *page, fz_obj *uri) +pdf_newlink(pdf_link **linkp, fz_rect bbox, fz_obj *dest) { pdf_link *link; @@ -17,9 +17,7 @@ pdf_newlink(pdf_link **linkp, fz_rect bbox, int ismap, fz_obj *page, fz_obj *uri return fz_outofmem; link->rect = bbox; - link->ismap = ismap; - link->page = page ? fz_keepobj(page) : nil; - link->uri = uri ? fz_keepobj(uri) : nil; + link->dest = fz_keepobj(dest); link->next = nil; *linkp = link; @@ -31,27 +29,27 @@ pdf_droplink(pdf_link *link) { if (link->next) pdf_droplink(link->next); - if (link->page) - fz_dropobj(link->page); - if (link->uri) - fz_dropobj(link->uri); + if (link->dest) + fz_dropobj(link->dest); fz_free(link); } static fz_obj * resolvedest(pdf_xref *xref, fz_obj *dest) { - if (fz_isname(dest) && xref->dests) + if (fz_isname(dest)) { - dest = pdf_lookupname(xref->dests, dest); - pdf_resolve(&dest, xref); /* XXX */ + dest = fz_dictget(xref->dests, dest); + if (dest) + pdf_resolve(&dest, xref); /* XXX */ return resolvedest(xref, dest); } - else if (fz_isstring(dest) && xref->dests) + else if (fz_isstring(dest)) { - dest = pdf_lookupname(xref->dests, dest); - pdf_resolve(&dest, xref); /* XXX */ + dest = fz_dictget(xref->dests, dest); + if (dest) + pdf_resolve(&dest, xref); /* XXX */ return resolvedest(xref, dest); } @@ -72,30 +70,31 @@ resolvedest(pdf_xref *xref, fz_obj *dest) return nil; } -static fz_error * -loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict) +fz_error * +pdf_loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict) { fz_error *error; pdf_link *link; - fz_obj *page; - fz_obj *uri; + fz_obj *dest; fz_obj *action; fz_obj *obj; fz_rect bbox; - int ismap; pdf_logpage("load link {\n"); link = nil; - page = nil; - uri = nil; - ismap = 0; + dest = nil; obj = fz_dictgets(dict, "Rect"); - bbox = pdf_torect(obj); - pdf_logpage("rect [%g %g %g %g]\n", - bbox.min.x, bbox.min.y, - bbox.max.x, bbox.max.y); + if (obj) + { + bbox = pdf_torect(obj); + pdf_logpage("rect [%g %g %g %g]\n", + bbox.min.x, bbox.min.y, + bbox.max.x, bbox.max.y); + } + else + bbox = fz_emptyrect; obj = fz_dictgets(dict, "Dest"); if (obj) @@ -103,8 +102,8 @@ loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict) error = pdf_resolve(&obj, xref); if (error) return error; - page = resolvedest(xref, obj); - pdf_logpage("dest %d %d R\n", fz_tonum(page), fz_togen(page)); + dest = resolvedest(xref, obj); + pdf_logpage("dest %d %d R\n", fz_tonum(dest), fz_togen(dest)); fz_dropobj(obj); } @@ -118,14 +117,13 @@ loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict) obj = fz_dictgets(action, "S"); if (!strcmp(fz_toname(obj), "GoTo")) { - page = resolvedest(xref, fz_dictgets(action, "D")); - pdf_logpage("action goto %d %d R\n", fz_tonum(page), fz_togen(page)); + dest = resolvedest(xref, fz_dictgets(action, "D")); + pdf_logpage("action goto %d %d R\n", fz_tonum(dest), fz_togen(dest)); } else if (!strcmp(fz_toname(obj), "URI")) { - uri = fz_dictgets(action, "URI"); - ismap = fz_tobool(fz_dictgets(action, "IsMap")); - pdf_logpage("action uri ismap=%d\n", ismap); + dest = fz_dictgets(action, "URI"); + pdf_logpage("action uri %s\n", fz_tostrbuf(dest)); } else pdf_logpage("action ... ?\n"); @@ -135,12 +133,11 @@ loadlink(pdf_link **linkp, pdf_xref *xref, fz_obj *dict) pdf_logpage("}\n"); - if (page || uri) + if (dest) { - error = pdf_newlink(&link, bbox, ismap, page, uri); + error = pdf_newlink(&link, bbox, dest); if (error) return error; - link->next = *linkp; *linkp = link; } @@ -171,14 +168,27 @@ pdf_loadannots(pdf_comment **cp, pdf_link **lp, pdf_xref *xref, fz_obj *annots) subtype = fz_dictgets(obj, "Subtype"); if (!strcmp(fz_toname(subtype), "Link")) - error = loadlink(&link, xref, obj); + { + pdf_link *temp = nil; + + error = pdf_loadlink(&temp, xref, obj); + fz_dropobj(obj); + if (error) + goto cleanup; + + if (temp) + { + temp->next = link; + link = temp; + } + } else + { error = loadcomment(&comment, xref, obj); - - fz_dropobj(obj); - - if (error) - goto cleanup; + fz_dropobj(obj); + if (error) + goto cleanup; + } } pdf_logpage("}\n"); diff --git a/mupdf/build.c b/mupdf/build.c index 93d1a26d..2c56e484 100644 --- a/mupdf/build.c +++ b/mupdf/build.c @@ -770,8 +770,8 @@ pdf_showtext(pdf_csi *csi, fz_obj *text) return nil; } - buf = fz_tostringbuf(text); - len = fz_tostringlen(text); + buf = fz_tostrbuf(text); + len = fz_tostrlen(text); end = buf + len; while (buf < end) diff --git a/mupdf/colorspace1.c b/mupdf/colorspace1.c index e9c384b9..e98beaa1 100644 --- a/mupdf/colorspace1.c +++ b/mupdf/colorspace1.c @@ -617,14 +617,14 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) return fz_outofmem; } - if (fz_isstring(lookup) && fz_tostringlen(lookup) == n) + if (fz_isstring(lookup) && fz_tostrlen(lookup) == n) { unsigned char *buf; int i; pdf_logrsrc("string lookup\n"); - buf = fz_tostringbuf(lookup); + buf = fz_tostrbuf(lookup); for (i = 0; i < n; i++) cs->lookup[i] = buf[i]; } diff --git a/mupdf/crypt.c b/mupdf/crypt.c index 03633c9e..d0cf1084 100644 --- a/mupdf/crypt.c +++ b/mupdf/crypt.c @@ -70,14 +70,14 @@ pdf_newdecrypt(pdf_crypt **cp, fz_obj *enc, fz_obj *id) crypt->id = nil; obj = fz_dictgets(enc, "O"); - if (!fz_isstring(obj) || fz_tostringlen(obj) != 32) + if (!fz_isstring(obj) || fz_tostrlen(obj) != 32) goto cleanup; - memcpy(crypt->o, fz_tostringbuf(obj), 32); + memcpy(crypt->o, fz_tostrbuf(obj), 32); obj = fz_dictgets(enc, "U"); - if (!fz_isstring(obj) || fz_tostringlen(obj) != 32) + if (!fz_isstring(obj) || fz_tostrlen(obj) != 32) goto cleanup; - memcpy(crypt->u, fz_tostringbuf(obj), 32); + memcpy(crypt->u, fz_tostrbuf(obj), 32); obj = fz_dictgets(enc, "P"); if (!fz_isint(obj)) @@ -179,7 +179,7 @@ createkey(pdf_crypt *crypt, char *userpw) fz_md5update(&md5, buf, 4); /* Step 5 */ - fz_md5update(&md5, fz_tostringbuf(crypt->id), fz_tostringlen(crypt->id)); + fz_md5update(&md5, fz_tostrbuf(crypt->id), fz_tostrlen(crypt->id)); fz_md5final(&md5, crypt->key); /* Step 6 (rev 3 only) */ @@ -255,7 +255,7 @@ createuser(pdf_crypt *crypt, char *userpw) fz_md5update(&md5, padding, 32); /* Step 3 */ - fz_md5update(&md5, fz_tostringbuf(crypt->id), fz_tostringlen(crypt->id)); + fz_md5update(&md5, fz_tostrbuf(crypt->id), fz_tostrlen(crypt->id)); fz_md5final(&md5, key); /* Step 4 */ @@ -349,8 +349,8 @@ pdf_cryptobj(pdf_crypt *crypt, fz_obj *obj, int oid, int gid) int i, n; if (fz_isstring(obj)) { - s = fz_tostringbuf(obj); - n = fz_tostringlen(obj); + s = fz_tostrbuf(obj); + n = fz_tostrlen(obj); createobjkey(crypt, oid, gid, key); fz_arc4init(&arc4, key, crypt->keylen); fz_arc4encrypt(&arc4, s, s, n); diff --git a/mupdf/font.c b/mupdf/font.c index 5c6aac57..d92ffe50 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -604,16 +604,16 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj return error; obj = fz_dictgets(cidinfo, "Registry"); - tmplen = MIN(sizeof tmpstr - 1, fz_tostringlen(obj)); - memcpy(tmpstr, fz_tostringbuf(obj), tmplen); + tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); + memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; strlcpy(collection, tmpstr, sizeof collection); strlcat(collection, "-", sizeof collection); obj = fz_dictgets(cidinfo, "Ordering"); - tmplen = MIN(sizeof tmpstr - 1, fz_tostringlen(obj)); - memcpy(tmpstr, fz_tostringbuf(obj), tmplen); + tmplen = MIN(sizeof tmpstr - 1, fz_tostrlen(obj)); + memcpy(tmpstr, fz_tostrbuf(obj), tmplen); tmpstr[tmplen] = '\0'; strlcat(collection, tmpstr, sizeof collection); diff --git a/mupdf/fontenc.c b/mupdf/fontenc.c index cdf082d7..7de7b5e9 100644 --- a/mupdf/fontenc.c +++ b/mupdf/fontenc.c @@ -24,6 +24,42 @@ void pdf_loadencoding(char **estrings, char *encoding) estrings[i] = bstrings[i]; } +unsigned short pdf_docencoding[256] = +{ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x02d8, 0x02c7, 0x02c6, 0x02d9, 0x02dd, 0x02db, 0x02da, 0x02dc, + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, + 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f, + 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, + 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, + 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, + 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f, + 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, + 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f, + 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, + 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f, + 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, + 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0000, + 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x0192, 0x2044, + 0x2039, 0x203a, 0x2212, 0x2030, 0x201e, 0x201c, 0x201d, 0x2018, + 0x2019, 0x201a, 0x2122, 0xfb01, 0xfb02, 0x0141, 0x0152, 0x0160, + 0x0178, 0x017d, 0x0131, 0x0142, 0x0153, 0x0161, 0x017e, 0x0000, + 0x20ac, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x0000, 0x00ae, 0x00af, + 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf, + 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7, + 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, + 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, + 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df, + 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, + 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, + 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, + 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff +}; + char *pdf_macroman[256] = { _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, _notdef, diff --git a/mupdf/fontfile.c b/mupdf/fontfile.c index e5e4e3a8..5c894c75 100644 --- a/mupdf/fontfile.c +++ b/mupdf/fontfile.c @@ -83,10 +83,10 @@ static struct subent fontsubs[] = { GB, MINCHO, "mingliu.ttc" }, { GB, GOTHIC, "mingliu.ttc" }, - { Japan, MINCHO, "\343\203\222\343\203\251\343\202\255\343\202\231\343\203\216\346\230\216\346\234\235 Pro W3.otf" }, - { Japan, GOTHIC, "\343\203\222\343\203\251\343\202\255\343\202\231\343\203\216\350\247\222\343\202\263\343\202\231 Pro W3.otf" }, { Japan, MINCHO, "kochi-mincho.ttf" }, { Japan, GOTHIC, "kochi-gothic.ttf" }, + { Japan, MINCHO, "\343\203\222\343\203\251\343\202\255\343\202\231\343\203\216\346\230\216\346\234\235 Pro W3.otf" }, + { Japan, GOTHIC, "\343\203\222\343\203\251\343\202\255\343\202\231\343\203\216\350\247\222\343\202\263\343\202\231 Pro W3.otf" }, { Japan, MINCHO, "msmincho.ttc" }, { Japan, GOTHIC, "msgothic.ttc" }, diff --git a/mupdf/nametree.c b/mupdf/nametree.c index b806ec83..1b766e64 100644 --- a/mupdf/nametree.c +++ b/mupdf/nametree.c @@ -2,24 +2,7 @@ #include <mupdf.h> static fz_error * -grownametree(pdf_nametree *tree, int amount) -{ - struct fz_keyval_s *newitems; - int newcap; - - newcap = tree->cap + amount; - newitems = fz_realloc(tree->items, sizeof(struct fz_keyval_s) * newcap); - if (!newitems) - return fz_outofmem; - - tree->items = newitems; - tree->cap = newcap; - - return nil; -} - -static fz_error * -loadnametreenode(pdf_nametree *tree, pdf_xref *xref, fz_obj *node) +loadnametreenode(fz_obj *tree, pdf_xref *xref, fz_obj *node) { fz_error *error; fz_obj *names; @@ -41,21 +24,16 @@ loadnametreenode(pdf_nametree *tree, pdf_xref *xref, fz_obj *node) len = fz_arraylen(names) / 2; - error = grownametree(tree, len); - if (error) - { - fz_dropobj(names); - goto cleanup; - } - for (i = 0; i < len; ++i) { key = fz_arrayget(names, i * 2 + 0); val = fz_arrayget(names, i * 2 + 1); - - tree->items[tree->len].k = fz_keepobj(key); - tree->items[tree->len].v = fz_keepobj(val); - tree->len ++; + error = fz_dictput(tree, key, val); + if (error) + { + fz_dropobj(names); + goto cleanup; + } } fz_dropobj(names); @@ -90,130 +68,61 @@ cleanup: return error; } -void -pdf_dropnametree(pdf_nametree *tree) -{ - int i; - for (i = 0; i < tree->len; i++) - { - fz_dropobj(tree->items[i].k); - fz_dropobj(tree->items[i].v); - } - fz_free(tree->items); - fz_free(tree); -} - fz_error * -pdf_loadnametree(pdf_nametree **treep, pdf_xref *xref, fz_obj *root) +pdf_loadnametree(fz_obj **dictp, pdf_xref *xref, fz_obj *root) { fz_error *error; - pdf_nametree *tree; - - tree = fz_malloc(sizeof(pdf_nametree)); - if (!tree) - return fz_outofmem; + fz_obj *tree; - tree->len = 0; - tree->cap = 0; - tree->items = nil; + error = fz_newdict(&tree, 128); + if (error) + return error; error = loadnametreenode(tree, xref, root); if (error) { - pdf_dropnametree(tree); + fz_dropobj(tree); return error; } - *treep = tree; - return nil; -} - -void -pdf_debugnametree(pdf_nametree *tree) -{ - int i; - for (i = 0; i < tree->len; i++) { - printf(" "); - fz_debugobj(tree->items[i].k); - printf(" "); - fz_debugobj(tree->items[i].v); - printf("\n"); - } -} - -static fz_obj * -lookup(pdf_nametree *tree, char *namestr, int namelen) -{ - int l = 0; - int r = tree->len - 1; - - while (l <= r) - { - int m = (l + r) >> 1; - char *keystr = fz_tostringbuf(tree->items[m].k); - int keylen = fz_tostringlen(tree->items[m].k); - int cmplen = MIN(namelen, keylen); - int c = strncmp(namestr, keystr, cmplen); - if (c < 0) - r = m - 1; - else if (c > 0) - l = m + 1; - else - return tree->items[m].v; - } +// fz_sortdict(tree); + *dictp = tree; return nil; } -fz_obj * -pdf_lookupname(pdf_nametree *tree, fz_obj *name) -{ - return lookup(tree, fz_tostringbuf(name), fz_tostringlen(name)); -} - -fz_obj * -pdf_lookupnames(pdf_nametree *tree, char *name) -{ - return lookup(tree, name, strlen(name)); -} - fz_error * pdf_loadnametrees(pdf_xref *xref) { fz_error *error; - fz_obj *catalog; fz_obj *names; fz_obj *dests; - catalog = fz_dictgets(xref->trailer, "Root"); - error = pdf_resolve(&catalog, xref); - if (error) - return error; + /* PDF 1.1 */ + dests = fz_dictgets(xref->root, "Dests"); + if (dests) + { + error = pdf_resolve(&dests, xref); + if (error) + return error; + xref->dests = dests; + return nil; + } - names = fz_dictgets(catalog, "Names"); + /* PDF 1.2 */ + names = fz_dictgets(xref->root, "Names"); if (names) { error = pdf_resolve(&names, xref); if (error) - { - fz_dropobj(names); - fz_dropobj(catalog); return error; - } - dests = fz_dictgets(names, "Dests"); error = pdf_loadnametree(&xref->dests, xref, dests); + fz_dropobj(names); if (error) - { - fz_dropobj(names); - fz_dropobj(catalog); return error; - } - - fz_dropobj(names); } - fz_dropobj(catalog); return nil; } diff --git a/mupdf/open.c b/mupdf/open.c index 840690b4..34caa862 100644 --- a/mupdf/open.c +++ b/mupdf/open.c @@ -473,51 +473,35 @@ cleanup1: } /* - * open xref in normal mode (as opposed to repair mode) + * open and load xref tables from pdf */ fz_error * -pdf_openpdf(pdf_xref **xrefp, char *filename) +pdf_loadxref(pdf_xref *xref, char *filename) { fz_error *error; - pdf_xref *xref; fz_obj *size; int i; char buf[65536]; /* yeowch! */ - xref = fz_malloc(sizeof(pdf_xref)); - if (!xref) - return fz_outofmem; - memset(xref, 0, sizeof(pdf_xref)); - - xref->file = nil; - xref->version = 1.0; - xref->startxref = 0; - xref->trailer = nil; - xref->crypt = nil; - - xref->len = 0; - xref->cap = 0; - xref->table = nil; - - pdf_logxref("openxref '%s' %p\n", filename, xref); + pdf_logxref("loadxref '%s' %p\n", filename, xref); error = fz_openfile(&xref->file, filename, FZ_READ); if (error) - goto cleanup; + return error; error = loadversion(xref); if (error) - goto cleanup; + return error; error = readstartxref(xref); if (error) - goto cleanup; + return error; error = readtrailer(xref, buf, sizeof buf); if (error) - goto cleanup; + return error; size = fz_dictgets(xref->trailer, "Size"); if (!size) @@ -525,9 +509,10 @@ pdf_openpdf(pdf_xref **xrefp, char *filename) pdf_logxref(" size %d\n", fz_toint(size)); + assert(xref->table == nil); + xref->cap = fz_toint(size); xref->len = fz_toint(size); - xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry)); if (!xref->table) return fz_outofmem; @@ -545,19 +530,8 @@ pdf_openpdf(pdf_xref **xrefp, char *filename) error = readxrefsections(xref, xref->startxref, buf, sizeof buf); if (error) - goto cleanup; - - error = pdf_newstore(&xref->store); - if (error) - goto cleanup; - - xref->dests = nil; + return error; - *xrefp = xref; return nil; - -cleanup: - pdf_closepdf(xref); - return error; } diff --git a/mupdf/outline.c b/mupdf/outline.c index fa8fffed..c41d96f5 100644 --- a/mupdf/outline.c +++ b/mupdf/outline.c @@ -2,187 +2,141 @@ #include <mupdf.h> static fz_error * -loadoutlinetree(pdf_xref *xref, pdf_outline *outline, fz_obj *obj) +loadoutline(pdf_outline **nodep, pdf_xref *xref, fz_obj *dict) { -/*XXX please call this 'error' */ - fz_error *err; - fz_obj *first; - fz_obj *next; - fz_obj *ref; - fz_obj *t; - pdf_outline *o; - int i; - - t = fz_dictgets(obj, "Title"); -/*XXX check for failure after each malloc */ - outline->title = fz_malloc(sizeof(char) * fz_tostringlen(t) + 1); -/*XXX use strlcpy instead. strncpy does not null terminate. */ - strncpy(outline->title, fz_tostringbuf(t), fz_tostringlen(t)); - outline->title[fz_tostringlen(t)] = 0; - - t = fz_dictgets(obj, "Count"); - outline->count = fz_toint(t); - - outline->dest = fz_dictgets(obj, "Dest"); - if (outline->dest) fz_keepobj(outline->dest); - outline->a = fz_dictgets(obj, "A"); - if (outline->a) fz_keepobj(outline->a); - outline->se = fz_dictgets(obj, "SE"); - if (outline->se) fz_keepobj(outline->se); - - t = fz_dictgets(obj, "C"); - if (t) { - for (i = 0; i < 3; i++) - outline->c[i] = fz_toreal(fz_arrayget(t, i)); - } else { - for (i = 0; i < 3; i++) - outline->c[i] = 0.; - } - - t = fz_dictgets(obj, "F"); - if (t) - outline->f = fz_toint(t); + fz_error *error; + pdf_outline *node; + fz_obj *obj; - first = fz_dictgets(obj, "First"); - if (first) { - err = pdf_loadindirect(&ref, xref, first); - if (err) return err; + node = fz_malloc(sizeof(pdf_outline)); + node->title = "<unknown>"; + node->link = nil; + node->child = nil; + node->next = nil; - o = fz_malloc(sizeof(pdf_outline)); -/*XXX you leak ref */ - if (!o) { err = fz_outofmem; return err; } + pdf_logpage("load outline {\n"); - loadoutlinetree(xref, o, ref); -/*XXX check error return */ - - outline->first = o; - - fz_dropobj(ref); - } else { - outline->first = nil; + obj = fz_dictgets(dict, "Title"); + if (obj) + { + error = pdf_toutf8(&node->title, obj); + if (error) + return error; + pdf_logpage("title %s\n", node->title); } - next = fz_dictgets(obj, "Next"); - if (next) { - err = pdf_loadindirect(&ref, xref, next); - if (err) return err; + if (fz_dictgets(dict, "Dest") || fz_dictgets(dict, "A")) + { + error = pdf_loadlink(&node->link, xref, dict); + if (error) + return error; + } - o = fz_malloc(sizeof(pdf_outline)); -/*XXX you leak ref */ - if (!o) { err = fz_outofmem; return err; } + obj = fz_dictgets(dict, "First"); + if (obj) + { + error = pdf_resolve(&obj, xref); + if (error) + return error; + error = loadoutline(&node->child, xref, obj); + fz_dropobj(obj); + if (error) + return error; + } - loadoutlinetree(xref, o, ref); -/*XXX check error return? */ - - outline->next = o; + pdf_logpage("}\n"); - fz_dropobj(ref); - } else { - outline->next = nil; + obj = fz_dictgets(dict, "Next"); + if (obj) + { + error = pdf_resolve(&obj, xref); + if (error) + return error; + error = loadoutline(&node->next, xref, obj); + fz_dropobj(obj); + if (error) + return error; } + *nodep = node; return nil; } fz_error * -pdf_loadoutlinetree(pdf_outlinetree **oo, pdf_xref *xref) +pdf_loadoutline(pdf_outline **nodep, pdf_xref *xref) { -/*XXX please rename to 'error' */ - fz_error *err; - pdf_outlinetree *o = nil; - fz_obj *outline = nil; - fz_obj *catalog = nil; - fz_obj *outlines = nil; - fz_obj *trailer; - fz_obj *ref; - int count; - - trailer = xref->trailer; - - ref = fz_dictgets(trailer, "Root"); - err = pdf_loadindirect(&catalog, xref, ref); - if (err) goto error; - -/*XXX create empty tree if no outlines exist instead of failing? */ - ref = fz_dictgets(catalog, "Outlines"); - if (!ref) goto error; - err = pdf_loadindirect(&outlines, xref, ref); - if (err) goto error; - - ref = fz_dictgets(outlines, "Count"); - count = fz_toint(ref); - - o = *oo = fz_malloc(sizeof(pdf_outlinetree)); - if (!o) { err = fz_outofmem; goto error; } - - o->count = count; - o->first = fz_malloc(sizeof(pdf_outline)); - if (!o->first) { err = fz_outofmem; goto error; } - - ref = fz_dictgets(outlines, "First"); - err = pdf_loadindirect(&outline, xref, ref); -/*XXX check error */ - err = loadoutlinetree(xref, o->first, outline); - if (err) goto error; - - fz_dropobj(outline); - fz_dropobj(outlines); - fz_dropobj(catalog); - return nil; + fz_error *error; + pdf_outline *node; + fz_obj *obj; + fz_obj *first; + + pdf_logpage("load outlines {\n"); + + node = nil; + + obj = fz_dictgets(xref->root, "Outlines"); + if (obj) + { + error = pdf_resolve(&obj, xref); + if (error) + return error; + + first = fz_dictgets(obj, "First"); + if (first) + { + error = pdf_resolve(&first, xref); + fz_dropobj(obj); + if (error) + return error; + error = loadoutline(&node, xref, first); + fz_dropobj(first); + if (error) + return error; + } + else + fz_dropobj(obj); + } + + pdf_logpage("}\n"); -error: - if (outlines) fz_dropobj(outlines); - if (catalog) fz_dropobj(catalog); - if (o) fz_free(o); + *nodep = node; return nil; } void pdf_dropoutline(pdf_outline *outline) { - if (outline->first) - pdf_dropoutline(outline->first); + if (outline->child) + pdf_dropoutline(outline->child); if (outline->next) pdf_dropoutline(outline->next); - + pdf_droplink(outline->link); fz_free(outline->title); - if (outline->dest) fz_dropobj(outline->dest); - if (outline->a) fz_dropobj(outline->a); - if (outline->se) fz_dropobj(outline->se); - fz_free(outline); } void -pdf_dropoutlinetree(pdf_outlinetree *outlinetree) -{ - if (outlinetree->first) - pdf_dropoutline(outlinetree->first); - fz_free(outlinetree); -} - -static void -debugoutline(pdf_outline *outline, int level) +pdf_debugoutline(pdf_outline *outline, int level) { int i; while (outline) { - for (i = 0; i < level; i++) putchar(' '); - printf("(%s) ", outline->title); - if (outline->dest) - fz_debugobj(outline->dest); - if (outline->a) - fz_debugobj(outline->a); + for (i = 0; i < level; i++) + putchar(' '); + + printf("%s ", outline->title); + + if (outline->link) + fz_debugobj(outline->link->dest); + else + printf("<nil>"); + printf("\n"); - if (outline->first) - debugoutline(outline->first, level + 2); + + if (outline->child) + pdf_debugoutline(outline->child, level + 2); + outline = outline->next; } } -void -pdf_debugoutlinetree(pdf_outlinetree *outlinetree) -{ - debugoutline(outlinetree->first, 0); -} - diff --git a/mupdf/parse.c b/mupdf/parse.c index 32d8b698..ba2fcf2c 100644 --- a/mupdf/parse.c +++ b/mupdf/parse.c @@ -28,6 +28,55 @@ fz_matrix pdf_tomatrix(fz_obj *array) } fz_error * +pdf_toutf8(char **dstp, fz_obj *src) +{ + unsigned char *srcptr = fz_tostrbuf(src); + char *dstptr; + int srclen = fz_tostrlen(src); + int dstlen = 0; + int ucs; + int i; + + if (srclen > 2 && srcptr[0] == 254 && srcptr[1] == 255) + { + for (i = 2; i < srclen; i += 2) + { + ucs = (srcptr[i] << 8) | srcptr[i+1]; + dstlen += runelen(srcptr[i]); + } + + dstptr = *dstp = fz_malloc(dstlen + 1); + if (!dstptr) + return fz_outofmem; + + for (i = 2; i < srclen; i += 2) + { + ucs = (srcptr[i] << 8) | srcptr[i+1]; + dstptr += runetochar(dstptr, &ucs); + } + } + + else + { + for (i = 0; i < srclen; i++) + dstlen += runelen(srcptr[i]); + + dstptr = *dstp = fz_malloc(dstlen + 1); + if (!dstptr) + return fz_outofmem; + + for (i = 0; i < srclen; i++) + { + ucs = srcptr[i]; + dstptr += runetochar(dstptr, &ucs); + } + } + + *dstptr = '\0'; + return nil; +} + +fz_error * pdf_parsearray(fz_obj **op, fz_file *file, char *buf, int cap) { fz_error *error = nil; diff --git a/mupdf/repair.c b/mupdf/repair.c index bd0f6add..e533d826 100644 --- a/mupdf/repair.c +++ b/mupdf/repair.c @@ -1,6 +1,10 @@ #include <fitz.h> #include <mupdf.h> +/* + * open pdf and scan objects to reconstruct xref table + */ + struct entry { int oid; @@ -101,10 +105,9 @@ atobjend: } fz_error * -pdf_repairpdf(pdf_xref **xrefp, char *filename) +pdf_repairxref(pdf_xref *xref, char *filename) { fz_error *error; - pdf_xref *xref; fz_file *file; struct entry *list = nil; @@ -124,22 +127,11 @@ pdf_repairpdf(pdf_xref **xrefp, char *filename) int next; int i; - xref = fz_malloc(sizeof(pdf_xref)); - if (!xref) - return fz_outofmem; - memset(xref, 0, sizeof(pdf_xref)); - - xref->file = nil; - xref->version = 0.0; - xref->startxref = 0; - xref->trailer = nil; - xref->crypt = nil; - - pdf_logxref("repairxref '%s' %p\n", filename, xref); - error = fz_openfile(&file, filename, FZ_READ); if (error) - goto cleanup; + return error; + + pdf_logxref("repairxref '%s' %p\n", filename, xref); xref->file = file; @@ -224,11 +216,11 @@ pdf_repairpdf(pdf_xref **xrefp, char *filename) if (error) goto cleanup; - xref->version = 1.3; /* FIXME */ xref->len = maxoid + 1; xref->cap = xref->len; xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry)); - if (!xref->table) { + if (!xref->table) + { error = fz_outofmem; goto cleanup; } @@ -300,18 +292,10 @@ pdf_repairpdf(pdf_xref **xrefp, char *filename) fz_free(list); - error = pdf_newstore(&xref->store); - if (error) - goto cleanup; - - xref->dests = nil; - - *xrefp = xref; return nil; cleanup: fz_closefile(file); - fz_free(xref); fz_free(list); return error; } diff --git a/mupdf/save.c b/mupdf/save.c index aaa02a75..344d942c 100644 --- a/mupdf/save.c +++ b/mupdf/save.c @@ -104,7 +104,7 @@ static int countmodified(pdf_xref *xref, int oid) } fz_error * -pdf_updatepdf(pdf_xref *xref, char *path) +pdf_updatexref(pdf_xref *xref, char *path) { fz_error *error; fz_file *out; @@ -207,7 +207,7 @@ cleanup: } fz_error * -pdf_savepdf(pdf_xref *xref, char *path, pdf_crypt *encrypt) +pdf_savexref(pdf_xref *xref, char *path, pdf_crypt *encrypt) { fz_error *error; fz_file *out; diff --git a/mupdf/store.c b/mupdf/store.c index bfeb5bff..d46cd628 100644 --- a/mupdf/store.c +++ b/mupdf/store.c @@ -172,7 +172,7 @@ pdf_finditem(pdf_store *store, pdf_itemkind kind, fz_obj *key) else { for (item = store->root; item; item = item->next) - if (item->kind == kind && !fz_cmpobj(item->key, key)) + if (item->kind == kind && !fz_objcmp(item->key, key)) return item->val; } diff --git a/mupdf/xref.c b/mupdf/xref.c index 29972b8f..2c92bbe6 100644 --- a/mupdf/xref.c +++ b/mupdf/xref.c @@ -6,7 +6,7 @@ */ fz_error * -pdf_newpdf(pdf_xref **xrefp) +pdf_newxref(pdf_xref **xrefp) { fz_error *error; pdf_xref *xref; @@ -19,31 +19,24 @@ pdf_newpdf(pdf_xref **xrefp) pdf_logxref("newxref %p\n", xref); xref->file = nil; - xref->version = 1.3; + xref->version = 1.0; xref->startxref = 0; - xref->trailer = nil; xref->crypt = nil; - xref->cap = 256; - xref->len = 1; - xref->table = fz_malloc(xref->cap * sizeof(pdf_xrefentry)); - if (!xref->table) { - fz_free(xref); - return fz_outofmem; - } + xref->trailer = nil; + xref->root = nil; + xref->info = nil; + xref->dests = nil; + xref->store = nil; - xref->table[0].type = 'f'; - xref->table[0].mark = 0; - xref->table[0].ofs = 0; - xref->table[0].gen = 65535; - xref->table[0].stmbuf = nil; - xref->table[0].stmofs = 0; - xref->table[0].obj = nil; + xref->cap = 0; + xref->len = 0; + xref->table = nil; error = pdf_newstore(&xref->store); if (error) { - pdf_closepdf(xref); + pdf_closexref(xref); return error; } @@ -51,40 +44,37 @@ pdf_newpdf(pdf_xref **xrefp) return nil; } -fz_error * -pdf_decryptpdf(pdf_xref *xref) +void +pdf_closexref(pdf_xref *xref) { - fz_error *error; - fz_obj *encrypt; - fz_obj *id; + pdf_logxref("closexref %p\n", xref); - encrypt = fz_dictgets(xref->trailer, "Encrypt"); - id = fz_dictgets(xref->trailer, "ID"); + if (xref->store) + pdf_dropstore(xref->store); - if (encrypt && id) + if (xref->table) { - error = pdf_resolve(&encrypt, xref); - if (error) - return error; + pdf_flushxref(xref, 1); + fz_free(xref->table); + } - error = pdf_resolve(&id, xref); - if (error) - { - fz_dropobj(encrypt); - return error; - } + if (xref->file) + fz_closefile(xref->file); - error = pdf_newdecrypt(&xref->crypt, encrypt, id); - fz_dropobj(encrypt); - fz_dropobj(id); - return error; - } + if (xref->trailer) + fz_dropobj(xref->trailer); + if (xref->root) + fz_dropobj(xref->root); + if (xref->info) + fz_dropobj(xref->info); + if (xref->dests) + fz_dropobj(xref->dests); - return nil; + fz_free(xref); } void -pdf_flushpdf(pdf_xref *xref, int force) +pdf_flushxref(pdf_xref *xref, int force) { int i; @@ -112,7 +102,7 @@ pdf_flushpdf(pdf_xref *xref, int force) fz_dropbuffer(xref->table[i].stmbuf); xref->table[i].stmbuf = nil; } - if (xref->table[i].obj && xref->table[i].stmbuf->refs == 1) + if (xref->table[i].obj && xref->table[i].obj->refs == 1) { fz_dropobj(xref->table[i].obj); xref->table[i].obj = nil; @@ -122,30 +112,7 @@ pdf_flushpdf(pdf_xref *xref, int force) } void -pdf_closepdf(pdf_xref *xref) -{ - pdf_logxref("closexref %p\n", xref); - - if (xref->store) - pdf_dropstore(xref->store); - - if (xref->table) - { - pdf_flushpdf(xref, 1); - fz_free(xref->table); - } - - if (xref->file) - fz_closefile(xref->file); - - if (xref->trailer) - fz_dropobj(xref->trailer); - - fz_free(xref); -} - -void -pdf_debugpdf(pdf_xref *xref) +pdf_debugxref(pdf_xref *xref) { int i; printf("xref\n0 %d\n", xref->len); @@ -161,6 +128,39 @@ pdf_debugpdf(pdf_xref *xref) } } +/* ICKY! */ +fz_error * +pdf_decryptxref(pdf_xref *xref) +{ + fz_error *error; + fz_obj *encrypt; + fz_obj *id; + + encrypt = fz_dictgets(xref->trailer, "Encrypt"); + id = fz_dictgets(xref->trailer, "ID"); + + if (encrypt && id) + { + error = pdf_resolve(&encrypt, xref); + if (error) + return error; + + error = pdf_resolve(&id, xref); + if (error) + { + fz_dropobj(encrypt); + return error; + } + + error = pdf_newdecrypt(&xref->crypt, encrypt, id); + fz_dropobj(encrypt); + fz_dropobj(id); + return error; + } + + return nil; +} + /* * mutate objects */ diff --git a/object/dict.c b/object/dict.c index c41dbab1..a0fb6d25 100644 --- a/object/dict.c +++ b/object/dict.c @@ -1,6 +1,26 @@ #include <fitz.h> -void fz_dropdict(fz_obj *obj); +/* keep either names or strings in the dict. don't mix & match. */ + +static int keyvalcmp(const void *ap, const void *bp) +{ + const fz_keyval *a = ap; + const fz_keyval *b = bp; + if (fz_isname(a->k)) + return strcmp(fz_toname(a->k), fz_toname(b->k)); + if (fz_isstring(a->k)) + return strcmp(fz_tostrbuf(a->k), fz_tostrbuf(b->k)); + return -1; +} + +static inline int keystrcmp(fz_obj *key, char *s) +{ + if (fz_isname(key)) + return strcmp(fz_toname(key), s); + if (fz_isstring(key)) + return strcmp(fz_tostrbuf(key), s); + return -1; +} fz_error * fz_newdict(fz_obj **op, int initialcap) @@ -14,10 +34,11 @@ fz_newdict(fz_obj **op, int initialcap) obj->refs = 1; obj->kind = FZ_DICT; + obj->u.d.sorted = 1; obj->u.d.len = 0; obj->u.d.cap = initialcap > 0 ? initialcap : 10; - obj->u.d.items = fz_malloc(sizeof(struct fz_keyval_s) * obj->u.d.cap); + obj->u.d.items = fz_malloc(sizeof(fz_keyval) * obj->u.d.cap); if (!obj->u.d.items) { fz_free(obj); return fz_outofmem; } for (i = 0; i < obj->u.d.cap; i++) { @@ -44,7 +65,7 @@ fz_copydict(fz_obj **op, fz_obj *obj) for (i = 0; i < fz_dictlen(obj); i++) { error = fz_dictput(new, fz_dictgetkey(obj, i), fz_dictgetval(obj, i)); - if (error) { fz_dropdict(new); return error; } + if (error) { fz_dropobj(new); return error; } } return nil; @@ -71,23 +92,23 @@ fz_deepcopydict(fz_obj **op, fz_obj *obj) if (fz_isarray(val)) { error = fz_deepcopyarray(&val, val); - if (error) { fz_dropdict(new); return error; } + if (error) { fz_dropobj(new); return error; } error = fz_dictput(new, fz_dictgetkey(obj, i), val); - if (error) { fz_dropobj(val); fz_dropdict(new); return error; } + if (error) { fz_dropobj(val); fz_dropobj(new); return error; } fz_dropobj(val); } else if (fz_isdict(val)) { error = fz_deepcopydict(&val, val); - if (error) { fz_dropdict(new); return error; } + if (error) { fz_dropobj(new); return error; } error = fz_dictput(new, fz_dictgetkey(obj, i), val); - if (error) { fz_dropobj(val); fz_dropdict(new); return error; } + if (error) { fz_dropobj(val); fz_dropobj(new); return error; } fz_dropobj(val); } else { error = fz_dictput(new, fz_dictgetkey(obj, i), val); - if (error) { fz_dropdict(new); return error; } + if (error) { fz_dropobj(new); return error; } } } @@ -97,13 +118,13 @@ fz_deepcopydict(fz_obj **op, fz_obj *obj) static fz_error * growdict(fz_obj *obj) { - struct fz_keyval_s *newitems; + fz_keyval *newitems; int newcap; int i; newcap = obj->u.d.cap * 2; - newitems = fz_realloc(obj->u.d.items, sizeof(struct fz_keyval_s) * newcap); + newitems = fz_realloc(obj->u.d.items, sizeof(fz_keyval) * newcap); if (!newitems) return fz_outofmem; obj->u.d.items = newitems; @@ -148,6 +169,36 @@ fz_dictgetval(fz_obj *obj, int i) return obj->u.d.items[i].v; } +static inline int dictfinds(fz_obj *obj, char *key) +{ + if (obj->u.d.sorted) + { + int l = 0; + int r = obj->u.d.len - 1; + while (l <= r) + { + int m = (l + r) >> 1; + int c = -keystrcmp(obj->u.d.items[m].k, key); + if (c < 0) + r = m - 1; + else if (c > 0) + l = m + 1; + else + return m; + } + } + + else + { + int i; + for (i = 0; i < obj->u.d.len; i++) + if (keystrcmp(obj->u.d.items[i].k, key) == 0) + return i; + } + + return -1; +} + fz_obj * fz_dictgets(fz_obj *obj, char *key) { @@ -156,9 +207,9 @@ fz_dictgets(fz_obj *obj, char *key) if (!fz_isdict(obj)) return nil; - for (i = 0; i < obj->u.d.len; i++) - if (strcmp(fz_toname(obj->u.d.items[i].k), key) == 0) - return obj->u.d.items[i].v; + i = dictfinds(obj, key); + if (i >= 0) + return obj->u.d.items[i].v; return nil; } @@ -166,7 +217,11 @@ fz_dictgets(fz_obj *obj, char *key) fz_obj * fz_dictget(fz_obj *obj, fz_obj *key) { - return fz_dictgets(obj, fz_toname(key)); + if (fz_isname(key)) + return fz_dictgets(obj, fz_toname(key)); + if (fz_isstring(key)) + return fz_dictgets(obj, fz_tostrbuf(key)); + return nil; } fz_obj * @@ -183,29 +238,39 @@ fz_error * fz_dictput(fz_obj *obj, fz_obj *key, fz_obj *val) { fz_error *error; - int i; char *s; + int i; if (!fz_isdict(obj)) return fz_throw("typecheck in dictput"); - if (!fz_isname(key)) - return fz_throw("typecheck in dictput"); - s = fz_toname(key); + if (fz_isname(key)) + s = fz_toname(key); + else if (fz_isstring(key)) + s = fz_tostrbuf(key); + else + return fz_throw("typecheck in dictput"); - for (i = 0; i < obj->u.d.len; i++) { - if (strcmp(fz_toname(obj->u.d.items[i].k), s) == 0) { - fz_dropobj(obj->u.d.items[i].v); - obj->u.d.items[i].v = fz_keepobj(val); - return nil; - } + i = dictfinds(obj, s); + if (i >= 0) + { + fz_dropobj(obj->u.d.items[i].v); + obj->u.d.items[i].v = fz_keepobj(val); + return nil; } - if (obj->u.d.len + 1 > obj->u.d.cap) { + if (obj->u.d.len + 1 > obj->u.d.cap) + { error = growdict(obj); - if (error) return error; + if (error) + return error; } + /* borked! */ + if (obj->u.d.len) + if (keystrcmp(obj->u.d.items[obj->u.d.len - 1].k, s) > 0) + obj->u.d.sorted = 0; + obj->u.d.items[obj->u.d.len].k = fz_keepobj(key); obj->u.d.items[obj->u.d.len].v = fz_keepobj(val); obj->u.d.len ++; @@ -233,13 +298,14 @@ fz_dictdels(fz_obj *obj, char *key) if (!fz_isdict(obj)) return fz_throw("typecheck in dictdel"); - for (i = 0; i < obj->u.d.len; i++) { - if (strcmp(fz_toname(obj->u.d.items[i].k), key) == 0) { - fz_dropobj(obj->u.d.items[i].k); - fz_dropobj(obj->u.d.items[i].v); - obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1]; - obj->u.d.len --; - } + i = dictfinds(obj, key); + if (i >= 0) + { + fz_dropobj(obj->u.d.items[i].k); + fz_dropobj(obj->u.d.items[i].v); + obj->u.d.sorted = 0; + obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1]; + obj->u.d.len --; } return nil; @@ -248,7 +314,12 @@ fz_dictdels(fz_obj *obj, char *key) fz_error * fz_dictdel(fz_obj *obj, fz_obj *key) { - return fz_dictdels(obj, fz_toname(key)); + if (fz_isname(key)) + return fz_dictdels(obj, fz_toname(key)); + else if (fz_isstring(key)) + return fz_dictdels(obj, fz_tostrbuf(key)); + else + return fz_throw("typecheck in dictdel"); } void @@ -270,3 +341,15 @@ fz_dropdict(fz_obj *obj) fz_free(obj); } +void +fz_sortdict(fz_obj *obj) +{ + if (!fz_isdict(obj)) + return; + if (!obj->u.d.sorted) + { + qsort(obj->u.d.items, obj->u.d.len, sizeof(fz_keyval), keyvalcmp); + obj->u.d.sorted = 1; + } +} + diff --git a/object/simple.c b/object/simple.c index d9a0e12e..131e11b4 100644 --- a/object/simple.c +++ b/object/simple.c @@ -44,9 +44,10 @@ fz_newreal(fz_obj **op, float f) fz_error * fz_newstring(fz_obj **op, char *str, int len) { - NEWOBJ(FZ_STRING, offsetof(fz_obj, u.s.buf) + len); + NEWOBJ(FZ_STRING, offsetof(fz_obj, u.s.buf) + len + 1); o->u.s.len = len; memcpy(o->u.s.buf, str, len); + o->u.s.buf[len] = '\0'; return nil; } @@ -78,6 +79,7 @@ fz_newpointer(fz_obj **op, void *p) fz_obj * fz_keepobj(fz_obj *o) { + assert(o != nil); o->refs ++; return o; } @@ -85,6 +87,7 @@ fz_keepobj(fz_obj *o) void fz_dropobj(fz_obj *o) { + assert(o != nil); if (--o->refs == 0) { if (o->kind == FZ_ARRAY) @@ -193,7 +196,7 @@ fz_toname(fz_obj *obj) } char * -fz_tostringbuf(fz_obj *obj) +fz_tostrbuf(fz_obj *obj) { if (fz_isstring(obj)) return obj->u.s.buf; @@ -201,7 +204,7 @@ fz_tostringbuf(fz_obj *obj) } int -fz_tostringlen(fz_obj *obj) +fz_tostrlen(fz_obj *obj) { if (fz_isstring(obj)) return obj->u.s.len; @@ -232,8 +235,17 @@ fz_topointer(fz_obj *obj) return nil; } +fz_error * +fz_newnamefromstring(fz_obj **op, fz_obj *str) +{ + NEWOBJ(FZ_NAME, offsetof(fz_obj, u.n) + fz_tostrlen(str) + 1); + memcpy(o->u.n, fz_tostrbuf(str), fz_tostrlen(str)); + o->u.n[fz_tostrlen(str)] = '\0'; + return nil; +} + int -fz_cmpobj(fz_obj *a, fz_obj *b) +fz_objcmp(fz_obj *a, fz_obj *b) { int i; @@ -264,7 +276,7 @@ fz_cmpobj(fz_obj *a, fz_obj *b) if (a->u.a.len != b->u.a.len) return a->u.a.len - b->u.a.len; for (i = 0; i < a->u.a.len; i++) - if (fz_cmpobj(a->u.a.items[i], b->u.a.items[i])) + if (fz_objcmp(a->u.a.items[i], b->u.a.items[i])) return 1; return 0; @@ -273,9 +285,9 @@ fz_cmpobj(fz_obj *a, fz_obj *b) return a->u.d.len - b->u.d.len; for (i = 0; i < a->u.d.len; i++) { - if (fz_cmpobj(a->u.d.items[i].k, b->u.d.items[i].k)) + if (fz_objcmp(a->u.d.items[i].k, b->u.d.items[i].k)) return 1; - if (fz_cmpobj(a->u.d.items[i].v, b->u.d.items[i].v)) + if (fz_objcmp(a->u.d.items[i].v, b->u.d.items[i].v)) return 1; } return 0; diff --git a/test/pdfclean.c b/test/pdfclean.c index 32acacd9..a55b94ef 100644 --- a/test/pdfclean.c +++ b/test/pdfclean.c @@ -5,7 +5,7 @@ void usage() { fprintf(stderr, "usage: pdfclean [options] infile.pdf outfile.pdf\n" - " -r\treconstruct broken xref table\n" + " -r\trebuild xref table\n" " -g\tgarbage collect unused objects\n" " -x\texpand compressed streams\n" " -d -\tset user password for decryption\n" @@ -118,14 +118,16 @@ int main(int argc, char **argv) infile = argv[optind++]; outfile = argv[optind++]; + error = pdf_newxref(&xref); + if (dorepair) - error = pdf_repairpdf(&xref, infile); + error = pdf_repairxref(xref, infile); else - error = pdf_openpdf(&xref, infile); + error = pdf_loadxref(xref, infile); if (error) fz_abort(error); - error = pdf_decryptpdf(xref); + error = pdf_decryptxref(xref); if (error) fz_abort(error); @@ -157,14 +159,14 @@ int main(int argc, char **argv) pdf_garbagecollect(xref); } - error = pdf_savepdf(xref, outfile, encrypt); + error = pdf_savexref(xref, outfile, encrypt); if (error) fz_abort(error); if (encrypt) pdf_dropcrypt(encrypt); - pdf_closepdf(xref); + pdf_closexref(xref); return 0; } diff --git a/test/pdfdebug.c b/test/pdfdebug.c index eefa0a74..2a18ade7 100644 --- a/test/pdfdebug.c +++ b/test/pdfdebug.c @@ -3,12 +3,11 @@ static char *password = ""; static int dodecode = 0; -static int dorepair = 0; static int doprintxref = 0; void usage() { - fprintf(stderr, "usage: pdfdebug [-drxs] [-u password] file.pdf [oid ...]\n"); + fprintf(stderr, "usage: pdfdebug [-dxs] [-u password] file.pdf [oid ...]\n"); exit(1); } @@ -127,9 +126,6 @@ int main(int argc, char **argv) case 'd': dodecode ++; break; - case 'r': - dorepair ++; - break; case 'x': doprintxref ++; break; @@ -146,14 +142,20 @@ int main(int argc, char **argv) filename = argv[optind++]; - if (dorepair) - error = pdf_repairpdf(&xref, filename); - else - error = pdf_openpdf(&xref, filename); + error = pdf_newxref(&xref); if (error) fz_abort(error); - error = pdf_decryptpdf(xref); + error = pdf_loadxref(xref, filename); + if (error) + { + fz_warn("trying to repair"); + error = pdf_repairxref(xref, filename); + if (error) + fz_abort(error); + } + + error = pdf_decryptxref(xref); if (error) fz_abort(error); @@ -177,9 +179,9 @@ int main(int argc, char **argv) } if (doprintxref) - pdf_debugpdf(xref); + pdf_debugxref(xref); - pdf_closepdf(xref); + pdf_closexref(xref); return 0; } diff --git a/test/x11pdf.c b/test/x11pdf.c index 3200b893..e35f90a6 100644 --- a/test/x11pdf.c +++ b/test/x11pdf.c @@ -24,7 +24,7 @@ static XEvent xevt; static int mapped = 0; static Cursor xcarrow, xchand, xcwait; -static char doctitle[256]; +static char *doctitle = "<untitled>"; static float zoom = 1.0; static int rotate = 0; @@ -43,6 +43,7 @@ static int pagebufidx = 0; static pdf_xref *xref; static pdf_pagetree *pages; +static pdf_outline *outline; static fz_renderer *rast; static fz_pixmap *image; @@ -201,17 +202,21 @@ static void pdfopen(char *filename, char *password) fz_error *error; fz_obj *obj; - error = pdf_openpdf(&xref, filename); + error = pdf_newxref(&xref); + if (error) + fz_abort(error); + + error = pdf_loadxref(xref, filename); if (error) { fz_warn(error->msg); printf("trying to repair...\n"); - error = pdf_repairpdf(&xref, filename); + error = pdf_repairxref(xref, filename); if (error) fz_abort(error); } - error = pdf_decryptpdf(xref); + error = pdf_decryptxref(xref); if (error) fz_abort(error); @@ -221,28 +226,44 @@ static void pdfopen(char *filename, char *password) if (error) fz_abort(error); } - error = pdf_loadnametrees(xref); + obj = fz_dictgets(xref->trailer, "Root"); + if (!obj) + fz_abort(fz_throw("syntaxerror: missing Root object")); + error = pdf_loadindirect(&xref->root, xref, obj); if (error) fz_abort(error); - error = pdf_loadpagetree(&pages, xref); + obj = fz_dictgets(xref->trailer, "Info"); + if (obj) + { + error = pdf_loadindirect(&xref->info, xref, obj); + if (error) fz_abort(error); + } + + error = pdf_loadnametrees(xref); if (error) fz_abort(error); - count = pdf_getpagecount(pages); + error = pdf_loadoutline(&outline, xref); + if (error) fz_abort(error); - strlcpy(doctitle, filename, sizeof doctitle); - obj = fz_dictgets(xref->trailer, "Info"); - if (fz_isindirect(obj)) + doctitle = filename; + if (xref->info) { - pdf_resolve(&obj, xref); - obj = fz_dictgets(obj, "Title"); + obj = fz_dictgets(xref->info, "Title"); if (obj) { - int n = MIN(fz_tostringlen(obj) + 1, sizeof doctitle); - if (obj) - strlcpy(doctitle, fz_tostringbuf(obj), n); + error = pdf_toutf8(&doctitle, obj); + if (error) fz_abort(error); } } + if (outline) + pdf_debugoutline(outline, 0); + + error = pdf_loadpagetree(&pages, xref); + if (error) fz_abort(error); + + count = pdf_getpagecount(pages); + error = fz_newrenderer(&rast, pdf_devicergb, 0, 1024 * 512); if (error) fz_abort(error); @@ -274,8 +295,8 @@ static void gotouri(fz_obj *uri) fz_debugobj(uri); printf("\n"); - memcpy(buf, fz_tostringbuf(uri), fz_tostringlen(uri)); - buf[fz_tostringlen(uri)] = 0; + memcpy(buf, fz_tostrbuf(uri), fz_tostrlen(uri)); + buf[fz_tostrlen(uri)] = 0; if (getenv("BROWSER")) sprintf(cmd, "$BROWSER %s &", buf); @@ -477,10 +498,10 @@ static void handlemouse(float x, int y, int btn) XDefineCursor(xdpy, xwin, xchand); if (btn) { - if (link->uri) - gotouri(link->uri); - if (link->page) - gotopage(link->page); + if (fz_isstring(link->dest)) + gotouri(link->dest); + if (fz_isindirect(link->dest)) + gotopage(link->dest); } } else @@ -562,7 +583,7 @@ int main(int argc, char **argv) } } - pdf_closepdf(xref); + pdf_closexref(xref); return 0; } |