Reputation: 137
I am trying to build a PDF from scratch and it has to be accessible (PDF/UA). However, I got a problem when I tried to add an underline text. The accessibility checker complained "a Path cannot has span as parent". When I checked the actual PDF generated, I noticed the Path is not tagged as an Artifact. My question is, how to tag this Path? Or, how to properly add an underline text? The code snipet is blow:
PdfDocument pdfDoc = new PdfDocument(new PdfWriter("output.pdf",
(new WriterProperties()).AddUAXmpMetadata().SetPdfVersion(PdfVersion.PDF_1_7)));
Document document = new Document(pdfDoc, PageSize.A4);
//TAGGED PDF
pdfDoc.SetTagged();
pdfDoc.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
pdfDoc.GetCatalog().SetLang(new PdfString("en-US"));
PdfDocumentInfo info = pdfDoc.GetDocumentInfo();
info.SetTitle("Decision No. 1234/12");
Paragraph header = new Paragraph("HEADER");
header.SetFont(fontDefault)
.SetBold()
.SetUnderline();//Set underline. A Path object was added by iText.
header.GetAccessibilityProperties().SetRole(StandardRoles.H1);
document.Add(header);
document.Close();
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = new System.Diagnostics.ProcessStartInfo("output.pdf") { UseShellExecute = true };
process.Start();
EDIT: Seems like the only way to make the underline accessible, is to use the low-level functions. I post my code below:
PdfDocument pdfDoc = new PdfDocument(new PdfWriter("output.pdf",
(new WriterProperties()).AddUAXmpMetadata().SetPdfVersion(PdfVersion.PDF_1_7)));
Document document = new Document(pdfDoc, PageSize.A4);
PdfFont font = PdfFontFactory.CreateFont("arial.ttf", true);
//TAGGED PDF
pdfDoc.SetTagged();
pdfDoc.GetCatalog().SetViewerPreferences(new PdfViewerPreferences().SetDisplayDocTitle(true));
pdfDoc.GetCatalog().SetLang(new PdfString("en-US"));
PdfDocumentInfo info = pdfDoc.GetDocumentInfo();
info.SetTitle("Decision No. 1234/12");
//Method 1 - to create a underlined header
//The Path added for the underline is not accessible (Not tagged as Artifact).
Paragraph header = new Paragraph("HEADER");
header.SetFont(font)
.SetBold()
.SetUnderline(); //Path created but not tagged as Artifact.
header.GetAccessibilityProperties().SetRole(StandardRoles.H1);
document.Add(header);
//Method 2 - to create a underlined header
//The Path added and properly tagged as Artifact
PdfCanvas canvas = new PdfCanvas(pdfDoc.GetLastPage());
TagTreePointer tagPointer = new TagTreePointer(pdfDoc);
tagPointer.SetPageForTagging(pdfDoc.GetFirstPage());
tagPointer.AddTag(StandardRoles.H1).AddTag(StandardRoles.SPAN);
canvas
.BeginText()
.MoveText(50, 700)
.SetFontAndSize(font, 12)
.OpenTag(tagPointer.GetTagReference())
.ShowText("HEADER")
.CloseTag()
.EndText();
//Manually draw the underline (Path)
float w = font.GetWidth("HEADER", 12);
canvas
.MoveTo(50, 700 - 1)
.LineTo(50 + w, 700 - 1)
.SetLineWidth(0.5F)
.Stroke();
//Close document
document.Close();
//Open the PDF
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = new System.Diagnostics.ProcessStartInfo("output.pdf") { UseShellExecute = true };
process.Start();
Upvotes: 0
Views: 1451
Reputation: 11
The following code underlines text and produces PDF/UA output that passes the PAC3 checker and the Acrobat Preflight PDF/UA checker.
public void testUnderline() throws IOException {
// Create PDF/UA with underline text
String filename = "./results/Underline.pdf";
WriterProperties properties = new WriterProperties();
properties.addUAXmpMetadata().setPdfVersion(PdfVersion.PDF_1_7);
PdfWriter writer = new PdfWriter(filename, properties);
pdfDoc = new PdfDocument(writer);
//Make document tagged
pdfDoc.setTagged();
pdfDoc.getCatalog().setLang(new PdfString("en-US"));
pdfDoc.getCatalog().setViewerPreferences(new PdfViewerPreferences().setDisplayDocTitle(true));
PdfDocumentInfo info = pdfDoc.getDocumentInfo();
info.setTitle("Hello Underline!");
document = new Document(pdfDoc);
// Must embed font for PDF/UA
byte[] inputBytes = Files.readAllBytes(Paths.get("./resources/fonts/opensans-regular.ttf"));
boolean embedded = true;
boolean cached = false;
PdfFont font = PdfFontFactory.createFont(inputBytes, PdfEncodings.CP1252, embedded, cached);
Text text = new Text("This is an underlined Text object");
text.setFont(font);
text.setFontSize(16F);
text.setUnderline();
Paragraph para = new Paragraph();
para.add(text);
document.add(para);
document.close();
System.out.println(CREATED + filename);
}
Upvotes: 1
Reputation: 11
I suspect the problem is that PDF/UA output requires all fonts to be embedded and you may be using a built-in font. To using something like the following to load a font for embedding.
byte[] inputBytes = Files.readAllBytes(Paths.get("./resources/fonts/opensans-regular.ttf"));
boolean embedded = true;
boolean cached = false;
PdfFont font = setFont(inputBytes, PdfEncodings.CP1252, embedded, cached);
You might also need to create a Text object then set the font, point size, underline attributes to the Text object and finally add the Text object to the Paragraph. For example,
Text text = new Text("HEADER");
text.setFont(font);
int pointSize = 10;
text.setFontSize(pointSize);
text.setUnderline();
Upvotes: 0