Commit 8cb245739c76a1766473174500275d5d8b215d98

Authored by Jay Berkenbilt
1 parent 009767d9

Add QPDFObjectHandle::getUniqueResourceName

ChangeLog
1 2019-01-25 Jay Berkenbilt <ejb@ql.org> 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 * Add new method QPDFPageObjectHelper::getAttribute() that 7 * Add new method QPDFPageObjectHelper::getAttribute() that
4 properly handles inherited attributes and allows for creation of a 8 properly handles inherited attributes and allows for creation of a
5 copy of shared attributes. This is very useful if you are getting 9 copy of shared attributes. This is very useful if you are getting
include/qpdf/QPDFObjectHandle.hh
@@ -600,6 +600,18 @@ class QPDFObjectHandle @@ -600,6 +600,18 @@ class QPDFObjectHandle
600 QPDF_DLL 600 QPDF_DLL
601 std::set<std::string> getResourceNames(); 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 // Return the QPDF object that owns an indirect object. Returns 615 // Return the QPDF object that owns an indirect object. Returns
604 // null for a direct object. 616 // null for a direct object.
605 QPDF_DLL 617 QPDF_DLL
libqpdf/QPDFObjectHandle.cc
@@ -931,6 +931,30 @@ QPDFObjectHandle::getResourceNames() @@ -931,6 +931,30 @@ QPDFObjectHandle::getResourceNames()
931 return result; 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 // Indirect object accessors 958 // Indirect object accessors
935 QPDF* 959 QPDF*
936 QPDFObjectHandle::getOwningQPDF() 960 QPDFObjectHandle::getOwningQPDF()
libqpdf/QPDFPageDocumentHelper.cc
@@ -155,35 +155,15 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage( @@ -155,35 +155,15 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage(
155 { 155 {
156 QTC::TC("qpdf", "QPDFPageDocumentHelper non-widget annotation"); 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 std::string content = aoh.getPageContentForAppearance( 160 std::string content = aoh.getPageContentForAppearance(
179 name, rotate, required_flags, forbidden_flags); 161 name, rotate, required_flags, forbidden_flags);
180 if (! content.empty()) 162 if (! content.empty())
181 { 163 {
182 resources.mergeResources( 164 resources.mergeResources(
183 - QPDFObjectHandle::parse(  
184 - "<< /XObject << " + name + " null >> >>")); 165 + QPDFObjectHandle::parse("<< /XObject << >> >>"));
185 resources.getKey("/XObject").replaceKey(name, as); 166 resources.getKey("/XObject").replaceKey(name, as);
186 - names.insert(name);  
187 ++next_fx; 167 ++next_fx;
188 } 168 }
189 new_content += content; 169 new_content += content;