/// <summary>Adds a new tag to the tag structure.</summary> /// <remarks> /// Adds a new tag to the tag structure. /// This method call moves this /// <c>TagTreePointer</c> /// to the added kid. /// <br/> /// New tag will have a role and attributes defined by the given IAccessibleElement. /// <br /><br /> /// If /// /// is true then a newly created tag will retain the connection with given /// accessible element. See /// <see cref="MoveToTag(IAccessibleElement)"/> /// for more explanations about tag connections concept. /// <br/><br/> /// If the same accessible element is connected to the tag and is added twice to the same parent - /// this /// <c>TagTreePointer</c> /// instance would move to connected kid instead of creating tag twice. /// But if it is added to some other parent, then connection will be removed. /// <p> /// <br/><br/> /// This call is equivalent of calling sequentially /// <see cref="SetNextNewKidIndex(int)"/> /// and /// <see cref="AddTag(IAccessibleElement, bool)"/> /// . /// </remarks> /// <param name="index">zero-based index in kids array of parent tag at which new tag will be added.</param> /// <param name="element">accessible element which represents a new tag.</param> /// <param name="keepConnectedToTag">defines if to retain the connection between accessible element and the tag. /// </param> /// <returns> /// this /// <see cref="TagTreePointer"/> /// instance. /// </returns> public virtual iText.Kernel.Pdf.Tagutils.TagTreePointer AddTag(int index, IAccessibleElement element, bool keepConnectedToTag) { tagStructureContext.ThrowExceptionIfRoleIsInvalid(element.GetRole()); if (!tagStructureContext.IsElementConnectedToTag(element)) { SetNextNewKidIndex(index); SetCurrentStructElem(AddNewKid(element, keepConnectedToTag)); } else { PdfStructElem connectedStruct = tagStructureContext.GetStructConnectedToModel(element); if (connectedStruct.GetParent() != null && GetCurrentStructElem().GetPdfObject() == ((PdfStructElem)connectedStruct .GetParent()).GetPdfObject()) { SetCurrentStructElem(connectedStruct); } else { tagStructureContext.RemoveElementConnectionToTag(element); SetNextNewKidIndex(index); SetCurrentStructElem(AddNewKid(element, keepConnectedToTag)); } } return(this); }
internal virtual iText.Kernel.Pdf.Tagutils.TagTreePointer SetCurrentStructElem(PdfStructElem structElem) { if (structElem.GetParent() == null) { throw new PdfException(PdfException.StructureElementShallContainParentObject); } currentStructElem = structElem; return(this); }
private void RemoveWaitingStateAndFlushIfParentFlushed(PdfStructElem structElem) { if (structElem != null) { waitingTagToAssociatedObj.JRemove(structElem.GetPdfObject()); IStructureNode parent = structElem.GetParent(); if (parent is PdfStructElem && ((PdfStructElem)parent).IsFlushed()) { FlushStructElementAndItKids(structElem); } } }
/// <returns>parent of the flushed tag</returns> internal virtual IStructureNode FlushTag(PdfStructElem tagStruct) { Object associatedObj = waitingTagToAssociatedObj.JRemove(tagStruct.GetPdfObject()); if (associatedObj != null) { associatedObjToWaitingTag.JRemove(associatedObj); } IStructureNode parent = tagStruct.GetParent(); FlushStructElementAndItKids(tagStruct); return(parent); }
/// <returns>parent of the flushed tag</returns> internal virtual IPdfStructElem FlushTag(PdfStructElem tagStruct) { IAccessibleElement modelElement = connectedStructToModel.JRemove(tagStruct.GetPdfObject()); if (modelElement != null) { connectedModelToStruct.JRemove(modelElement); } IPdfStructElem parent = tagStruct.GetParent(); FlushStructElementAndItKids(tagStruct); return(parent); }
private void RemoveStructToModelConnection(PdfStructElem structElem) { if (structElem != null) { IAccessibleElement element = connectedStructToModel.JRemove(structElem.GetPdfObject()); structElem.SetRole(element.GetRole()); if (element.GetAccessibilityProperties() != null) { element.GetAccessibilityProperties().SetToStructElem(structElem); } if (structElem.GetParent() == null) { // is flushed FlushStructElementAndItKids(structElem); } } }
/// <summary>Removes the current tag.</summary> /// <remarks> /// Removes the current tag. If it has kids, they will become kids of the current tag parent. /// This method call moves this /// <c>TagTreePointer</c> /// to the current tag parent. /// <br /><br /> /// You cannot remove root tag, and also you cannot remove the tag if it's parent is already flushed; /// in this two cases an exception will be thrown. /// </remarks> /// <returns> /// this /// <see cref="TagStructureContext"/> /// instance. /// </returns> public virtual iText.Kernel.Pdf.Tagutils.TagTreePointer RemoveTag() { PdfStructElem currentStructElem = GetCurrentStructElem(); IStructureNode parentElem = currentStructElem.GetParent(); if (parentElem is PdfStructTreeRoot) { throw new PdfException(PdfException.CannotRemoveDocumentRootTag); } IList <IStructureNode> kids = currentStructElem.GetKids(); PdfStructElem parent = (PdfStructElem)parentElem; if (parent.IsFlushed()) { throw new PdfException(PdfException.CannotRemoveTagBecauseItsParentIsFlushed); } // remove waiting tag state if tag is removed Object objForStructDict = tagStructureContext.GetWaitingTagsManager().GetObjForStructDict(currentStructElem .GetPdfObject()); tagStructureContext.GetWaitingTagsManager().RemoveWaitingState(objForStructDict); int removedKidIndex = parent.RemoveKid(currentStructElem); PdfIndirectReference indRef = currentStructElem.GetPdfObject().GetIndirectReference(); if (indRef != null) { // TODO how about possible references to structure element from refs or structure destination for instance? indRef.SetFree(); } foreach (IStructureNode kid in kids) { if (kid is PdfStructElem) { parent.AddKid(removedKidIndex++, (PdfStructElem)kid); } else { PdfMcr mcr = PrepareMcrForMovingToNewParent((PdfMcr)kid, parent); parent.AddKid(removedKidIndex++, mcr); } } currentStructElem.GetPdfObject().Clear(); SetCurrentStructElem(parent); return(this); }
// it is StructTreeRoot // should never happen as we always should have only one root tag and we don't remove it private void FlushParentIfBelongsToPage(PdfStructElem parent, PdfPage currentPage) { if (parent.IsFlushed() || connectedStructToModel.ContainsKey(parent.GetPdfObject()) || parent.GetPdfObject () == rootTagElement.GetPdfObject()) { return; } IList <IPdfStructElem> kids = parent.GetKids(); bool allKidsBelongToPage = true; foreach (IPdfStructElem kid in kids) { if (kid is PdfMcr) { PdfDictionary kidPage = ((PdfMcr)kid).GetPageObject(); if (!kidPage.IsFlushed() && !kidPage.Equals(currentPage.GetPdfObject())) { allKidsBelongToPage = false; break; } } else { if (kid is PdfStructElem) { // If kid is structElem and was already flushed then in kids list there will be null for it instead of // PdfStructElem. And therefore if we get into this if clause it means that some StructElem wasn't flushed. allKidsBelongToPage = false; break; } } } if (allKidsBelongToPage) { IPdfStructElem parentsParent = parent.GetParent(); parent.Flush(); if (parentsParent is PdfStructElem) { FlushParentIfBelongsToPage((PdfStructElem)parentsParent, currentPage); } } return; }
internal virtual void FlushParentIfBelongsToPage(PdfStructElem parent, PdfPage currentPage) { if (parent.IsFlushed() || waitingTagsManager.GetObjForStructDict(parent.GetPdfObject()) != null || parent. GetParent() is PdfStructTreeRoot) { return; } IList <IStructureNode> kids = parent.GetKids(); bool readyToBeFlushed = true; foreach (IStructureNode kid in kids) { if (kid is PdfMcr) { PdfDictionary kidPage = ((PdfMcr)kid).GetPageObject(); if (!kidPage.IsFlushed() && (currentPage == null || !kidPage.Equals(currentPage.GetPdfObject()))) { readyToBeFlushed = false; break; } } else { if (kid is PdfStructElem) { // If kid is structElem and was already flushed then in kids list there will be null for it instead of // PdfStructElement. And therefore if we get into this if-clause it means that some StructElem wasn't flushed. readyToBeFlushed = false; break; } } } if (readyToBeFlushed) { IStructureNode parentsParent = parent.GetParent(); parent.Flush(); if (parentsParent is PdfStructElem) { FlushParentIfBelongsToPage((PdfStructElem)parentsParent, currentPage); } } }
private void RemovePageTagFromParent(IStructureNode pageTag, IStructureNode parent) { if (parent is PdfStructElem) { PdfStructElem structParent = (PdfStructElem)parent; if (!structParent.IsFlushed()) { structParent.RemoveKid(pageTag); PdfDictionary parentStructDict = structParent.GetPdfObject(); if (waitingTagsManager.GetObjForStructDict(parentStructDict) == null && parent.GetKids().Count == 0 && !(structParent .GetParent() is PdfStructTreeRoot)) { RemovePageTagFromParent(structParent, parent.GetParent()); PdfIndirectReference indRef = parentStructDict.GetIndirectReference(); if (indRef != null) { // TODO how about possible references to structure element from refs or structure destination for instance? indRef.SetFree(); } } } else { if (pageTag is PdfMcr) { throw new PdfException(PdfException.CannotRemoveTagBecauseItsParentIsFlushed); } } } }