diff options
-rw-r--r-- | Jamfile | 1 | ||||
-rw-r--r-- | include/mupdf.h | 3 | ||||
-rw-r--r-- | mupdf/doctor.c | 104 | ||||
-rw-r--r-- | test/pdfclean.c | 4 |
4 files changed, 111 insertions, 1 deletions
@@ -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); |