Commit 8cb245739c76a1766473174500275d5d8b215d98

Authored by Jay Berkenbilt
1 parent 009767d9

Add QPDFObjectHandle::getUniqueResourceName

ChangeLog
1 1 2019-01-25 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Add new method QPDFObjectHandle::getUniqueResourceName() to
  4 + return an unused key available to be used in a resource
  5 + dictionary.
  6 +
3 7 * Add new method QPDFPageObjectHelper::getAttribute() that
4 8 properly handles inherited attributes and allows for creation of a
5 9 copy of shared attributes. This is very useful if you are getting
... ...
include/qpdf/QPDFObjectHandle.hh
... ... @@ -600,6 +600,18 @@ class QPDFObjectHandle
600 600 QPDF_DLL
601 601 std::set<std::string> getResourceNames();
602 602  
  603 + // Find a unique name within a resource dictionary starting with a
  604 + // given prefix. This method works by appending a number to the
  605 + // given prefix. It searches starting with min_suffix and sets
  606 + // min_suffix to selected value upon return. This can be used to
  607 + // increase efficiency if adding multiple items with the same
  608 + // prefix. (Why doesn't it set min_suffix to the next number?
  609 + // Well, maybe you aren't going to actually use the name it
  610 + // returns.)
  611 + QPDF_DLL
  612 + std::string getUniqueResourceName(std::string const& prefix,
  613 + int& min_suffix);
  614 +
603 615 // Return the QPDF object that owns an indirect object. Returns
604 616 // null for a direct object.
605 617 QPDF_DLL
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -931,6 +931,30 @@ QPDFObjectHandle::getResourceNames()
931 931 return result;
932 932 }
933 933  
  934 +std::string
  935 +QPDFObjectHandle::getUniqueResourceName(std::string const& prefix,
  936 + int& min_suffix)
  937 +{
  938 + std::set<std::string> names = getResourceNames();
  939 + int max_suffix = min_suffix + names.size();
  940 + while (min_suffix <= max_suffix)
  941 + {
  942 + std::string candidate = prefix + QUtil::int_to_string(min_suffix);
  943 + if (names.count(candidate) == 0)
  944 + {
  945 + return candidate;
  946 + }
  947 + // Increment after return; min_suffix should be the value
  948 + // used, not the next value.
  949 + ++min_suffix;
  950 + }
  951 + // This could only happen if there is a coding error.
  952 + // The number of candidates we test is more than the
  953 + // number of keys we're checking against.
  954 + throw std::logic_error("unable to find unconflicting name in"
  955 + " QPDFObjectHandle::getUniqueResourceName");
  956 +}
  957 +
934 958 // Indirect object accessors
935 959 QPDF*
936 960 QPDFObjectHandle::getOwningQPDF()
... ...
libqpdf/QPDFPageDocumentHelper.cc
... ... @@ -155,35 +155,15 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage(
155 155 {
156 156 QTC::TC("qpdf", "QPDFPageDocumentHelper non-widget annotation");
157 157 }
158   - std::set<std::string> names = resources.getResourceNames();
159   - std::string name;
160   - int max_fx = next_fx + names.size() + 1;
161   - while (next_fx <= max_fx)
162   - {
163   - std::string candidate = "/Fxo" + QUtil::int_to_string(next_fx);
164   - if (names.count(candidate) == 0)
165   - {
166   - name = candidate;
167   - break;
168   - }
169   - ++next_fx;
170   - }
171   - if (name.empty())
172   - {
173   - // This could only happen if there is a coding error.
174   - // The number of candidates we test is more than the
175   - // number of keys we're checking against.
176   - name = "/FxConflict";
177   - }
  158 + std::string name = resources.getUniqueResourceName(
  159 + "/Fxo", next_fx);
178 160 std::string content = aoh.getPageContentForAppearance(
179 161 name, rotate, required_flags, forbidden_flags);
180 162 if (! content.empty())
181 163 {
182 164 resources.mergeResources(
183   - QPDFObjectHandle::parse(
184   - "<< /XObject << " + name + " null >> >>"));
  165 + QPDFObjectHandle::parse("<< /XObject << >> >>"));
185 166 resources.getKey("/XObject").replaceKey(name, as);
186   - names.insert(name);
187 167 ++next_fx;
188 168 }
189 169 new_content += content;
... ...