Commit 8cb245739c76a1766473174500275d5d8b215d98
1 parent
009767d9
Add QPDFObjectHandle::getUniqueResourceName
Showing
4 changed files
with
43 additions
and
23 deletions
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; | ... | ... |