Commit c1150a449b9ca33fc496eda6e3622e7d4d5394e0
1 parent
2d36aedf
Refactor `QPDFJob`: introduce `PageNo` structure to simplify and standardize pag…
…e number and index handling, update related logic accordingly.
Showing
2 changed files
with
38 additions
and
14 deletions
include/qpdf/QPDFJob.hh
| @@ -425,6 +425,7 @@ class QPDFJob | @@ -425,6 +425,7 @@ class QPDFJob | ||
| 425 | [[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1(); | 425 | [[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1(); |
| 426 | 426 | ||
| 427 | private: | 427 | private: |
| 428 | + struct PageNo; | ||
| 428 | struct RotationSpec; | 429 | struct RotationSpec; |
| 429 | struct UnderOverlay; | 430 | struct UnderOverlay; |
| 430 | struct PageLabelSpec; | 431 | struct PageLabelSpec; |
libqpdf/QPDFJob.cc
| @@ -243,6 +243,30 @@ ImageOptimizer::provideStreamData(QPDFObjGen const&, Pipeline* pipeline) | @@ -243,6 +243,30 @@ ImageOptimizer::provideStreamData(QPDFObjGen const&, Pipeline* pipeline) | ||
| 243 | image.pipeStreamData(p.get(), 0, decode_level, false, false); | 243 | image.pipeStreamData(p.get(), 0, decode_level, false, false); |
| 244 | } | 244 | } |
| 245 | 245 | ||
| 246 | +// Page number (1 based) and index (0 based). Defaults to page number 1 / index 0. | ||
| 247 | +struct QPDFJob::PageNo | ||
| 248 | +{ | ||
| 249 | + PageNo() = default; | ||
| 250 | + PageNo(PageNo const&) = default; | ||
| 251 | + | ||
| 252 | + PageNo(int no) : | ||
| 253 | + idx{QIntC::to_size(no - 1)}, | ||
| 254 | + no{no} | ||
| 255 | + { | ||
| 256 | + } | ||
| 257 | + | ||
| 258 | + PageNo& | ||
| 259 | + operator++() | ||
| 260 | + { | ||
| 261 | + ++idx; | ||
| 262 | + ++no; | ||
| 263 | + return *this; | ||
| 264 | + } | ||
| 265 | + | ||
| 266 | + size_t idx{0}; | ||
| 267 | + int no{1}; | ||
| 268 | +}; | ||
| 269 | + | ||
| 246 | QPDFJob::PageSpec::PageSpec( | 270 | QPDFJob::PageSpec::PageSpec( |
| 247 | std::string const& filename, std::string const& password, std::string const& range) : | 271 | std::string const& filename, std::string const& password, std::string const& range) : |
| 248 | filename(filename), | 272 | filename(filename), |
| @@ -1906,13 +1930,13 @@ QPDFJob::doUnderOverlayForPage( | @@ -1906,13 +1930,13 @@ QPDFJob::doUnderOverlayForPage( | ||
| 1906 | std::string content; | 1930 | std::string content; |
| 1907 | int min_suffix = 1; | 1931 | int min_suffix = 1; |
| 1908 | QPDFObjectHandle resources = dest_page.getAttribute("/Resources", true); | 1932 | QPDFObjectHandle resources = dest_page.getAttribute("/Resources", true); |
| 1909 | - for (int from_pageno: pagenos[pageno][uo_idx]) { | 1933 | + for (PageNo from_no: pagenos[pageno][uo_idx]) { |
| 1910 | doIfVerbose([&](Pipeline& v, std::string const& prefix) { | 1934 | doIfVerbose([&](Pipeline& v, std::string const& prefix) { |
| 1911 | - v << " " << uo.filename << " " << uo.which << " " << from_pageno << "\n"; | 1935 | + v << " " << uo.filename << " " << uo.which << " " << from_no.no << "\n"; |
| 1912 | }); | 1936 | }); |
| 1913 | - auto from_page = pages.at(QIntC::to_size(from_pageno - 1)); | ||
| 1914 | - if (!fo[from_pageno].contains(uo_idx)) { | ||
| 1915 | - fo[from_pageno][uo_idx] = pdf.copyForeignObject(from_page.getFormXObjectForPage()); | 1937 | + auto from_page = pages.at(from_no.idx); |
| 1938 | + if (!fo[from_no.no].contains(uo_idx)) { | ||
| 1939 | + fo[from_no.no][uo_idx] = pdf.copyForeignObject(from_page.getFormXObjectForPage()); | ||
| 1916 | } | 1940 | } |
| 1917 | 1941 | ||
| 1918 | // If the same page is overlaid or underlaid multiple times, we'll generate multiple names | 1942 | // If the same page is overlaid or underlaid multiple times, we'll generate multiple names |
| @@ -1920,13 +1944,13 @@ QPDFJob::doUnderOverlayForPage( | @@ -1920,13 +1944,13 @@ QPDFJob::doUnderOverlayForPage( | ||
| 1920 | std::string name = resources.getUniqueResourceName("/Fx", min_suffix); | 1944 | std::string name = resources.getUniqueResourceName("/Fx", min_suffix); |
| 1921 | QPDFMatrix cm; | 1945 | QPDFMatrix cm; |
| 1922 | std::string new_content = dest_page.placeFormXObject( | 1946 | std::string new_content = dest_page.placeFormXObject( |
| 1923 | - fo[from_pageno][uo_idx], name, dest_page.getTrimBox().getArrayAsRectangle(), cm); | 1947 | + fo[from_no.no][uo_idx], name, dest_page.getTrimBox().getArrayAsRectangle(), cm); |
| 1924 | dest_page.copyAnnotations(from_page, cm, &dest_afdh, &from_page.qpdf()->acroform()); | 1948 | dest_page.copyAnnotations(from_page, cm, &dest_afdh, &from_page.qpdf()->acroform()); |
| 1925 | if (!new_content.empty()) { | 1949 | if (!new_content.empty()) { |
| 1926 | resources.mergeResources("<< /XObject << >> >>"_qpdf); | 1950 | resources.mergeResources("<< /XObject << >> >>"_qpdf); |
| 1927 | auto xobject = resources.getKey("/XObject"); | 1951 | auto xobject = resources.getKey("/XObject"); |
| 1928 | if (xobject.isDictionary()) { | 1952 | if (xobject.isDictionary()) { |
| 1929 | - xobject.replaceKey(name, fo[from_pageno][uo_idx]); | 1953 | + xobject.replaceKey(name, fo[from_no.no][uo_idx]); |
| 1930 | } | 1954 | } |
| 1931 | ++min_suffix; | 1955 | ++min_suffix; |
| 1932 | content += new_content; | 1956 | content += new_content; |
| @@ -1999,18 +2023,17 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) | @@ -1999,18 +2023,17 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) | ||
| 1999 | QPDFPageDocumentHelper main_pdh(pdf); | 2023 | QPDFPageDocumentHelper main_pdh(pdf); |
| 2000 | auto main_pages = main_pdh.getAllPages(); | 2024 | auto main_pages = main_pdh.getAllPages(); |
| 2001 | size_t main_npages = main_pages.size(); | 2025 | size_t main_npages = main_pages.size(); |
| 2002 | - for (size_t page_idx = 0; page_idx < main_npages; ++page_idx) { | ||
| 2003 | - auto pageno = QIntC::to_int(page_idx) + 1; | 2026 | + for (PageNo page; page.idx < main_npages; ++page) { |
| 2004 | doIfVerbose( | 2027 | doIfVerbose( |
| 2005 | - [&](Pipeline& v, std::string const& prefix) { v << " page " << pageno << "\n"; }); | ||
| 2006 | - if (underlay_pagenos[pageno].empty() && overlay_pagenos[pageno].empty()) { | 2028 | + [&](Pipeline& v, std::string const& prefix) { v << " page " << page.no << "\n"; }); |
| 2029 | + if (underlay_pagenos[page.no].empty() && overlay_pagenos[page.no].empty()) { | ||
| 2007 | continue; | 2030 | continue; |
| 2008 | } | 2031 | } |
| 2009 | // This code converts the original page, any underlays, and any overlays to form XObjects. | 2032 | // This code converts the original page, any underlays, and any overlays to form XObjects. |
| 2010 | // Then it concatenates display of all underlays, the original page, and all overlays. Prior | 2033 | // Then it concatenates display of all underlays, the original page, and all overlays. Prior |
| 2011 | // to 11.3.0, the original page contents were wrapped in q/Q, but this didn't work if the | 2034 | // to 11.3.0, the original page contents were wrapped in q/Q, but this didn't work if the |
| 2012 | // original page had unbalanced q/Q operators. See GitHub issue #904. | 2035 | // original page had unbalanced q/Q operators. See GitHub issue #904. |
| 2013 | - auto& dest_page = main_pages.at(page_idx); | 2036 | + auto& dest_page = main_pages.at(page.idx); |
| 2014 | auto dest_page_oh = dest_page.getObjectHandle(); | 2037 | auto dest_page_oh = dest_page.getObjectHandle(); |
| 2015 | auto this_page_fo = dest_page.getFormXObjectForPage(); | 2038 | auto this_page_fo = dest_page.getFormXObjectForPage(); |
| 2016 | // The resulting form xobject lazily reads the content from the original page, which we are | 2039 | // The resulting form xobject lazily reads the content from the original page, which we are |
| @@ -2027,7 +2050,7 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) | @@ -2027,7 +2050,7 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) | ||
| 2027 | pdf, | 2050 | pdf, |
| 2028 | underlay, | 2051 | underlay, |
| 2029 | underlay_pagenos, | 2052 | underlay_pagenos, |
| 2030 | - page_idx, | 2053 | + page.idx, |
| 2031 | uo_idx, | 2054 | uo_idx, |
| 2032 | underlay_fo, | 2055 | underlay_fo, |
| 2033 | upages[uo_idx], | 2056 | upages[uo_idx], |
| @@ -2047,7 +2070,7 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) | @@ -2047,7 +2070,7 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) | ||
| 2047 | pdf, | 2070 | pdf, |
| 2048 | overlay, | 2071 | overlay, |
| 2049 | overlay_pagenos, | 2072 | overlay_pagenos, |
| 2050 | - page_idx, | 2073 | + page.idx, |
| 2051 | uo_idx, | 2074 | uo_idx, |
| 2052 | overlay_fo, | 2075 | overlay_fo, |
| 2053 | opages[uo_idx], | 2076 | opages[uo_idx], |