All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.jasperreports.engine.export.JRPdfExporterTagHelper Maven / Gradle / Ivy

There is a newer version: 6.21.2
Show newest version
/*
 * JasperReports - Free Java Reporting Library.
 * Copyright (C) 2001 - 2014 TIBCO Software Inc. All rights reserved.
 * http://www.jaspersoft.com
 *
 * Unless you have purchased a commercial license agreement from Jaspersoft,
 * the following license terms apply:
 *
 * This program is part of JasperReports.
 *
 * JasperReports is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JasperReports is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with JasperReports. If not, see .
 */

/*
 * Contributors:
 * Adrian Jackson - [email protected]
 * David Taylor - [email protected]
 * Lars Kristensen - [email protected]
 * Ling Li - [email protected]
 * Martin Clough - [email protected]
 */
package net.sf.jasperreports.engine.export;

import java.util.Stack;

import net.sf.jasperreports.crosstabs.JRCellContents;
import net.sf.jasperreports.engine.JRPrintElement;
import net.sf.jasperreports.engine.JRPrintFrame;
import net.sf.jasperreports.engine.JRPrintImage;

import com.lowagie.text.pdf.PdfArray;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfDictionary;
import com.lowagie.text.pdf.PdfName;
import com.lowagie.text.pdf.PdfNumber;
import com.lowagie.text.pdf.PdfObject;
import com.lowagie.text.pdf.PdfString;
import com.lowagie.text.pdf.PdfStructureElement;
import com.lowagie.text.pdf.PdfStructureTreeRoot;
import com.lowagie.text.pdf.PdfWriter;


/**
 * Provides support for tagged PDF documents.
 * 

* PDF files can contain hidden tags that describe the structure of the document. Some of * the tags are used by the automated reader tool that reads PDF documents aloud to people * with disabilities. *

Marking Headings

* JasperReports currently supports specifying type 1, 2 and 3 level headings. * In order to mark a text field as a level 1 heading, the following custom element property * should be used in JRXML: *

* <property name="net.sf.jasperreports.export.pdf.tag.h1" value="full"/> *

* Value full means that a full <H1> tag will be embedded in the PDF wrapping the * current text element. * If two or more text fields make up a single level 1 heading, there are two ways to mark * the heading: *

    *
  • In the first, the text elements making up the heading are placed inside a frame and * the frame is marked with the following custom property: *
    * <property name="net.sf.jasperreports.export.pdf.tag.h1" value="full"/>
  • *
  • In the second, the first element of the heading (respective to the Z-Order, or the * order in which the elements appear in JRXML) is tagged with: *
    * <property name="net.sf.jasperreports.export.pdf.tag.h1" value="start"/> *
    * and the last element from the heading (respective to the same order) is marked with *
    * <property name="net.sf.jasperreports.export.pdf.tag.h1" value="end"/>
  • *
*

* Level 2 and level 3 headings are marked the same way, except that the properties are: *

* net.sf.jasperreports.export.pdf.tag.h2 *

* and *

* net.sf.jasperreports.export.pdf.tag.h3. *

Marking Tables

* Tables are comprised of column headers, row headers, and a data section. Each table * section is made of cells. Marking table structures in PDF is similar to the way tables are * described in HTML and uses the same techniques as those for marking headings. *

* When marking a table, the user has to indicate in the report template where the table * starts and where it ends. *

* If the entire table is placed in a container, such as a frame element, marking the table * requires only marking the parent frame with the following custom element property: *

* <property name="net.sf.jasperreports.export.pdf.tag.table" value="full"/> *

* However, most of the time, tables cannot be isolated in a frame unless they are * subreports, because they generally span multiple report sections and bands. In such * cases, marking a table requires marking in JRXML the first and last element making up * the table structure. *

* The first element of the table (probably the first element in the table header) should be * marked with the following custom property: *

* <property name="net.sf.jasperreports.export.pdf.tag.table" value="start"/> *

* The last element of the table should be marked with: *

* <property name="net.sf.jasperreports.export.pdf.tag.table" value="end"/> *

* Tables are made of rows, and each row has to be precisely delimited within the table * structure. This includes the column header rows at the top of the table. Similar to the * headings and table marking, a table row can be identified in two ways: *

    *
  • If the entire content that makes up the row is isolated within a frame, the frame can be * marked with the following custom property: *
    * <property name="net.sf.jasperreports.export.pdf.tag.tr" value="full"/> *
  • *
  • If the content of the row is not grouped in a container frame, its first and last elements * (respective to the Z-order or the order in which they appear in JRXML) have to be * marked with the following custom properties: *
    * <property name="net.sf.jasperreports.export.pdf.tag.tr" value="start"/> *
    * for the first element and *
    * <property name="net.sf.jasperreports.export.pdf.tag.tr" value="start"/> *
    * for the last element.
  • *
*

* Each table row can contain header cells or data cells. Regardless of their type, and * similar to headings, tables, and table rows, cells can be marked either by marking a * single element representing the cell content (this single cell element can actually be a * frame element), or by marking the first and last element from the cell content. *

* Header cells made of a single element (this single element can actually be a frame) are * marked with *

* <property name="net.sf.jasperreports.export.pdf.tag.th" value="full"/> *

* A header cell made of multiple elements is marked with *

* <property name="net.sf.jasperreports.export.pdf.tag.th" value="start"/> * on its first element and *

* <property name="net.sf.jasperreports.export.pdf.tag.th" value="end"/> * on its last element. *

* Normal data cells made of a single element (that can be frame) are marked with *

* <property name="net.sf.jasperreports.export.pdf.tag.td" value="full"/> *

* Normal data cells made of multiple elements are marked with *

* <property name="net.sf.jasperreports.export.pdf.tag.td" value="start"/> * on their first element and *

* <property name="net.sf.jasperreports.export.pdf.tag.td" value="end"/> * on their last element. *

* Just as in HTML tables, cells can span multiple rows and/or columns. Column span and * row span values for the current table cell can be specified using the following custom * properties on the same element where the cell start was marked (the element with the * full or start property marking the cell): *

* <property name="net.sf.jasperreports.export.pdf.tag.colspan" value="<number>"/> *

* <property name="net.sf.jasperreports.export.pdf.tag.rowspan" value="<number>"/> *

PDF Content Reading Order

* JasperReports uses the Z-order of the elements as present in the report template * (JRXML) to control reading order in the resulting PDF files. This is usually the intended * way for the documents to be read, so no specific modifications were required in order to * achieve it. * * @author Teodor Danciu ([email protected]) */ public class JRPdfExporterTagHelper { public static final String PROPERTY_TAG_TABLE = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.table"; public static final String PROPERTY_TAG_TR = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.tr"; public static final String PROPERTY_TAG_TH = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.th"; public static final String PROPERTY_TAG_TD = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.td"; public static final String PROPERTY_TAG_L = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.l"; public static final String PROPERTY_TAG_LI = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.li"; public static final String PROPERTY_TAG_H1 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h1"; public static final String PROPERTY_TAG_H2 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h2"; public static final String PROPERTY_TAG_H3 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h3"; public static final String PROPERTY_TAG_H4 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h4"; public static final String PROPERTY_TAG_H5 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h5"; public static final String PROPERTY_TAG_H6 = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.h6"; public static final String PROPERTY_TAG_COLSPAN = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.colspan"; public static final String PROPERTY_TAG_ROWSPAN = JRPdfExporter.PDF_EXPORTER_PROPERTIES_PREFIX + "tag.rowspan"; public static final String TAG_START = "start"; public static final String TAG_END = "end"; public static final String TAG_FULL = "full"; protected JRPdfExporter exporter; protected PdfContentByte pdfContentByte; protected PdfWriter pdfWriter; protected PdfStructureElement allTag; protected Stack tagStack; protected boolean isTagEmpty = true; protected int crtCrosstabRowY = -1; protected int crosstabFrameDepth; protected boolean isDataCellPrinted; protected boolean isTagged; protected String language; /** * */ protected JRPdfExporterTagHelper(JRPdfExporter exporter) { this.exporter = exporter; } /** * */ protected void setTagged(boolean isTagged) { this.isTagged = isTagged; } /** * */ protected void setLanguage(String language) { this.language = language; } /** * */ protected void setPdfWriter(PdfWriter pdfWriter) { this.pdfWriter = pdfWriter; if (isTagged) { pdfWriter.setTagged(); } } /** * */ protected void init(PdfContentByte pdfContentByte) { this.pdfContentByte = pdfContentByte; if (isTagged) { PdfStructureTreeRoot root = pdfWriter.getStructureTreeRoot(); PdfName pdfNameALL = new PdfName("All"); root.mapRole(pdfNameALL, PdfName.SECT); root.mapRole(PdfName.IMAGE, PdfName.FIGURE); root.mapRole(PdfName.TEXT, PdfName.TEXT); allTag = new PdfStructureElement(root, pdfNameALL); if(pdfWriter.getPDFXConformance() == PdfWriter.PDFA1A) { root.mapRole(new PdfName("Anchor"), PdfName.NONSTRUCT); root.mapRole(PdfName.TEXT, PdfName.SPAN); } else { root.mapRole(new PdfName("Anchor"), PdfName.TEXT); } if (language != null) { allTag.put(PdfName.LANG, new PdfString(language)); } tagStack = new Stack(); tagStack.push(allTag); } } protected void startPageAnchor() { if (isTagged) { PdfStructureElement textTag = new PdfStructureElement(allTag, new PdfName("Anchor")); pdfContentByte.beginMarkedContentSequence(textTag); } } protected void endPageAnchor() { if (isTagged) { pdfContentByte.endMarkedContentSequence(); } } protected void startPage() { crtCrosstabRowY = -1; crosstabFrameDepth = 0; isDataCellPrinted = false; } protected void endPage() { if (isTagged) { if (crtCrosstabRowY >= 0) //crosstab still open { //end the current row //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); //end the table //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); } } } protected void startElement(JRPrintElement element) { if (isTagged) { if (element instanceof JRPrintFrame) { JRPrintFrame frame = (JRPrintFrame) element; boolean isCellContentsFrame = frame.getPropertiesMap().hasProperties() && frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE) != null; if (crtCrosstabRowY >= 0) //crosstab already started { //frame depth must be incremented for all frame, when inside a crosstab crosstabFrameDepth++; if (isCellContentsFrame) { if (JRCellContents.TYPE_DATA.equals(frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE))) { isDataCellPrinted = true; } if (crtCrosstabRowY != frame.getY()) { //this is the first cell on a new row //end the current row //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); if ( isDataCellPrinted && (JRCellContents.TYPE_CROSSTAB_HEADER.equals(frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE)) || JRCellContents.TYPE_COLUMN_HEADER.equals(frame.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE))) ) { //end the table //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); //start table createTableStartTag(); //start crosstab isDataCellPrinted = false; } //start the new row createTrStartTag(); //keep crosstab open, but mark new row position and frame depth crtCrosstabRowY = frame.getY(); } } else { if (crosstabFrameDepth == 1) { //normal frame outside crosstab //end the current row //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); //end the table //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); //end crosstab crtCrosstabRowY = -1; //make depth zero because it will not be decremented after frame export // due to crosstab being ended here crosstabFrameDepth = 0; } } } else { if (isCellContentsFrame) { //start table and firts row createTableStartTag(); createTrStartTag(); //start crosstab crtCrosstabRowY = frame.getY(); crosstabFrameDepth++; isDataCellPrinted = false; } // else // { // //normal frame outside crosstab // } } } else { if (crtCrosstabRowY >= 0) //crosstab already started { if (crosstabFrameDepth == 0) { //normal element outside crosstab //end the current row //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); //end the table //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); //end crosstab crtCrosstabRowY = -1; crosstabFrameDepth = 0; } } } createStartTags(element); } } protected void endElement(JRPrintElement element) { if (isTagged) { if (element instanceof JRPrintFrame) { if (crtCrosstabRowY >= 0) // crosstab started { crosstabFrameDepth--; } } createEndTags(element); } } protected void startImage(JRPrintImage printImage) { if (isTagged) { PdfStructureElement imageTag = new PdfStructureElement(allTag, PdfName.IMAGE); pdfContentByte.beginMarkedContentSequence(imageTag); if (printImage.getHyperlinkTooltip() != null) { imageTag.put(PdfName.ALT, new PdfString(printImage.getHyperlinkTooltip())); } } } protected void endImage() { if (isTagged) { pdfContentByte.endMarkedContentSequence(); } } protected void startText(boolean isHyperlink) { if (isTagged) { // PdfStructureElement parentTag = tableCellTag == null ? (tableHeaderTag == null ? allTag : tableHeaderTag): tableCellTag; // PdfStructureElement textTag = new PdfStructureElement(parentTag, PdfName.TEXT); PdfStructureElement textTag = new PdfStructureElement(tagStack.peek(), isHyperlink ? PdfName.LINK : PdfName.TEXT); pdfContentByte.beginMarkedContentSequence(textTag); } } protected void startText(String text, boolean isHyperlink) { if (isTagged) { PdfDictionary markedContentProps = new PdfDictionary(); markedContentProps.put(PdfName.ACTUALTEXT, new PdfString(text, PdfObject.TEXT_UNICODE)); PdfStructureElement textTag = new PdfStructureElement(tagStack.peek(), isHyperlink ? PdfName.LINK : PdfName.TEXT); // the following method is part of the patched iText pdfContentByte.beginMarkedContentSequence(textTag, markedContentProps); } } protected void endText() { if (isTagged) { pdfContentByte.endMarkedContentSequence(); isTagEmpty = false; } } protected void createStartTags(JRPrintElement element) { if (element.hasProperties()) { String prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TABLE); if (TAG_START.equals(prop) || TAG_FULL.equals(prop)) { createTableStartTag(); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TR); if (TAG_START.equals(prop) || TAG_FULL.equals(prop)) { createTrStartTag(); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TH); if (TAG_START.equals(prop) || TAG_FULL.equals(prop)) { createThStartTag(element); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TD); if (TAG_START.equals(prop) || TAG_FULL.equals(prop)) { createTdStartTag(element); } prop = element.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE); if ( JRCellContents.TYPE_CROSSTAB_HEADER.equals(prop) || JRCellContents.TYPE_COLUMN_HEADER.equals(prop) || JRCellContents.TYPE_ROW_HEADER.equals(prop) ) { createThStartTag(element); } if (JRCellContents.TYPE_DATA.equals(prop)) { createTdStartTag(element); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_L); if (TAG_START.equals(prop) || TAG_FULL.equals(prop)) { createListStartTag(); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_LI); if (TAG_START.equals(prop) || TAG_FULL.equals(prop)) { createListItemStartTag(element); } createStartHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H1), PdfName.H1); createStartHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H2), PdfName.H2); createStartHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H3), PdfName.H3); createStartHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H4), PdfName.H4); createStartHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H5), PdfName.H5); createStartHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H6), PdfName.H6); } } protected void createStartHeadingTags(String prop, PdfName pdfName) { if (TAG_START.equals(prop) || TAG_FULL.equals(prop)) { PdfStructureElement headingTag = new PdfStructureElement(tagStack.peek(), pdfName); //pdfContentByte.beginMarkedContentSequence(headingTag); headingTag.put(PdfName.K, new PdfArray()); tagStack.push(headingTag); isTagEmpty = true; } } protected void createTableStartTag() { PdfStructureElement tableTag = new PdfStructureElement(allTag, PdfName.TABLE); //pdfContentByte.beginMarkedContentSequence(tableTag); tableTag.put(PdfName.K, new PdfArray()); tagStack.push(tableTag); } protected void createTrStartTag() { PdfStructureElement tableRowTag = new PdfStructureElement(tagStack.peek(), PdfName.TABLEROW); //pdfContentByte.beginMarkedContentSequence(tableRowTag); tableRowTag.put(PdfName.K, new PdfArray()); tagStack.push(tableRowTag); } protected void createThStartTag(JRPrintElement element) { PdfStructureElement tableHeaderTag = new PdfStructureElement(tagStack.peek(), PdfName.TH); //pdfContentByte.beginMarkedContentSequence(tableHeaderTag); tableHeaderTag.put(PdfName.K, new PdfArray()); tagStack.push(tableHeaderTag); isTagEmpty = true; createSpanTags(element, tableHeaderTag); } protected void createTdStartTag(JRPrintElement element) { PdfStructureElement tableCellTag = new PdfStructureElement(tagStack.peek(), PdfName.TD); //pdfContentByte.beginMarkedContentSequence(tableCellTag); tableCellTag.put(PdfName.K, new PdfArray()); tagStack.push(tableCellTag); isTagEmpty = true; createSpanTags(element, tableCellTag); } protected void createSpanTags(JRPrintElement element, PdfStructureElement parentTag) { int colSpan = 0; int rowSpan = 0; try { colSpan = Integer.valueOf(element.getPropertiesMap().getProperty(PROPERTY_TAG_COLSPAN)).intValue(); } catch (NumberFormatException e) { try { colSpan = Integer.valueOf(element.getPropertiesMap().getProperty(JRCellContents.PROPERTY_COLUMN_SPAN)).intValue(); } catch (NumberFormatException ex) {} } try { rowSpan = Integer.valueOf(element.getPropertiesMap().getProperty(PROPERTY_TAG_ROWSPAN)).intValue(); } catch (NumberFormatException e) { try { rowSpan = Integer.valueOf(element.getPropertiesMap().getProperty(JRCellContents.PROPERTY_ROW_SPAN)).intValue(); } catch (NumberFormatException ex) {} } if (colSpan > 1 || rowSpan > 1) { PdfArray a = new PdfArray(); PdfDictionary dict = new PdfDictionary(); if (colSpan > 1) { dict.put(new PdfName("ColSpan"), new PdfNumber(colSpan)); } if (rowSpan > 1) { dict.put(new PdfName("RowSpan"), new PdfNumber(rowSpan)); } dict.put(PdfName.O, PdfName.TABLE); a.add(dict); parentTag.put(PdfName.A, a); } } protected void createListStartTag() { PdfStructureElement listTag = new PdfStructureElement(allTag, PdfName.L); //pdfContentByte.beginMarkedContentSequence(tableTag); listTag.put(PdfName.K, new PdfArray()); tagStack.push(listTag); } protected void createListItemStartTag(JRPrintElement element) { PdfStructureElement listItemTag = new PdfStructureElement(tagStack.peek(), PdfName.LI); //pdfContentByte.beginMarkedContentSequence(tableHeaderTag); listItemTag.put(PdfName.K, new PdfArray()); tagStack.push(listItemTag); isTagEmpty = true; } protected void createEndTags(JRPrintElement element)// throws DocumentException, IOException, JRException { if (element.hasProperties()) { createEndHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H6)); createEndHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H5)); createEndHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H4)); createEndHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H3)); createEndHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H2)); createEndHeadingTags(element.getPropertiesMap().getProperty(PROPERTY_TAG_H1)); String prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_LI); if (TAG_END.equals(prop) || TAG_FULL.equals(prop)) { //pdfContentByte.endMarkedContentSequence(); if (isTagEmpty) { pdfContentByte.beginMarkedContentSequence(new PdfStructureElement(tagStack.peek(), PdfName.SPAN)); pdfContentByte.endMarkedContentSequence(); } tagStack.pop(); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_L); if (TAG_END.equals(prop) || TAG_FULL.equals(prop)) { //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); } prop = element.getPropertiesMap().getProperty(JRCellContents.PROPERTY_TYPE); if ( prop != null && (JRCellContents.TYPE_CROSSTAB_HEADER.equals(prop) || JRCellContents.TYPE_COLUMN_HEADER.equals(prop) || JRCellContents.TYPE_ROW_HEADER.equals(prop) || JRCellContents.TYPE_DATA.equals(prop))) { //pdfContentByte.endMarkedContentSequence(); if (isTagEmpty) { pdfContentByte.beginMarkedContentSequence(new PdfStructureElement(tagStack.peek(), PdfName.SPAN)); pdfContentByte.endMarkedContentSequence(); } tagStack.pop(); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TD); if (TAG_END.equals(prop) || TAG_FULL.equals(prop)) { //pdfContentByte.endMarkedContentSequence(); if (isTagEmpty) { pdfContentByte.beginMarkedContentSequence(new PdfStructureElement(tagStack.peek(), PdfName.SPAN)); pdfContentByte.endMarkedContentSequence(); } tagStack.pop(); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TH); if (TAG_END.equals(prop) || TAG_FULL.equals(prop)) { //pdfContentByte.endMarkedContentSequence(); if (isTagEmpty) { pdfContentByte.beginMarkedContentSequence(new PdfStructureElement(tagStack.peek(), PdfName.SPAN)); pdfContentByte.endMarkedContentSequence(); } tagStack.pop(); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TR); if (TAG_END.equals(prop) || TAG_FULL.equals(prop)) { //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); } prop = element.getPropertiesMap().getProperty(PROPERTY_TAG_TABLE); if (TAG_END.equals(prop) || TAG_FULL.equals(prop)) { //pdfContentByte.endMarkedContentSequence(); tagStack.pop(); } } } protected void createEndHeadingTags(String prop) { if (TAG_END.equals(prop) || TAG_FULL.equals(prop)) { //pdfContentByte.endMarkedContentSequence(); if (isTagEmpty) { pdfContentByte.beginMarkedContentSequence(new PdfStructureElement(tagStack.peek(), PdfName.SPAN)); pdfContentByte.endMarkedContentSequence(); } tagStack.pop(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy