Commit b48a0ff0e8e1861884b2dac62d98d39f8e194086
1 parent
8cf7f2bf
Add qpdf_empty_pdf to C API
Showing
8 changed files
with
61 additions
and
7 deletions
ChangeLog
| 1 | 2022-02-05 Jay Berkenbilt <ejb@ql.org> | 1 | 2022-02-05 Jay Berkenbilt <ejb@ql.org> |
| 2 | 2 | ||
| 3 | + * Expose QPDF::emptyPDF to the C API as qpdf_empty_pdf() | ||
| 4 | + | ||
| 3 | * Add comments letting people know that the version string | 5 | * Add comments letting people know that the version string |
| 4 | returned by QPDF::QPDFVersion and qpdf_get_qpdf_version is static. | 6 | returned by QPDF::QPDFVersion and qpdf_get_qpdf_version is static. |
| 5 | 7 |
TODO
| 1 | 10.6 | 1 | 10.6 |
| 2 | ==== | 2 | ==== |
| 3 | 3 | ||
| 4 | -* Expose emptyPDF to the C API. Ensure that qpdf_get_qpdf_version is | ||
| 5 | - always static. | ||
| 6 | - | ||
| 7 | * Consider doing one big commit to reformat the entire codebase using | 4 | * Consider doing one big commit to reformat the entire codebase using |
| 8 | clang-format or a similar tool. Consider using blame.ignoreRevsFile | 5 | clang-format or a similar tool. Consider using blame.ignoreRevsFile |
| 9 | or similar (or otherwise study git blame to see how to minimize the | 6 | or similar (or otherwise study git blame to see how to minimize the |
include/qpdf/qpdf-c.h
| @@ -178,9 +178,9 @@ extern "C" { | @@ -178,9 +178,9 @@ extern "C" { | ||
| 178 | char const* qpdf_get_qpdf_version(); | 178 | char const* qpdf_get_qpdf_version(); |
| 179 | 179 | ||
| 180 | /* Returns dynamically allocated qpdf_data pointer; must be freed | 180 | /* Returns dynamically allocated qpdf_data pointer; must be freed |
| 181 | - * by calling qpdf_cleanup. You must call qpdf_read or one of the | ||
| 182 | - * other qpdf_read_* functions before calling any function that | ||
| 183 | - * would need to operate on the PDF file. | 181 | + * by calling qpdf_cleanup. You must call qpdf_read, one of the |
| 182 | + * other qpdf_read_* functions, or qpdf_empty_pdf before calling | ||
| 183 | + * any function that would need to operate on the PDF file. | ||
| 184 | */ | 184 | */ |
| 185 | QPDF_DLL | 185 | QPDF_DLL |
| 186 | qpdf_data qpdf_init(); | 186 | qpdf_data qpdf_init(); |
| @@ -289,6 +289,13 @@ extern "C" { | @@ -289,6 +289,13 @@ extern "C" { | ||
| 289 | unsigned long long size, | 289 | unsigned long long size, |
| 290 | char const* password); | 290 | char const* password); |
| 291 | 291 | ||
| 292 | + /* Calling qpdf_empty_pdf initializes this qpdf object with an | ||
| 293 | + * empty PDF, making it possible to create a PDF from scratch | ||
| 294 | + * using the C API. Added in 10.6. | ||
| 295 | + */ | ||
| 296 | + QPDF_DLL | ||
| 297 | + QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf); | ||
| 298 | + | ||
| 292 | /* Read functions below must be called after qpdf_read or | 299 | /* Read functions below must be called after qpdf_read or |
| 293 | * qpdf_read_memory. */ | 300 | * qpdf_read_memory. */ |
| 294 | 301 |
libqpdf/qpdf-c.cc
| @@ -356,6 +356,14 @@ QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf, | @@ -356,6 +356,14 @@ QPDF_ERROR_CODE qpdf_read_memory(qpdf_data qpdf, | ||
| 356 | return status; | 356 | return status; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | +QPDF_ERROR_CODE qpdf_empty_pdf(qpdf_data qpdf) | ||
| 360 | +{ | ||
| 361 | + qpdf->filename = "empty PDF"; | ||
| 362 | + qpdf->qpdf->emptyPDF(); | ||
| 363 | + QTC::TC("qpdf", "qpdf-c called qpdf_empty_pdf"); | ||
| 364 | + return QPDF_SUCCESS; | ||
| 365 | +} | ||
| 366 | + | ||
| 359 | char const* qpdf_get_pdf_version(qpdf_data qpdf) | 367 | char const* qpdf_get_pdf_version(qpdf_data qpdf) |
| 360 | { | 368 | { |
| 361 | QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_version"); | 369 | QTC::TC("qpdf", "qpdf-c called qpdf_get_pdf_version"); |
qpdf/qpdf-ctest.c
| @@ -1242,6 +1242,19 @@ static void test40(char const* infile, | @@ -1242,6 +1242,19 @@ static void test40(char const* infile, | ||
| 1242 | report_errors(); | 1242 | report_errors(); |
| 1243 | } | 1243 | } |
| 1244 | 1244 | ||
| 1245 | +static void test41(char const* infile, | ||
| 1246 | + char const* password, | ||
| 1247 | + char const* outfile, | ||
| 1248 | + char const* xarg) | ||
| 1249 | +{ | ||
| 1250 | + /* Empty PDF -- infile is ignored*/ | ||
| 1251 | + assert(qpdf_empty_pdf(qpdf) == 0); | ||
| 1252 | + qpdf_init_write(qpdf, outfile); | ||
| 1253 | + qpdf_set_static_ID(qpdf, QPDF_TRUE); | ||
| 1254 | + qpdf_write(qpdf); | ||
| 1255 | + report_errors(); | ||
| 1256 | +} | ||
| 1257 | + | ||
| 1245 | int main(int argc, char* argv[]) | 1258 | int main(int argc, char* argv[]) |
| 1246 | { | 1259 | { |
| 1247 | char* p = 0; | 1260 | char* p = 0; |
| @@ -1322,6 +1335,7 @@ int main(int argc, char* argv[]) | @@ -1322,6 +1335,7 @@ int main(int argc, char* argv[]) | ||
| 1322 | (n == 38) ? test38 : | 1335 | (n == 38) ? test38 : |
| 1323 | (n == 39) ? test39 : | 1336 | (n == 39) ? test39 : |
| 1324 | (n == 40) ? test40 : | 1337 | (n == 40) ? test40 : |
| 1338 | + (n == 41) ? test41 : | ||
| 1325 | 0); | 1339 | 0); |
| 1326 | 1340 | ||
| 1327 | if (fn == 0) | 1341 | if (fn == 0) |
qpdf/qpdf.testcov
| @@ -639,3 +639,4 @@ QPDFJob json encrypt no key length 0 | @@ -639,3 +639,4 @@ QPDFJob json encrypt no key length 0 | ||
| 639 | QPDFJob json encrypt duplicate key length 0 | 639 | QPDFJob json encrypt duplicate key length 0 |
| 640 | QPDFJob json encrypt missing password 0 | 640 | QPDFJob json encrypt missing password 0 |
| 641 | QPDFJob json pages no file 0 | 641 | QPDFJob json pages no file 0 |
| 642 | +qpdf-c called qpdf_empty_pdf 0 |
qpdf/qtest/qpdf.test
| @@ -3553,7 +3553,7 @@ my @capi = ( | @@ -3553,7 +3553,7 @@ my @capi = ( | ||
| 3553 | [8, 'no original object ids'], | 3553 | [8, 'no original object ids'], |
| 3554 | [9, 'uncompressed streams'], | 3554 | [9, 'uncompressed streams'], |
| 3555 | ); | 3555 | ); |
| 3556 | -$n_tests += (2 * @capi) + 3; | 3556 | +$n_tests += (2 * @capi) + 5; |
| 3557 | foreach my $d (@capi) | 3557 | foreach my $d (@capi) |
| 3558 | { | 3558 | { |
| 3559 | my ($n, $description) = @$d; | 3559 | my ($n, $description) = @$d; |
| @@ -3590,6 +3590,14 @@ $td->runtest("write damaged", | @@ -3590,6 +3590,14 @@ $td->runtest("write damaged", | ||
| 3590 | $td->EXIT_STATUS => 0}, | 3590 | $td->EXIT_STATUS => 0}, |
| 3591 | $td->NORMALIZE_NEWLINES); | 3591 | $td->NORMALIZE_NEWLINES); |
| 3592 | 3592 | ||
| 3593 | +$td->runtest("empty PDF", | ||
| 3594 | + {$td->COMMAND => "qpdf-ctest 41 - '' a.pdf"}, | ||
| 3595 | + {$td->STRING => "C test 41 done\n", $td->EXIT_STATUS => 0}, | ||
| 3596 | + $td->NORMALIZE_NEWLINES); | ||
| 3597 | +$td->runtest("check output", | ||
| 3598 | + {$td->FILE => "a.pdf"}, | ||
| 3599 | + {$td->FILE => "c-empty.pdf"}); | ||
| 3600 | + | ||
| 3593 | show_ntests(); | 3601 | show_ntests(); |
| 3594 | # ---------- | 3602 | # ---------- |
| 3595 | $td->notify("--- Deterministic ID Tests ---"); | 3603 | $td->notify("--- Deterministic ID Tests ---"); |
qpdf/qtest/qpdf/c-empty.pdf
0 → 100644
| 1 | +%PDF-1.3 | ||
| 2 | +%¿÷¢þ | ||
| 3 | +1 0 obj | ||
| 4 | +<< /Pages 2 0 R /Type /Catalog >> | ||
| 5 | +endobj | ||
| 6 | +2 0 obj | ||
| 7 | +<< /Count 0 /Kids [ ] /Type /Pages >> | ||
| 8 | +endobj | ||
| 9 | +xref | ||
| 10 | +0 3 | ||
| 11 | +0000000000 65535 f | ||
| 12 | +0000000015 00000 n | ||
| 13 | +0000000064 00000 n | ||
| 14 | +trailer << /Root 1 0 R /Size 3 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> | ||
| 15 | +startxref | ||
| 16 | +117 | ||
| 17 | +%%EOF |