/// <summary>Transforms root tags in a way that complies with the tagged PDF specification.</summary> /// <remarks> /// Transforms root tags in a way that complies with the tagged PDF specification. /// Depending on PDF version behaviour may differ. /// <br /> /// ISO 32000-1 (PDF 1.7 and lower) /// 14.8.4.2 Grouping Elements /// <br /> /// "In a tagged PDF document, the structure tree shall contain a single top-level element; that is, /// the structure tree root (identified by the StructTreeRoot entry in the document catalogue) shall /// have only one child in its K (kids) array. If the PDF file contains a complete document, the structure /// type Document should be used for this top-level element in the logical structure hierarchy. If the file /// contains a well-formed document fragment, one of the structure types Part, Art, Sect, or Div may be used instead." /// <br /> /// For PDF 2.0 and higher root tag is allowed to have only the Document role. /// </remarks> public virtual void NormalizeDocumentRootTag() { // in this method we could deal with existing document, so we don't won't to throw exceptions here bool forbid = forbidUnknownRoles; forbidUnknownRoles = false; IList <IStructureNode> rootKids = document.GetStructTreeRoot().GetKids(); IRoleMappingResolver mapping = null; if (rootKids.Count > 0) { PdfStructElem firstKid = (PdfStructElem)rootKids[0]; mapping = ResolveMappingToStandardOrDomainSpecificRole(firstKid.GetRole().GetValue(), firstKid.GetNamespace ()); } if (rootKids.Count == 1 && mapping != null && mapping.CurrentRoleIsStandard() && IsRoleAllowedToBeRoot(mapping .GetRole())) { rootTagElement = (PdfStructElem)rootKids[0]; } else { document.GetStructTreeRoot().GetPdfObject().Remove(PdfName.K); rootTagElement = new RootTagNormalizer(this, rootTagElement, document).MakeSingleStandardRootTag(rootKids); } forbidUnknownRoles = forbid; }
private void SetNamespaceForNewTagsBasedOnExistingRoot() { IList <IStructureNode> rootKids = document.GetStructTreeRoot().GetKids(); if (rootKids.Count > 0) { PdfStructElem firstKid = (PdfStructElem)rootKids[0]; IRoleMappingResolver resolvedMapping = ResolveMappingToStandardOrDomainSpecificRole(firstKid.GetRole().GetValue (), firstKid.GetNamespace()); if (resolvedMapping == null || !resolvedMapping.CurrentRoleIsStandard()) { ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.Tagutils.TagStructureContext)); String nsStr; if (firstKid.GetNamespace() != null) { nsStr = firstKid.GetNamespace().GetNamespaceName(); } else { nsStr = StandardNamespaces.GetDefault(); } logger.Warn(String.Format(iText.IO.LogMessageConstant.EXISTING_TAG_STRUCTURE_ROOT_IS_NOT_STANDARD, firstKid .GetRole().GetValue(), nsStr)); } if (resolvedMapping == null || !StandardNamespaces.PDF_1_7.Equals(resolvedMapping.GetNamespace().GetNamespaceName ())) { documentDefaultNamespace = FetchNamespace(StandardNamespaces.PDF_2_0); } } else { documentDefaultNamespace = FetchNamespace(StandardNamespaces.PDF_2_0); } }
/// <summary> /// Gets an instance of the /// <see cref="IRoleMappingResolver"/> /// which is already in the "resolved" state: it returns /// role in the standard or domain-specific namespace for the /// <see cref="IRoleMappingResolver.GetRole()"/> /// and /// <see cref="IRoleMappingResolver.GetNamespace()"/> /// methods calls which correspond to the mapping of the given role; or null if the given role is not mapped to the standard or domain-specific one. /// </summary> /// <param name="role">a role in the given namespace which mapping is to be resolved.</param> /// <param name="namespace"> /// a /// <see cref="iText.Kernel.Pdf.Tagging.PdfNamespace"/> /// which this role belongs to. /// </param> /// <returns> /// an instance of the /// <see cref="IRoleMappingResolver"/> /// which returns false /// for the /// <see cref="IRoleMappingResolver.CurrentRoleShallBeMappedToStandard()"/> /// method call; if mapping cannot be resolved /// to this state, this method returns null, which means that the given role /// in the specified namespace is not mapped to the standard role in the standard namespace. /// </returns> public virtual IRoleMappingResolver ResolveMappingToStandardOrDomainSpecificRole(String role, PdfNamespace @namespace) { IRoleMappingResolver mappingResolver = GetRoleMappingResolver(role, @namespace); mappingResolver.ResolveNextMapping(); int i = 0; // reasonably large arbitrary number that will help to avoid a possible infinite loop int maxIters = 100; while (mappingResolver.CurrentRoleShallBeMappedToStandard()) { if (++i > maxIters) { ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.Tagutils.TagStructureContext)); logger.Error(ComposeTooMuchTransitiveMappingsException(role, @namespace)); return(null); } if (!mappingResolver.ResolveNextMapping()) { return(null); } } return(mappingResolver); }
public static PdfStructureAttributes GetLayoutAttributes(AbstractRenderer renderer, TagTreePointer taggingPointer ) { IRoleMappingResolver resolvedMapping = ResolveMappingToStandard(taggingPointer); if (resolvedMapping == null) { return(null); } String role = resolvedMapping.GetRole(); int tagType = AccessibleTypes.IdentifyType(role); PdfDictionary attributes = new PdfDictionary(); attributes.Put(PdfName.O, PdfName.Layout); //TODO WritingMode attribute applying when needed ApplyCommonLayoutAttributes(renderer, attributes); if (tagType == AccessibleTypes.BlockLevel) { ApplyBlockLevelLayoutAttributes(role, renderer, attributes); } if (tagType == AccessibleTypes.InlineLevel) { ApplyInlineLevelLayoutAttributes(renderer, attributes); } if (tagType == AccessibleTypes.Illustration) { ApplyIllustrationLayoutAttributes(renderer, attributes); } return(attributes.Size() > 1 ? new PdfStructureAttributes(attributes) : null); }
public static PdfStructureAttributes GetTableAttributes(AbstractRenderer renderer, TagTreePointer taggingPointer ) { IRoleMappingResolver resolvedMapping = ResolveMappingToStandard(taggingPointer); if (resolvedMapping == null || !StandardRoles.TD.Equals(resolvedMapping.GetRole()) && !StandardRoles.TH.Equals (resolvedMapping.GetRole())) { return(null); } PdfDictionary attributes = new PdfDictionary(); attributes.Put(PdfName.O, PdfName.Table); if (renderer.GetModelElement() is Cell) { Cell cell = (Cell)renderer.GetModelElement(); if (cell.GetRowspan() != 1) { attributes.Put(PdfName.RowSpan, new PdfNumber(cell.GetRowspan())); } if (cell.GetColspan() != 1) { attributes.Put(PdfName.ColSpan, new PdfNumber(cell.GetColspan())); } } return(attributes.Size() > 1 ? new PdfStructureAttributes(attributes) : null); }
public static PdfStructureAttributes GetListAttributes(AbstractRenderer renderer, TagTreePointer taggingPointer ) { IRoleMappingResolver resolvedMapping = null; resolvedMapping = ResolveMappingToStandard(taggingPointer); if (resolvedMapping == null || !StandardRoles.L.Equals(resolvedMapping.GetRole())) { return(null); } PdfDictionary attributes = new PdfDictionary(); attributes.Put(PdfName.O, PdfName.List); Object listSymbol = renderer.GetProperty <Object>(Property.LIST_SYMBOL); bool tagStructurePdf2 = IsTagStructurePdf2(resolvedMapping.GetNamespace()); if (listSymbol is ListNumberingType) { ListNumberingType numberingType = (ListNumberingType)listSymbol; attributes.Put(PdfName.ListNumbering, TransformNumberingTypeToName(numberingType, tagStructurePdf2)); } else { if (tagStructurePdf2) { if (listSymbol is IListSymbolFactory) { attributes.Put(PdfName.ListNumbering, PdfName.Ordered); } else { attributes.Put(PdfName.ListNumbering, PdfName.Unordered); } } } return(attributes.Size() > 1 ? new PdfStructureAttributes(attributes) : null); }
private void LogCreatedRootTagHasMappingIssue(PdfNamespace rootTagOriginalNs, IRoleMappingResolver mapping ) { String origRootTagNs = ""; if (rootTagOriginalNs != null && rootTagOriginalNs.GetNamespaceName() != null) { origRootTagNs = " in \"" + rootTagOriginalNs.GetNamespaceName() + "\" namespace"; } String mappingRole = " to "; if (mapping != null) { mappingRole += "\"" + mapping.GetRole() + "\""; if (mapping.GetNamespace() != null && !StandardNamespaces.PDF_1_7.Equals(mapping.GetNamespace().GetNamespaceName ())) { mappingRole += " in \"" + mapping.GetNamespace().GetNamespaceName() + "\" namespace"; } } else { mappingRole += "not standard role"; } ILog logger = LogManager.GetLogger(typeof(iText.Kernel.Pdf.Tagutils.RootTagNormalizer)); logger.Warn(String.Format(iText.IO.LogMessageConstant.CREATED_ROOT_TAG_HAS_MAPPING, origRootTagNs, mappingRole )); }