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.
This commit is contained in:
Jay Berkenbilt 2024-01-05 12:16:13 -05:00
parent 1921e44ca7
commit a0e70b370a
7 changed files with 201 additions and 0 deletions

View File

@ -296,6 +296,23 @@ class QPDFJob
Config* config;
};
class PageLabelsConfig {
friend class QPDFJob;
friend class Config;
public:
QPDF_DLL
Config* endSetPageLabels();
#include <qpdf/auto_job_c_set_page_labels.hh>
private:
PageLabelsConfig(Config*);
PageLabelsConfig(PagesConfig const&) = delete;
Config* config;
};
class Config
{
friend class QPDFJob;
@ -313,6 +330,8 @@ class QPDFJob
Config* outputFile(std::string const& filename);
QPDF_DLL
Config* replaceInput();
QPDF_DLL
Config* setPageLabels(std::vector<std::string> const& specs);
QPDF_DLL
std::shared_ptr<CopyAttConfig> copyAttachmentsFrom();
@ -675,6 +694,7 @@ class QPDFJob
bool json_output{false};
std::string update_from_json;
bool report_mem_usage{false};
std::vector<std::string> page_label_specs;
};
std::shared_ptr<Members> m;
};

View File

@ -94,6 +94,7 @@ options:
- underlay
- empty
- replace-input
- set-page-labels
positional: true
bare:
- add-attachment
@ -134,6 +135,7 @@ options:
- report-memory-usage
- requires-password
- remove-restrictions
- set-page-labels
- show-encryption
- show-encryption-key
- show-linearization
@ -282,6 +284,9 @@ options:
required_parameter:
prefix: prefix
password: password
- table: set page labels
prefix: PageLabels
positional: true
json:
# The structure of this section defines what the json input to
# QPDFJob looks like. If a key starts with underscore, it does not
@ -437,6 +442,8 @@ json:
remove-page-labels:
report-memory-usage:
rotate:
set-page-labels:
- null
overlay:
_file: "source file for overlay"
UO.password:

View File

@ -408,6 +408,26 @@ ArgParser::argEndCopyAttachment()
c_copy_att = nullptr;
}
void
ArgParser::argSetPageLabels()
{
this->ap.selectOptionTable(O_SET_PAGE_LABELS);
accumulated_args.clear();
}
void
ArgParser::argPageLabelsPositional(std::string const& arg)
{
accumulated_args.push_back(arg);
}
void
ArgParser::argEndSetPageLabels()
{
c_main->setPageLabels(accumulated_args);
accumulated_args.clear();
}
void
ArgParser::argJobJsonHelp()
{

View File

@ -1059,6 +1059,17 @@ QPDFJob::Config::encrypt(
return std::shared_ptr<EncConfig>(new EncConfig(this));
}
QPDFJob::Config*
QPDFJob::Config::setPageLabels(const std::vector<std::string>& specs)
{
// XXX validate
for (auto const& xxx: specs) {
std::cout << "XXX config: spec: " << xxx << std::endl;
}
o.m->page_label_specs = specs;
return this;
}
QPDFJob::EncConfig::EncConfig(Config* c) :
config(c)
{
@ -1213,3 +1224,14 @@ QPDFJob::EncConfig::forceR5()
config->o.m->force_R5 = true;
return this;
}
QPDFJob::PageLabelsConfig::PageLabelsConfig(Config* c) :
config(c)
{
}
QPDFJob::Config*
QPDFJob::PageLabelsConfig::endSetPageLabels()
{
return this->config;
}

View File

@ -66,6 +66,7 @@ namespace
std::shared_ptr<QPDFJob::PagesConfig> c_pages;
std::shared_ptr<QPDFJob::UOConfig> c_uo;
std::shared_ptr<QPDFJob::EncConfig> c_enc;
std::vector<std::string> accumulated_args;
};
} // namespace
@ -564,6 +565,26 @@ Handlers::setupUnderlayPassword()
addParameter([this](char const* p) { c_uo->password(p); });
}
void
Handlers::setupSetPageLabels()
{
accumulated_args.clear();
addParameter([this](char const* p) { accumulated_args.push_back(p); });
}
void
Handlers::endSetPageLabelsArray()
{
c_main->setPageLabels(accumulated_args);
accumulated_args.clear();
}
void
Handlers::beginSetPageLabelsArray(JSON)
{
// nothing needed
}
void
QPDFJob::initializeFromJson(std::string const& json, bool partial)
{

View File

@ -1748,6 +1748,116 @@ Related Options
Exclude page labels (explicit page numbers) from the output file.
Exclude page labels (explicit page numbers) from the output file.
See also :qpdf:ref:`--set-page-labels`.
.. qpdf:option:: --set-page-labels label-spec ... --
.. help: number pages for the entire document
Set page labels (explicit page numbers) for the entire file.
Each label-spec has the form
first-page:[type][/start[/prefix]]
where
- "first-page" represents a sequential page number using the
same format as page ranges: a number, a number preceded by "r"
to indicate counting from the end, or "z" indicating the last
page
- "type" is one of
- D: Arabic numerals (digits)
- A: Upper-case alphabetic characters
- a: Lower-case alphabetic characters
- R: Upper-case Roman numerals
- r: Lower-case Roman numerals
- omitted: the page number does not appear, though the prefix,
if specified will still appear
- "prefix"` may be any string and is prepended to each page
label
A given page label spec causes pages to be numbered according to
that scheme starting with first-page and continuing until the
next label spec or the end of the document. If you want to omit
numbering starting at a certain page, you can use first-page: as
the spec.
Example: "1:r 5:D" would number the first four pages i through
iv, then the remaining pages with Arabic numerals starting with
1 and continuing sequentially until the end of the document. For
additional examples, please consult the manual.
Set page labels (explicit page numbers) for the entire file. A PDF
file's pages can be explicitly numbered using page labels. Page
labels in a PDF file have an optional type (Arabic numerals,
upper/lower-case alphabetic characters, upper/lower-case Roman
numerals), an optional prefix, and an optional starting value,
which defaults to 1. A qpdf page label spec has the form
:samp:`{first-page}:[{type}][/{start}[/{prefix}]]`
where
- :samp:`{first-page}` represents a sequential page number using
the same format as page ranges (see :ref:`page-ranges`): a
number, a number preceded by ``r`` to indicate counting from the
end, or ``z`` indicating the last page
- :samp:`{type}` may be one of
- ``D``: Arabic numerals (digits)
- ``A``: Upper-case alphabetic characters
- ``a``: Lower-case alphabetic characters
- ``R``: Upper-case Roman numerals
- ``r``: Lower-case Roman numerals
- omitted: the page number does not appear, though the prefix, if
specified will still appear
- :samp:`{prefix}` may be any string and is prepended to each page
label
A given page label spec causes pages to be numbered according to
that scheme starting with :samp:`{first-page}` and continuing until
the next label spec or the end of the document. If you want to omit
numbering starting at a certain page, you can use
:samp:`{first-page}:` as the spec.
Here are some example page labeling schemes. First these examples,
assume a 50-page document.
- ``1:a 5:D``
- The first four pages will be numbered ``a`` through ``d``, then
the remaining pages will numbered ``1`` through ``46``.
- ``1:r 5:D 12: 14:D/10 r5:D//A- z://"end note"``:
- The first four pages are numbered ``i`` through ``iv``
- The 5th page is numbered ``1``, and pages are numbered
sequentially through the 11th page, which will be numbered
``7``
- The 12th and 13th pages will not have labels
- The 14th page is numbered ``10``. Pages will be numered
sequentially up through the 45th page, which will be numbered
``41``
- Starting with the 46th page (the fifth to last page) and going
to the 49th page, pages will be labeled ``A-1`` through ``A-4``
- The 50th page (the last page) will be labeled ``end note``.
The limitations on the range of formats for page labels are as
specified in Section 12.4.2 of the PDF spec, ISO 32000.
See also :qpdf:ref:`--remove-page-labels`.
.. _encryption-options:

View File

@ -101,6 +101,7 @@ main()
print_size(QPDFJob::EncConfig);
print_size(QPDFJob::PagesConfig);
print_size(QPDFJob::UOConfig);
print_size(QPDFJob::PageLabelsConfig);
print_size(QPDFLogger);
print_size(QPDFMatrix);
print_size(QPDFNameTreeObjectHelper);