Commit b6bdc0f5950287c1c9e76115bdec230dcf99b964
1 parent
a0768e41
Add factory methods for creating empty arrays and dictionaries.
Also updated pdf_from_scratch test driver to use the new factories, and made some cosmetic improvements and documentation updates for the emptyPDF() method.
Showing
8 changed files
with
59 additions
and
40 deletions
ChangeLog
| 1 | +2012-06-22 Jay Berkenbilt <ejb@ql.org> | ||
| 2 | + | ||
| 3 | + * Add empty QPDFObjectHandle factories for array and dictionary. | ||
| 4 | + With PDF-from-scratch capability, it is useful to be able to | ||
| 5 | + create empty arrays and dictionaries and add keys to them. | ||
| 6 | + Updated pdf_from_scratch.cc to use these interfaces. | ||
| 7 | + | ||
| 1 | 2012-06-21 Jay Berkenbilt <ejb@ql.org> | 8 | 2012-06-21 Jay Berkenbilt <ejb@ql.org> |
| 2 | 9 | ||
| 3 | * Add QPDF::emptyPDF() to create an empty QPDF object suitable for | 10 | * Add QPDF::emptyPDF() to create an empty QPDF object suitable for |
TODO
| @@ -37,7 +37,10 @@ Next | @@ -37,7 +37,10 @@ Next | ||
| 37 | space to do the tests, probably enough space for two coipes of | 37 | space to do the tests, probably enough space for two coipes of |
| 38 | the file. The test program should also have an interactive mode | 38 | the file. The test program should also have an interactive mode |
| 39 | so we can generate the large file and then look at it with a | 39 | so we can generate the large file and then look at it with a |
| 40 | - PDF viewer like Adobe Reader. | 40 | + PDF viewer like Adobe Reader. The test suite should actually |
| 41 | + read the file back in and look at all the page and stream | ||
| 42 | + contents to make sure the file is really correct. We need to | ||
| 43 | + test normal writing and linearization. | ||
| 41 | 44 | ||
| 42 | * Consider adding an example that uses the page APIs, or update the | 45 | * Consider adding an example that uses the page APIs, or update the |
| 43 | documentation to refer the user to the test suite. | 46 | documentation to refer the user to the test suite. |
include/qpdf/QPDFObjectHandle.hh
| @@ -106,9 +106,13 @@ class QPDFObjectHandle | @@ -106,9 +106,13 @@ class QPDFObjectHandle | ||
| 106 | QPDF_DLL | 106 | QPDF_DLL |
| 107 | static QPDFObjectHandle newString(std::string const& str); | 107 | static QPDFObjectHandle newString(std::string const& str); |
| 108 | QPDF_DLL | 108 | QPDF_DLL |
| 109 | + static QPDFObjectHandle newArray(); | ||
| 110 | + QPDF_DLL | ||
| 109 | static QPDFObjectHandle newArray( | 111 | static QPDFObjectHandle newArray( |
| 110 | std::vector<QPDFObjectHandle> const& items); | 112 | std::vector<QPDFObjectHandle> const& items); |
| 111 | QPDF_DLL | 113 | QPDF_DLL |
| 114 | + static QPDFObjectHandle newDictionary(); | ||
| 115 | + QPDF_DLL | ||
| 112 | static QPDFObjectHandle newDictionary( | 116 | static QPDFObjectHandle newDictionary( |
| 113 | std::map<std::string, QPDFObjectHandle> const& items); | 117 | std::map<std::string, QPDFObjectHandle> const& items); |
| 114 | 118 |
include/qpdf/QUtil.hh
libqpdf/QPDF.cc
| @@ -370,7 +370,7 @@ QPDF::processMemoryFile(char const* description, | @@ -370,7 +370,7 @@ QPDF::processMemoryFile(char const* description, | ||
| 370 | void | 370 | void |
| 371 | QPDF::emptyPDF() | 371 | QPDF::emptyPDF() |
| 372 | { | 372 | { |
| 373 | - processMemoryFile("empty file", EMPTY_PDF, strlen(EMPTY_PDF)); | 373 | + processMemoryFile("empty PDF", EMPTY_PDF, strlen(EMPTY_PDF)); |
| 374 | } | 374 | } |
| 375 | 375 | ||
| 376 | void | 376 | void |
libqpdf/QPDFObjectHandle.cc
| @@ -616,12 +616,24 @@ QPDFObjectHandle::newString(std::string const& str) | @@ -616,12 +616,24 @@ QPDFObjectHandle::newString(std::string const& str) | ||
| 616 | } | 616 | } |
| 617 | 617 | ||
| 618 | QPDFObjectHandle | 618 | QPDFObjectHandle |
| 619 | +QPDFObjectHandle::newArray() | ||
| 620 | +{ | ||
| 621 | + return newArray(std::vector<QPDFObjectHandle>()); | ||
| 622 | +} | ||
| 623 | + | ||
| 624 | +QPDFObjectHandle | ||
| 619 | QPDFObjectHandle::newArray(std::vector<QPDFObjectHandle> const& items) | 625 | QPDFObjectHandle::newArray(std::vector<QPDFObjectHandle> const& items) |
| 620 | { | 626 | { |
| 621 | return QPDFObjectHandle(new QPDF_Array(items)); | 627 | return QPDFObjectHandle(new QPDF_Array(items)); |
| 622 | } | 628 | } |
| 623 | 629 | ||
| 624 | QPDFObjectHandle | 630 | QPDFObjectHandle |
| 631 | +QPDFObjectHandle::newDictionary() | ||
| 632 | +{ | ||
| 633 | + return newDictionary(std::map<std::string, QPDFObjectHandle>()); | ||
| 634 | +} | ||
| 635 | + | ||
| 636 | +QPDFObjectHandle | ||
| 625 | QPDFObjectHandle::newDictionary( | 637 | QPDFObjectHandle::newDictionary( |
| 626 | std::map<std::string, QPDFObjectHandle> const& items) | 638 | std::map<std::string, QPDFObjectHandle> const& items) |
| 627 | { | 639 | { |
libqpdf/QUtil.cc
| 1 | -#include <qpdf/QUtil.hh> | 1 | +// Include qpdf-config.h first so off_t is gauaranteed to have the right size. |
| 2 | #include <qpdf/qpdf-config.h> | 2 | #include <qpdf/qpdf-config.h> |
| 3 | + | ||
| 4 | +#include <qpdf/QUtil.hh> | ||
| 5 | + | ||
| 3 | #include <stdio.h> | 6 | #include <stdio.h> |
| 4 | #include <errno.h> | 7 | #include <errno.h> |
| 5 | #include <ctype.h> | 8 | #include <ctype.h> |
qpdf/pdf_from_scratch.cc
| @@ -40,49 +40,40 @@ void runtest(int n) | @@ -40,49 +40,40 @@ void runtest(int n) | ||
| 40 | { | 40 | { |
| 41 | // Create a minimal PDF from scratch. | 41 | // Create a minimal PDF from scratch. |
| 42 | 42 | ||
| 43 | - std::map<std::string, QPDFObjectHandle> keys; | ||
| 44 | - std::vector<QPDFObjectHandle> items; | ||
| 45 | - | ||
| 46 | - keys.clear(); | ||
| 47 | - keys["/Type"] = newName("/Font"); | ||
| 48 | - keys["/Subtype"] = newName("/Type1"); | ||
| 49 | - keys["/Name"] = newName("/F1"); | ||
| 50 | - keys["/BaseFont"] = newName("/Helvetica"); | ||
| 51 | - keys["/Encoding"] = newName("/WinAnsiEncoding"); | ||
| 52 | QPDFObjectHandle font = pdf.makeIndirectObject( | 43 | QPDFObjectHandle font = pdf.makeIndirectObject( |
| 53 | - QPDFObjectHandle::newDictionary(keys)); | 44 | + QPDFObjectHandle::newDictionary()); |
| 45 | + font.replaceKey("/Type", newName("/Font")); | ||
| 46 | + font.replaceKey("/Subtype", newName("/Type1")); | ||
| 47 | + font.replaceKey("/Name", newName("/F1")); | ||
| 48 | + font.replaceKey("/BaseFont", newName("/Helvetica")); | ||
| 49 | + font.replaceKey("/Encoding", newName("/WinAnsiEncoding")); | ||
| 54 | 50 | ||
| 55 | - items.clear(); | ||
| 56 | - items.push_back(newName("/PDF")); | ||
| 57 | - items.push_back(newName("/Text")); | ||
| 58 | QPDFObjectHandle procset = pdf.makeIndirectObject( | 51 | QPDFObjectHandle procset = pdf.makeIndirectObject( |
| 59 | - QPDFObjectHandle::newArray(items)); | 52 | + QPDFObjectHandle::newArray()); |
| 53 | + procset.appendItem(newName("/PDF")); | ||
| 54 | + procset.appendItem(newName("/Text")); | ||
| 60 | 55 | ||
| 61 | QPDFObjectHandle contents = createPageContents(pdf, "First Page"); | 56 | QPDFObjectHandle contents = createPageContents(pdf, "First Page"); |
| 62 | 57 | ||
| 63 | - items.clear(); | ||
| 64 | - items.push_back(QPDFObjectHandle::newInteger(0)); | ||
| 65 | - items.push_back(QPDFObjectHandle::newInteger(0)); | ||
| 66 | - items.push_back(QPDFObjectHandle::newInteger(612)); | ||
| 67 | - items.push_back(QPDFObjectHandle::newInteger(792)); | ||
| 68 | - QPDFObjectHandle mediabox = QPDFObjectHandle::newArray(items); | ||
| 69 | - | ||
| 70 | - keys.clear(); | ||
| 71 | - keys["/F1"] = font; | ||
| 72 | - QPDFObjectHandle rfont = QPDFObjectHandle::newDictionary(keys); | ||
| 73 | - | ||
| 74 | - keys.clear(); | ||
| 75 | - keys["/ProcSet"] = procset; | ||
| 76 | - keys["/Font"] = rfont; | ||
| 77 | - QPDFObjectHandle resources = QPDFObjectHandle::newDictionary(keys); | ||
| 78 | - | ||
| 79 | - keys.clear(); | ||
| 80 | - keys["/Type"] = newName("/Page"); | ||
| 81 | - keys["/MediaBox"] = mediabox; | ||
| 82 | - keys["/Contents"] = contents; | ||
| 83 | - keys["/Resources"] = resources; | 58 | + QPDFObjectHandle mediabox = QPDFObjectHandle::newArray(); |
| 59 | + mediabox.appendItem(QPDFObjectHandle::newInteger(0)); | ||
| 60 | + mediabox.appendItem(QPDFObjectHandle::newInteger(0)); | ||
| 61 | + mediabox.appendItem(QPDFObjectHandle::newInteger(612)); | ||
| 62 | + mediabox.appendItem(QPDFObjectHandle::newInteger(792)); | ||
| 63 | + | ||
| 64 | + QPDFObjectHandle rfont = QPDFObjectHandle::newDictionary(); | ||
| 65 | + rfont.replaceKey("/F1", font); | ||
| 66 | + | ||
| 67 | + QPDFObjectHandle resources = QPDFObjectHandle::newDictionary(); | ||
| 68 | + resources.replaceKey("/ProcSet", procset); | ||
| 69 | + resources.replaceKey("/Font", rfont); | ||
| 70 | + | ||
| 84 | QPDFObjectHandle page = pdf.makeIndirectObject( | 71 | QPDFObjectHandle page = pdf.makeIndirectObject( |
| 85 | - QPDFObjectHandle::newDictionary(keys)); | 72 | + QPDFObjectHandle::newDictionary()); |
| 73 | + page.replaceKey("/Type", newName("/Page")); | ||
| 74 | + page.replaceKey("/MediaBox", mediabox); | ||
| 75 | + page.replaceKey("/Contents", contents); | ||
| 76 | + page.replaceKey("/Resources", resources); | ||
| 86 | 77 | ||
| 87 | pdf.addPage(page, true); | 78 | pdf.addPage(page, true); |
| 88 | 79 |