如何使用 iText 7 使下划线文本可访问
Posted
技术标签:
【中文标题】如何使用 iText 7 使下划线文本可访问【英文标题】:How to make underline text accessible using iText 7 【发布时间】:2021-04-01 18:55:36 【问题描述】:我正在尝试从头开始构建 PDF,并且它必须是可访问的 (PDF/UA)。但是,当我尝试添加下划线文本时遇到了问题。可访问性检查器抱怨“路径不能有跨度作为父级”。当我检查生成的实际 PDF 时,我注意到路径没有被标记为工件。我的问题是,如何标记此路径?或者,如何正确添加下划线文本?代码片段很精彩:
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();
编辑: 似乎使下划线可访问的唯一方法是使用低级函数。我在下面发布我的代码:
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();
【问题讨论】:
【参考方案1】:以下代码为文本添加下划线并生成通过 PAC3 检查器和 Acrobat Preflight PDF/UA 检查器的 PDF/UA 输出。
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);
【讨论】:
顺便说一句,我在生成包含超链接的 PDF/UA 输出时遇到问题。请参阅***.com/questions/66873854/… 如果您已经解决了这个问题,我将不胜感激。谢谢 不幸的是,它没有通过 Commonlook 验证器。您正在使用相同的 SetUnderline 函数,该函数无法正常工作。但是,低级功能可以正常工作。我稍后会发布代码作为响应。 @tjackson 顺便说一句,我已经为您遇到的超链接问题发布了答案。希望它可以提供帮助。 @tjackson【参考方案2】:我怀疑问题在于 PDF/UA 输出需要嵌入所有字体,而您可能正在使用内置字体。使用类似下面的东西来加载嵌入字体。
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);
您可能还需要创建一个 Text 对象,然后为 Text 对象设置字体、磅值、下划线属性,最后将 Text 对象添加到 Paragraph。例如,
Text text = new Text("HEADER");
text.setFont(font);
int pointSize = 10;
text.setFontSize(pointSize);
text.setUnderline();
【讨论】:
感谢您的回复,但这不是问题所在。我没有包含创建 fontDefault 的代码。这里是。 PdfFont fontDefault = PdfFontFactory.CreateFont("arial.ttf", true); 它是一个truetype字体并且是嵌入的。真正的问题是,这个 Path 对象没有被标记为 Artifact。我不知道如何标记这个 Path(下划线)对象。 必须是在 Paragraph 对象上设置下划线的问题。以上是关于如何使用 iText 7 使下划线文本可访问的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 iText 列表将具有不同权重的文本添加到单个 ListItem