Commit eaacf94005ff8189e215447ffeadc341eca6c019
1 parent
40ecba41
Update C API with new QPDFWriter methods
Showing
7 changed files
with
130 additions
and
5 deletions
ChangeLog
| 1 | +2017-09-12 Jay Berkenbilt <ejb@ql.org> | ||
| 2 | + | ||
| 3 | + * Add new methods to the C API to correspond to new additions to | ||
| 4 | + QPDFWriter: | ||
| 5 | + - qpdf_set_compress_streams | ||
| 6 | + - qpdf_set_decode_level | ||
| 7 | + - qpdf_set_preserve_unreferenced_objects | ||
| 8 | + - qpdf_set_newline_before_endstream | ||
| 9 | + | ||
| 1 | 2017-08-25 Jay Berkenbilt <ejb@ql.org> | 10 | 2017-08-25 Jay Berkenbilt <ejb@ql.org> |
| 2 | 11 | ||
| 3 | * Re-implement parser iteratively to avoid stack overflow on very | 12 | * Re-implement parser iteratively to avoid stack overflow on very |
TODO
| 1 | Before final 7.0.0 | 1 | Before final 7.0.0 |
| 2 | ================== | 2 | ================== |
| 3 | 3 | ||
| 4 | - * Update C API | ||
| 5 | - | ||
| 6 | * Create release notes | 4 | * Create release notes |
| 7 | 5 | ||
| 8 | * See if the error message that gets generated when retrying a stream | 6 | * See if the error message that gets generated when retrying a stream |
include/qpdf/qpdf-c.h
| @@ -319,6 +319,21 @@ extern "C" { | @@ -319,6 +319,21 @@ extern "C" { | ||
| 319 | enum qpdf_stream_data_e mode); | 319 | enum qpdf_stream_data_e mode); |
| 320 | 320 | ||
| 321 | QPDF_DLL | 321 | QPDF_DLL |
| 322 | + void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value); | ||
| 323 | + | ||
| 324 | + | ||
| 325 | + QPDF_DLL | ||
| 326 | + void qpdf_set_decode_level(qpdf_data qpdf, | ||
| 327 | + enum qpdf_stream_decode_level_e level); | ||
| 328 | + | ||
| 329 | + QPDF_DLL | ||
| 330 | + void qpdf_set_preserve_unreferenced_objects( | ||
| 331 | + qpdf_data qpdf, QPDF_BOOL value); | ||
| 332 | + | ||
| 333 | + QPDF_DLL | ||
| 334 | + void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value); | ||
| 335 | + | ||
| 336 | + QPDF_DLL | ||
| 322 | void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value); | 337 | void qpdf_set_content_normalization(qpdf_data qpdf, QPDF_BOOL value); |
| 323 | 338 | ||
| 324 | QPDF_DLL | 339 | QPDF_DLL |
libqpdf/qpdf-c.cc
| @@ -502,6 +502,30 @@ void qpdf_set_object_stream_mode(qpdf_data qpdf, qpdf_object_stream_e mode) | @@ -502,6 +502,30 @@ void qpdf_set_object_stream_mode(qpdf_data qpdf, qpdf_object_stream_e mode) | ||
| 502 | qpdf->qpdf_writer->setObjectStreamMode(mode); | 502 | qpdf->qpdf_writer->setObjectStreamMode(mode); |
| 503 | } | 503 | } |
| 504 | 504 | ||
| 505 | +void qpdf_set_compress_streams(qpdf_data qpdf, QPDF_BOOL value) | ||
| 506 | +{ | ||
| 507 | + QTC::TC("qpdf", "qpdf-c called qpdf_set_compress_streams"); | ||
| 508 | + qpdf->qpdf_writer->setCompressStreams(value); | ||
| 509 | +} | ||
| 510 | + | ||
| 511 | +void qpdf_set_decode_level(qpdf_data qpdf, qpdf_stream_decode_level_e level) | ||
| 512 | +{ | ||
| 513 | + QTC::TC("qpdf", "qpdf-c called qpdf_set_decode_level"); | ||
| 514 | + qpdf->qpdf_writer->setDecodeLevel(level); | ||
| 515 | +} | ||
| 516 | + | ||
| 517 | +void qpdf_set_preserve_unreferenced_objects(qpdf_data qpdf, QPDF_BOOL value) | ||
| 518 | +{ | ||
| 519 | + QTC::TC("qpdf", "qpdf-c called qpdf_set_preserve_unreferenced_objects"); | ||
| 520 | + qpdf->qpdf_writer->setPreserveUnreferencedObjects(value); | ||
| 521 | +} | ||
| 522 | + | ||
| 523 | +void qpdf_set_newline_before_endstream(qpdf_data qpdf, QPDF_BOOL value) | ||
| 524 | +{ | ||
| 525 | + QTC::TC("qpdf", "qpdf-c called qpdf_set_newline_before_endstream"); | ||
| 526 | + qpdf->qpdf_writer->setNewlineBeforeEndstream(value); | ||
| 527 | +} | ||
| 528 | + | ||
| 505 | void qpdf_set_stream_data_mode(qpdf_data qpdf, qpdf_stream_data_e mode) | 529 | void qpdf_set_stream_data_mode(qpdf_data qpdf, qpdf_stream_data_e mode) |
| 506 | { | 530 | { |
| 507 | QTC::TC("qpdf", "qpdf-c called qpdf_set_stream_data_mode"); | 531 | QTC::TC("qpdf", "qpdf-c called qpdf_set_stream_data_mode"); |
qpdf/qpdf-ctest.c
| @@ -440,6 +440,50 @@ static void test19(char const* infile, | @@ -440,6 +440,50 @@ static void test19(char const* infile, | ||
| 440 | report_errors(); | 440 | report_errors(); |
| 441 | } | 441 | } |
| 442 | 442 | ||
| 443 | +static void test20(char const* infile, | ||
| 444 | + char const* password, | ||
| 445 | + char const* outfile, | ||
| 446 | + char const* outfile2) | ||
| 447 | +{ | ||
| 448 | + qpdf_read(qpdf, infile, password); | ||
| 449 | + qpdf_init_write(qpdf, outfile); | ||
| 450 | + qpdf_set_static_ID(qpdf, QPDF_TRUE); | ||
| 451 | + qpdf_set_static_aes_IV(qpdf, QPDF_TRUE); | ||
| 452 | + qpdf_set_compress_streams(qpdf, QPDF_FALSE); | ||
| 453 | + qpdf_set_decode_level(qpdf, qpdf_dl_specialized); | ||
| 454 | + qpdf_write(qpdf); | ||
| 455 | + report_errors(); | ||
| 456 | +} | ||
| 457 | + | ||
| 458 | +static void test21(char const* infile, | ||
| 459 | + char const* password, | ||
| 460 | + char const* outfile, | ||
| 461 | + char const* outfile2) | ||
| 462 | +{ | ||
| 463 | + qpdf_read(qpdf, infile, password); | ||
| 464 | + qpdf_init_write(qpdf, outfile); | ||
| 465 | + qpdf_set_static_ID(qpdf, QPDF_TRUE); | ||
| 466 | + qpdf_set_static_aes_IV(qpdf, QPDF_TRUE); | ||
| 467 | + qpdf_set_preserve_unreferenced_objects(qpdf, QPDF_TRUE); | ||
| 468 | + qpdf_write(qpdf); | ||
| 469 | + report_errors(); | ||
| 470 | +} | ||
| 471 | + | ||
| 472 | +static void test22(char const* infile, | ||
| 473 | + char const* password, | ||
| 474 | + char const* outfile, | ||
| 475 | + char const* outfile2) | ||
| 476 | +{ | ||
| 477 | + qpdf_read(qpdf, infile, password); | ||
| 478 | + qpdf_init_write(qpdf, outfile); | ||
| 479 | + qpdf_set_static_ID(qpdf, QPDF_TRUE); | ||
| 480 | + qpdf_set_static_aes_IV(qpdf, QPDF_TRUE); | ||
| 481 | + qpdf_set_compress_streams(qpdf, QPDF_FALSE); | ||
| 482 | + qpdf_set_newline_before_endstream(qpdf, QPDF_TRUE); | ||
| 483 | + qpdf_write(qpdf); | ||
| 484 | + report_errors(); | ||
| 485 | +} | ||
| 486 | + | ||
| 443 | int main(int argc, char* argv[]) | 487 | int main(int argc, char* argv[]) |
| 444 | { | 488 | { |
| 445 | char* p = 0; | 489 | char* p = 0; |
| @@ -499,6 +543,9 @@ int main(int argc, char* argv[]) | @@ -499,6 +543,9 @@ int main(int argc, char* argv[]) | ||
| 499 | (n == 17) ? test17 : | 543 | (n == 17) ? test17 : |
| 500 | (n == 18) ? test18 : | 544 | (n == 18) ? test18 : |
| 501 | (n == 19) ? test19 : | 545 | (n == 19) ? test19 : |
| 546 | + (n == 20) ? test20 : | ||
| 547 | + (n == 21) ? test21 : | ||
| 548 | + (n == 22) ? test22 : | ||
| 502 | 0); | 549 | 0); |
| 503 | 550 | ||
| 504 | if (fn == 0) | 551 | if (fn == 0) |
qpdf/qpdf.testcov
| @@ -297,3 +297,7 @@ QPDFWriter ignore self-referential object stream 0 | @@ -297,3 +297,7 @@ QPDFWriter ignore self-referential object stream 0 | ||
| 297 | QPDFObjectHandle found old angle 1 | 297 | QPDFObjectHandle found old angle 1 |
| 298 | QPDF_Stream special filters 3 | 298 | QPDF_Stream special filters 3 |
| 299 | QPDFTokenizer block long token 0 | 299 | QPDFTokenizer block long token 0 |
| 300 | +qpdf-c called qpdf_set_decode_level 0 | ||
| 301 | +qpdf-c called qpdf_set_compress_streams 0 | ||
| 302 | +qpdf-c called qpdf_set_preserve_unreferenced_objects 0 | ||
| 303 | +qpdf-c called qpdf_set_newline_before_endstream 0 |
qpdf/qtest/qpdf.test
| @@ -687,7 +687,7 @@ $td->runtest("short /O or /U", | @@ -687,7 +687,7 @@ $td->runtest("short /O or /U", | ||
| 687 | show_ntests(); | 687 | show_ntests(); |
| 688 | # ---------- | 688 | # ---------- |
| 689 | $td->notify("--- Newline before endstream ---"); | 689 | $td->notify("--- Newline before endstream ---"); |
| 690 | -$n_tests += 8; | 690 | +$n_tests += 10; |
| 691 | 691 | ||
| 692 | # From issue 133, http://verapdf.org/software/ is an open source | 692 | # From issue 133, http://verapdf.org/software/ is an open source |
| 693 | # package that can verify PDF/A compliance. This could potentially be | 693 | # package that can verify PDF/A compliance. This could potentially be |
| @@ -716,6 +716,16 @@ foreach my $d ( | @@ -716,6 +716,16 @@ foreach my $d ( | ||
| 716 | {$td->FILE => "a.pdf", $td->EXIT_STATUS => 0}); | 716 | {$td->FILE => "a.pdf", $td->EXIT_STATUS => 0}); |
| 717 | } | 717 | } |
| 718 | } | 718 | } |
| 719 | + | ||
| 720 | +$td->runtest("newline before endstream (C)", | ||
| 721 | + {$td->COMMAND => | ||
| 722 | + "qpdf-ctest 22 streams-with-newlines.pdf '' a.pdf"}, | ||
| 723 | + {$td->STRING => "", $td->EXIT_STATUS => 0}, | ||
| 724 | + $td->NORMALIZE_NEWLINES); | ||
| 725 | +$td->runtest("check output", | ||
| 726 | + {$td->FILE => "a.pdf"}, | ||
| 727 | + {$td->FILE => "newline-before-endstream-nl.pdf"}); | ||
| 728 | + | ||
| 719 | show_ntests(); | 729 | show_ntests(); |
| 720 | # ---------- | 730 | # ---------- |
| 721 | $td->notify("--- Split Pages ---"); | 731 | $td->notify("--- Split Pages ---"); |
| @@ -949,7 +959,7 @@ $td->runtest("check output", | @@ -949,7 +959,7 @@ $td->runtest("check output", | ||
| 949 | show_ntests(); | 959 | show_ntests(); |
| 950 | # ---------- | 960 | # ---------- |
| 951 | $td->notify("--- Decode levels ---"); | 961 | $td->notify("--- Decode levels ---"); |
| 952 | -$n_tests += 12; | 962 | +$n_tests += 14; |
| 953 | 963 | ||
| 954 | # image-streams.pdf is the output of examples/pdf-create. | 964 | # image-streams.pdf is the output of examples/pdf-create. |
| 955 | # examples/pdf-create validates the actual image data. | 965 | # examples/pdf-create validates the actual image data. |
| @@ -967,6 +977,17 @@ foreach my $l (qw(none generalized specialized all)) | @@ -967,6 +977,17 @@ foreach my $l (qw(none generalized specialized all)) | ||
| 967 | $td->NORMALIZE_NEWLINES); | 977 | $td->NORMALIZE_NEWLINES); |
| 968 | } | 978 | } |
| 969 | 979 | ||
| 980 | +# C API | ||
| 981 | +$td->runtest("image-streams: C", | ||
| 982 | + {$td->COMMAND => "qpdf-ctest 20 image-streams.pdf '' a.pdf"}, | ||
| 983 | + {$td->STRING => "", $td->EXIT_STATUS => 0}, | ||
| 984 | + $td->NORMALIZE_NEWLINES); | ||
| 985 | +$td->runtest("check image-streams: C", | ||
| 986 | + {$td->COMMAND => "test_driver 39 a.pdf"}, | ||
| 987 | + {$td->FILE => "image-streams-specialized.out", | ||
| 988 | + $td->EXIT_STATUS => 0}, | ||
| 989 | + $td->NORMALIZE_NEWLINES); | ||
| 990 | + | ||
| 970 | # Bad JPEG data | 991 | # Bad JPEG data |
| 971 | $td->runtest("check finds bad jpeg data", | 992 | $td->runtest("check finds bad jpeg data", |
| 972 | {$td->COMMAND => "qpdf --check bad-jpeg.pdf"}, | 993 | {$td->COMMAND => "qpdf --check bad-jpeg.pdf"}, |
| @@ -990,7 +1011,7 @@ $td->runtest("get data", | @@ -990,7 +1011,7 @@ $td->runtest("get data", | ||
| 990 | show_ntests(); | 1011 | show_ntests(); |
| 991 | # ---------- | 1012 | # ---------- |
| 992 | $td->notify("--- Preserve unreferenced objects ---"); | 1013 | $td->notify("--- Preserve unreferenced objects ---"); |
| 993 | -$n_tests += 4; | 1014 | +$n_tests += 6; |
| 994 | 1015 | ||
| 995 | $td->runtest("drop unused objects", | 1016 | $td->runtest("drop unused objects", |
| 996 | {$td->COMMAND => "qpdf --static-id unreferenced-objects.pdf a.pdf"}, | 1017 | {$td->COMMAND => "qpdf --static-id unreferenced-objects.pdf a.pdf"}, |
| @@ -1005,6 +1026,13 @@ $td->runtest("keep unused objects", | @@ -1005,6 +1026,13 @@ $td->runtest("keep unused objects", | ||
| 1005 | $td->runtest("check output", | 1026 | $td->runtest("check output", |
| 1006 | {$td->FILE => "a.pdf"}, | 1027 | {$td->FILE => "a.pdf"}, |
| 1007 | {$td->FILE => "unreferenced-preserved.pdf"}); | 1028 | {$td->FILE => "unreferenced-preserved.pdf"}); |
| 1029 | +$td->runtest("keep unused objects (C)", | ||
| 1030 | + {$td->COMMAND => | ||
| 1031 | + "qpdf-ctest 21 unreferenced-objects.pdf '' a.pdf"}, | ||
| 1032 | + {$td->STRING => "", $td->EXIT_STATUS => 0}); | ||
| 1033 | +$td->runtest("check output", | ||
| 1034 | + {$td->FILE => "a.pdf"}, | ||
| 1035 | + {$td->FILE => "unreferenced-preserved.pdf"}); | ||
| 1008 | show_ntests(); | 1036 | show_ntests(); |
| 1009 | # ---------- | 1037 | # ---------- |
| 1010 | $td->notify("--- Copy Foreign Objects ---"); | 1038 | $td->notify("--- Copy Foreign Objects ---"); |