From 99231c437860d3b07d99ff12e41529492419f6a7 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sun, 5 Mar 2023 15:13:34 +0000 Subject: [PATCH] Add example qpdfjob-remove-annotations --- examples/CMakeLists.txt | 1 + examples/qpdfjob-remove-annotations.cc | 78 ++ .../qtest/qpdfjob-remove-annotations.test | 28 + .../annotations-out.pdf | Bin 0 -> 5284 bytes .../annotations.pdf | 942 ++++++++++++++++++ 5 files changed, 1049 insertions(+) create mode 100644 examples/qpdfjob-remove-annotations.cc create mode 100644 examples/qtest/qpdfjob-remove-annotations.test create mode 100644 examples/qtest/qpdfjob-remove-annotations/annotations-out.pdf create mode 100644 examples/qtest/qpdfjob-remove-annotations/annotations.pdf diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 947068dd..9af85fe2 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -15,6 +15,7 @@ set(EXAMPLE_CXX_PROGRAMS pdf-set-form-values pdf-split-pages qpdf-job + qpdfjob-remove-annotations qpdfjob-save-attachment) set(EXAMPLE_C_PROGRAMS pdf-c-objects diff --git a/examples/qpdfjob-remove-annotations.cc b/examples/qpdfjob-remove-annotations.cc new file mode 100644 index 00000000..dfab3f7b --- /dev/null +++ b/examples/qpdfjob-remove-annotations.cc @@ -0,0 +1,78 @@ +#include +#include +#include + +#include +#include +#include +#include + +// This example demonstrates how we can use the QPDFJob createQPDF and writeQPDF +// methods to add custom transformations to the output produced by QPDFJob runs. +// The example is a full copy of the qpdf program modified to allways remove all +// annotations from the final output. + +static char const* whoami = 0; + +static void +usageExit(std::string const& msg) +{ + std::cerr << std::endl + << whoami << ": " << msg << std::endl + << std::endl + << "For help:" << std::endl + << " " << whoami << " --help=usage usage information" + << std::endl + << " " << whoami << " --help=topic help on a topic" + << std::endl + << " " << whoami << " --help=--option help on an option" + << std::endl + << " " << whoami + << " --help general help and a topic list" + << std::endl + << std::endl; + exit(QPDFJob::EXIT_ERROR); +} + +int +realmain(int argc, char* argv[]) +{ + whoami = QUtil::getWhoami(argv[0]); + QUtil::setLineBuf(stdout); + + QPDFJob j; + try { + // See "HOW TO ADD A COMMAND-LINE ARGUMENT" in README-maintainer. + j.initializeFromArgv(argv); + auto qpdf_sp = j.createQPDF(); + auto& pdf = *qpdf_sp; + for (auto page: pdf.getAllPages()) { + page.replaceKey("/Annots", "null"_qpdf); + } + j.writeQPDF(pdf); + } catch (QPDFUsage& e) { + usageExit(e.what()); + } catch (std::exception& e) { + std::cerr << whoami << ": " << e.what() << std::endl; + return QPDFJob::EXIT_ERROR; + } + return j.getExitCode(); +} + +#ifdef WINDOWS_WMAIN + +extern "C" int +wmain(int argc, wchar_t* argv[]) +{ + return QUtil::call_main_from_wmain(argc, argv, realmain); +} + +#else + +int +main(int argc, char* argv[]) +{ + return realmain(argc, argv); +} + +#endif diff --git a/examples/qtest/qpdfjob-remove-annotations.test b/examples/qtest/qpdfjob-remove-annotations.test new file mode 100644 index 00000000..32abf3ef --- /dev/null +++ b/examples/qtest/qpdfjob-remove-annotations.test @@ -0,0 +1,28 @@ +#!/usr/bin/env perl +require 5.008; +use warnings; +use strict; + +chdir("qpdfjob-remove-annotations"); + +require TestDriver; + +my $td = new TestDriver('qpdfjob-remove-annotations'); + +cleanup(); + +$td->runtest("remove-annotations", + {$td->COMMAND => "qpdfjob-remove-annotations --static-id annotations.pdf out.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}); +$td->runtest("compare files", + {$td->FILE => "out.pdf"}, + {$td->FILE => "annotations-out.pdf"}); + +cleanup(); + +$td->report(2); + +sub cleanup +{ + unlink("out.pdf"); +} diff --git a/examples/qtest/qpdfjob-remove-annotations/annotations-out.pdf b/examples/qtest/qpdfjob-remove-annotations/annotations-out.pdf new file mode 100644 index 0000000000000000000000000000000000000000..88056506b1a3dee0b8c63b4f3a5babb691107b0a GIT binary patch literal 5284 zcmd5=4OCQR8dh8?XE8N(EnC`;k^q11-2b@~2m!+=iZBg?KSXk8<_?a*3=J2-QVEWF zPWXqSxVFXym1%A!X02MTr;-(I0jqTx3?GFm-S zo~saLAx61pl`E%Qvr%j;GNy|8QlT;_Dc>QvT$0P`$pZ_ojKL#pVlLd9lzU^woB|0M z6Gd6f^X0+<2FdHfF5vAnSFAp-tgL9Ikf1HoJrsMQ4UM-c15=S%8)vk{qev2w1a{S* z3lUI=5>SRaDljZdCW-`uH3JzlO5ocKgN=5{DMO?t8nGslFqv3HnMp!GtiTdxnnu~k zm|oi)f`KR)Mva0Ic!FXf4v30@sD4TucAq@f=`7Yqg1MkY0;n1(71adUtH8>dDUL?Q zNgjnn6lRO76FnJKDb3KYG~5bb6tk9hR_l`xA-VgLXVoR?#=}vyg8f zTRYe2%v*)C|1};Kr(t(IlSSF@Q6r|%Sj+|d2habf10<_>4 z1qE#)m_R5PGr`;(6up)s3W?%)$cd~*ZSPobLVsw+N z2&`&JR<(p9T2*=D<5ulo41l#4A=d;G_YVb<6X7X(xes7rVC_kSrU57qQmK{$<7CO@ z5jBA&AsiZ+AnAbQoypPJk?6EXm2F%Wuw-gF7g&oDx|gMBg5;o};p_E6)|q=ZB-s?h z10+A9+2fYi-~9m@Vks_dXbRa}#d@dxI`qEEnEKk6GDAY-6Bm+G8gh2MTh&}0{qLNe z>&`CSH$hmka@n9|!|JI8@%3+<^-Q+KtV9gudU{qwiW|M4i>I`A*@l!$h{ECv?aTaV05 z6f=LYqtDQXgIe`2_FmJciv?~AlyZj%wCQf`{#W%@#7z^vTOTZA`oGg4GxYT%nf4_| zPcAG=pFJ(&TK1y4%EdKBEkn*!M;qp}JyP!|KDW#2D>+Eg|821RcrQFq zwEp%%b1QhD=<)4y@y3#P7f#{@#c@g!f9jn!DVj!-BQZWHB!v9e_anUxIme14t~F+N zI3D@q*`-lc1^0%BhW&Qap7miNi(2{}`;Lzr{NUmT-yAvURP@-jM04$>O7YYK#*lTN z)>n7D_<^mlHuuPdJ%{~k5^AC&_^+GiZr+#%56{_yJ$5F}l$=kc7s0_*AVr38J1L5EaH7c}I9L}aI0P4Gk_3u%IHByMd!CUH zG}qnPF2m{VA=+J#Cwja}X;$Sw@G#reS<^QV$E4<#(aBAtA8SlYpD-pWIipXkTTDv1!{sUtROc4}Ez0 z;f8yD(|+KGdBcCTaqrqMw;Y~#{+l*uOG-j{?zh~@5f}Tv*WsELw7P$dR7syPzjDI< z;r*BPJb7qsf6JJ#U~6B;YkQJEXt38#w&3@UF)hAvaiwW1huABo zR?K`oJN#mK=)s5h9V=FQW^anlAAay^=A4v~S0}EmD~q(3y%x3oZ{us$pQ~Qf*gmrE z$wTSyKi9x#!nO8!SuieECGirZ=C8i7tI+Z!ML-@UJJ1 zZF}Q>ciF;Kv4ft^tC=7(qjvHi&&Zy7{&M2bsec;rLcyNU)or#rrmr|^Zd$bZodmM9 z->lX{Bi0b7gU@Z6fAYJ?+B0FhS8)Bx6NM4mP7gXT*mQBj(VQzy8|dYi+v`6so^f|| zYR>N_X8n2n_|J;gUp#c*;UTZSO{}VY`kmzy;|!MuzMR^;K~IOkc1CIb;Yg^wgt7U3 z&UAR&kOjSq#R>;Y{Kg^hysHe&MZw9s`=;_2YPb9JD~{;-v*a=N|*7v7Y-f46U2X@T3j{#sqJB zdiczk1)YuM^mAE`55PtCi_m@hmDb(vgLhb+Cm2;Xp*u;opsW~?c2g|x5+w)k0%a9V zEX{Fnsx-SqhglHl*cgUlDb7suKrg{;GBY$IusqGP3?o2HW-eA?Z=o#uWrdh5Pcnw^ J@T4@W;XhxFRnh> + /Names << + /EmbeddedFiles 6 0 R + >> + /Pages 7 0 R + /Type /Catalog +>> +endobj + +2 0 obj +<< + /Font << + /F1 8 0 R + >> +>> +endobj + +3 0 obj +<< + /AP << + /N 9 0 R + >> + /DA (0 0.4 0 rg /F1 18 Tf) + /DR 2 0 R + /DV () + /FT /Tx + /Ff 0 + /Rect [ + 72 + 470.774 + 190.8 + 484.922 + ] + /Subtype /Widget + /T (Text Box 1) + /Type /Annot + /V (Formy field) +>> +endobj + +4 0 obj +<< + /AP << + /N 11 0 R + >> + /DA (0 0.4 0 rg /F1 18 Tf) + /DR 2 0 R + /DV () + /FT /Tx + /Ff 0 + /Rect [ + 372 + 330.774 + 386.148 + 470.374 + ] + /Subtype /Widget + /T (Text Box 1) + /Type /Annot + /V (Rot-ccw field) +>> +endobj + +5 0 obj +<< + /DV /1 + /FT /Btn + /Ff 49152 + /Kids [ + 13 0 R + 14 0 R + 15 0 R + ] + /T (r1) + /V /2 +>> +endobj + +6 0 obj +<< + /Names [ + (attachment1.txt) + 16 0 R + ] +>> +endobj + +7 0 obj +<< + /Count 1 + /Kids [ + 17 0 R + ] + /Type /Pages +>> +endobj + +8 0 obj +<< + /BaseFont /Courier + /Encoding /WinAnsiEncoding + /Subtype /Type1 + /Type /Font +>> +endobj + +9 0 obj +<< + /BBox [ + 0 + -2.826 + 118.8 + 11.322 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 10 0 R +>> +stream +/Tx BMC +q +BT + /F1 18 Tf + (Formy field) Tj +ET +Q +EMC +endstream +endobj + +10 0 obj +53 +endobj + +11 0 obj +<< + /BBox [ + 0 + -2.826 + 140.4 + 11.322 + ] + /Matrix [ + 0 + 1 + -1 + 0 + 0 + 0 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 12 0 R +>> +stream +/Tx BMC +q +BT + /F1 18 Tf + (Rot-ccw field) Tj +ET +Q +EMC +endstream +endobj + +12 0 obj +55 +endobj + +13 0 obj +<< + /AP << + /N << + /1 18 0 R + /Off 20 0 R + >> + >> + /AS /1 + /DA (0.18039 0.20392 0.21176 rg /ZaDi 0 Tf) + /DR << + /Font << + /ZaDi 22 0 R + >> + >> + /F 4 + /FT /Btn + /MK << + /CA (l) + >> + /Parent 5 0 R + /Rect [ + 152.749 + 648.501 + 164.801 + 660.549 + ] + /Subtype /Widget + /Type /Annot +>> +endobj + +14 0 obj +<< + /AP << + /N << + /2 23 0 R + /Off 25 0 R + >> + >> + /AS /2 + /DA (0.18039 0.20392 0.21176 rg /ZaDi 0 Tf) + /DR << + /Font << + /ZaDi 22 0 R + >> + >> + /F 4 + /FT /Btn + /MK << + /CA (l) + >> + /Parent 5 0 R + /Rect [ + 152.749 + 627.301 + 164.801 + 639.349 + ] + /Subtype /Widget + /Type /Annot +>> +endobj + +15 0 obj +<< + /AP << + /N << + /3 27 0 R + /Off 29 0 R + >> + >> + /AS /3 + /DA (0.18039 0.20392 0.21176 rg /ZaDi 0 Tf) + /DR << + /Font << + /ZaDi 22 0 R + >> + >> + /F 4 + /FT /Btn + /MK << + /CA (l) + >> + /Parent 5 0 R + /Rect [ + 151.399 + 606.501 + 163.451 + 618.549 + ] + /Subtype /Widget + /Type /Annot +>> +endobj + +16 0 obj +<< + /EF << + /F 31 0 R + /UF 31 0 R + >> + /F (attachment1.txt) + /Type /Filespec + /UF (attachment1.txt) +>> +endobj + +%% Page 1 +17 0 obj +<< + /Annots [ + 33 0 R + 3 0 R + 34 0 R + 4 0 R + 35 0 R + 36 0 R + 37 0 R + 38 0 R + 13 0 R + 14 0 R + 15 0 R + ] + /Contents 39 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 7 0 R + /Resources 2 0 R + /Type /Page +>> +endobj + +18 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 19 0 R +>> +stream +/Tx BMC +q BT +0.18039 0.20392 0.21176 rg /ZaDi 12.05 Tf +0 0 Td +ET +Q +1 0 0 rg +6 8.4 m 7.35 8.4 8.45 7.35 8.45 6 c +8.45 4.65 7.35 3.55 6 3.55 c +4.65 3.55 3.6 4.65 3.6 6 c +3.6 7.35 4.65 8.4 6 8.4 c f* + +EMC +endstream +endobj + +19 0 obj +202 +endobj + +20 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 21 0 R +>> +stream +/Tx BMC +EMC +endstream +endobj + +21 0 obj +12 +endobj + +22 0 obj +<< + /BaseFont /ZapfDingbats + /Subtype /Type1 + /Type /Font +>> +endobj + +23 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 24 0 R +>> +stream +/Tx BMC +q BT +0.18039 0.20392 0.21176 rg /ZaDi 12.05 Tf +0 0 Td +ET +Q +0 1 0 rg +6 8.4 m 7.35 8.4 8.45 7.35 8.45 6 c +8.45 4.65 7.35 3.55 6 3.55 c +4.65 3.55 3.6 4.65 3.6 6 c +3.6 7.35 4.65 8.4 6 8.4 c f* + +EMC +endstream +endobj + +24 0 obj +202 +endobj + +25 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 26 0 R +>> +stream +/Tx BMC +EMC +endstream +endobj + +26 0 obj +12 +endobj + +27 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 28 0 R +>> +stream +/Tx BMC +q BT +0.18039 0.20392 0.21176 rg /ZaDi 12.05 Tf +0 0 Td +ET +Q +0 0 1 rg +6 8.4 m 7.35 8.4 8.45 7.35 8.45 6 c +8.45 4.65 7.35 3.55 6 3.55 c +4.65 3.55 3.6 4.65 3.6 6 c +3.6 7.35 4.65 8.4 6 8.4 c f* + +EMC +endstream +endobj + +28 0 obj +202 +endobj + +29 0 obj +<< + /BBox [ + 0 + 0 + 12.05 + 12.05 + ] + /Resources 41 0 R + /Subtype /Form + /Type /XObject + /Length 30 0 R +>> +stream +/Tx BMC +EMC +endstream +endobj + +30 0 obj +12 +endobj + +31 0 obj +<< + /Params << + /CheckSum <80a33fc110b5a7b8b4d58b8d57e814bc> + /Size 22 + /Subtype /text#2fplain + >> + /Type /EmbeddedFile + /Length 32 0 R +>> +stream +content of attachment +endstream +endobj + +32 0 obj +22 +endobj + +33 0 obj +<< + /A << + /S /URI + /URI (https://www.qbilt.org/) + >> + /Border [ + 0 + 0 + .4 + ] + /C [ + .8 + .6 + .6 + ] + /H /I + /Rect [ + 72 + 501.832 + 374.4 + 520.696 + ] + /Subtype /Link + /Type /Annot +>> +endobj + +34 0 obj +<< + /AP << + /N 42 0 R + >> + /Contents (attachment1.txt) + /FS 16 0 R + /NM (attachment1.txt) + /Rect [ + 72 + 400 + 92 + 420 + ] + /Subtype /FileAttachment + /Type /Annot +>> +endobj + +35 0 obj +<< + /AP << + /N 44 0 R + >> + /DA () + /Rect [ + 72 + 350 + 92 + 360 + ] + /Subtype /FreeText + /Type /Annot +>> +endobj + +36 0 obj +<< + /AP << + /N 46 0 R + >> + /DA () + /Rect [ + 102 + 350 + 112 + 370 + ] + /Subtype /FreeText + /Type /Annot +>> +endobj + +37 0 obj +<< + /AP << + /N 48 0 R + >> + /DA () + /Rect [ + 122 + 350 + 142 + 360 + ] + /Subtype /FreeText + /Type /Annot +>> +endobj + +38 0 obj +<< + /AP << + /N 50 0 R + >> + /DA () + /Rect [ + 152 + 350 + 162 + 370 + ] + /Subtype /FreeText + /Type /Annot +>> +endobj + +%% Contents for page 1 +39 0 obj +<< + /Length 40 0 R +>> +stream +q +1 1 .7 rg +.5 .5 0 RG +72 470.77 118.8 14.15 re +B +Q +q +0 .5 .5 RG +0 1 1 rg +372 330.77 14.15 139.4 re +B +Q +q +1 0 0 RG +72 310 20 10 re +72 310 5 10 re +S +0 1 0 RG +102 310 10 20 re +102 310 10 5 re +S +0 0 1 RG +122 310 20 10 re +137 310 5 10 re +S +0.5 0 1 RG +152 310 10 20 re +152 325 10 5 re +S +10 w +0.14 .33 .18 RG +5 5 602 782 re +S +Q +BT + /F1 16 Tf + 20.6 TL + 170 650 Td + (radio button 1) Tj + (radio button 2) ' + (radio button 3) ' + 1 0 0 1 72 546 Tm + /F1 20 Tf + (Thick green border surrounds page.) Tj + 0 -40 Td + /F1 24 Tf + 0 0 1 rg + (https://www.qbilt.org) Tj + /F1 12 Tf + 1 0 0 1 202 474 Tm + (<- Formy field in yellow) Tj + 1 0 0 1 392 410 Tm + 14.4 TL + (<- Rot-ccw field) Tj + (with "Rot" at bottom) ' + (and text going up) ' + 0 g + 1 0 0 1 102 405 Tm + (Arrow to the left points down.) Tj + 1 0 0 1 182 310 Tm + (<- Drawn rectangles appear below annotations.) Tj +ET +endstream +endobj + +40 0 obj +874 +endobj + +41 0 obj +<< + /Font 52 0 R + /ProcSet [ + /PDF + /Text + ] +>> +endobj + +42 0 obj +<< + /BBox [ + 0 + 0 + 20 + 20 + ] + /Resources << + >> + /Subtype /Form + /Type /XObject + /Length 43 0 R +>> +stream +0 10 m +10 0 l +20 10 l +10 0 m +10 20 l +0 0 20 20 re +S +endstream +endobj + +43 0 obj +52 +endobj + +44 0 obj +<< + /BBox [ + 0 + 0 + 20 + 10 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 45 0 R +>> +stream +1 0 0 RG +0 0 20 10 re +0 0 5 10 re +S +endstream +endobj + +45 0 obj +36 +endobj + +46 0 obj +<< + /BBox [ + 0 + 0 + 20 + 10 + ] + /Matrix [ + 0 + 1 + -1 + 0 + 0 + 0 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 47 0 R +>> +stream +0 1 0 RG +0 0 20 10 re +0 0 5 10 re +S +endstream +endobj + +47 0 obj +36 +endobj + +48 0 obj +<< + /BBox [ + 0 + 0 + 20 + 10 + ] + /Matrix [ + -1 + 0 + 0 + -1 + 0 + 0 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 49 0 R +>> +stream +0 0 1 RG +0 0 20 10 re +0 0 5 10 re +S +endstream +endobj + +49 0 obj +36 +endobj + +50 0 obj +<< + /BBox [ + 0 + 0 + 20 + 10 + ] + /Matrix [ + 0 + -1 + 1 + 0 + 0 + 0 + ] + /Resources 2 0 R + /Subtype /Form + /Type /XObject + /Length 51 0 R +>> +stream +0.5 0 1 RG +0 0 20 10 re +0 0 5 10 re +S +endstream +endobj + +51 0 obj +38 +endobj + +52 0 obj +<< + /ZaDi 22 0 R +>> +endobj + +xref +0 53 +0000000000 65535 f +0000000025 00000 n +0000000211 00000 n +0000000263 00000 n +0000000506 00000 n +0000000755 00000 n +0000000874 00000 n +0000000944 00000 n +0000001017 00000 n +0000001121 00000 n +0000001335 00000 n +0000001355 00000 n +0000001625 00000 n +0000001645 00000 n +0000001997 00000 n +0000002349 00000 n +0000002701 00000 n +0000002842 00000 n +0000003114 00000 n +0000003473 00000 n +0000003494 00000 n +0000003663 00000 n +0000003683 00000 n +0000003764 00000 n +0000004123 00000 n +0000004144 00000 n +0000004313 00000 n +0000004333 00000 n +0000004692 00000 n +0000004713 00000 n +0000004882 00000 n +0000004902 00000 n +0000005110 00000 n +0000005130 00000 n +0000005374 00000 n +0000005578 00000 n +0000005718 00000 n +0000005860 00000 n +0000006002 00000 n +0000006167 00000 n +0000007098 00000 n +0000007119 00000 n +0000007193 00000 n +0000007397 00000 n +0000007417 00000 n +0000007603 00000 n +0000007623 00000 n +0000007862 00000 n +0000007882 00000 n +0000008122 00000 n +0000008142 00000 n +0000008383 00000 n +0000008403 00000 n +trailer << + /Root 1 0 R + /Size 53 + /ID [<7b639c67bfc16b5e891fa5468aac3a14>] +>> +startxref +8441 +%%EOF