summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-12-02 06:55:46 +0100
committerTor Andersson <tor@ghostscript.com>2004-12-02 06:55:46 +0100
commit5c335f9337724f61c14af143b18f0891c58dbacd (patch)
treebe1c7eef2412c09d4ae0caebd933a17e4b8b80f0
parent615d27315a131bea0df699c3daa1102289b433c6 (diff)
downloadmupdf-5c335f9337724f61c14af143b18f0891c58dbacd.tar.xz
optimise object store. refcount resources. colorkeyed transparency. font bbox.
-rw-r--r--TODO5
-rw-r--r--base/hash.c7
-rw-r--r--include/fitz/hash.h1
-rw-r--r--include/mupdf/rsrc.h11
-rw-r--r--include/mupdf/xref.h1
-rw-r--r--mupdf/build.c39
-rw-r--r--mupdf/font.c42
-rw-r--r--mupdf/function.c93
-rw-r--r--mupdf/image.c74
-rw-r--r--mupdf/interpret.c1
-rw-r--r--mupdf/pattern.c25
-rw-r--r--mupdf/store.c138
-rw-r--r--mupdf/xobject.c40
-rw-r--r--mupdf/xref.c44
-rw-r--r--tree/colorspace.c2
-rw-r--r--tree/image.c2
-rw-r--r--tree/node2.c40
-rw-r--r--tree/text.c3
18 files changed, 435 insertions, 133 deletions
diff --git a/TODO b/TODO
index 29504752..d90fbf81 100644
--- a/TODO
+++ b/TODO
@@ -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);
}