2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-09-28 21:19:06 +00:00
qpdf/libqpdf/QPDFPageLabelDocumentHelper.cc
Jay Berkenbilt 9044a24097 PointerHolder: deprecate getPointer() and getRefcount()
Use get() and use_count() instead. Add #define
NO_POINTERHOLDER_DEPRECATION to remove deprecation markers for these
only.

This commit also removes all deprecated PointerHolder API calls from
qpdf's code except in PointerHolder's test suite, which must continue
to test the deprecated APIs.
2022-02-04 13:12:37 -05:00

127 lines
3.9 KiB
C++

#include <qpdf/QPDFPageLabelDocumentHelper.hh>
#include <qpdf/QTC.hh>
QPDFPageLabelDocumentHelper::Members::~Members()
{
}
QPDFPageLabelDocumentHelper::Members::Members()
{
}
QPDFPageLabelDocumentHelper::QPDFPageLabelDocumentHelper(QPDF& qpdf) :
QPDFDocumentHelper(qpdf),
m(new Members())
{
QPDFObjectHandle root = qpdf.getRoot();
if (root.hasKey("/PageLabels"))
{
this->m->labels = new QPDFNumberTreeObjectHelper(
root.getKey("/PageLabels"), this->qpdf);
}
}
bool
QPDFPageLabelDocumentHelper::hasPageLabels()
{
return 0 != this->m->labels.get();
}
QPDFObjectHandle
QPDFPageLabelDocumentHelper::getLabelForPage(long long page_idx)
{
QPDFObjectHandle result(QPDFObjectHandle::newNull());
if (! hasPageLabels())
{
return result;
}
QPDFNumberTreeObjectHelper::numtree_number offset = 0;
QPDFObjectHandle label;
if (! this->m->labels->findObjectAtOrBelow(page_idx, label, offset))
{
return result;
}
if (! label.isDictionary())
{
return result;
}
QPDFObjectHandle S = label.getKey("/S"); // type (D, R, r, A, a)
QPDFObjectHandle P = label.getKey("/P"); // prefix
QPDFObjectHandle St = label.getKey("/St"); // starting number
long long start = 1;
if (St.isInteger())
{
start = St.getIntValue();
}
QIntC::range_check(start, offset);
start += offset;
result = QPDFObjectHandle::newDictionary();
result.replaceOrRemoveKey("/S", S);
result.replaceOrRemoveKey("/P", P);
result.replaceOrRemoveKey("/St", QPDFObjectHandle::newInteger(start));
return result;
}
void
QPDFPageLabelDocumentHelper::getLabelsForPageRange(
long long start_idx, long long end_idx, long long new_start_idx,
std::vector<QPDFObjectHandle>& new_labels)
{
// Start off with a suitable label for the first page. For every
// remaining page, if that page has an explicit entry, copy it.
// Otherwise, let the subsequent page just sequence from the prior
// entry. If there is no entry for the first page, fabricate one
// that would match how the page would look in a new file in which
// it also didn't have an explicit label.
QPDFObjectHandle label = getLabelForPage(start_idx);
if (label.isNull())
{
label = QPDFObjectHandle::newDictionary();
label.replaceKey(
"/St", QPDFObjectHandle::newInteger(1 + new_start_idx));
}
// See if the new label is redundant based on the previous entry
// in the vector. If so, don't add it.
size_t size = new_labels.size();
bool skip_first = false;
if (size >= 2)
{
QPDFObjectHandle last = new_labels.at(size - 1);
QPDFObjectHandle last_idx = new_labels.at(size - 2);
if (last_idx.isInteger() && last.isDictionary() &&
(label.getKey("/S").unparse() == last.getKey("/S").unparse()) &&
(label.getKey("/P").unparse() == last.getKey("/P").unparse()) &&
label.getKey("/St").isInteger() &&
last.getKey("/St").isInteger())
{
long long int st_delta =
label.getKey("/St").getIntValue() -
last.getKey("/St").getIntValue();
long long int idx_delta =
new_start_idx - last_idx.getIntValue();
if (st_delta == idx_delta)
{
QTC::TC("qpdf", "QPDFPageLabelDocumentHelper skip first");
skip_first = true;
}
}
}
if (! skip_first)
{
new_labels.push_back(QPDFObjectHandle::newInteger(new_start_idx));
new_labels.push_back(label);
}
long long int idx_offset = new_start_idx - start_idx;
for (long long i = start_idx + 1; i <= end_idx; ++i)
{
if (this->m->labels->hasIndex(i) &&
(label = getLabelForPage(i)).isDictionary())
{
new_labels.push_back(QPDFObjectHandle::newInteger(i + idx_offset));
new_labels.push_back(label);
}
}
}