Skip to content

Commit 85a914a

Browse files
Merge branch 'layout_tagging_helper' into 7.1
2 parents adfb79f + 9c50f4d commit 85a914a

File tree

124 files changed

+1462
-373
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

124 files changed

+1462
-373
lines changed

io/src/main/java/com/itextpdf/io/LogMessageConstant.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,23 @@ This file is part of the iText (R) project.
4949
public final class LogMessageConstant {
5050

5151
public static final String ACTION_WAS_SET_TO_LINK_ANNOTATION_WITH_DESTINATION = "Action was set for a link annotation containing destination. The old destination will be cleared.";
52-
public static final String ASSOCIATED_FILE_SPEC_SHALL_INCLUDE_AFRELATIONSHIP = "For associated files their associated file specification dictionaries shall include the AFRelationship key.";
5352
public static final String ALREADY_FLUSHED_INDIRECT_OBJECT_MADE_FREE = "An attempt is made to free already flushed indirect object reference. Indirect reference wasn't freed.";
53+
public static final String ALREADY_TAGGED_HINT_MARKED_ARTIFACT = "A layout tagging hint for which an actual tag was already created in tags structure is marked as artifact. Existing tag will be left in the tags tree.";
54+
public static final String ASSOCIATED_FILE_SPEC_SHALL_INCLUDE_AFRELATIONSHIP = "For associated files their associated file specification dictionaries shall include the AFRelationship key.";
55+
public static final String ATTEMPT_TO_CREATE_A_TAG_FOR_FINISHED_HINT = "Attempt to create a tag for a hint which is already marked as finished, tag will not be created.";
5456
public static final String ATTEMPT_TO_MOVE_TO_FLUSHED_PARENT = "An attempt is made to move the tag tree pointer to the tag parent which has been already flushed. Tag tree pointer is moved to the root tag instead.";
5557
public static final String CALCULATE_HASHCODE_FOR_MODIFIED_PDFNUMBER = "Calculate hashcode for modified PdfNumber.";
58+
public static final String CANNOT_ADD_FINISHED_HINT_AS_A_NEW_KID_HINT = "Layout tagging hints addition failed: cannot add a hint that is already marked as finished. Consider using com.itextpdf.layout.tagging.LayoutTaggingHelper#moveKidHint method for moving already finished kid hint from not yet finished parent hint.";
59+
public static final String CANNOT_ADD_HINTS_TO_FINISHED_PARENT = "Layout tagging hints addition failed: cannot add new kid hints to a parent which hint is already marked as finished. Consider using com.itextpdf.layout.tagging.LayoutTaggingHelper#replaceKidHint method for replacing not yet finished kid hint of a finished parent hint.";
60+
public static final String CANNOT_ADD_KID_HINT_WHICH_IS_ALREADY_ADDED_TO_ANOTHER_PARENT = "Layout tagging hints addition failed: cannot add a kid hint to a new parent if it is already added to another parent. Consider using com.itextpdf.layout.tagging.LayoutTaggingHelper#moveHint method instead.";
61+
public static final String CANNOT_MOVE_FINISHED_HINT = "Layout tagging hints modification failed: cannot move kid hint for which both itself and it's parent are already marked as finished.";
62+
public static final String CANNOT_MOVE_HINT_TO_FINISHED_PARENT = "Layout tagging hints modification failed: cannot move kid hint to a parent that is already marked as finished.";
63+
public static final String CANNOT_REPLACE_FINISHED_HINT = "Layout tagging hints modification failed: cannot replace a kid hint that is already marked as finished.";
5664
public static final String CANNOT_RESOLVE_ROLE_IN_NAMESPACE_TOO_MUCH_TRANSITIVE_MAPPINGS = "Cannot resolve \"{0}\" role in {1} namespace mapping to standard role, because of the too much transitive mappings.";
5765
public static final String CANNOT_RESOLVE_ROLE_TOO_MUCH_TRANSITIVE_MAPPINGS = "Cannot resolve \"{0}\" role mapping to standard role, because of the too much transitive mappings.";
5866
public static final String CLIP_ELEMENT = "Element content was clipped because some height properties are set.";
59-
public static final String COLOR_ALPHA_CHANNEL_IS_IGNORED = "Alpha channel {0} was ignored during color creation. Note that opacity can be achieved in some places by using 'setOpacity' method or 'TransparentColor' class";
6067
public static final String COLORANT_INTENSITIES_INVALID = "Some of colorant intensities are invalid: they are bigger than 1 or less than 0. We will force them to become 1 or 0 respectively.";
68+
public static final String COLOR_ALPHA_CHANNEL_IS_IGNORED = "Alpha channel {0} was ignored during color creation. Note that opacity can be achieved in some places by using 'setOpacity' method or 'TransparentColor' class";
6169
public static final String COLOR_NOT_PARSED = "Color \"{0}\" was not parsed. It has invalid value. Defaulting to black color.";
6270
public static final String COULD_NOT_FIND_GLYPH_WITH_CODE = "Could not find glyph with the following code: {0}";
6371
public static final String CREATED_ROOT_TAG_HAS_MAPPING = "Created root tag has role mapping: \"/Document\" role{0} is mapped{1}. Resulting tag structure might have invalid root tag.";
@@ -127,6 +135,7 @@ public final class LogMessageConstant {
127135
public static final String STRUCTURE_ELEMENT_REPLACED_BY_ITS_ID_IN_STRUCTURE_DESTINATION = "Structure destinations shall specify structure element ID in remote go-to actions. Structure element has been replaced with its ID in the structure destination";
128136
public static final String SUM_OF_TABLE_COLUMNS_IS_GREATER_THAN_100 = "Sum of table columns is greater than 100%.";
129137
public static final String TABLE_WIDTH_IS_MORE_THAN_EXPECTED_DUE_TO_MIN_WIDTH = "Table width is more than expected due to min width of cell(s).";
138+
public static final String TAGGING_HINT_NOT_FINISHED_BEFORE_CLOSE = "Tagging hint wasn't finished before closing.";
130139
public static final String TAG_STRUCTURE_CONTEXT_WILL_BE_REINITIALIZED_ON_SERIALIZATION = "Tag structure context is not null and will be reinitialized in the copy of document. The copy may lose some data";
131140
public static final String TAG_STRUCTURE_INIT_FAILED = "Tag structure initialization failed, tag structure is ignored, it might be corrupted.";
132141
public static final String TYPE3_FONT_CANNOT_BE_ADDED = "Type 3 font cannot be added to FontSet. Custom FontProvider class may be created for this purpose.";

kernel/src/main/java/com/itextpdf/kernel/PdfException.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ public class PdfException extends RuntimeException {
106106
public static final String CannotReadAStreamInOrderToAppendNewBytes = "Cannot read a stream in order to append new bytes.";
107107
public static final String CannotReadPdfObject = "Cannot read PdfObject.";
108108
public static final String CannotRecogniseDocumentFontWithEncoding = "Cannot recognise document font {0} with {1} encoding";
109+
public static final String CannotRelocateRootTag = "Cannot relocate root tag.";
110+
public static final String CannotRelocateTagWhichIsAlreadyFlushed = "Cannot relocate tag which is already flushed.";
111+
public static final String CannotRelocateTagWhichParentIsAlreadyFlushed = "Cannot relocate tag which parent is already flushed.";
109112
public static final String CannotRemoveDocumentRootTag = "Cannot remove document root tag.";
110113
public static final String CannotRemoveMarkedContentReferenceBecauseItsPageWasAlreadyFlushed = "Cannot remove marked content reference, because its page has been already flushed.";
111114
public static final String CannotRemoveTagBecauseItsParentIsFlushed = "Cannot remove tag, because its parent is flushed.";

kernel/src/main/java/com/itextpdf/kernel/pdf/tagutils/TagStructureContext.java

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,38 @@ boolean targetTagStructureVersionIs2() {
528528
return PdfVersion.PDF_2_0.compareTo(tagStructureTargetVersion) <= 0;
529529
}
530530

531+
void flushParentIfBelongsToPage(PdfStructElem parent, PdfPage currentPage) {
532+
if (parent.isFlushed() || waitingTagsManager.getObjForStructDict(parent.getPdfObject()) != null
533+
|| parent.getPdfObject() == getRootTag().getPdfObject()) {
534+
return;
535+
}
536+
537+
List<IStructureNode> kids = parent.getKids();
538+
boolean readyToBeFlushed = true;
539+
for (IStructureNode kid : kids) {
540+
if (kid instanceof PdfMcr) {
541+
PdfDictionary kidPage = ((PdfMcr) kid).getPageObject();
542+
if (!kidPage.isFlushed() && (currentPage == null || !kidPage.equals(currentPage.getPdfObject()))) {
543+
readyToBeFlushed = false;
544+
break;
545+
}
546+
} else if (kid instanceof PdfStructElem) {
547+
// If kid is structElem and was already flushed then in kids list there will be null for it instead of
548+
// PdfStructElement. And therefore if we get into this if-clause it means that some StructElem wasn't flushed.
549+
readyToBeFlushed = false;
550+
break;
551+
}
552+
}
553+
554+
if (readyToBeFlushed) {
555+
IStructureNode parentsParent = parent.getParent();
556+
parent.flush();
557+
if (parentsParent instanceof PdfStructElem) {
558+
flushParentIfBelongsToPage((PdfStructElem)parentsParent, currentPage);
559+
}
560+
}
561+
}
562+
531563
private boolean isRoleAllowedToBeRoot(PdfName role) {
532564
if (targetTagStructureVersionIs2()) {
533565
return PdfName.Document.equals(role);
@@ -622,40 +654,6 @@ private void removePageTagFromParent(IStructureNode pageTag, IStructureNode pare
622654
}
623655
}
624656

625-
private void flushParentIfBelongsToPage(PdfStructElem parent, PdfPage currentPage) {
626-
if (parent.isFlushed() || waitingTagsManager.getObjForStructDict(parent.getPdfObject()) != null
627-
|| parent.getPdfObject() == getRootTag().getPdfObject()) {
628-
return;
629-
}
630-
631-
List<IStructureNode> kids = parent.getKids();
632-
boolean allKidsBelongToPage = true;
633-
for (IStructureNode kid : kids) {
634-
if (kid instanceof PdfMcr) {
635-
PdfDictionary kidPage = ((PdfMcr) kid).getPageObject();
636-
if (!kidPage.isFlushed() && !kidPage.equals(currentPage.getPdfObject())) {
637-
allKidsBelongToPage = false;
638-
break;
639-
}
640-
} else if (kid instanceof PdfStructElem) {
641-
// If kid is structElem and was already flushed then in kids list there will be null for it instead of
642-
// PdfStructElement. And therefore if we get into this if-clause it means that some StructElem wasn't flushed.
643-
allKidsBelongToPage = false;
644-
break;
645-
}
646-
}
647-
648-
if (allKidsBelongToPage) {
649-
IStructureNode parentsParent = parent.getParent();
650-
parent.flush();
651-
if (parentsParent instanceof PdfStructElem) {
652-
flushParentIfBelongsToPage((PdfStructElem)parentsParent, currentPage);
653-
}
654-
}
655-
656-
return;
657-
}
658-
659657
private String composeExceptionBasedOnNamespacePresence(String role, PdfNamespace namespace, String withoutNsEx, String withNsEx) {
660658
if (namespace == null) {
661659
return MessageFormat.format(withoutNsEx, role);

0 commit comments

Comments
 (0)