Commit 3844aedd932df16be623059cb64ed0ef7d751b70

Authored by Jay Berkenbilt
1 parent eb802cfa

Add testing for page APIs

libqpdf/QPDF_pages.cc
... ... @@ -126,18 +126,23 @@ QPDF::insertPageobjToPage(QPDFObjectHandle const& obj, int pos,
126 126 bool check_duplicate)
127 127 {
128 128 ObjGen og(obj.getObjectID(), obj.getGeneration());
129   - bool duplicate =
130   - (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second);
131   - if (duplicate && check_duplicate)
132   - {
133   - QTC::TC("qpdf", "QPDF duplicate page reference");
134   - setLastObjectDescription("page " + QUtil::int_to_string(pos) +
135   - " (numbered from zero)",
136   - og.obj, og.gen);
137   - throw QPDFExc(qpdf_e_pages, this->file->getName(),
138   - this->last_object_description, 0,
139   - "duplicate page reference found;"
140   - " this would cause loss of data");
  129 + if (check_duplicate)
  130 + {
  131 + if (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second)
  132 + {
  133 + QTC::TC("qpdf", "QPDF duplicate page reference");
  134 + setLastObjectDescription("page " + QUtil::int_to_string(pos) +
  135 + " (numbered from zero)",
  136 + og.obj, og.gen);
  137 + throw QPDFExc(qpdf_e_pages, this->file->getName(),
  138 + this->last_object_description, 0,
  139 + "duplicate page reference found;"
  140 + " this would cause loss of data");
  141 + }
  142 + }
  143 + else
  144 + {
  145 + this->pageobj_to_pages_pos[og] = pos;
141 146 }
142 147 }
143 148  
... ... @@ -150,6 +155,16 @@ QPDF::insertPage(QPDFObjectHandle newpage, int pos)
150 155 flattenPagesTree();
151 156 newpage.assertPageObject();
152 157  
  158 + if (! newpage.isIndirect())
  159 + {
  160 + QTC::TC("qpdf", "QPDF insert non-indirect page");
  161 + newpage = this->makeIndirectObject(newpage);
  162 + }
  163 + else
  164 + {
  165 + QTC::TC("qpdf", "QPDF insert indirect page");
  166 + }
  167 +
153 168 QTC::TC("qpdf", "QPDF insert page",
154 169 (pos == 0) ? 0 : // insert at beginning
155 170 (pos == ((int)this->all_pages.size())) ? 1 : // insert at end
... ...
qpdf/qpdf.testcov
... ... @@ -207,3 +207,5 @@ QPDF duplicate page reference 0
207 207 QPDF remove page 2
208 208 QPDF insert page 2
209 209 QPDF updateAllPagesCache 0
  210 +QPDF insert non-indirect page 0
  211 +QPDF insert indirect page 0
... ...
qpdf/qtest/qpdf.test
... ... @@ -110,6 +110,28 @@ $td->runtest("new stream",
110 110  
111 111 show_ntests();
112 112 # ----------
  113 +$td->notify("--- Page API Tests ---");
  114 +$n_tests += 5;
  115 +
  116 +$td->runtest("basic page API",
  117 + {$td->COMMAND => "test_driver 15 page_api_1.pdf"},
  118 + {$td->STRING => "test 15 done\n", $td->EXIT_STATUS => 0},
  119 + $td->NORMALIZE_NEWLINES);
  120 +$td->runtest("check output",
  121 + {$td->FILE => "a.pdf"},
  122 + {$td->FILE => "page_api_1-out.pdf"});
  123 +$td->runtest("manual page manipulation",
  124 + {$td->COMMAND => "test_driver 16 page_api_1.pdf"},
  125 + {$td->STRING => "test 16 done\n", $td->EXIT_STATUS => 0},
  126 + $td->NORMALIZE_NEWLINES);
  127 +$td->runtest("check output",
  128 + {$td->FILE => "a.pdf"},
  129 + {$td->FILE => "page_api_1-out2.pdf"});
  130 +$td->runtest("duplicate page",
  131 + {$td->COMMAND => "test_driver 17 page_api_2.pdf"},
  132 + {$td->FILE => "page_api_2.out", $td->EXIT_STATUS => 2},
  133 + $td->NORMALIZE_NEWLINES);
  134 +# ----------
113 135 $td->notify("--- Miscellaneous Tests ---");
114 136 $n_tests += 37;
115 137  
... ...
qpdf/qtest/qpdf/page_api_1-out.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +1 0 obj
  4 +<< /Pages 3 0 R /Type /Catalog >>
  5 +endobj
  6 +2 0 obj
  7 +<< /CreationDate (D:20120621111522) /Producer (Apex PDFWriter) >>
  8 +endobj
  9 +3 0 obj
  10 +<< /Count 13 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R ] /Type /Pages >>
  11 +endobj
  12 +4 0 obj
  13 +<< /Contents 17 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  14 +endobj
  15 +5 0 obj
  16 +<< /Contents 19 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  17 +endobj
  18 +6 0 obj
  19 +<< /Contents 20 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  20 +endobj
  21 +7 0 obj
  22 +<< /Contents 21 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  23 +endobj
  24 +8 0 obj
  25 +<< /Contents 22 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  26 +endobj
  27 +9 0 obj
  28 +<< /Contents 23 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  29 +endobj
  30 +10 0 obj
  31 +<< /Contents 24 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  32 +endobj
  33 +11 0 obj
  34 +<< /Contents 25 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  35 +endobj
  36 +12 0 obj
  37 +<< /Contents 26 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  38 +endobj
  39 +13 0 obj
  40 +<< /Contents 27 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  41 +endobj
  42 +14 0 obj
  43 +<< /Contents 28 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  44 +endobj
  45 +15 0 obj
  46 +<< /Contents 29 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  47 +endobj
  48 +16 0 obj
  49 +<< /Contents 30 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 18 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  50 +endobj
  51 +17 0 obj
  52 +<< /Length 42 >>
  53 +stream
  54 +BT /F1 15 Tf 72 720 Td (New page 0) Tj ET
  55 +endstream
  56 +endobj
  57 +18 0 obj
  58 +<< /BaseFont /Times-Roman /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font >>
  59 +endobj
  60 +19 0 obj
  61 +<< /Length 42 >>
  62 +stream
  63 +BT /F1 15 Tf 72 720 Td (New page 1) Tj ET
  64 +endstream
  65 +endobj
  66 +20 0 obj
  67 +<< /Length 47 >>
  68 +stream
  69 +BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET
  70 +endstream
  71 +endobj
  72 +21 0 obj
  73 +<< /Length 47 >>
  74 +stream
  75 +BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
  76 +endstream
  77 +endobj
  78 +22 0 obj
  79 +<< /Length 47 >>
  80 +stream
  81 +BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
  82 +endstream
  83 +endobj
  84 +23 0 obj
  85 +<< /Length 42 >>
  86 +stream
  87 +BT /F1 15 Tf 72 720 Td (New page 5) Tj ET
  88 +endstream
  89 +endobj
  90 +24 0 obj
  91 +<< /Length 42 >>
  92 +stream
  93 +BT /F1 15 Tf 72 720 Td (New page 6) Tj ET
  94 +endstream
  95 +endobj
  96 +25 0 obj
  97 +<< /Length 47 >>
  98 +stream
  99 +BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET
  100 +endstream
  101 +endobj
  102 +26 0 obj
  103 +<< /Length 47 >>
  104 +stream
  105 +BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET
  106 +endstream
  107 +endobj
  108 +27 0 obj
  109 +<< /Length 47 >>
  110 +stream
  111 +BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET
  112 +endstream
  113 +endobj
  114 +28 0 obj
  115 +<< /Length 47 >>
  116 +stream
  117 +BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET
  118 +endstream
  119 +endobj
  120 +29 0 obj
  121 +<< /Length 43 >>
  122 +stream
  123 +BT /F1 15 Tf 72 720 Td (New page 11) Tj ET
  124 +endstream
  125 +endobj
  126 +30 0 obj
  127 +<< /Length 43 >>
  128 +stream
  129 +BT /F1 15 Tf 72 720 Td (New page 12) Tj ET
  130 +endstream
  131 +endobj
  132 +xref
  133 +0 31
  134 +0000000000 65535 f
  135 +0000000015 00000 n
  136 +0000000064 00000 n
  137 +0000000145 00000 n
  138 +0000000284 00000 n
  139 +0000000438 00000 n
  140 +0000000592 00000 n
  141 +0000000746 00000 n
  142 +0000000900 00000 n
  143 +0000001054 00000 n
  144 +0000001208 00000 n
  145 +0000001363 00000 n
  146 +0000001518 00000 n
  147 +0000001673 00000 n
  148 +0000001828 00000 n
  149 +0000001983 00000 n
  150 +0000002138 00000 n
  151 +0000002293 00000 n
  152 +0000002385 00000 n
  153 +0000002485 00000 n
  154 +0000002577 00000 n
  155 +0000002674 00000 n
  156 +0000002771 00000 n
  157 +0000002868 00000 n
  158 +0000002960 00000 n
  159 +0000003052 00000 n
  160 +0000003149 00000 n
  161 +0000003246 00000 n
  162 +0000003343 00000 n
  163 +0000003440 00000 n
  164 +0000003533 00000 n
  165 +trailer << /Info 2 0 R /Root 1 0 R /Size 31 /ID [<21f7a6fb083dab8e29743918a08bfa31><31415926535897932384626433832795>] >>
  166 +startxref
  167 +3626
  168 +%%EOF
... ...
qpdf/qtest/qpdf/page_api_1-out2.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +1 0 obj
  4 +<< /Pages 3 0 R /Type /Catalog >>
  5 +endobj
  6 +2 0 obj
  7 +<< /CreationDate (D:20120621111522) /Producer (Apex PDFWriter) >>
  8 +endobj
  9 +3 0 obj
  10 +<< /Count 11 /Kids [ 4 0 R 5 0 R 6 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R ] /Type /Pages >>
  11 +endobj
  12 +4 0 obj
  13 +<< /Contents 15 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  14 +endobj
  15 +5 0 obj
  16 +<< /Contents 17 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  17 +endobj
  18 +6 0 obj
  19 +<< /Contents 18 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  20 +endobj
  21 +7 0 obj
  22 +<< /Contents 19 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  23 +endobj
  24 +8 0 obj
  25 +<< /Contents 20 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  26 +endobj
  27 +9 0 obj
  28 +<< /Contents 21 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  29 +endobj
  30 +10 0 obj
  31 +<< /Contents 22 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  32 +endobj
  33 +11 0 obj
  34 +<< /Contents 23 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  35 +endobj
  36 +12 0 obj
  37 +<< /Contents 24 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  38 +endobj
  39 +13 0 obj
  40 +<< /Contents 25 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  41 +endobj
  42 +14 0 obj
  43 +<< /Contents 26 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 16 0 R >> /ProcSet [ /PDF /Text ] >> /Type /Page >>
  44 +endobj
  45 +15 0 obj
  46 +<< /Length 47 >>
  47 +stream
  48 +BT /F1 15 Tf 72 720 Td (Original page 0) Tj ET
  49 +endstream
  50 +endobj
  51 +16 0 obj
  52 +<< /BaseFont /Times-Roman /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font >>
  53 +endobj
  54 +17 0 obj
  55 +<< /Length 47 >>
  56 +stream
  57 +BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET
  58 +endstream
  59 +endobj
  60 +18 0 obj
  61 +<< /Length 47 >>
  62 +stream
  63 +BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
  64 +endstream
  65 +endobj
  66 +19 0 obj
  67 +<< /Length 47 >>
  68 +stream
  69 +BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
  70 +endstream
  71 +endobj
  72 +20 0 obj
  73 +<< /Length 47 >>
  74 +stream
  75 +BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET
  76 +endstream
  77 +endobj
  78 +21 0 obj
  79 +<< /Length 47 >>
  80 +stream
  81 +BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET
  82 +endstream
  83 +endobj
  84 +22 0 obj
  85 +<< /Length 47 >>
  86 +stream
  87 +BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET
  88 +endstream
  89 +endobj
  90 +23 0 obj
  91 +<< /Length 47 >>
  92 +stream
  93 +BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET
  94 +endstream
  95 +endobj
  96 +24 0 obj
  97 +<< /Length 47 >>
  98 +stream
  99 +BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET
  100 +endstream
  101 +endobj
  102 +25 0 obj
  103 +<< /Length 47 >>
  104 +stream
  105 +BT /F1 15 Tf 72 720 Td (Original page 9) Tj ET
  106 +endstream
  107 +endobj
  108 +26 0 obj
  109 +<< /Length 43 >>
  110 +stream
  111 +BT /F1 15 Tf 72 720 Td (New page 10) Tj ET
  112 +endstream
  113 +endobj
  114 +xref
  115 +0 27
  116 +0000000000 65535 f
  117 +0000000015 00000 n
  118 +0000000064 00000 n
  119 +0000000145 00000 n
  120 +0000000270 00000 n
  121 +0000000424 00000 n
  122 +0000000578 00000 n
  123 +0000000732 00000 n
  124 +0000000886 00000 n
  125 +0000001040 00000 n
  126 +0000001194 00000 n
  127 +0000001349 00000 n
  128 +0000001504 00000 n
  129 +0000001659 00000 n
  130 +0000001814 00000 n
  131 +0000001969 00000 n
  132 +0000002066 00000 n
  133 +0000002166 00000 n
  134 +0000002263 00000 n
  135 +0000002360 00000 n
  136 +0000002457 00000 n
  137 +0000002554 00000 n
  138 +0000002651 00000 n
  139 +0000002748 00000 n
  140 +0000002845 00000 n
  141 +0000002942 00000 n
  142 +0000003039 00000 n
  143 +trailer << /Info 2 0 R /Root 1 0 R /Size 27 /ID [<21f7a6fb083dab8e29743918a08bfa31><31415926535897932384626433832795>] >>
  144 +startxref
  145 +3132
  146 +%%EOF
... ...
qpdf/qtest/qpdf/page_api_1.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +%QDF-1.0
  4 +
  5 +1 0 obj
  6 +<<
  7 + /Pages 3 0 R
  8 + /Type /Catalog
  9 +>>
  10 +endobj
  11 +
  12 +2 0 obj
  13 +<<
  14 + /CreationDate (D:20120621111522)
  15 + /Producer (Apex PDFWriter)
  16 +>>
  17 +endobj
  18 +
  19 +3 0 obj
  20 +<<
  21 + /Count 10
  22 + /Kids [
  23 + 4 0 R
  24 + 5 0 R
  25 + 6 0 R
  26 + 7 0 R
  27 + 8 0 R
  28 + 9 0 R
  29 + 10 0 R
  30 + 11 0 R
  31 + 12 0 R
  32 + 13 0 R
  33 + ]
  34 + /Type /Pages
  35 +>>
  36 +endobj
  37 +
  38 +%% Page 1
  39 +4 0 obj
  40 +<<
  41 + /Contents 14 0 R
  42 + /MediaBox [
  43 + 0
  44 + 0
  45 + 612
  46 + 792
  47 + ]
  48 + /Parent 3 0 R
  49 + /Resources <<
  50 + /Font <<
  51 + /F1 16 0 R
  52 + >>
  53 + /ProcSet [
  54 + /PDF
  55 + /Text
  56 + ]
  57 + >>
  58 + /Type /Page
  59 +>>
  60 +endobj
  61 +
  62 +%% Page 2
  63 +5 0 obj
  64 +<<
  65 + /Contents 17 0 R
  66 + /MediaBox [
  67 + 0
  68 + 0
  69 + 612
  70 + 792
  71 + ]
  72 + /Parent 3 0 R
  73 + /Resources <<
  74 + /Font <<
  75 + /F1 16 0 R
  76 + >>
  77 + /ProcSet [
  78 + /PDF
  79 + /Text
  80 + ]
  81 + >>
  82 + /Type /Page
  83 +>>
  84 +endobj
  85 +
  86 +%% Page 3
  87 +6 0 obj
  88 +<<
  89 + /Contents 19 0 R
  90 + /MediaBox [
  91 + 0
  92 + 0
  93 + 612
  94 + 792
  95 + ]
  96 + /Parent 3 0 R
  97 + /Resources <<
  98 + /Font <<
  99 + /F1 16 0 R
  100 + >>
  101 + /ProcSet [
  102 + /PDF
  103 + /Text
  104 + ]
  105 + >>
  106 + /Type /Page
  107 +>>
  108 +endobj
  109 +
  110 +%% Page 4
  111 +7 0 obj
  112 +<<
  113 + /Contents 21 0 R
  114 + /MediaBox [
  115 + 0
  116 + 0
  117 + 612
  118 + 792
  119 + ]
  120 + /Parent 3 0 R
  121 + /Resources <<
  122 + /Font <<
  123 + /F1 16 0 R
  124 + >>
  125 + /ProcSet [
  126 + /PDF
  127 + /Text
  128 + ]
  129 + >>
  130 + /Type /Page
  131 +>>
  132 +endobj
  133 +
  134 +%% Page 5
  135 +8 0 obj
  136 +<<
  137 + /Contents 23 0 R
  138 + /MediaBox [
  139 + 0
  140 + 0
  141 + 612
  142 + 792
  143 + ]
  144 + /Parent 3 0 R
  145 + /Resources <<
  146 + /Font <<
  147 + /F1 16 0 R
  148 + >>
  149 + /ProcSet [
  150 + /PDF
  151 + /Text
  152 + ]
  153 + >>
  154 + /Type /Page
  155 +>>
  156 +endobj
  157 +
  158 +%% Page 6
  159 +9 0 obj
  160 +<<
  161 + /Contents 25 0 R
  162 + /MediaBox [
  163 + 0
  164 + 0
  165 + 612
  166 + 792
  167 + ]
  168 + /Parent 3 0 R
  169 + /Resources <<
  170 + /Font <<
  171 + /F1 16 0 R
  172 + >>
  173 + /ProcSet [
  174 + /PDF
  175 + /Text
  176 + ]
  177 + >>
  178 + /Type /Page
  179 +>>
  180 +endobj
  181 +
  182 +%% Page 7
  183 +10 0 obj
  184 +<<
  185 + /Contents 27 0 R
  186 + /MediaBox [
  187 + 0
  188 + 0
  189 + 612
  190 + 792
  191 + ]
  192 + /Parent 3 0 R
  193 + /Resources <<
  194 + /Font <<
  195 + /F1 16 0 R
  196 + >>
  197 + /ProcSet [
  198 + /PDF
  199 + /Text
  200 + ]
  201 + >>
  202 + /Type /Page
  203 +>>
  204 +endobj
  205 +
  206 +%% Page 8
  207 +11 0 obj
  208 +<<
  209 + /Contents 29 0 R
  210 + /MediaBox [
  211 + 0
  212 + 0
  213 + 612
  214 + 792
  215 + ]
  216 + /Parent 3 0 R
  217 + /Resources <<
  218 + /Font <<
  219 + /F1 16 0 R
  220 + >>
  221 + /ProcSet [
  222 + /PDF
  223 + /Text
  224 + ]
  225 + >>
  226 + /Type /Page
  227 +>>
  228 +endobj
  229 +
  230 +%% Page 9
  231 +12 0 obj
  232 +<<
  233 + /Contents 31 0 R
  234 + /MediaBox [
  235 + 0
  236 + 0
  237 + 612
  238 + 792
  239 + ]
  240 + /Parent 3 0 R
  241 + /Resources <<
  242 + /Font <<
  243 + /F1 16 0 R
  244 + >>
  245 + /ProcSet [
  246 + /PDF
  247 + /Text
  248 + ]
  249 + >>
  250 + /Type /Page
  251 +>>
  252 +endobj
  253 +
  254 +%% Page 10
  255 +13 0 obj
  256 +<<
  257 + /Contents 33 0 R
  258 + /MediaBox [
  259 + 0
  260 + 0
  261 + 612
  262 + 792
  263 + ]
  264 + /Parent 3 0 R
  265 + /Resources <<
  266 + /Font <<
  267 + /F1 16 0 R
  268 + >>
  269 + /ProcSet [
  270 + /PDF
  271 + /Text
  272 + ]
  273 + >>
  274 + /Type /Page
  275 +>>
  276 +endobj
  277 +
  278 +%% Contents for page 1
  279 +14 0 obj
  280 +<<
  281 + /Length 15 0 R
  282 +>>
  283 +stream
  284 +BT /F1 15 Tf 72 720 Td (Original page 0) Tj ET
  285 +endstream
  286 +endobj
  287 +
  288 +15 0 obj
  289 +47
  290 +endobj
  291 +
  292 +16 0 obj
  293 +<<
  294 + /BaseFont /Times-Roman
  295 + /Encoding /WinAnsiEncoding
  296 + /Subtype /Type1
  297 + /Type /Font
  298 +>>
  299 +endobj
  300 +
  301 +%% Contents for page 2
  302 +17 0 obj
  303 +<<
  304 + /Length 18 0 R
  305 +>>
  306 +stream
  307 +BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET
  308 +endstream
  309 +endobj
  310 +
  311 +18 0 obj
  312 +47
  313 +endobj
  314 +
  315 +%% Contents for page 3
  316 +19 0 obj
  317 +<<
  318 + /Length 20 0 R
  319 +>>
  320 +stream
  321 +BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
  322 +endstream
  323 +endobj
  324 +
  325 +20 0 obj
  326 +47
  327 +endobj
  328 +
  329 +%% Contents for page 4
  330 +21 0 obj
  331 +<<
  332 + /Length 22 0 R
  333 +>>
  334 +stream
  335 +BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET
  336 +endstream
  337 +endobj
  338 +
  339 +22 0 obj
  340 +47
  341 +endobj
  342 +
  343 +%% Contents for page 5
  344 +23 0 obj
  345 +<<
  346 + /Length 24 0 R
  347 +>>
  348 +stream
  349 +BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET
  350 +endstream
  351 +endobj
  352 +
  353 +24 0 obj
  354 +47
  355 +endobj
  356 +
  357 +%% Contents for page 6
  358 +25 0 obj
  359 +<<
  360 + /Length 26 0 R
  361 +>>
  362 +stream
  363 +BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET
  364 +endstream
  365 +endobj
  366 +
  367 +26 0 obj
  368 +47
  369 +endobj
  370 +
  371 +%% Contents for page 7
  372 +27 0 obj
  373 +<<
  374 + /Length 28 0 R
  375 +>>
  376 +stream
  377 +BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET
  378 +endstream
  379 +endobj
  380 +
  381 +28 0 obj
  382 +47
  383 +endobj
  384 +
  385 +%% Contents for page 8
  386 +29 0 obj
  387 +<<
  388 + /Length 30 0 R
  389 +>>
  390 +stream
  391 +BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET
  392 +endstream
  393 +endobj
  394 +
  395 +30 0 obj
  396 +47
  397 +endobj
  398 +
  399 +%% Contents for page 9
  400 +31 0 obj
  401 +<<
  402 + /Length 32 0 R
  403 +>>
  404 +stream
  405 +BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET
  406 +endstream
  407 +endobj
  408 +
  409 +32 0 obj
  410 +47
  411 +endobj
  412 +
  413 +%% Contents for page 10
  414 +33 0 obj
  415 +<<
  416 + /Length 34 0 R
  417 +>>
  418 +stream
  419 +BT /F1 15 Tf 72 720 Td (Original page 9) Tj ET
  420 +endstream
  421 +endobj
  422 +
  423 +34 0 obj
  424 +47
  425 +endobj
  426 +
  427 +xref
  428 +0 35
  429 +0000000000 65535 f
  430 +0000000025 00000 n
  431 +0000000079 00000 n
  432 +0000000165 00000 n
  433 +0000000342 00000 n
  434 +0000000571 00000 n
  435 +0000000800 00000 n
  436 +0000001029 00000 n
  437 +0000001258 00000 n
  438 +0000001487 00000 n
  439 +0000001716 00000 n
  440 +0000001946 00000 n
  441 +0000002176 00000 n
  442 +0000002407 00000 n
  443 +0000002650 00000 n
  444 +0000002754 00000 n
  445 +0000002774 00000 n
  446 +0000002906 00000 n
  447 +0000003010 00000 n
  448 +0000003053 00000 n
  449 +0000003157 00000 n
  450 +0000003200 00000 n
  451 +0000003304 00000 n
  452 +0000003347 00000 n
  453 +0000003451 00000 n
  454 +0000003494 00000 n
  455 +0000003598 00000 n
  456 +0000003641 00000 n
  457 +0000003745 00000 n
  458 +0000003788 00000 n
  459 +0000003892 00000 n
  460 +0000003935 00000 n
  461 +0000004039 00000 n
  462 +0000004083 00000 n
  463 +0000004187 00000 n
  464 +trailer <<
  465 + /Info 2 0 R
  466 + /Root 1 0 R
  467 + /Size 35
  468 + /ID [<21f7a6fb083dab8e29743918a08bfa31><21f7a6fb083dab8e29743918a08bfa31>]
  469 +>>
  470 +startxref
  471 +4207
  472 +%%EOF
... ...
qpdf/qtest/qpdf/page_api_2.out 0 → 100644
  1 +page_api_2.pdf (page 1 (numbered from zero): object 4 0): duplicate page reference found; this would cause loss of data
... ...
qpdf/qtest/qpdf/page_api_2.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +%QDF-1.0
  4 +
  5 +1 0 obj
  6 +<<
  7 + /Pages 3 0 R
  8 + /Type /Catalog
  9 +>>
  10 +endobj
  11 +
  12 +2 0 obj
  13 +<<
  14 + /CreationDate (D:20120621124041)
  15 + /Producer (Apex PDFWriter)
  16 +>>
  17 +endobj
  18 +
  19 +3 0 obj
  20 +<<
  21 + /Count 3
  22 + /Kids [
  23 + 4 0 R
  24 + 4 0 R
  25 + 5 0 R
  26 + ]
  27 + /Type /Pages
  28 +>>
  29 +endobj
  30 +
  31 +%% Page 2
  32 +4 0 obj
  33 +<<
  34 + /Contents 6 0 R
  35 + /MediaBox [
  36 + 0
  37 + 0
  38 + 612
  39 + 792
  40 + ]
  41 + /Parent 3 0 R
  42 + /Resources <<
  43 + /Font <<
  44 + /F1 8 0 R
  45 + >>
  46 + /ProcSet [
  47 + /PDF
  48 + /Text
  49 + ]
  50 + >>
  51 + /Type /Page
  52 +>>
  53 +endobj
  54 +
  55 +%% Page 3
  56 +5 0 obj
  57 +<<
  58 + /Contents 9 0 R
  59 + /MediaBox [
  60 + 0
  61 + 0
  62 + 612
  63 + 792
  64 + ]
  65 + /Parent 3 0 R
  66 + /Resources <<
  67 + /Font <<
  68 + /F1 8 0 R
  69 + >>
  70 + /ProcSet [
  71 + /PDF
  72 + /Text
  73 + ]
  74 + >>
  75 + /Type /Page
  76 +>>
  77 +endobj
  78 +
  79 +%% Contents for page 2
  80 +6 0 obj
  81 +<<
  82 + /Length 7 0 R
  83 +>>
  84 +stream
  85 +BT /F1 15 Tf 72 720 Td (Original page 0) Tj ET
  86 +endstream
  87 +endobj
  88 +
  89 +7 0 obj
  90 +47
  91 +endobj
  92 +
  93 +8 0 obj
  94 +<<
  95 + /BaseFont /Times-Roman
  96 + /Encoding /WinAnsiEncoding
  97 + /Subtype /Type1
  98 + /Type /Font
  99 +>>
  100 +endobj
  101 +
  102 +%% Contents for page 3
  103 +9 0 obj
  104 +<<
  105 + /Length 10 0 R
  106 +>>
  107 +stream
  108 +BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET
  109 +endstream
  110 +endobj
  111 +
  112 +10 0 obj
  113 +47
  114 +endobj
  115 +
  116 +xref
  117 +0 11
  118 +0000000000 65535 f
  119 +0000000025 00000 n
  120 +0000000079 00000 n
  121 +0000000165 00000 n
  122 +0000000267 00000 n
  123 +0000000494 00000 n
  124 +0000000734 00000 n
  125 +0000000836 00000 n
  126 +0000000855 00000 n
  127 +0000000986 00000 n
  128 +0000001089 00000 n
  129 +trailer <<
  130 + /Info 2 0 R
  131 + /Root 1 0 R
  132 + /Size 11
  133 + /ID [<fb18b786ff7b358705da8a532aba8f6f><f7179eb35159bfd4c00f128abcfd1f02>]
  134 +>>
  135 +startxref
  136 +1109
  137 +%%EOF
... ...
qpdf/test_driver.cc
... ... @@ -14,6 +14,7 @@
14 14 #include <stdio.h>
15 15 #include <string.h>
16 16 #include <stdlib.h>
  17 +#include <assert.h>
17 18 #include <map>
18 19  
19 20 static char const* whoami = 0;
... ... @@ -56,8 +57,34 @@ class Provider: public QPDFObjectHandle::StreamDataProvider
56 57 bool bad_length;
57 58 };
58 59  
  60 +static void checkPageContents(QPDFObjectHandle page,
  61 + std::string const& wanted_string)
  62 +{
  63 + PointerHolder<Buffer> b1 =
  64 + page.getKey("/Contents").getStreamData();
  65 + std::string contents = std::string((char *)(b1->getBuffer()));
  66 + if (contents.find(wanted_string) == std::string::npos)
  67 + {
  68 + std::cout << "didn't find " << wanted_string << " in "
  69 + << contents << std::endl;
  70 + }
  71 +}
  72 +
  73 +static QPDFObjectHandle createPageContents(QPDF& pdf, std::string const& text)
  74 +{
  75 + std::string contents = "BT /F1 15 Tf 72 720 Td (" + text + ") Tj ET\n";
  76 + PointerHolder<Buffer> b = new Buffer(contents.length());
  77 + unsigned char* bp = b->getBuffer();
  78 + memcpy(bp, (char*)contents.c_str(), contents.length());
  79 + return QPDFObjectHandle::newStream(&pdf, b);
  80 +}
  81 +
59 82 void runtest(int n, char const* filename)
60 83 {
  84 + // Most tests here are crafted to work on specific files. Look at
  85 + // the test suite to see how the test is invoked to find the file
  86 + // that the test is supposed to operate on.
  87 +
61 88 QPDF pdf;
62 89 PointerHolder<char> file_buf;
63 90 FILE* filep = 0;
... ... @@ -629,6 +656,129 @@ void runtest(int n, char const* filename)
629 656 fclose(f);
630 657 delete b;
631 658 }
  659 + else if (n == 15)
  660 + {
  661 + std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
  662 + // Reference to original page numbers for this test case are
  663 + // numbered from 0.
  664 +
  665 + // Remove pages from various places, checking to make sure
  666 + // that our pages reference is getting updated.
  667 + assert(pages.size() == 10);
  668 + pdf.removePage(pages.back()); // original page 9
  669 + assert(pages.size() == 9);
  670 + pdf.removePage(*pages.begin()); // original page 0
  671 + assert(pages.size() == 8);
  672 + checkPageContents(pages[4], "Original page 5");
  673 + pdf.removePage(pages[4]); // original page 5
  674 + assert(pages.size() == 7);
  675 + checkPageContents(pages[4], "Original page 6");
  676 + checkPageContents(pages[0], "Original page 1");
  677 + checkPageContents(pages[6], "Original page 8");
  678 +
  679 + // Insert pages
  680 +
  681 + // Create some content streams.
  682 + std::vector<QPDFObjectHandle> contents;
  683 + contents.push_back(createPageContents(pdf, "New page 1"));
  684 + contents.push_back(createPageContents(pdf, "New page 0"));
  685 + contents.push_back(createPageContents(pdf, "New page 5"));
  686 + contents.push_back(createPageContents(pdf, "New page 6"));
  687 + contents.push_back(createPageContents(pdf, "New page 11"));
  688 + contents.push_back(createPageContents(pdf, "New page 12"));
  689 +
  690 + // Create some page objects. Start with an existing
  691 + // dictionary and modify it. Using the results of
  692 + // getDictAsMap to create a new dictionary effectively creates
  693 + // a shallow copy.
  694 + std::map<std::string, QPDFObjectHandle> page_dict_keys =
  695 + QPDFObjectHandle(pages[0]).getDictAsMap();
  696 + std::vector<QPDFObjectHandle> new_pages;
  697 + for (std::vector<QPDFObjectHandle>::iterator iter = contents.begin();
  698 + iter != contents.end(); ++iter)
  699 + {
  700 + // We will retain indirect object references to other
  701 + // indirect objects other than page content.
  702 + page_dict_keys["/Contents"] = *iter;
  703 + QPDFObjectHandle page =
  704 + QPDFObjectHandle::newDictionary(page_dict_keys);
  705 + if (iter == contents.begin())
  706 + {
  707 + // leave direct
  708 + new_pages.push_back(page);
  709 + }
  710 + else
  711 + {
  712 + new_pages.push_back(pdf.makeIndirectObject(page));
  713 + }
  714 + }
  715 +
  716 + // Now insert the pages
  717 + pdf.addPage(new_pages[0], true);
  718 + checkPageContents(pages[0], "New page 1");
  719 + pdf.addPageAt(new_pages[1], true, pages[0]);
  720 + assert(pages[0].getObjectID() == new_pages[1].getObjectID());
  721 + pdf.addPageAt(new_pages[2], true, pages[5]);
  722 + assert(pages[5].getObjectID() == new_pages[2].getObjectID());
  723 + pdf.addPageAt(new_pages[3], false, pages[5]);
  724 + assert(pages[6].getObjectID() == new_pages[3].getObjectID());
  725 + assert(pages.size() == 11);
  726 + pdf.addPage(new_pages[4], false);
  727 + assert(pages[11].getObjectID() == new_pages[4].getObjectID());
  728 + pdf.addPageAt(new_pages[5], false, pages.back());
  729 + assert(pages.size() == 13);
  730 + checkPageContents(pages[0], "New page 0");
  731 + checkPageContents(pages[1], "New page 1");
  732 + checkPageContents(pages[5], "New page 5");
  733 + checkPageContents(pages[6], "New page 6");
  734 + checkPageContents(pages[11], "New page 11");
  735 + checkPageContents(pages[12], "New page 12");
  736 +
  737 + QPDFWriter w(pdf, "a.pdf");
  738 + w.setStaticID(true);
  739 + w.setStreamDataMode(qpdf_s_preserve);
  740 + w.write();
  741 + }
  742 + else if (n == 16)
  743 + {
  744 + // Insert a page manually and then update the cache.
  745 + std::vector<QPDFObjectHandle> const& all_pages = pdf.getAllPages();
  746 +
  747 + QPDFObjectHandle contents = createPageContents(pdf, "New page 10");
  748 + std::map<std::string, QPDFObjectHandle> page_dict_keys =
  749 + QPDFObjectHandle(all_pages[0]).getDictAsMap();
  750 + page_dict_keys["/Contents"] = contents;
  751 + QPDFObjectHandle page =
  752 + pdf.makeIndirectObject(
  753 + QPDFObjectHandle::newDictionary(page_dict_keys));
  754 +
  755 + // Insert the page manually.
  756 + QPDFObjectHandle root = pdf.getRoot();
  757 + QPDFObjectHandle pages = root.getKey("/Pages");
  758 + QPDFObjectHandle kids = pages.getKey("/Kids");
  759 + page.replaceKey("/Parent", pages);
  760 + pages.replaceKey(
  761 + "/Count",
  762 + QPDFObjectHandle::newInteger(1 + (int)all_pages.size()));
  763 + kids.appendItem(page);
  764 + assert(all_pages.size() == 10);
  765 + pdf.updateAllPagesCache();
  766 + assert(all_pages.size() == 11);
  767 + assert(all_pages.back().getObjectID() == page.getObjectID());
  768 +
  769 + QPDFWriter w(pdf, "a.pdf");
  770 + w.setStaticID(true);
  771 + w.setStreamDataMode(qpdf_s_preserve);
  772 + w.write();
  773 + }
  774 + else if (n == 17)
  775 + {
  776 + // The input file to this test case is broken to exercise an
  777 + // error condition.
  778 + std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages();
  779 + pdf.removePage(pages[0]);
  780 + std::cout << "you can't see this" << std::endl;
  781 + }
632 782 else
633 783 {
634 784 throw std::runtime_error(std::string("invalid test ") +
... ...