QRCoder icon indicating copy to clipboard operation
QRCoder copied to clipboard

Fix PDF creation: /Kids must contain indirect references

Open Shane32 opened this issue 2 months ago • 0 comments

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

Shane32 avatar Oct 19 '25 03:10 Shane32