diff options
Diffstat (limited to 'src/book.vala')
-rw-r--r-- | src/book.vala | 123 |
1 files changed, 93 insertions, 30 deletions
diff --git a/src/book.vala b/src/book.vala index 5782838..4119cfc 100644 --- a/src/book.vala +++ b/src/book.vala @@ -264,6 +264,22 @@ public class Book var stream = file.replace (null, false, FileCreateFlags.NONE, null); var writer = new PDFWriter (stream); + /* Choose object numbers */ + var catalog_number = writer.add_object (); + var metadata_number = writer.add_object (); + var pages_number = writer.add_object (); + var info_number = writer.add_object (); + var page_numbers = new uint[n_pages]; + var page_image_numbers = new uint[n_pages]; + var page_content_numbers = new uint[n_pages]; + for (var i = 0; i < n_pages; i++) + { + page_numbers[i] = writer.add_object (); + page_image_numbers[i] = writer.add_object (); + page_content_numbers[i] = writer.add_object (); + } + var struct_tree_root_number = writer.add_object (); + /* Header */ writer.write_string ("%PDF-1.3\n"); @@ -271,40 +287,59 @@ public class Book writer.write_string ("%\xe2\xe3\xcf\xd3\n"); /* Catalog */ - var catalog_number = writer.start_object (); + writer.start_object (catalog_number); writer.write_string ("%u 0 obj\n".printf (catalog_number)); writer.write_string ("<<\n"); writer.write_string ("/Type /Catalog\n"); - //FIXMEwriter.write_string ("/Metadata %u 0 R\n".printf (catalog_number + 1)); - //FIXMEwriter.write_string ("/MarkInfo << /Marked true >>"); - writer.write_string ("/Pages %u 0 R\n".printf (catalog_number + 1)); //+2 + writer.write_string ("/Metadata %u 0 R\n".printf (metadata_number)); + writer.write_string ("/MarkInfo << /Marked true >>\n"); + writer.write_string ("/StructTreeRoot %u 0 R\n".printf (struct_tree_root_number)); + writer.write_string ("/Pages %u 0 R\n".printf (pages_number)); writer.write_string (">>\n"); writer.write_string ("endobj\n"); /* Metadata */ - /* FIXME writer.write_string ("\n"); - number = writer.start_object (); - writer.write_string ("%u 0 obj\n".printf (number)); + var now = new DateTime.now_local (); + var date_string = now.format ("%FT%H:%M:%S%:z"); + /* NOTE: The id has to be hardcoded to this value according to the spec... */ + var metadata = """<?xpacket begin="%s" id="W5M0MpCehiHzreSzNTczkc9d"?> +<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:xmp="http://ns.adobe.com/xap/1.0/"> + <rdf:Description rdf:about="" + xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" + xmlns:xmp="http://ns.adobe.com/xap/1.0/"> + <pdfaid:part>1</pdfaid:part> + <pdfaid:conformance>A</pdfaid:conformance> + <xmp:CreatorTool>Simple Scan %s</xmp:CreatorTool> + <xmp:CreateDate>%s</xmp:CreateDate> + <xmp:ModifyDate>%s</xmp:ModifyDate> + <xmp:MetadataDate>%s</xmp:MetadataDate> + </rdf:Description> +</rdf:RDF> +<?xpacket end="w"?>""".printf (((unichar) 0xFEFF).to_string (), VERSION, date_string, date_string, date_string); + writer.write_string ("\n"); + writer.start_object (metadata_number); + writer.write_string ("%u 0 obj\n".printf (metadata_number)); writer.write_string ("<<\n"); writer.write_string ("/Type /Metadata\n"); writer.write_string ("/Subtype /XML\n"); - writer.write_string ("/Length %u\n".printf (...)); + writer.write_string ("/Length %u\n".printf (metadata.length)); writer.write_string (">>\n"); writer.write_string ("stream\n"); - // ... + writer.write_string (metadata); writer.write_string ("\n"); writer.write_string ("endstream\n"); - writer.write_string ("endobj\n");*/ + writer.write_string ("endobj\n"); /* Pages */ writer.write_string ("\n"); - var pages_number = writer.start_object (); + writer.start_object (pages_number); writer.write_string ("%u 0 obj\n".printf (pages_number)); writer.write_string ("<<\n"); writer.write_string ("/Type /Pages\n"); writer.write_string ("/Kids ["); for (var i = 0; i < n_pages; i++) - writer.write_string (" %u 0 R".printf (pages_number + 1 + (i*3))); + writer.write_string (" %u 0 R".printf (page_numbers[i])); writer.write_string (" ]\n"); writer.write_string ("/Count %u\n".printf (n_pages)); writer.write_string (">>\n"); @@ -469,21 +504,21 @@ public class Book /* Page */ writer.write_string ("\n"); - var number = writer.start_object (); - writer.write_string ("%u 0 obj\n".printf (number)); + writer.start_object (page_numbers[i]); + writer.write_string ("%u 0 obj\n".printf (page_numbers[i])); writer.write_string ("<<\n"); writer.write_string ("/Type /Page\n"); writer.write_string ("/Parent %u 0 R\n".printf (pages_number)); - writer.write_string ("/Resources << /XObject << /Im%d %u 0 R >> >>\n".printf (i, number+1)); + writer.write_string ("/Resources << /XObject << /Im%d %u 0 R >> >>\n".printf (i, page_image_numbers[i])); writer.write_string ("/MediaBox [ 0 0 %s %s ]\n".printf (page_width.format (width_buffer, "%.2f"), page_height.format (height_buffer, "%.2f"))); - writer.write_string ("/Contents %u 0 R\n".printf (number+2)); + writer.write_string ("/Contents %u 0 R\n".printf (page_content_numbers[i])); writer.write_string (">>\n"); writer.write_string ("endobj\n"); /* Page image */ writer.write_string ("\n"); - number = writer.start_object (); - writer.write_string ("%u 0 obj\n".printf (number)); + writer.start_object (page_image_numbers[i]); + writer.write_string ("%u 0 obj\n".printf (page_image_numbers[i])); writer.write_string ("<<\n"); writer.write_string ("/Type /XObject\n"); writer.write_string ("/Subtype /Image\n"); @@ -501,11 +536,20 @@ public class Book writer.write_string ("endstream\n"); writer.write_string ("endobj\n"); + /* Structure tree */ + writer.write_string ("\n"); + writer.start_object (struct_tree_root_number); + writer.write_string ("%u 0 obj\n".printf (struct_tree_root_number)); + writer.write_string ("<<\n"); + writer.write_string ("/Type /StructTreeRoot\n"); + writer.write_string (">>\n"); + writer.write_string ("endobj\n"); + /* Page contents */ var command = "q\n%s 0 0 %s 0 0 cm\n/Im%d Do\nQ".printf (page_width.format (width_buffer, "%f"), page_height.format (height_buffer, "%f"), i); writer.write_string ("\n"); - number = writer.start_object (); - writer.write_string ("%u 0 obj\n".printf (number)); + writer.start_object (page_content_numbers[i]); + writer.write_string ("%u 0 obj\n".printf (page_content_numbers[i])); writer.write_string ("<<\n"); writer.write_string ("/Length %d\n".printf (command.length)); writer.write_string (">>\n"); @@ -520,7 +564,7 @@ public class Book /* Info */ writer.write_string ("\n"); - var info_number = writer.start_object (); + writer.start_object (info_number); writer.write_string ("%u 0 obj\n".printf (info_number)); writer.write_string ("<<\n"); writer.write_string ("/Creator (Simple Scan %s)\n".printf (VERSION)); @@ -531,16 +575,19 @@ public class Book writer.write_string ("\n"); var xref_offset = writer.offset; writer.write_string ("xref\n"); - writer.write_string ("0 %zu\n".printf (writer.object_offsets.length () + 1)); - writer.write_string ("0000000000 65535 f \n"); - foreach (var offset in writer.object_offsets) - writer.write_string ("%010zu 00000 n \n".printf (offset)); + writer.write_string ("0 %zu\n".printf (writer.object_offsets.length + 1)); + writer.write_string ("%010zu 65535 f \n".printf (next_empty_object (writer, 0))); + for (var i = 0; i < writer.object_offsets.length; i++) + if (writer.object_offsets[i] == 0) + writer.write_string ("%010zu 65535 f \n".printf (next_empty_object (writer, i + 1))); + else + writer.write_string ("%010zu 00000 n \n".printf (writer.object_offsets[i])); /* Trailer */ writer.write_string ("\n"); writer.write_string ("trailer\n"); writer.write_string ("<<\n"); - writer.write_string ("/Size %zu\n".printf (writer.object_offsets.length () + 1)); + writer.write_string ("/Size %zu\n".printf (writer.object_offsets.length + 1)); writer.write_string ("/Info %u 0 R\n".printf (info_number)); writer.write_string ("/Root %u 0 R\n".printf (catalog_number)); writer.write_string ("/ID [<%s> <%s>]\n".printf (id, id)); @@ -550,6 +597,14 @@ public class Book writer.write_string ("%%EOF\n"); } + static int next_empty_object (PDFWriter writer, int start) + { + for (var i = start; i < writer.object_offsets.length; i++) + if (writer.object_offsets[i] == 0) + return i + 1; + return 0; + } + public void save (string type, int quality, File file) throws Error { switch (type) @@ -572,12 +627,13 @@ public class Book private class PDFWriter { public size_t offset = 0; - public List<uint> object_offsets; + public uint[] object_offsets; private FileOutputStream stream; public PDFWriter (FileOutputStream stream) { this.stream = stream; + object_offsets = new uint[0]; } public void write (uint8[] data) @@ -598,10 +654,17 @@ private class PDFWriter write ((uint8[]) text.to_utf8 ()); } - public uint start_object () + public uint add_object () + { + object_offsets.resize (object_offsets.length + 1); + var index = object_offsets.length - 1; + object_offsets[index] = 0; + return index + 1; + } + + public void start_object (uint index) { - object_offsets.append ((uint)offset); - return object_offsets.length (); + object_offsets[index - 1] = (uint)offset; } } |