Commit 4489c4bcc59af95f88f88776134bd1bbfd98fd1e

Authored by m-holger
1 parent f9287c41

Refactor `QPDFAcroFormDocumentHelper`: replace `std::list<QPDFObjectHandle>` wit…

…h `std::list<Dictionary>`, simplify `/Kids` handling, and update method calls for consistency.
libqpdf/QPDFAcroFormDocumentHelper.cc
... ... @@ -480,6 +480,9 @@ QPDFAcroFormDocumentHelper::adjustInheritedFields(
480 480 bool override_q,
481 481 int from_default_q)
482 482 {
  483 + if (!(override_da || override_q)) {
  484 + return;
  485 + }
483 486 // Override /Q or /DA if needed. If this object has a field type, directly or inherited, it is a
484 487 // field and not just an annotation. In that case, we need to override if we are getting a value
485 488 // from the document that is different from the value we would have gotten from the old
... ... @@ -892,65 +895,60 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
892 895 }
893 896  
894 897 // Traverse the field, copying kids, and preserving integrity.
895   - std::list<QPDFObjectHandle> queue;
896   - QPDFObjGen::set seen;
897 898 if (maybe_copy_object(top_field)) {
  899 + std::list<Dictionary> queue;
  900 + QPDFObjGen::set seen;
898 901 queue.emplace_back(top_field);
899   - }
900   - for (; !queue.empty(); queue.pop_front()) {
901   - auto& obj = queue.front();
902   - if (seen.add(obj)) {
903   - auto parent = obj["/Parent"];
904   - if (parent.isIndirect()) {
905   - auto parent_og = parent.getObjGen();
906   - if (orig_to_copy.contains(parent_og)) {
907   - obj.replaceKey("/Parent", orig_to_copy[parent_og]);
908   - } else {
909   - parent.warn(
910   - "while traversing field " + obj.getObjGen().unparse(',') +
911   - ", found parent (" + parent_og.unparse(',') +
912   - ") that had not been seen, indicating likely invalid field structure");
  902 + for (; !queue.empty(); queue.pop_front()) {
  903 + auto& obj = queue.front();
  904 + if (seen.add(obj)) {
  905 + auto parent = obj["/Parent"];
  906 + if (parent.isIndirect()) {
  907 + auto parent_og = parent.id_gen();
  908 + if (orig_to_copy.contains(parent_og)) {
  909 + obj.replaceKey("/Parent", orig_to_copy[parent_og]);
  910 + } else {
  911 + parent.warn(
  912 + "while traversing field " + obj.id_gen().unparse(',') +
  913 + ", found parent (" + parent_og.unparse(',') +
  914 + ") that had not been seen, indicating likely invalid field "
  915 + "structure");
  916 + }
913 917 }
914   - }
915   - auto kids = obj["/Kids"];
916   - int sz = static_cast<int>(kids.size());
917   - if (sz != 1 || kids.isArray()) {
918   - for (int i = 0; i < sz; ++i) {
919   - auto kid = kids.getArrayItem(i);
  918 + size_t i = 0;
  919 + Array Kids = obj["/Kids"];
  920 + for (auto& kid: Kids) {
920 921 if (maybe_copy_object(kid)) {
921   - kids.setArrayItem(i, kid);
  922 + Kids.set(i, kid);
922 923 queue.emplace_back(kid);
923 924 }
  925 + ++i;
924 926 }
925   - }
926   -
927   - if (override_da || override_q) {
928 927 adjustInheritedFields(
929 928 obj, override_da, from_default_da, override_q, from_default_q);
930   - }
931   - if (foreign) {
932   - // Lazily initialize our /DR and the conflict map.
933   - init_dr_map();
934   - // The spec doesn't say anything about /DR on the field, but lots of writers
935   - // put one there, and it is frequently the same as the document-level /DR.
936   - // To avoid having the field's /DR point to information that we are not
937   - // maintaining, just reset it to that if it exists. Empirical evidence
938   - // suggests that many readers, including Acrobat, Adobe Acrobat Reader,
939   - // chrome, firefox, the mac Preview application, and several of the free
940   - // readers on Linux all ignore /DR at the field level.
941   - if (obj.hasKey("/DR")) {
942   - obj.replaceKey("/DR", dr);
  929 + if (foreign) {
  930 + // Lazily initialize our /DR and the conflict map.
  931 + init_dr_map();
  932 + // The spec doesn't say anything about /DR on the field, but lots of writers
  933 + // put one there, and it is frequently the same as the document-level /DR.
  934 + // To avoid having the field's /DR point to information that we are not
  935 + // maintaining, just reset it to that if it exists. Empirical evidence
  936 + // suggests that many readers, including Acrobat, Adobe Acrobat Reader,
  937 + // chrome, firefox, the mac Preview application, and several of the free
  938 + // readers on Linux all ignore /DR at the field level.
  939 + if (obj.contains("/DR")) {
  940 + obj.replaceKey("/DR", dr);
  941 + }
  942 + if (obj["/DA"].isString() && !dr_map.empty()) {
  943 + adjustDefaultAppearances(obj, dr_map);
  944 + }
943 945 }
944 946 }
945   - if (foreign && obj["/DA"].isString() && !dr_map.empty()) {
946   - adjustDefaultAppearances(obj, dr_map);
947   - }
948 947 }
949 948 }
950 949  
951 950 // Now switch to copies. We already switched for top_field
952 951 maybe_copy_object(ffield_oh);
953   - ffield = QPDFFormFieldObjectHelper(ffield_oh);
954 952 return {top_field, true, have_parent};
955 953 };
956 954  
... ...