Skip to content

Fix PDF creation: /Kids must contain indirect references #687

@Shane32

Description

@Shane32

Per CodeRabbit:

⚠️ Potential issue | 🔴 Critical

PDF Pages/Kids must reference an indirect Page object (not an inline dictionary).

Kids arrays shall contain indirect references to Page objects. The current inline page dictionary under /Kids violates the spec and may break validators/readers. Create a separate Page object and shift the content stream to the next object.

Apply this minimal restructuring:

-            "/Kids [ <<\r\n" +                                                      // Array of page objects - begin inline page dictionary
-                "/Type /Page\r\n" +                                                 // Declares this as a page
-                "/Parent 2 0 R\r\n" +                                               // References parent Pages object
-                "/MediaBox [0 0 " + pdfMediaSize + " " + pdfMediaSize + "]\r\n" +   // Page dimensions [x1 y1 x2 y2]
-                "/Resources << /ProcSet [ /PDF ] >>\r\n" +                          // Required resources: PDF operations only (no images)
-                "/Contents 3 0 R\r\n" +                                             // References content stream (object 3)
-                ">> ]\r\n" +                                                        // End inline page dictionary and Kids array
+            "/Kids [ 3 0 R ]\r\n" +                                                 // Kids must be indirect Page refs
             ">>\r\n" +
             "endobj\r\n"
         );
 
-        // Content stream - PDF drawing instructions
+        // Content stream - PDF drawing instructions
         var scale = ToStr(imgSize * 72 / (float)dpi / moduleCount);
         var pathCommands = CreatePathFromModules();
         var content = "q\r\n" +
           ...
           "Q";
 
-        writer.Flush();
-        xrefs.Add(stream.Position);
-
-        // Object 3: Content stream - contains the drawing instructions
-        writer.Write(
-            ToStr(xrefs.Count) + " 0 obj\r\n" +
-            "<< /Length " + ToStr(content.Length) + " >>\r\n" +
-            "stream\r\n" +
-            content + "endstream\r\n" +
-            "endobj\r\n"
-        );
+        // Object 3: Page (must be indirect)
+        writer.Flush();
+        xrefs.Add(stream.Position);
+        writer.Write(
+            ToStr(xrefs.Count) + " 0 obj\r\n" +
+            "<< /Type /Page\r\n" +
+            "/Parent 2 0 R\r\n" +
+            "/MediaBox [0 0 " + pdfMediaSize + " " + pdfMediaSize + "]\r\n" +
+            "/Resources << /ProcSet [ /PDF ] >>\r\n" +
+            "/Contents 4 0 R\r\n" +
+            ">>\r\n" +
+            "endobj\r\n"
+        );
+
+        // Object 4: Content stream - contains the drawing instructions
+        writer.Flush();
+        xrefs.Add(stream.Position);
+        writer.Write(
+            ToStr(xrefs.Count) + " 0 obj\r\n" +
+            "<< /Length " + ToStr(Encoding.ASCII.GetByteCount(content)) + " >>\r\n" +
+            "stream\r\n" +
+            content + "endstream\r\n" +
+            "endobj\r\n"
+        );

Also applies to: 117-124

🤖 Prompt for AI Agents

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions