Add QPDFObjectHandle::getUniqueResourceName

This commit is contained in:
Jay Berkenbilt 2019-01-25 18:15:23 -05:00
parent 009767d97a
commit 8cb245739c
4 changed files with 43 additions and 23 deletions

View File

@ -1,5 +1,9 @@
2019-01-25 Jay Berkenbilt <ejb@ql.org>
* Add new method QPDFObjectHandle::getUniqueResourceName() to
return an unused key available to be used in a resource
dictionary.
* Add new method QPDFPageObjectHelper::getAttribute() that
properly handles inherited attributes and allows for creation of a
copy of shared attributes. This is very useful if you are getting

View File

@ -600,6 +600,18 @@ class QPDFObjectHandle
QPDF_DLL
std::set<std::string> getResourceNames();
// Find a unique name within a resource dictionary starting with a
// given prefix. This method works by appending a number to the
// given prefix. It searches starting with min_suffix and sets
// min_suffix to selected value upon return. This can be used to
// increase efficiency if adding multiple items with the same
// prefix. (Why doesn't it set min_suffix to the next number?
// Well, maybe you aren't going to actually use the name it
// returns.)
QPDF_DLL
std::string getUniqueResourceName(std::string const& prefix,
int& min_suffix);
// Return the QPDF object that owns an indirect object. Returns
// null for a direct object.
QPDF_DLL

View File

@ -931,6 +931,30 @@ QPDFObjectHandle::getResourceNames()
return result;
}
std::string
QPDFObjectHandle::getUniqueResourceName(std::string const& prefix,
int& min_suffix)
{
std::set<std::string> names = getResourceNames();
int max_suffix = min_suffix + names.size();
while (min_suffix <= max_suffix)
{
std::string candidate = prefix + QUtil::int_to_string(min_suffix);
if (names.count(candidate) == 0)
{
return candidate;
}
// Increment after return; min_suffix should be the value
// used, not the next value.
++min_suffix;
}
// This could only happen if there is a coding error.
// The number of candidates we test is more than the
// number of keys we're checking against.
throw std::logic_error("unable to find unconflicting name in"
" QPDFObjectHandle::getUniqueResourceName");
}
// Indirect object accessors
QPDF*
QPDFObjectHandle::getOwningQPDF()

View File

@ -155,35 +155,15 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage(
{
QTC::TC("qpdf", "QPDFPageDocumentHelper non-widget annotation");
}
std::set<std::string> names = resources.getResourceNames();
std::string name;
int max_fx = next_fx + names.size() + 1;
while (next_fx <= max_fx)
{
std::string candidate = "/Fxo" + QUtil::int_to_string(next_fx);
if (names.count(candidate) == 0)
{
name = candidate;
break;
}
++next_fx;
}
if (name.empty())
{
// This could only happen if there is a coding error.
// The number of candidates we test is more than the
// number of keys we're checking against.
name = "/FxConflict";
}
std::string name = resources.getUniqueResourceName(
"/Fxo", next_fx);
std::string content = aoh.getPageContentForAppearance(
name, rotate, required_flags, forbidden_flags);
if (! content.empty())
{
resources.mergeResources(
QPDFObjectHandle::parse(
"<< /XObject << " + name + " null >> >>"));
QPDFObjectHandle::parse("<< /XObject << >> >>"));
resources.getKey("/XObject").replaceKey(name, as);
names.insert(name);
++next_fx;
}
new_content += content;