Commit c1150a449b9ca33fc496eda6e3622e7d4d5394e0

Authored by m-holger
1 parent 2d36aedf

Refactor `QPDFJob`: introduce `PageNo` structure to simplify and standardize pag…

…e number and index handling, update related logic accordingly.
include/qpdf/QPDFJob.hh
... ... @@ -425,6 +425,7 @@ class QPDFJob
425 425 [[deprecated("use job_json_schema(version)")]] static std::string QPDF_DLL job_json_schema_v1();
426 426  
427 427 private:
  428 + struct PageNo;
428 429 struct RotationSpec;
429 430 struct UnderOverlay;
430 431 struct PageLabelSpec;
... ...
libqpdf/QPDFJob.cc
... ... @@ -243,6 +243,30 @@ ImageOptimizer::provideStreamData(QPDFObjGen const&, Pipeline* pipeline)
243 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 270 QPDFJob::PageSpec::PageSpec(
247 271 std::string const& filename, std::string const& password, std::string const& range) :
248 272 filename(filename),
... ... @@ -1906,13 +1930,13 @@ QPDFJob::doUnderOverlayForPage(
1906 1930 std::string content;
1907 1931 int min_suffix = 1;
1908 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 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 1942 // If the same page is overlaid or underlaid multiple times, we'll generate multiple names
... ... @@ -1920,13 +1944,13 @@ QPDFJob::doUnderOverlayForPage(
1920 1944 std::string name = resources.getUniqueResourceName("/Fx", min_suffix);
1921 1945 QPDFMatrix cm;
1922 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 1948 dest_page.copyAnnotations(from_page, cm, &dest_afdh, &from_page.qpdf()->acroform());
1925 1949 if (!new_content.empty()) {
1926 1950 resources.mergeResources("<< /XObject << >> >>"_qpdf);
1927 1951 auto xobject = resources.getKey("/XObject");
1928 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 1955 ++min_suffix;
1932 1956 content += new_content;
... ... @@ -1999,18 +2023,17 @@ QPDFJob::handleUnderOverlay(QPDF&amp; pdf)
1999 2023 QPDFPageDocumentHelper main_pdh(pdf);
2000 2024 auto main_pages = main_pdh.getAllPages();
2001 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 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 2030 continue;
2008 2031 }
2009 2032 // This code converts the original page, any underlays, and any overlays to form XObjects.
2010 2033 // Then it concatenates display of all underlays, the original page, and all overlays. Prior
2011 2034 // to 11.3.0, the original page contents were wrapped in q/Q, but this didn't work if the
2012 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 2037 auto dest_page_oh = dest_page.getObjectHandle();
2015 2038 auto this_page_fo = dest_page.getFormXObjectForPage();
2016 2039 // The resulting form xobject lazily reads the content from the original page, which we are
... ... @@ -2027,7 +2050,7 @@ QPDFJob::handleUnderOverlay(QPDF&amp; pdf)
2027 2050 pdf,
2028 2051 underlay,
2029 2052 underlay_pagenos,
2030   - page_idx,
  2053 + page.idx,
2031 2054 uo_idx,
2032 2055 underlay_fo,
2033 2056 upages[uo_idx],
... ... @@ -2047,7 +2070,7 @@ QPDFJob::handleUnderOverlay(QPDF&amp; pdf)
2047 2070 pdf,
2048 2071 overlay,
2049 2072 overlay_pagenos,
2050   - page_idx,
  2073 + page.idx,
2051 2074 uo_idx,
2052 2075 overlay_fo,
2053 2076 opages[uo_idx],
... ...