Commit a0e70b370afcb628caabb3e8610d600fea6966f3

Authored by Jay Berkenbilt
1 parent 1921e44c

Wiring for --set-page-labels: manual (non-bisectable commit)

This commit contains only the manual changes. It is separated for
clarity. This commit would not pass CI because it lacks the automated
changes, which appear in the next commit.
include/qpdf/QPDFJob.hh
@@ -296,6 +296,23 @@ class QPDFJob @@ -296,6 +296,23 @@ class QPDFJob
296 Config* config; 296 Config* config;
297 }; 297 };
298 298
  299 + class PageLabelsConfig {
  300 + friend class QPDFJob;
  301 + friend class Config;
  302 +
  303 + public:
  304 + QPDF_DLL
  305 + Config* endSetPageLabels();
  306 +
  307 +#include <qpdf/auto_job_c_set_page_labels.hh>
  308 +
  309 + private:
  310 + PageLabelsConfig(Config*);
  311 + PageLabelsConfig(PagesConfig const&) = delete;
  312 +
  313 + Config* config;
  314 + };
  315 +
299 class Config 316 class Config
300 { 317 {
301 friend class QPDFJob; 318 friend class QPDFJob;
@@ -313,6 +330,8 @@ class QPDFJob @@ -313,6 +330,8 @@ class QPDFJob
313 Config* outputFile(std::string const& filename); 330 Config* outputFile(std::string const& filename);
314 QPDF_DLL 331 QPDF_DLL
315 Config* replaceInput(); 332 Config* replaceInput();
  333 + QPDF_DLL
  334 + Config* setPageLabels(std::vector<std::string> const& specs);
316 335
317 QPDF_DLL 336 QPDF_DLL
318 std::shared_ptr<CopyAttConfig> copyAttachmentsFrom(); 337 std::shared_ptr<CopyAttConfig> copyAttachmentsFrom();
@@ -675,6 +694,7 @@ class QPDFJob @@ -675,6 +694,7 @@ class QPDFJob
675 bool json_output{false}; 694 bool json_output{false};
676 std::string update_from_json; 695 std::string update_from_json;
677 bool report_mem_usage{false}; 696 bool report_mem_usage{false};
  697 + std::vector<std::string> page_label_specs;
678 }; 698 };
679 std::shared_ptr<Members> m; 699 std::shared_ptr<Members> m;
680 }; 700 };
@@ -94,6 +94,7 @@ options: @@ -94,6 +94,7 @@ options:
94 - underlay 94 - underlay
95 - empty 95 - empty
96 - replace-input 96 - replace-input
  97 + - set-page-labels
97 positional: true 98 positional: true
98 bare: 99 bare:
99 - add-attachment 100 - add-attachment
@@ -134,6 +135,7 @@ options: @@ -134,6 +135,7 @@ options:
134 - report-memory-usage 135 - report-memory-usage
135 - requires-password 136 - requires-password
136 - remove-restrictions 137 - remove-restrictions
  138 + - set-page-labels
137 - show-encryption 139 - show-encryption
138 - show-encryption-key 140 - show-encryption-key
139 - show-linearization 141 - show-linearization
@@ -282,6 +284,9 @@ options: @@ -282,6 +284,9 @@ options:
282 required_parameter: 284 required_parameter:
283 prefix: prefix 285 prefix: prefix
284 password: password 286 password: password
  287 + - table: set page labels
  288 + prefix: PageLabels
  289 + positional: true
285 json: 290 json:
286 # The structure of this section defines what the json input to 291 # The structure of this section defines what the json input to
287 # QPDFJob looks like. If a key starts with underscore, it does not 292 # QPDFJob looks like. If a key starts with underscore, it does not
@@ -437,6 +442,8 @@ json: @@ -437,6 +442,8 @@ json:
437 remove-page-labels: 442 remove-page-labels:
438 report-memory-usage: 443 report-memory-usage:
439 rotate: 444 rotate:
  445 + set-page-labels:
  446 + - null
440 overlay: 447 overlay:
441 _file: "source file for overlay" 448 _file: "source file for overlay"
442 UO.password: 449 UO.password:
libqpdf/QPDFJob_argv.cc
@@ -409,6 +409,26 @@ ArgParser::argEndCopyAttachment() @@ -409,6 +409,26 @@ ArgParser::argEndCopyAttachment()
409 } 409 }
410 410
411 void 411 void
  412 +ArgParser::argSetPageLabels()
  413 +{
  414 + this->ap.selectOptionTable(O_SET_PAGE_LABELS);
  415 + accumulated_args.clear();
  416 +}
  417 +
  418 +void
  419 +ArgParser::argPageLabelsPositional(std::string const& arg)
  420 +{
  421 + accumulated_args.push_back(arg);
  422 +}
  423 +
  424 +void
  425 +ArgParser::argEndSetPageLabels()
  426 +{
  427 + c_main->setPageLabels(accumulated_args);
  428 + accumulated_args.clear();
  429 +}
  430 +
  431 +void
412 ArgParser::argJobJsonHelp() 432 ArgParser::argJobJsonHelp()
413 { 433 {
414 *QPDFLogger::defaultLogger()->getInfo() 434 *QPDFLogger::defaultLogger()->getInfo()
libqpdf/QPDFJob_config.cc
@@ -1059,6 +1059,17 @@ QPDFJob::Config::encrypt( @@ -1059,6 +1059,17 @@ QPDFJob::Config::encrypt(
1059 return std::shared_ptr<EncConfig>(new EncConfig(this)); 1059 return std::shared_ptr<EncConfig>(new EncConfig(this));
1060 } 1060 }
1061 1061
  1062 +QPDFJob::Config*
  1063 +QPDFJob::Config::setPageLabels(const std::vector<std::string>& specs)
  1064 +{
  1065 + // XXX validate
  1066 + for (auto const& xxx: specs) {
  1067 + std::cout << "XXX config: spec: " << xxx << std::endl;
  1068 + }
  1069 + o.m->page_label_specs = specs;
  1070 + return this;
  1071 +}
  1072 +
1062 QPDFJob::EncConfig::EncConfig(Config* c) : 1073 QPDFJob::EncConfig::EncConfig(Config* c) :
1063 config(c) 1074 config(c)
1064 { 1075 {
@@ -1213,3 +1224,14 @@ QPDFJob::EncConfig::forceR5() @@ -1213,3 +1224,14 @@ QPDFJob::EncConfig::forceR5()
1213 config->o.m->force_R5 = true; 1224 config->o.m->force_R5 = true;
1214 return this; 1225 return this;
1215 } 1226 }
  1227 +
  1228 +QPDFJob::PageLabelsConfig::PageLabelsConfig(Config* c) :
  1229 + config(c)
  1230 +{
  1231 +}
  1232 +
  1233 +QPDFJob::Config*
  1234 +QPDFJob::PageLabelsConfig::endSetPageLabels()
  1235 +{
  1236 + return this->config;
  1237 +}
libqpdf/QPDFJob_json.cc
@@ -66,6 +66,7 @@ namespace @@ -66,6 +66,7 @@ namespace
66 std::shared_ptr<QPDFJob::PagesConfig> c_pages; 66 std::shared_ptr<QPDFJob::PagesConfig> c_pages;
67 std::shared_ptr<QPDFJob::UOConfig> c_uo; 67 std::shared_ptr<QPDFJob::UOConfig> c_uo;
68 std::shared_ptr<QPDFJob::EncConfig> c_enc; 68 std::shared_ptr<QPDFJob::EncConfig> c_enc;
  69 + std::vector<std::string> accumulated_args;
69 }; 70 };
70 } // namespace 71 } // namespace
71 72
@@ -565,6 +566,26 @@ Handlers::setupUnderlayPassword() @@ -565,6 +566,26 @@ Handlers::setupUnderlayPassword()
565 } 566 }
566 567
567 void 568 void
  569 +Handlers::setupSetPageLabels()
  570 +{
  571 + accumulated_args.clear();
  572 + addParameter([this](char const* p) { accumulated_args.push_back(p); });
  573 +}
  574 +
  575 +void
  576 +Handlers::endSetPageLabelsArray()
  577 +{
  578 + c_main->setPageLabels(accumulated_args);
  579 + accumulated_args.clear();
  580 +}
  581 +
  582 +void
  583 +Handlers::beginSetPageLabelsArray(JSON)
  584 +{
  585 + // nothing needed
  586 +}
  587 +
  588 +void
568 QPDFJob::initializeFromJson(std::string const& json, bool partial) 589 QPDFJob::initializeFromJson(std::string const& json, bool partial)
569 { 590 {
570 std::list<std::string> errors; 591 std::list<std::string> errors;
manual/cli.rst
@@ -1748,6 +1748,116 @@ Related Options @@ -1748,6 +1748,116 @@ Related Options
1748 Exclude page labels (explicit page numbers) from the output file. 1748 Exclude page labels (explicit page numbers) from the output file.
1749 1749
1750 Exclude page labels (explicit page numbers) from the output file. 1750 Exclude page labels (explicit page numbers) from the output file.
  1751 + See also :qpdf:ref:`--set-page-labels`.
  1752 +
  1753 +.. qpdf:option:: --set-page-labels label-spec ... --
  1754 +
  1755 + .. help: number pages for the entire document
  1756 +
  1757 + Set page labels (explicit page numbers) for the entire file.
  1758 + Each label-spec has the form
  1759 +
  1760 + first-page:[type][/start[/prefix]]
  1761 +
  1762 + where
  1763 +
  1764 + - "first-page" represents a sequential page number using the
  1765 + same format as page ranges: a number, a number preceded by "r"
  1766 + to indicate counting from the end, or "z" indicating the last
  1767 + page
  1768 + - "type" is one of
  1769 + - D: Arabic numerals (digits)
  1770 + - A: Upper-case alphabetic characters
  1771 + - a: Lower-case alphabetic characters
  1772 + - R: Upper-case Roman numerals
  1773 + - r: Lower-case Roman numerals
  1774 + - omitted: the page number does not appear, though the prefix,
  1775 + if specified will still appear
  1776 + - "prefix"` may be any string and is prepended to each page
  1777 + label
  1778 +
  1779 + A given page label spec causes pages to be numbered according to
  1780 + that scheme starting with first-page and continuing until the
  1781 + next label spec or the end of the document. If you want to omit
  1782 + numbering starting at a certain page, you can use first-page: as
  1783 + the spec.
  1784 +
  1785 + Example: "1:r 5:D" would number the first four pages i through
  1786 + iv, then the remaining pages with Arabic numerals starting with
  1787 + 1 and continuing sequentially until the end of the document. For
  1788 + additional examples, please consult the manual.
  1789 +
  1790 + Set page labels (explicit page numbers) for the entire file. A PDF
  1791 + file's pages can be explicitly numbered using page labels. Page
  1792 + labels in a PDF file have an optional type (Arabic numerals,
  1793 + upper/lower-case alphabetic characters, upper/lower-case Roman
  1794 + numerals), an optional prefix, and an optional starting value,
  1795 + which defaults to 1. A qpdf page label spec has the form
  1796 +
  1797 + :samp:`{first-page}:[{type}][/{start}[/{prefix}]]`
  1798 +
  1799 + where
  1800 +
  1801 + - :samp:`{first-page}` represents a sequential page number using
  1802 + the same format as page ranges (see :ref:`page-ranges`): a
  1803 + number, a number preceded by ``r`` to indicate counting from the
  1804 + end, or ``z`` indicating the last page
  1805 +
  1806 + - :samp:`{type}` may be one of
  1807 +
  1808 + - ``D``: Arabic numerals (digits)
  1809 +
  1810 + - ``A``: Upper-case alphabetic characters
  1811 +
  1812 + - ``a``: Lower-case alphabetic characters
  1813 +
  1814 + - ``R``: Upper-case Roman numerals
  1815 +
  1816 + - ``r``: Lower-case Roman numerals
  1817 +
  1818 + - omitted: the page number does not appear, though the prefix, if
  1819 + specified will still appear
  1820 +
  1821 + - :samp:`{prefix}` may be any string and is prepended to each page
  1822 + label
  1823 +
  1824 + A given page label spec causes pages to be numbered according to
  1825 + that scheme starting with :samp:`{first-page}` and continuing until
  1826 + the next label spec or the end of the document. If you want to omit
  1827 + numbering starting at a certain page, you can use
  1828 + :samp:`{first-page}:` as the spec.
  1829 +
  1830 + Here are some example page labeling schemes. First these examples,
  1831 + assume a 50-page document.
  1832 +
  1833 + - ``1:a 5:D``
  1834 +
  1835 + - The first four pages will be numbered ``a`` through ``d``, then
  1836 + the remaining pages will numbered ``1`` through ``46``.
  1837 +
  1838 + - ``1:r 5:D 12: 14:D/10 r5:D//A- z://"end note"``:
  1839 +
  1840 + - The first four pages are numbered ``i`` through ``iv``
  1841 +
  1842 + - The 5th page is numbered ``1``, and pages are numbered
  1843 + sequentially through the 11th page, which will be numbered
  1844 + ``7``
  1845 +
  1846 + - The 12th and 13th pages will not have labels
  1847 +
  1848 + - The 14th page is numbered ``10``. Pages will be numered
  1849 + sequentially up through the 45th page, which will be numbered
  1850 + ``41``
  1851 +
  1852 + - Starting with the 46th page (the fifth to last page) and going
  1853 + to the 49th page, pages will be labeled ``A-1`` through ``A-4``
  1854 +
  1855 + - The 50th page (the last page) will be labeled ``end note``.
  1856 +
  1857 + The limitations on the range of formats for page labels are as
  1858 + specified in Section 12.4.2 of the PDF spec, ISO 32000.
  1859 +
  1860 + See also :qpdf:ref:`--remove-page-labels`.
1751 1861
1752 .. _encryption-options: 1862 .. _encryption-options:
1753 1863
qpdf/sizes.cc
@@ -101,6 +101,7 @@ main() @@ -101,6 +101,7 @@ main()
101 print_size(QPDFJob::EncConfig); 101 print_size(QPDFJob::EncConfig);
102 print_size(QPDFJob::PagesConfig); 102 print_size(QPDFJob::PagesConfig);
103 print_size(QPDFJob::UOConfig); 103 print_size(QPDFJob::UOConfig);
  104 + print_size(QPDFJob::PageLabelsConfig);
104 print_size(QPDFLogger); 105 print_size(QPDFLogger);
105 print_size(QPDFMatrix); 106 print_size(QPDFMatrix);
106 print_size(QPDFNameTreeObjectHelper); 107 print_size(QPDFNameTreeObjectHelper);