summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-10-05 10:49:50 +0200
committerTor Andersson <tor@ghostscript.com>2004-10-05 10:49:50 +0200
commit98e44466052e654c6b34a685fe7dbc433632aecc (patch)
tree0353dafbe63b5a2c24f847bf45c55095b09fea43
parent422c3dfdb4f8d4ab61449001eff1427bf8fbff36 (diff)
downloadmupdf-98e44466052e654c6b34a685fe7dbc433632aecc.tar.xz
garbage collect unreferenced objects
-rw-r--r--Jamfile1
-rw-r--r--include/mupdf.h3
-rw-r--r--mupdf/doctor.c104
-rw-r--r--test/pdfclean.c4
4 files changed, 111 insertions, 1 deletions
diff --git a/Jamfile b/Jamfile
index 7ce394ce..083b91a5 100644
--- a/Jamfile
+++ b/Jamfile
@@ -93,6 +93,7 @@ Library libmupdf :
mupdf/repair.c
mupdf/save.c
mupdf/xref.c
+ mupdf/doctor.c
mupdf/cmap.c
mupdf/font.c
diff --git a/include/mupdf.h b/include/mupdf.h
index 98f40c62..3f8b242c 100644
--- a/include/mupdf.h
+++ b/include/mupdf.h
@@ -122,6 +122,9 @@ fz_error *pdf_resolve(fz_obj **, pdf_xref*);
fz_error *pdf_savestream(pdf_xref *xref, int oid, int gid, fz_buffer *buf);
fz_error *pdf_deletestream(pdf_xref *xref, int oid, int gid);
+/* doctor.c */
+fz_error *pdf_garbagecollect(pdf_xref *xref);
+
/* save.c */
fz_error *pdf_saveincrementalpdf(pdf_xref *xref, char *path);
fz_error *pdf_savepdf(pdf_xref *xref, char *path);
diff --git a/mupdf/doctor.c b/mupdf/doctor.c
new file mode 100644
index 00000000..fcc9032e
--- /dev/null
+++ b/mupdf/doctor.c
@@ -0,0 +1,104 @@
+#include <fitz.h>
+#include <mupdf.h>
+
+/*
+ * Garbage collection
+ */
+
+static fz_error *sweepref(pdf_xref *xref, fz_obj *ref);
+
+static fz_error *
+sweepobj(pdf_xref *xref, fz_obj *obj)
+{
+ fz_error *error;
+ int i;
+
+ if (fz_isdict(obj))
+ {
+ for (i = 0; i < fz_dictlen(obj); i++)
+ {
+ error = sweepobj(xref, fz_dictgetval(obj, i));
+ if (error)
+ return error;
+ }
+ }
+
+ if (fz_isarray(obj))
+ {
+ for (i = 0; i < fz_arraylen(obj); i++)
+ {
+ error = sweepobj(xref, fz_arrayget(obj, i));
+ if (error)
+ return error;
+ }
+ }
+
+ if (fz_isindirect(obj))
+ return sweepref(xref, obj);
+
+ return nil;
+}
+
+static fz_error *
+sweepref(pdf_xref *xref, fz_obj *ref)
+{
+ fz_error *error;
+ fz_obj *obj;
+ int oid;
+
+ oid = fz_toobjid(ref);
+
+ if (oid < 0 || oid >= xref->size)
+ return fz_throw("rangecheck: object number out of range");
+
+ if (xref->table[oid].mark)
+ return nil;
+
+ xref->table[oid].mark = 1;
+
+ error = pdf_loadobject(&obj, xref, ref, nil);
+ if (error)
+ return error;
+
+ error = sweepobj(xref, obj);
+ if (error)
+ {
+ fz_dropobj(obj);
+ return error;
+ }
+
+ fz_dropobj(obj);
+ return nil;
+}
+
+fz_error *
+pdf_garbagecollect(pdf_xref *xref)
+{
+ fz_error *error;
+ int i, g;
+
+ for (i = 0; i < xref->size; i++)
+ xref->table[i].mark = 0;
+
+ error = sweepobj(xref, xref->trailer);
+ if (error)
+ return error;
+
+ for (i = 0; i < xref->size; i++)
+ {
+ pdf_xrefentry *x = xref->table + i;
+ g = x->gen;
+ if (x->type == 'o')
+ g = 0;
+
+ if (!x->mark && x->type != 'f' && x->type != 'd')
+ {
+ error = pdf_deleteobject(xref, i, g);
+ if (error)
+ return error;
+ }
+ }
+
+ return nil;
+}
+
diff --git a/test/pdfclean.c b/test/pdfclean.c
index 7eb72cda..37d9de0d 100644
--- a/test/pdfclean.c
+++ b/test/pdfclean.c
@@ -122,10 +122,12 @@ int main(int argc, char **argv)
if (error) fz_abort(error);
}
+ if (dogc)
+ pdf_garbagecollect(xref);
+
if (doexpand)
expandstreams(xref);
-printf("saving %s...\n", outfile);
error = pdf_savepdf(xref, outfile);
if (error)
fz_abort(error);