public override void Draw(DrawContext drawContext) { if (occupiedArea == null) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ListItemRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.OCCUPIED_AREA_HAS_NOT_BEEN_INITIALIZED, "Drawing won't be performed.")); return; } if (drawContext.IsTaggingEnabled()) { LayoutTaggingHelper taggingHelper = this.GetProperty <LayoutTaggingHelper>(Property.TAGGING_HELPER); if (taggingHelper != null) { if (symbolRenderer != null) { LayoutTaggingHelper.AddTreeHints(taggingHelper, symbolRenderer); } if (taggingHelper.IsArtifact(this)) { taggingHelper.MarkArtifactHint(symbolRenderer); } else { TaggingHintKey hintKey = LayoutTaggingHelper.GetHintKey(this); TaggingHintKey parentHint = taggingHelper.GetAccessibleParentHint(hintKey); if (parentHint != null && !(StandardRoles.LI.Equals(parentHint.GetAccessibleElement().GetAccessibilityProperties ().GetRole()))) { TaggingDummyElement listItemIntermediate = new TaggingDummyElement(StandardRoles.LI); IList <TaggingHintKey> intermediateKid = JavaCollectionsUtil.SingletonList <TaggingHintKey>(LayoutTaggingHelper .GetOrCreateHintKey(listItemIntermediate)); taggingHelper.ReplaceKidHint(hintKey, intermediateKid); if (symbolRenderer != null) { taggingHelper.AddKidsHint(listItemIntermediate, JavaCollectionsUtil.SingletonList <IRenderer>(symbolRenderer )); } taggingHelper.AddKidsHint(listItemIntermediate, JavaCollectionsUtil.SingletonList <IRenderer>(this)); } } } } base.Draw(drawContext); // It will be null in case of overflow (only the "split" part will contain symbol renderer. if (symbolRenderer != null && !symbolAddedInside) { bool isRtl = BaseDirection.RIGHT_TO_LEFT.Equals(this.GetProperty <BaseDirection?>(Property.BASE_DIRECTION)); symbolRenderer.SetParent(this); float x = isRtl ? occupiedArea.GetBBox().GetRight() : occupiedArea.GetBBox().GetLeft(); ListSymbolPosition symbolPosition = (ListSymbolPosition)ListRenderer.GetListItemOrListProperty(this, parent , Property.LIST_SYMBOL_POSITION); if (symbolPosition != ListSymbolPosition.DEFAULT) { float?symbolIndent = this.GetPropertyAsFloat(Property.LIST_SYMBOL_INDENT); if (isRtl) { x += (symbolAreaWidth + (float)(symbolIndent == null ? 0 : symbolIndent)); } else { x -= (symbolAreaWidth + (float)(symbolIndent == null ? 0 : symbolIndent)); } if (symbolPosition == ListSymbolPosition.OUTSIDE) { if (isRtl) { UnitValue marginRightUV = this.GetPropertyAsUnitValue(Property.MARGIN_RIGHT); if (!marginRightUV.IsPointValue()) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ListItemRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property .MARGIN_RIGHT)); } x -= marginRightUV.GetValue(); } else { UnitValue marginLeftUV = this.GetPropertyAsUnitValue(Property.MARGIN_LEFT); if (!marginLeftUV.IsPointValue()) { ILog logger = LogManager.GetLogger(typeof(iText.Layout.Renderer.ListItemRenderer)); logger.Error(MessageFormatUtil.Format(iText.IO.LogMessageConstant.PROPERTY_IN_PERCENTS_NOT_SUPPORTED, Property .MARGIN_LEFT)); } x += marginLeftUV.GetValue(); } } } ApplyMargins(occupiedArea.GetBBox(), false); ApplyBorderBox(occupiedArea.GetBBox(), false); if (childRenderers.Count > 0) { float?yLine = null; for (int i = 0; i < childRenderers.Count; i++) { if (childRenderers[i].GetOccupiedArea().GetBBox().GetHeight() > 0) { yLine = ((AbstractRenderer)childRenderers[i]).GetFirstYLineRecursively(); if (yLine != null) { break; } } } if (yLine != null) { if (symbolRenderer is LineRenderer) { symbolRenderer.Move(0, (float)yLine - ((LineRenderer)symbolRenderer).GetYLine()); } else { symbolRenderer.Move(0, (float)yLine - symbolRenderer.GetOccupiedArea().GetBBox().GetY()); } } else { symbolRenderer.Move(0, occupiedArea.GetBBox().GetY() + occupiedArea.GetBBox().GetHeight() - (symbolRenderer .GetOccupiedArea().GetBBox().GetY() + symbolRenderer.GetOccupiedArea().GetBBox().GetHeight())); } } else { if (symbolRenderer is TextRenderer) { ((TextRenderer)symbolRenderer).MoveYLineTo(occupiedArea.GetBBox().GetY() + occupiedArea.GetBBox().GetHeight () - CalculateAscenderDescender()[0]); } else { symbolRenderer.Move(0, occupiedArea.GetBBox().GetY() + occupiedArea.GetBBox().GetHeight() - symbolRenderer .GetOccupiedArea().GetBBox().GetHeight() - symbolRenderer.GetOccupiedArea().GetBBox().GetY()); } } ApplyBorderBox(occupiedArea.GetBBox(), true); ApplyMargins(occupiedArea.GetBBox(), true); ListSymbolAlignment listSymbolAlignment = (ListSymbolAlignment)parent.GetProperty <ListSymbolAlignment?>(Property .LIST_SYMBOL_ALIGNMENT, isRtl ? ListSymbolAlignment.LEFT : ListSymbolAlignment.RIGHT); float dxPosition = x - symbolRenderer.GetOccupiedArea().GetBBox().GetX(); if (listSymbolAlignment == ListSymbolAlignment.RIGHT) { if (!isRtl) { dxPosition += symbolAreaWidth - symbolRenderer.GetOccupiedArea().GetBBox().GetWidth(); } } else { if (listSymbolAlignment == ListSymbolAlignment.LEFT) { if (isRtl) { dxPosition -= (symbolAreaWidth - symbolRenderer.GetOccupiedArea().GetBBox().GetWidth()); } } } if (symbolRenderer is LineRenderer) { if (isRtl) { symbolRenderer.Move(dxPosition - symbolRenderer.GetOccupiedArea().GetBBox().GetWidth(), 0); } else { symbolRenderer.Move(dxPosition, 0); } } else { symbolRenderer.Move(dxPosition, 0); } if (symbolRenderer.GetOccupiedArea().GetBBox().GetRight() > parent.GetOccupiedArea().GetBBox().GetLeft()) { BeginElementOpacityApplying(drawContext); symbolRenderer.Draw(drawContext); EndElementOpacityApplying(drawContext); } } }
protected void ManipulatePdf(String dest) { PdfDocument pdfDocument = new PdfDocument(new PdfWriter(dest)); pdfDocument.SetTagged(); Document doc = new Document(pdfDocument); Table table = new Table(UnitValue.CreatePercentArray(3)).UseAllAvailableWidth(); // Initialize ID strings beforehand. Every ID should be unique across the document PdfString[] headersId = { // Since '/ID' is a `byte string` according to specification we are not passing // encoding to the constructor of the PdfString new PdfString("header_id_0"), new PdfString("header_id_1"), new PdfString("header_id_2") }; PdfName idTreeName = new PdfName("IDTree"); PdfNameTree idTree = new PdfNameTree(pdfDocument.GetCatalog(), idTreeName); for (int i = 0; i < 3; ++i) { Cell c = new Cell().Add(new Paragraph("Header " + (i + 1))); c.GetAccessibilityProperties().SetRole(StandardRoles.TH); table.AddHeaderCell(c); PdfString headerId = headersId[i]; // Use custom renderer for cell header element in order to add ID to its tag CellRenderer renderer = new StructIdCellRenderer(c, doc, headerId, idTree); c.SetNextRenderer(renderer); } List <TaggingHintKey> colSpanHints = new List <TaggingHintKey>(); for (int i = 0; i < 4; i++) { Cell c; if (i < 3) { c = new Cell().Add(new Paragraph((i + 1).ToString())); } else { // Colspan creation c = new Cell(1, 3).Add(new Paragraph((i + 1).ToString())); } if (i < 3) { // Correct table tagging requires marking which headers correspond to the given cell. // The correspondence is defined by header cells tags IDs. For table cells without // col/row spans it's easy to reference a header: just add proper // PdfStructureAttributes to it. Table cells with col spans are processed below. PdfStructureAttributes tableAttributes = new PdfStructureAttributes("Table"); PdfArray headers; headers = new PdfArray(headersId[i % headersId.Length]); tableAttributes.GetPdfObject().Put(PdfName.Headers, headers); c.GetAccessibilityProperties().AddAttributes(tableAttributes); } else { // When we add PdfStructureAttributes to the element these attributes override any // attributes generated for it automatically. E.g. cells with colspan require properly // generated attributes which describe the colspan (e.g. which columns this cell spans). // So here we will use a different approach: fetch the tag which will be created for // the cell and modify attributes object directly. TaggingHintKey colSpanCellHint = LayoutTaggingHelper.GetOrCreateHintKey(c); colSpanHints.Add(colSpanCellHint); } table.AddCell(c); } doc.Add(table); // After table has been drawn on the page, we can modify the colspan cells tags foreach (TaggingHintKey colSpanHint in colSpanHints) { WaitingTagsManager waitingTagsManager = pdfDocument.GetTagStructureContext().GetWaitingTagsManager(); TagTreePointer p = new TagTreePointer(pdfDocument); // Move tag pointer to the colspan cell using its hint if (!waitingTagsManager.TryMovePointerToWaitingTag(p, colSpanHint)) { // It is not expected to happen ever if immediate-flush is enabled (which is by default), // otherwise this should be done after the flush throw new InvalidOperationException("A work-around does not work. A tag for the cell is " + "not created or cannot be found."); } foreach (PdfStructureAttributes attr in p.GetProperties().GetAttributesList()) { if ("Table".Equals(attr.GetAttributeAsEnum("O"))) { // Specify all the headers for the column spanning (all of 3) PdfArray headers = new PdfArray(headersId); attr.GetPdfObject().Put(PdfName.Headers, headers); break; } } } pdfDocument.GetStructTreeRoot().GetPdfObject().Put(idTreeName, idTree.BuildTree() .MakeIndirect(pdfDocument)); doc.Close(); }