summaryrefslogtreecommitdiff
path: root/source/pdf/pdf-write.c
diff options
context:
space:
mode:
authorPaul Gardiner <paulg.artifex@glidos.net>2013-07-04 12:11:20 +0100
committerPaul Gardiner <paulg.artifex@glidos.net>2013-07-04 12:11:20 +0100
commitac84904af638b243284e24d5f401c3f1a21cb0ef (patch)
tree32e9f6b3b0d0ad83cb8f2dd0c41bc5e60b53ed3e /source/pdf/pdf-write.c
parentb33b3b41100f2bb0b63dbf270bdd4401451c081a (diff)
downloadmupdf-ac84904af638b243284e24d5f401c3f1a21cb0ef.tar.xz
Update pdf_write_document to support incremental update
Diffstat (limited to 'source/pdf/pdf-write.c')
-rw-r--r--source/pdf/pdf-write.c156
1 files changed, 115 insertions, 41 deletions
diff --git a/source/pdf/pdf-write.c b/source/pdf/pdf-write.c
index 4e6ddb21..63fab4f1 100644
--- a/source/pdf/pdf-write.c
+++ b/source/pdf/pdf-write.c
@@ -46,6 +46,7 @@ typedef struct {
struct pdf_write_options_s
{
FILE *out;
+ int do_incremental;
int do_ascii;
int do_expand;
int do_garbage;
@@ -1750,16 +1751,11 @@ static void writeobject(pdf_document *doc, pdf_write_options *opts, int num, int
pdf_drop_obj(obj);
}
-static void writexref(pdf_document *doc, pdf_write_options *opts, int from, int to, int first, int main_xref_offset, int startxref)
+static void writexrefsubsect(pdf_write_options *opts, int from, int to)
{
- pdf_obj *trailer = NULL;
- pdf_obj *obj;
- pdf_obj *nobj = NULL;
int num;
- fz_context *ctx = doc->ctx;
- fprintf(opts->out, "xref\n%d %d\n", from, to - from);
- opts->first_xref_entry_offset = ftell(opts->out);
+ fprintf(opts->out, "%d %d\n", from, to - from);
for (num = from; num < to; num++)
{
if (opts->use_list[num])
@@ -1767,6 +1763,43 @@ static void writexref(pdf_document *doc, pdf_write_options *opts, int from, int
else
fprintf(opts->out, "%010d %05d f \n", opts->ofs_list[num], opts->gen_list[num]);
}
+}
+
+static void writexref(pdf_document *doc, pdf_write_options *opts, int from, int to, int first, int main_xref_offset, int startxref)
+{
+ pdf_obj *trailer = NULL;
+ pdf_obj *obj;
+ pdf_obj *nobj = NULL;
+ fz_context *ctx = doc->ctx;
+
+ fprintf(opts->out, "xref\n");
+ opts->first_xref_entry_offset = ftell(opts->out);
+
+ if (opts->do_incremental)
+ {
+ int subfrom = from;
+ int subto;
+
+ while (subfrom < to)
+ {
+ while (subfrom < to && !pdf_xref_is_incremental(doc, subfrom))
+ subfrom++;
+
+ subto = subfrom;
+ while (subto < to && pdf_xref_is_incremental(doc, subto))
+ subto++;
+
+ if (subfrom < subto)
+ writexrefsubsect(opts, subfrom, subto);
+
+ subfrom = subto;
+ }
+ }
+ else
+ {
+ writexrefsubsect(opts, from, to);
+ }
+
fprintf(opts->out, "\n");
fz_var(trailer);
@@ -1774,33 +1807,43 @@ static void writexref(pdf_document *doc, pdf_write_options *opts, int from, int
fz_try(ctx)
{
- trailer = pdf_new_dict(doc, 5);
-
- nobj = pdf_new_int(doc, to);
- pdf_dict_puts(trailer, "Size", nobj);
- pdf_drop_obj(nobj);
- nobj = NULL;
-
- if (first)
+ if (opts->do_incremental)
{
- obj = pdf_dict_gets(pdf_trailer(doc), "Info");
- if (obj)
- pdf_dict_puts(trailer, "Info", obj);
-
- obj = pdf_dict_gets(pdf_trailer(doc), "Root");
- if (obj)
- pdf_dict_puts(trailer, "Root", obj);
-
- obj = pdf_dict_gets(pdf_trailer(doc), "ID");
- if (obj)
- pdf_dict_puts(trailer, "ID", obj);
+ trailer = pdf_keep_obj(pdf_trailer(doc));
+ pdf_dict_puts_drop(trailer, "Size", pdf_new_int(doc, pdf_xref_len(doc)));
+ pdf_dict_puts_drop(trailer, "Prev", pdf_new_int(doc, doc->startxref));
+ doc->startxref = startxref;
}
- if (main_xref_offset != 0)
+ else
{
- nobj = pdf_new_int(doc, main_xref_offset);
- pdf_dict_puts(trailer, "Prev", nobj);
+ trailer = pdf_new_dict(doc, 5);
+
+ nobj = pdf_new_int(doc, to);
+ pdf_dict_puts(trailer, "Size", nobj);
pdf_drop_obj(nobj);
nobj = NULL;
+
+ if (first)
+ {
+ obj = pdf_dict_gets(pdf_trailer(doc), "Info");
+ if (obj)
+ pdf_dict_puts(trailer, "Info", obj);
+
+ obj = pdf_dict_gets(pdf_trailer(doc), "Root");
+ if (obj)
+ pdf_dict_puts(trailer, "Root", obj);
+
+ obj = pdf_dict_gets(pdf_trailer(doc), "ID");
+ if (obj)
+ pdf_dict_puts(trailer, "ID", obj);
+ }
+ if (main_xref_offset != 0)
+ {
+ nobj = pdf_new_int(doc, main_xref_offset);
+ pdf_dict_puts(trailer, "Prev", nobj);
+ pdf_drop_obj(nobj);
+ nobj = NULL;
+ }
}
}
fz_always(ctx)
@@ -1861,7 +1904,8 @@ dowriteobject(pdf_document *doc, pdf_write_options *opts, int num, int pass)
if (pass > 0)
padto(opts->out, opts->ofs_list[num]);
opts->ofs_list[num] = ftell(opts->out);
- writeobject(doc, opts, num, opts->gen_list[num]);
+ if (!opts->do_incremental || pdf_xref_is_incremental(doc, num))
+ writeobject(doc, opts, num, opts->gen_list[num]);
}
else
opts->use_list[num] = 0;
@@ -1873,8 +1917,11 @@ writeobjects(pdf_document *doc, pdf_write_options *opts, int pass)
int num;
int xref_len = pdf_xref_len(doc);
- fprintf(opts->out, "%%PDF-%d.%d\n", doc->version / 10, doc->version % 10);
- fprintf(opts->out, "%%\316\274\341\277\246\n\n");
+ if (!opts->do_incremental)
+ {
+ fprintf(opts->out, "%%PDF-%d.%d\n", doc->version / 10, doc->version % 10);
+ fprintf(opts->out, "%%\316\274\341\277\246\n\n");
+ }
dowriteobject(doc, opts, opts->start, pass);
@@ -2241,12 +2288,23 @@ void pdf_write_document(pdf_document *doc, char *filename, fz_write_options *fz_
xref_len = pdf_xref_len(doc);
- opts.out = fopen(filename, "wb");
+ if (fz_opts->do_incremental)
+ {
+ opts.out = fopen(filename, "ab");
+ if (opts.out)
+ fseek(opts.out, 0, SEEK_END);
+ }
+ else
+ {
+ opts.out = fopen(filename, "wb");
+ }
+
if (!opts.out)
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot open output file '%s'", filename);
fz_try(ctx)
{
+ opts.do_incremental = fz_opts ? fz_opts->do_incremental : 0;
opts.do_expand = fz_opts ? fz_opts->do_expand : 0;
opts.do_garbage = fz_opts ? fz_opts->do_garbage : 0;
opts.do_ascii = fz_opts ? fz_opts->do_ascii: 0;
@@ -2275,7 +2333,8 @@ void pdf_write_document(pdf_document *doc, char *filename, fz_write_options *fz_
}
/* Make sure any objects hidden in compressed streams have been loaded */
- preloadobjstms(doc);
+ if (!opts.do_incremental)
+ preloadobjstms(doc);
/* Sweep & mark objects from the trailer */
if (opts.do_garbage >= 1)
@@ -2307,15 +2366,30 @@ void pdf_write_document(pdf_document *doc, char *filename, fz_write_options *fz_
dump_object_details(doc, &opts);
#endif
- /* Construct linked list of free object slots */
- lastfree = 0;
- for (num = 0; num < xref_len; num++)
+ if (opts.do_incremental)
{
- if (!opts.use_list[num])
+ for (num = 0; num < xref_len; num++)
{
- opts.gen_list[num]++;
- opts.ofs_list[lastfree] = num;
- lastfree = num;
+ if (!opts.use_list[num] && pdf_xref_is_incremental(doc, num))
+ {
+ /* Make unreusable. FIXME: would be better to link to existing free list */
+ opts.gen_list[num] = 65535;
+ opts.ofs_list[num] = 0;
+ }
+ }
+ }
+ else
+ {
+ /* Construct linked list of free object slots */
+ lastfree = 0;
+ for (num = 0; num < xref_len; num++)
+ {
+ if (!opts.use_list[num])
+ {
+ opts.gen_list[num]++;
+ opts.ofs_list[lastfree] = num;
+ lastfree = num;
+ }
}
}