当前位置: 首页 > 知识库问答 >
问题:

非拉丁文本正在从pdf文本字段中消失

章茂
2023-03-14

我使用itext7.1.9库创建一个带有文本可填充字段的PDF文档。PdfTextFormField包含多语言文本。创建PDF文档后,我在Adobe Acrobat Reader中打开它,非拉丁符号从文本字段中消失,我只看到拉丁符号,但如果我单击该字段,整个文本将可见,包括非拉丁符号。[!打开文档后的PDF文本字段] 1.[!点击后的PDF文本字段到字段] 2.对于创建PDF文档,我使用如下代码:

public class Main {
    public static void main(String[] args) throws IOException, URISyntaxException {
        FontProviderAndFormFieldExample app = new FontProviderAndFormFieldExample();
        app.createPdf("Test1.pdf");
        app.fillExample("Test1.pdf", "Result.pdf", Paths.get(Main.class.getResource("/fonts").toURI()).toString());
    }

    public static class FontProviderAndFormFieldExample {
        public String FIELDNAME = "test";
        public Rectangle FIELDRECT = new Rectangle(50,300,300,20);
        public String FIELDVALUE = "ПриветHello";

        public void createPdf(String dest) throws IOException {
            PdfWriter writer = new PdfWriter(dest);
            PdfDocument pdfDoc = new PdfDocument(writer);
            Document doc = new Document(pdfDoc);

            Paragraph para = new Paragraph("Test document for multi-font appearance in a text formfield");
            doc.add(para);

            PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDoc,true);
            PdfTextFormField ff = PdfFormField.createText(pdfDoc,FIELDRECT,"test", FIELDVALUE);
            ff.setMultiline(true);
            ff.setScroll(true);
            acroForm.addField(ff,pdfDoc.getFirstPage());

            PdfCanvas pdfCanvas = new PdfCanvas(pdfDoc.getFirstPage());
            pdfCanvas.setLineWidth(1f).setStrokeColor(ColorConstants.BLUE).rectangle(FIELDRECT).stroke();

            doc.close();
        }

        public void fillExample(String src, String dest, String srcf) throws IOException, URISyntaxException {
            PdfReader reader = new PdfReader(src);
            PdfWriter writer = new PdfWriter(dest);
            PdfDocument pdfDoc = new PdfDocument(reader,writer);
            PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDoc,true);
            PdfFormField ff = acroForm.getField(FIELDNAME);
            String filename = Main.class.getResource("/fonts/arial unicode.ttf").toURI().toString();
            final PdfFont font = PdfFontFactory.createFont(filename, PdfEncodings.UTF8, false);
            ff.setFont(font).setValue(FIELDVALUE);

            pdfDoc.close();

        }
    }
}

我试图解决这个问题,我甚至在它的博客上找到了这篇文章,但它没有帮助我。我知道使用ff.setNeedEmerarence(true)方法,但我不能使用它,因为它会破坏我的应用程序的另一部分。我不能设置PdfEn编码。IDENTITY_H,因为它只嵌入了以编程方式包含到字段中的符号的子集,用户无法填写该字段。
有人能帮我吗?我做错了什么?


共有1个答案

子车高歌
2023-03-14

要确保嵌入了完整字体,而不仅仅是子集,请使用font.setSubset(false)

一般来说,您应该尽可能尝试使用包含值中所有字形的字体。否则,您的PDF的消费者可能会有问题。

作为一种解决方法,您可以通过使用自动选择适当字体的FontSet功能,使用layout模块创建自己的外观。在我的示例中,我只向FontSet添加了一种字体,但您可以在那里添加多种字体。但是,强烈建议将字体数量限制为一个,如果不可能,则将字体数量限制为最小。

因此,这里我们基本上创建了一个PdfFormXObject,作为我们的外观对象:

FontSet fontSet = new FontSet();
fontSet.addFont("C:/Windows/Fonts/arial.ttf");
FontProvider fontProvider = new FontProvider(fontSet);

PdfFormXObject xObject = new PdfFormXObject(FIELDRECT);
Canvas canvas = new Canvas(xObject, pdfDoc);
canvas.setProperty(Property.FONT_PROVIDER, fontProvider);
canvas.add(new Paragraph(FIELDVALUE).setMultipliedLeading(1).setFontFamily("Arial"));

然后我们必须将其设置为字段:

ff.setAppearance(PdfName.N, null, xObject.getPdfObject());

您的createPdf的完整代码如下所示:

PdfWriter writer = new PdfWriter(dest);
PdfDocument pdfDoc = new PdfDocument(writer);
Document doc = new Document(pdfDoc);

Paragraph para = new Paragraph("Test document for multi-font appearance in a text formfield");
doc.add(para);

PdfAcroForm acroForm = PdfAcroForm.getAcroForm(pdfDoc,true);
PdfTextFormField ff = PdfFormField.createText(pdfDoc,FIELDRECT,"test", FIELDVALUE);
ff.setMultiline(true);
ff.setScroll(true);

FontSet fontSet = new FontSet();
fontSet.addFont("C:/Windows/Fonts/arial.ttf");
FontProvider fontProvider = new FontProvider(fontSet);

PdfFormXObject xObject = new PdfFormXObject(FIELDRECT);
Canvas canvas = new Canvas(xObject, pdfDoc);
canvas.setProperty(Property.FONT_PROVIDER, fontProvider);
canvas.add(new Paragraph(FIELDVALUE).setMultipliedLeading(1).setFontFamily("Arial"));

ff.setAppearance(PdfName.N, null, xObject.getPdfObject());

acroForm.addField(ff,pdfDoc.getFirstPage());

PdfCanvas pdfCanvas = new PdfCanvas(pdfDoc.getFirstPage());
pdfCanvas.setLineWidth(1f).setStrokeColor(ColorConstants.BLUE).rectangle(FIELDRECT).stroke();

doc.close();

打开PDF时的视觉效果:

UPD上面的代码在AdobeAcrobat、Foxit、ChromePDF查看器中运行良好,但当您在AdobeReader中打开它时,您会看到空的表单字段。

为了让它在Acrobat中工作,你必须确保你的XObject bbox在原点启动:

PdfFormXObject xObject = new PdfFormXObject(new Rectangle(0, 0, FIELDRECT.getWidth(), FIELDRECT.getHeight()));

并将外观包装到/Tx BMC/EMC块中,该块标记重新生成外观时需要更换的零件。

代码的固定部分也会在Adobe Acrobat Reader中产生正确的结果:

PdfFormXObject xObject = new PdfFormXObject(new Rectangle(0, 0, FIELDRECT.getWidth(), FIELDRECT.getHeight()));
Canvas canvas = new Canvas(xObject, pdfDoc);
canvas.getPdfCanvas().beginMarkedContent(new PdfName("Tx"));
canvas.setProperty(Property.FONT_PROVIDER, fontProvider);
canvas.add(new Paragraph(FIELDVALUE).setMultipliedLeading(1).setFontFamily("Arial"));
canvas.getPdfCanvas().endMarkedContent();

 类似资料:
  • 这是我调查的第二天,没有任何结果。至少现在,我能够问一些非常具体的问题。 我试图编写一个有效的超文本标记语言代码,其中包含一些非拉丁字符在PDF文件中使用iText,更具体地说,使用飞碟的IText渲染器。 我的简短示例/代码首先使用以下值初始化字符串变量doc: 这是我用于调试的代码。我将此字符串保存到超文本标记语言文件中,然后通过浏览器打开它,只是为了仔细检查超文本标记语言内容是否有效,我仍然

  • 问题内容: 当我在文本字段中输入文本时,它将被删除。 这是代码: 问题答案: 同意Subir Kumar Sao和Faiz。

  • 当我在文本字段中输入文本时,它会被删除。 代码如下:

  • 我想将占位符添加到类似于HTML5占位符属性的TextField,但我找不到合适的方法。有没有或唯一的方法是实现自己?

  • 问题内容: 在我的应用程序中,我想要一个带有文本字段的警报。单击“完成”后,我想将文本字段输入保存为字符串。单击“取消”后,我只想关闭警报。我创建了这样的警报: 警报如下所示: 我想知道如何从文本字段中获取文本,以及如何为“完成”按钮和“取消”按钮创建事件。 问题答案: 您可以使用UIAlertController而不是UIAlertView。 我已经使用UIAlertController实现和测

  • 我正在开发一个应用程序,用于将阿拉伯语文本从PDF中提取到字符串变量中,每个单词以相反的顺序出现(而不是专用于解决),有时以正确的顺序出现,但分开的字符(专用于解决)类似于英语字符,但在阿拉伯语中,字符是连接在一起的。任何解决方案:我正在使用visual studio 2017 C#MVC应用程序,在windows 10本地,使用iTextSharp从PDF中读取文本。 注意:问题不仅仅是颠倒顺序