diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-12-02 06:55:46 +0100 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-12-02 06:55:46 +0100 |
commit | 5c335f9337724f61c14af143b18f0891c58dbacd (patch) | |
tree | be1c7eef2412c09d4ae0caebd933a17e4b8b80f0 | |
parent | 615d27315a131bea0df699c3daa1102289b433c6 (diff) | |
download | mupdf-5c335f9337724f61c14af143b18f0891c58dbacd.tar.xz |
optimise object store. refcount resources. colorkeyed transparency. font bbox.
-rw-r--r-- | TODO | 5 | ||||
-rw-r--r-- | base/hash.c | 7 | ||||
-rw-r--r-- | include/fitz/hash.h | 1 | ||||
-rw-r--r-- | include/mupdf/rsrc.h | 11 | ||||
-rw-r--r-- | include/mupdf/xref.h | 1 | ||||
-rw-r--r-- | mupdf/build.c | 39 | ||||
-rw-r--r-- | mupdf/font.c | 42 | ||||
-rw-r--r-- | mupdf/function.c | 93 | ||||
-rw-r--r-- | mupdf/image.c | 74 | ||||
-rw-r--r-- | mupdf/interpret.c | 1 | ||||
-rw-r--r-- | mupdf/pattern.c | 25 | ||||
-rw-r--r-- | mupdf/store.c | 138 | ||||
-rw-r--r-- | mupdf/xobject.c | 40 | ||||
-rw-r--r-- | mupdf/xref.c | 44 | ||||
-rw-r--r-- | tree/colorspace.c | 2 | ||||
-rw-r--r-- | tree/image.c | 2 | ||||
-rw-r--r-- | tree/node2.c | 40 | ||||
-rw-r--r-- | tree/text.c | 3 |
18 files changed, 435 insertions, 133 deletions
@@ -1,12 +1,7 @@ immediate plan: - - fast parsed object store (scrap r* cache) - global font/cmap cache - - image color key transparency - text fill + clip mode - - pdf logging - - refcount resources - altivec optimize - - gtk+pdf - page labels + dests + outline + annots - design gui for editor - go through spec and check all features! diff --git a/base/hash.c b/base/hash.c index e54ac7ea..65bc7130 100644 --- a/base/hash.c +++ b/base/hash.c @@ -73,6 +73,13 @@ fz_newhash(fz_hashtable **tablep, int initialsize, int keylen) return nil; } +void +fz_emptyhash(fz_hashtable *table) +{ + table->load = 0; + memset(table->ents, 0, sizeof(fz_hashentry) * table->size); +} + int fz_hashlen(fz_hashtable *table) { diff --git a/include/fitz/hash.h b/include/fitz/hash.h index c53056bc..2ada17f4 100644 --- a/include/fitz/hash.h +++ b/include/fitz/hash.h @@ -3,6 +3,7 @@ typedef struct fz_hashtable_s fz_hashtable; fz_error *fz_newhash(fz_hashtable **tablep, int initialsize, int keylen); fz_error *fz_resizehash(fz_hashtable *table, int newsize); void fz_debughash(fz_hashtable *table); +void fz_emptyhash(fz_hashtable *table); void fz_drophash(fz_hashtable *table); void *fz_hashfind(fz_hashtable *table, void *key); diff --git a/include/mupdf/rsrc.h b/include/mupdf/rsrc.h index 0e69621b..e840ccec 100644 --- a/include/mupdf/rsrc.h +++ b/include/mupdf/rsrc.h @@ -15,9 +15,11 @@ typedef enum pdf_itemkind_e } pdf_itemkind; fz_error *pdf_newstore(pdf_store **storep); +void pdf_emptystore(pdf_store *store); +void pdf_dropstore(pdf_store *store); + fz_error *pdf_storeitem(pdf_store *store, pdf_itemkind tag, fz_obj *key, void *val); void *pdf_finditem(pdf_store *store, pdf_itemkind tag, fz_obj *key); -void pdf_dropstore(pdf_store *store); fz_error *pdf_loadresources(fz_obj **rdb, pdf_xref *xref, fz_obj *orig); @@ -29,6 +31,7 @@ typedef struct pdf_function_s pdf_function; fz_error *pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *ref); fz_error *pdf_evalfunction(pdf_function *func, float *in, int inlen, float *out, int outlen); +pdf_function *pdf_keepfunction(pdf_function *func); void pdf_dropfunction(pdf_function *func); /* @@ -64,6 +67,7 @@ typedef struct pdf_pattern_s pdf_pattern; struct pdf_pattern_s { + int refs; int ismask; float xstep; float ystep; @@ -73,6 +77,7 @@ struct pdf_pattern_s }; fz_error *pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *obj, fz_obj *ref); +pdf_pattern *pdf_keeppattern(pdf_pattern *pat); void pdf_droppattern(pdf_pattern *pat); fz_error *pdf_loadshade(fz_shade **shadep, pdf_xref *xref, fz_obj *obj, fz_obj *ref); @@ -85,6 +90,7 @@ typedef struct pdf_xobject_s pdf_xobject; struct pdf_xobject_s { + int refs; fz_matrix matrix; fz_rect bbox; fz_obj *resources; @@ -92,6 +98,7 @@ struct pdf_xobject_s }; fz_error *pdf_loadxobject(pdf_xobject **xobjp, pdf_xref *xref, fz_obj *obj, fz_obj *ref); +pdf_xobject *pdf_keepxobject(pdf_xobject *xobj); void pdf_dropxobject(pdf_xobject *xobj); /* @@ -104,6 +111,8 @@ struct pdf_image_s { fz_image super; fz_image *mask; /* explicit mask with subimage */ + int usecolorkey; /* explicit color-keyed masking */ + int colorkey[FZ_MAXCOLORS * 2]; pdf_indexed *indexed; float decode[32]; int bpc; diff --git a/include/mupdf/xref.h b/include/mupdf/xref.h index 7ad417da..c1307e45 100644 --- a/include/mupdf/xref.h +++ b/include/mupdf/xref.h @@ -42,6 +42,7 @@ fz_error *pdf_updatepdf(pdf_xref *, char *filename); fz_error *pdf_savepdf(pdf_xref *, char *filename, pdf_crypt *encrypt); void pdf_debugpdf(pdf_xref *); +void pdf_flushpdf(pdf_xref *, int force); void pdf_closepdf(pdf_xref *); fz_error *pdf_allocobject(pdf_xref *, int *oidp, int *genp); diff --git a/mupdf/build.c b/mupdf/build.c index 18a1d053..2010ca20 100644 --- a/mupdf/build.c +++ b/mupdf/build.c @@ -13,12 +13,18 @@ pdf_initgstate(pdf_gstate *gs) memset(gs->dashlist, 0, sizeof(gs->dashlist)); gs->stroke.kind = PDF_MCOLOR; - gs->stroke.cs = pdf_devicegray; + gs->stroke.cs = fz_keepcolorspace(pdf_devicegray); gs->stroke.v[0] = 0; + gs->stroke.indexed = nil; + gs->stroke.pattern = nil; + gs->stroke.shade = nil; gs->fill.kind = PDF_MCOLOR; - gs->fill.cs = pdf_devicegray; + gs->fill.cs = fz_keepcolorspace(pdf_devicegray); gs->fill.v[0] = 0; + gs->fill.indexed = nil; + gs->fill.pattern = nil; + gs->fill.shade = nil; gs->charspace = 0; gs->wordspace = 0; @@ -45,8 +51,10 @@ pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs) mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; + fz_dropcolorspace(mat->cs); + mat->kind = PDF_MCOLOR; - mat->cs = cs; + mat->cs = fz_keepcolorspace(cs); mat->v[0] = 0; /* FIXME: default color */ mat->v[1] = 0; /* FIXME: default color */ @@ -130,8 +138,14 @@ pdf_setpattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v) mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; + if (mat->pattern) + pdf_droppattern(mat->pattern); + mat->kind = PDF_MPATTERN; - mat->pattern = pat; + if (pat) + mat->pattern = pdf_keeppattern(pat); + else + mat->pattern = nil; if (v) return pdf_setcolor(csi, what, v); @@ -152,8 +166,11 @@ pdf_setshade(pdf_csi *csi, int what, fz_shade *shade) mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; + if (mat->shade) + fz_dropshade(mat->shade); + mat->kind = PDF_MSHADE; - mat->shade = shade; + mat->shade = fz_keepshade(shade); return nil; } @@ -342,21 +359,11 @@ pdf_addshade(pdf_gstate *gs, fz_shade *shade) { fz_error *error; fz_node *node; - fz_node *xform; - fz_matrix ctm; - fz_matrix inv; - - ctm = getmatrix(gs->head); - inv = fz_invertmatrix(ctm); - - error = fz_newtransformnode(&xform, inv); - if (error) return error; error = fz_newshadenode(&node, shade); if (error) return error; - fz_insertnodelast(xform, node); - fz_insertnodelast(gs->head, xform); + fz_insertnodelast(gs->head, node); return nil; } diff --git a/mupdf/font.c b/mupdf/font.c index 6f146b51..50d2b187 100644 --- a/mupdf/font.c +++ b/mupdf/font.c @@ -292,6 +292,7 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) fz_obj *widths = nil; unsigned short *etable = nil; pdf_font *font; + fz_irect bbox; FT_Face face; FT_CharMap cmap; int kind; @@ -330,16 +331,17 @@ loadsimplefont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) pdf_logfont("ft name '%s' '%s'\n", face->family_name, face->style_name); - pdf_logfont("ft bbox [%d %d %d %d]\n", - face->bbox.xMin, face->bbox.yMin, - face->bbox.xMax, face->bbox.yMax); + bbox.min.x = (face->bbox.xMin * 1000) / face->units_per_EM; + bbox.min.y = (face->bbox.yMin * 1000) / face->units_per_EM; + bbox.max.x = (face->bbox.xMax * 1000) / face->units_per_EM; + bbox.max.y = (face->bbox.yMax * 1000) / face->units_per_EM; - if (face->bbox.xMax == face->bbox.xMin) + pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); + + if (bbox.min.x == bbox.max.x) fz_setfontbbox((fz_font*)font, -1000, -1000, 2000, 2000); else - fz_setfontbbox((fz_font*)font, - face->bbox.xMin, face->bbox.yMin, - face->bbox.xMax, face->bbox.yMax); + fz_setfontbbox((fz_font*)font, bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); /* * Encoding @@ -577,6 +579,7 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj fz_obj *descriptor; pdf_font *font; FT_Face face; + fz_irect bbox; int kind; char collection[256]; char *basefont; @@ -640,16 +643,17 @@ loadcidfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref, fz_obj face = font->ftface; kind = ftkind(face); - if (face->bbox.xMax == face->bbox.xMin) + bbox.min.x = (face->bbox.xMin * 1000) / face->units_per_EM; + bbox.min.y = (face->bbox.yMin * 1000) / face->units_per_EM; + bbox.max.x = (face->bbox.xMax * 1000) / face->units_per_EM; + bbox.max.y = (face->bbox.yMax * 1000) / face->units_per_EM; + + pdf_logfont("ft bbox [%d %d %d %d]\n", bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); + + if (bbox.min.x == bbox.max.x) fz_setfontbbox((fz_font*)font, -1000, -1000, 2000, 2000); else - fz_setfontbbox((fz_font*)font, - face->bbox.xMin, face->bbox.yMin, - face->bbox.xMax, face->bbox.yMax); - - pdf_logfont("ft bbox [%d %d %d %d]\n", - face->bbox.xMin, face->bbox.yMin, - face->bbox.xMax, face->bbox.yMax); + fz_setfontbbox((fz_font*)font, bbox.min.x, bbox.min.y, bbox.max.x, bbox.max.y); /* * Encoding @@ -926,6 +930,7 @@ pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *colle { fz_error *error; fz_obj *obj1, *obj2, *obj3, *obj; + fz_rect bbox; char *fontname; error = pdf_resolve(&desc, xref); @@ -946,6 +951,11 @@ pdf_loadfontdescriptor(pdf_font *font, pdf_xref *xref, fz_obj *desc, char *colle font->xheight = fz_toreal(fz_dictgets(desc, "XHeight")); font->missingwidth = fz_toreal(fz_dictgets(desc, "MissingWidth")); + bbox = pdf_torect(fz_dictgets(desc, "FontBBox")); + pdf_logfont("bbox [%g %g %g %g]\n", + bbox.min.x, bbox.min.y, + bbox.max.x, bbox.max.y); + pdf_logfont("flags %d\n", font->flags); obj1 = fz_dictgets(desc, "FontFile"); @@ -989,7 +999,7 @@ pdf_loadfont(pdf_font **fontp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) subtype = fz_toname(fz_dictgets(dict, "Subtype")); if (!strcmp(subtype, "Type0")) error = loadtype0(fontp, xref, dict, ref); - if (!strcmp(subtype, "Type1") || !strcmp(subtype, "MMType1")) + else if (!strcmp(subtype, "Type1") || !strcmp(subtype, "MMType1")) error = loadsimplefont(fontp, xref, dict, ref); else if (!strcmp(subtype, "TrueType")) error = loadsimplefont(fontp, xref, dict, ref); diff --git a/mupdf/function.c b/mupdf/function.c index c300b89e..84431e8c 100644 --- a/mupdf/function.c +++ b/mupdf/function.c @@ -7,7 +7,8 @@ typedef struct psobj_s psobj; struct pdf_function_s { - unsigned short type; /* 0=sample 2=exponential 3=stitching 4=postscript */ + int refs; + int type; /* 0=sample 2=exponential 3=stitching 4=postscript */ int m; /* number of input values */ int n; /* number of output values */ float *domain; /* even index : min value, odd index : max value */ @@ -1396,50 +1397,60 @@ cleanup: return error; } +pdf_function * +pdf_keepfunction(pdf_function *func) +{ + func->refs ++; + return func; +} + void pdf_dropfunction(pdf_function *func) { - int i; - - if(func->domain) - fz_free(func->domain); - - if(func->range) - fz_free(func->range); - - switch(func->type) { - case PDF_FUNC_SAMPLE: - if(func->u.sa.decode) - fz_free(func->u.sa.decode); - if(func->u.sa.encode) - fz_free(func->u.sa.encode); - if(func->u.sa.samples) - fz_free(func->u.sa.samples); - break; - case PDF_FUNC_EXPONENTIAL: - if(func->u.e.c0) - fz_free(func->u.e.c0); - if(func->u.e.c1) - fz_free(func->u.e.c1); - break; - case PDF_FUNC_STITCHING: - if(func->u.st.bounds) - fz_free(func->u.st.bounds); - if(func->u.st.encode) - fz_free(func->u.st.encode); - if(func->u.st.funcs) { - for(i = 0; i < func->u.st.k; ++i) - pdf_dropfunction(func->u.st.funcs[i]); - - fz_free(func->u.st.funcs); + if (--func->refs == 0) + { + int i; + + if(func->domain) + fz_free(func->domain); + + if(func->range) + fz_free(func->range); + + switch(func->type) { + case PDF_FUNC_SAMPLE: + if(func->u.sa.decode) + fz_free(func->u.sa.decode); + if(func->u.sa.encode) + fz_free(func->u.sa.encode); + if(func->u.sa.samples) + fz_free(func->u.sa.samples); + break; + case PDF_FUNC_EXPONENTIAL: + if(func->u.e.c0) + fz_free(func->u.e.c0); + if(func->u.e.c1) + fz_free(func->u.e.c1); + break; + case PDF_FUNC_STITCHING: + if(func->u.st.bounds) + fz_free(func->u.st.bounds); + if(func->u.st.encode) + fz_free(func->u.st.encode); + if(func->u.st.funcs) { + for(i = 0; i < func->u.st.k; ++i) + pdf_dropfunction(func->u.st.funcs[i]); + + fz_free(func->u.st.funcs); + } + break; + case PDF_FUNC_POSTSCRIPT: + if(func->u.p.code) + fz_free(func->u.p.code); + break; } - break; - case PDF_FUNC_POSTSCRIPT: - if(func->u.p.code) - fz_free(func->u.p.code); - break; + fz_free(func); } - fz_free(func); } fz_error * @@ -1459,6 +1470,8 @@ pdf_loadfunction(pdf_function **func, pdf_xref *xref, fz_obj *ref) newfunc = fz_malloc(sizeof(pdf_function)); if(!newfunc) return fz_outofmem; memset(newfunc,0,sizeof(pdf_function)); + + newfunc->refs = 1; objfunc = ref; error = pdf_resolve(&objfunc,xref); diff --git a/mupdf/image.c b/mupdf/image.c index 94168d68..d7014e0a 100644 --- a/mupdf/image.c +++ b/mupdf/image.c @@ -32,6 +32,7 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, img->super.n = 0; img->super.a = 0; img->indexed = nil; + img->usecolorkey = 0; img->mask = nil; img->super.w = fz_toint(fz_dictgetsa(dict, "Width", "W")); @@ -159,6 +160,29 @@ pdf_loadinlineimage(pdf_image **imgp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict, return nil; } +static void +loadcolorkey(int *colorkey, int bpc, int indexed, fz_obj *obj) +{ + int scale = 1; + int i; + + pdf_logimage("keyed mask\n"); + + if (!indexed) + { + switch (bpc) + { + case 1: scale = 255; break; + case 2: scale = 85; break; + case 4: scale = 17; break; + case 8: scale = 1; break; + } + } + + for (i = 0; i < fz_arraylen(obj); i++) + colorkey[i] = fz_toint(fz_arrayget(obj, i)) * scale; +} + /* TODO error cleanup */ fz_error * pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) @@ -174,6 +198,7 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) int w, h, bpc; int n = 0; int a = 0; + int usecolorkey = 0; fz_colorspace *cs = nil; pdf_indexed *indexed = nil; int stride; @@ -273,8 +298,8 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) return error; if (fz_isarray(sub)) { - pdf_logimage("color keyed transparency\n"); - /* FIXME */ + usecolorkey = 1; + loadcolorkey(img->colorkey, bpc, indexed != nil, sub); } else { @@ -287,8 +312,8 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) } else if (fz_isarray(obj)) { - pdf_logimage("color keyed transparency\n"); - /* FIXME */ + usecolorkey = 1; + loadcolorkey(img->colorkey, bpc, indexed != nil, obj); } /* @@ -364,6 +389,7 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) img->stride = stride; img->bpc = bpc; img->mask = (fz_image*)mask; + img->usecolorkey = usecolorkey; pdf_logimage("}\n"); @@ -378,6 +404,41 @@ pdf_loadimage(pdf_image **imgp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) return nil; } +static void +maskcolorkey(fz_pixmap *pix, int *colorkey) +{ + unsigned char *p = pix->samples; + int i, k, t; + for (i = 0; i < pix->w * pix->h; i++) + { + t = 1; + for (k = 1; k < pix->n; k++) + if (p[k] < colorkey[k * 2 - 2] || p[k] > colorkey[k * 2 - 1]) + t = 0; + if (t) + for (k = 0; k < pix->n; k++) + p[k] = 0; + p += pix->n; + } +} + +static void +maskcolorkeyindexed(fz_pixmap *ind, fz_pixmap *pix, int *colorkey) +{ + unsigned char *s = ind->samples; + unsigned char *d = pix->samples; + int i, k; + for (i = 0; i < pix->w * pix->h; i++) + { + if (s[0] >= colorkey[0] && s[0] <= colorkey[1]) + for (k = 0; k < pix->n; k++) + d[k] = 0; + d[0] = 255; + s += ind->n; + d += pix->n; + } +} + fz_error * pdf_loadtile(fz_image *img, fz_pixmap *tile) { @@ -438,6 +499,9 @@ pdf_loadtile(fz_image *img, fz_pixmap *tile) } } + if (src->usecolorkey) + maskcolorkeyindexed(tmp, tile, src->colorkey); + fz_droppixmap(tmp); } @@ -446,6 +510,8 @@ pdf_loadtile(fz_image *img, fz_pixmap *tile) tilefunc(src->samples->rp, src->stride, tile->samples, tile->w * tile->n, img->w * (img->n + img->a), img->h, img->a ? 0 : img->n); + if (src->usecolorkey) + maskcolorkey(tile, src->colorkey); fz_decodetile(tile, !img->a, src->decode); } diff --git a/mupdf/interpret.c b/mupdf/interpret.c index 910e5f6f..a2f23e13 100644 --- a/mupdf/interpret.c +++ b/mupdf/interpret.c @@ -65,6 +65,7 @@ clearstack(pdf_csi *csi) void pdf_dropcsi(pdf_csi *csi) { + /* TODO: drop gstates */ if (csi->path) fz_dropnode((fz_node*)csi->path); if (csi->clip) fz_dropnode((fz_node*)csi->clip); if (csi->textclip) fz_dropnode((fz_node*)csi->textclip); diff --git a/mupdf/pattern.c b/mupdf/pattern.c index 7c29dc97..ebd0d743 100644 --- a/mupdf/pattern.c +++ b/mupdf/pattern.c @@ -1,14 +1,22 @@ #include <fitz.h> #include <mupdf.h> +pdf_pattern * +pdf_keeppattern(pdf_pattern *pat) +{ + pat->refs ++; + return pat; +} + void pdf_droppattern(pdf_pattern *pat) { - pdf_logrsrc("drop pattern %p\n", pat); - - if (pat->tree) - fz_droptree(pat->tree); - fz_free(pat); + if (--pat->refs == 0) + { + if (pat->tree) + fz_droptree(pat->tree); + fz_free(pat); + } } fz_error * @@ -20,6 +28,9 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict, fz_obj *stmref fz_obj *obj; pdf_csi *csi; + if ((*patp = pdf_finditem(xref->store, PDF_KPATTERN, stmref))) + return nil; + pdf_logrsrc("load pattern %d %d {\n", fz_tonum(stmref), fz_togen(stmref)); pat = fz_malloc(sizeof(pdf_pattern)); @@ -107,6 +118,10 @@ pdf_loadpattern(pdf_pattern **patp, pdf_xref *xref, fz_obj *dict, fz_obj *stmref pdf_logrsrc("}\n"); + error = pdf_storeitem(xref->store, PDF_KPATTERN, stmref, pat); + if (error) + goto cleanup; + *patp = pat; return nil; diff --git a/mupdf/store.c b/mupdf/store.c index 03dee670..a5e19b18 100644 --- a/mupdf/store.c +++ b/mupdf/store.c @@ -11,51 +11,142 @@ struct pdf_item_s pdf_item *next; }; +struct refkey +{ + pdf_itemkind kind; + int oid; + int gen; +}; + struct pdf_store_s { - int len; - int cap; - pdf_item *root; + fz_hashtable *hash; /* hash for oid/gen keys */ + pdf_item *root; /* linked list for everything else */ }; fz_error * pdf_newstore(pdf_store **storep) { + fz_error *error; pdf_store *store; store = fz_malloc(sizeof(pdf_store)); if (!store) return fz_outofmem; + error = fz_newhash(&store->hash, 4096, sizeof(struct refkey)); + if (error) + { + fz_free(store); + return error; + } + store->root = nil; *storep = store; return nil; } +static void dropitem(pdf_itemkind kind, void *val) +{ + switch (kind) + { + case PDF_KCOLORSPACE: fz_dropcolorspace(val); break; + case PDF_KFUNCTION: pdf_dropfunction(val); break; + case PDF_KXOBJECT: pdf_dropxobject(val); break; + case PDF_KIMAGE: fz_dropimage(val); break; + case PDF_KPATTERN: pdf_droppattern(val); break; + case PDF_KSHADE: fz_dropshade(val); break; + case PDF_KCMAP: fz_dropcmap(val); break; + case PDF_KFONT: fz_dropfont(val); break; + } +} + +void +pdf_emptystore(pdf_store *store) +{ + pdf_item *item; + pdf_item *next; + struct refkey *key; + void *val; + int i; + + for (i = 0; i < fz_hashlen(store->hash); i++) + { + key = fz_hashgetkey(store->hash, i); + val = fz_hashgetval(store->hash, i); + if (val) + dropitem(key->kind, val); + } + fz_emptyhash(store->hash); + + for (item = store->root; item; item = next) + { + next = item->next; + fz_dropobj(item->key); + dropitem(item->kind, item->val); + fz_free(item); + } + + store->root = nil; +} + void pdf_dropstore(pdf_store *store) { - /* TODO */ + pdf_emptystore(store); } fz_error * pdf_storeitem(pdf_store *store, pdf_itemkind kind, fz_obj *key, void *val) { - pdf_item *item; + fz_error *error; - item = fz_malloc(sizeof(pdf_item)); - if (!item) - return fz_outofmem; + switch (kind) + { + case PDF_KCOLORSPACE: fz_keepcolorspace(val); break; + case PDF_KFUNCTION: pdf_keepfunction(val); break; + case PDF_KXOBJECT: pdf_keepxobject(val); break; + case PDF_KIMAGE: fz_keepimage(val); break; + case PDF_KPATTERN: pdf_keeppattern(val); break; + case PDF_KSHADE: fz_keepshade(val); break; + case PDF_KCMAP: fz_keepcmap(val); break; + case PDF_KFONT: fz_keepfont(val); break; + } + + if (fz_isindirect(key)) + { + struct refkey item; - pdf_logrsrc("store item %d: %p\n", kind, val); + pdf_logrsrc("store item %d: %d %d R = %p\n", kind, fz_tonum(key), fz_togen(key), val); - item->kind = kind; - item->key = fz_keepobj(key); - item->val = val; /* heh. should do *keep() here */ + item.kind = kind; + item.oid = fz_tonum(key); + item.gen = fz_togen(key); + + error = fz_hashinsert(store->hash, &item, val); + if (error) + return error; + } + + else + { + pdf_item *item; + + item = fz_malloc(sizeof(pdf_item)); + if (!item) + return fz_outofmem; + + pdf_logrsrc("store item %d: ... = %p\n", kind, val); + + item->kind = kind; + item->key = fz_keepobj(key); + item->val = val; + + item->next = store->root; + store->root = item; + } - item->next = store->root; - store->root = item; return nil; } @@ -63,17 +154,24 @@ void * pdf_finditem(pdf_store *store, pdf_itemkind kind, fz_obj *key) { pdf_item *item; + struct refkey refkey; if (key == nil) return nil; - for (item = store->root; item; item = item->next) + if (fz_isindirect(key)) + { + refkey.kind = kind; + refkey.oid = fz_tonum(key); + refkey.gen = fz_togen(key); + return fz_hashfind(store->hash, &refkey); + } + + else { - if (item->kind == kind && !fz_cmpobj(item->key, key)) - { - pdf_logrsrc("find item %d: %p\n", kind, item->val); - return item->val; - } + for (item = store->root; item; item = item->next) + if (item->kind == kind && !fz_cmpobj(item->key, key)) + return item->val; } return nil; diff --git a/mupdf/xobject.c b/mupdf/xobject.c index e0e1fd2f..c3c3b882 100644 --- a/mupdf/xobject.c +++ b/mupdf/xobject.c @@ -15,6 +15,10 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) if (!form) return fz_outofmem; + form->refs = 1; + form->resources = nil; + form->contents = nil; + pdf_logrsrc("load xobject %d %d (%p) {\n", fz_tonum(ref), fz_togen(ref), form); obj = fz_dictgets(dict, "BBox"); @@ -35,34 +39,28 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) form->matrix.c, form->matrix.d, form->matrix.e, form->matrix.f); - form->resources = nil; obj = fz_dictgets(dict, "Resources"); if (obj) { error = pdf_resolve(&obj, xref); if (error) { - fz_free(form); + pdf_dropxobject(form); return error; } - error = pdf_loadresources(&form->resources, xref, obj); + fz_dropobj(obj); if (error) { - fz_dropobj(obj); - fz_free(form); + pdf_dropxobject(form); return error; } - - fz_dropobj(obj); } - form->contents = nil; error = pdf_loadstream(&form->contents, xref, fz_tonum(ref), fz_togen(ref)); if (error) { - fz_dropobj(form->resources); - fz_free(form); + pdf_dropxobject(form); return error; } @@ -73,9 +71,7 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) error = pdf_storeitem(xref->store, PDF_KXOBJECT, ref, form); if (error) { - fz_dropbuffer(form->contents); - fz_dropobj(form->resources); - fz_free(form); + pdf_dropxobject(form); return error; } @@ -83,3 +79,21 @@ pdf_loadxobject(pdf_xobject **formp, pdf_xref *xref, fz_obj *dict, fz_obj *ref) return nil; } +pdf_xobject * +pdf_keepxobject(pdf_xobject *xobj) +{ + xobj->refs ++; + return xobj; +} + +void +pdf_dropxobject(pdf_xobject *xobj) +{ + if (--xobj->refs == 0) + { + if (xobj->contents) fz_dropbuffer(xobj->contents); + if (xobj->resources) fz_dropobj(xobj->resources); + fz_free(xobj); + } +} + diff --git a/mupdf/xref.c b/mupdf/xref.c index a4be93f2..29972b8f 100644 --- a/mupdf/xref.c +++ b/mupdf/xref.c @@ -84,24 +84,54 @@ pdf_decryptpdf(pdf_xref *xref) } void -pdf_closepdf(pdf_xref *xref) +pdf_flushpdf(pdf_xref *xref, int force) { int i; - pdf_logxref("closexref %p\n", xref); - - if (xref->store) - pdf_dropstore(xref->store); + pdf_logxref("flushxref %p (%d)\n", xref, force); - if (xref->table) + for (i = 0; i < xref->len; i++) { - for (i = 0; i < xref->len; i++) + if (force) { if (xref->table[i].stmbuf) + { fz_dropbuffer(xref->table[i].stmbuf); + xref->table[i].stmbuf = nil; + } if (xref->table[i].obj) + { + fz_dropobj(xref->table[i].obj); + xref->table[i].obj = nil; + } + } + else + { + if (xref->table[i].stmbuf && xref->table[i].stmbuf->refs == 1) + { + fz_dropbuffer(xref->table[i].stmbuf); + xref->table[i].stmbuf = nil; + } + if (xref->table[i].obj && xref->table[i].stmbuf->refs == 1) + { fz_dropobj(xref->table[i].obj); + xref->table[i].obj = nil; + } } + } +} + +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); } diff --git a/tree/colorspace.c b/tree/colorspace.c index aabf531b..65909bfe 100644 --- a/tree/colorspace.c +++ b/tree/colorspace.c @@ -15,6 +15,8 @@ fz_convertcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *ds fz_colorspace * fz_keepcolorspace(fz_colorspace *cs) { + if (cs->refs < 0) + return cs; cs->refs ++; return cs; } diff --git a/tree/image.c b/tree/image.c index 3b0a3594..dbeb1fd8 100644 --- a/tree/image.c +++ b/tree/image.c @@ -14,6 +14,8 @@ fz_dropimage(fz_image *image) { if (image->drop) image->drop(image); + if (image->cs) + fz_dropcolorspace(image->cs); fz_free(image); } } diff --git a/tree/node2.c b/tree/node2.c index ceb59ad6..f21ebf36 100644 --- a/tree/node2.c +++ b/tree/node2.c @@ -90,7 +90,7 @@ fz_newblendnode(fz_node **nodep, fz_colorspace *cs, fz_blendkind b, int k, int i *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NBLEND); - node->cs = cs; + node->cs = fz_keepcolorspace(cs); node->mode = b; node->knockout = k; node->isolated = i; @@ -101,7 +101,31 @@ fz_newblendnode(fz_node **nodep, fz_colorspace *cs, fz_blendkind b, int k, int i fz_rect fz_boundblendnode(fz_blendnode *node, fz_matrix ctm) { - return fz_emptyrect; + fz_node *child; + fz_rect bbox; + fz_rect temp; + + child = node->super.first; + if (!child) + return fz_emptyrect; + + bbox = fz_boundnode(child, ctm); + + child = child->next; + while (child) + { + temp = fz_boundnode(child, ctm); + bbox = fz_mergerects(temp, bbox); + child = child->next; + } + + return bbox; +} + +void +fz_dropblendnode(fz_blendnode *node) +{ + fz_dropcolorspace(node->cs); } /* @@ -223,7 +247,7 @@ fz_newcolornode(fz_node **nodep, fz_colorspace *cs, int n, float *v) *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NCOLOR); - node->cs = cs; + node->cs = fz_keepcolorspace(cs); node->n = n; for (i = 0; i < n; i++) node->samples[i] = v[i]; @@ -237,6 +261,12 @@ fz_boundcolornode(fz_colornode *node, fz_matrix ctm) return fz_infiniterect; } +void +fz_dropcolornode(fz_colornode *node) +{ + fz_dropcolorspace(node->cs); +} + /* * Image node */ @@ -252,7 +282,7 @@ fz_newimagenode(fz_node **nodep, fz_image *image) *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NIMAGE); - node->image = image; + node->image = fz_keepimage(image); return nil; } @@ -289,7 +319,7 @@ fz_newshadenode(fz_node **nodep, fz_shade *shade) *nodep = (fz_node*)node; fz_initnode((fz_node*)node, FZ_NSHADE); - node->shade = shade; + node->shade = fz_keepshade(shade); return nil; } diff --git a/tree/text.c b/tree/text.c index ef77f530..b94664b5 100644 --- a/tree/text.c +++ b/tree/text.c @@ -11,7 +11,7 @@ fz_newtextnode(fz_textnode **textp, fz_font *font) fz_initnode((fz_node*)text, FZ_NTEXT); - text->font = font; + text->font = fz_keepfont(font); text->trm = fz_identity(); text->len = 0; text->cap = 0; @@ -23,6 +23,7 @@ fz_newtextnode(fz_textnode **textp, fz_font *font) void fz_droptextnode(fz_textnode *text) { + fz_dropfont(text->font); fz_free(text->els); } |