PDF saving: Perform a pre-pass to load objects before saving.
authorRobin Watts <[email protected]>
Tue, 18 Feb 2025 12:46:22 +0000 (12:46 +0000)
committerSebastian Rasmussen <[email protected]>
Fri, 7 Mar 2025 13:38:34 +0000 (14:38 +0100)
With some files, we can trigger a repair during the writing out
of objects (seen with the test file from bug 708289).

We'd rather the repair happened BEFORE we started writing objects.
So perform a pre-pass at the start of the save operation to cache
objects. We would have cached all these objects at some point during
the save operation, so it's not really costing us anything extra.

source/pdf/pdf-write.c

index 24021d431800c466656b8093d5b20e86b14ee33e..7530904fc6d6a25dbfd23a4b01e47fa6118f1fac 100644 (file)
@@ -3723,6 +3723,15 @@ gather_to_objstms(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, int
        flush_gathered(ctx, doc, &data);
 }
 
+static void
+prepass(fz_context *ctx, pdf_document *doc)
+{
+       int num;
+
+       for (num = 1; num < pdf_xref_len(ctx, doc); ++num)
+               pdf_cache_object(ctx, doc, num);
+}
+
 static void
 do_pdf_save_document(fz_context *ctx, pdf_document *doc, pdf_write_state *opts, const pdf_write_options *in_opts)
 {
@@ -3745,11 +3754,16 @@ do_pdf_save_document(fz_context *ctx, pdf_document *doc, pdf_write_state *opts,
                fz_write_string(ctx, opts->out, "\n");
        }
 
-       xref_len = pdf_xref_len(ctx, doc);
-
        pdf_begin_operation(ctx, doc, "Save document");
        fz_try(ctx)
        {
+               /* First, we do a prepass across the document to load all the objects
+                * into memory. We'll end up doing this later on anyway, but by doing
+                * it here, we force any repairs to happen before writing proper
+                * starts. */
+               prepass(ctx, doc);
+               xref_len = pdf_xref_len(ctx, doc);
+
                initialise_write_state(ctx, doc, in_opts, opts);
 
                if (!opts->dont_regenerate_id)