Недостающий пробел перед разрывами строк в PDF / UA с iText 5

#itext

#itext

Вопрос:

При создании документа PDF / UA с iText 5.5.10 кажется, что все пробелы перед разрывом строк удалены, что, по-видимому, сбивает с толку некоторые программы чтения с экрана. Следующий пример создает этот текст (обратите внимание, что перед разрывом строки нет пробела):

 The quick brown fox jumps over the lazy dog. The quick
brown fox jumps over the lazy dog. The quick brown fox
jumps over the lazy dog. 
  

При чтении в программе чтения с экрана появляются объединенные слова (обратите внимание на «quickbrown» и «foxjumps»):

Слова объединяются в PAC

Объединенные слова в NVDA Speech Viewer

Конкатенация происходит там, где в документе PDF помещаются разрывы строк.

Вот минимальный образец для воспроизведения (PDFAWriter и встраивание шрифтов не используются для уменьшения размера выборки, поскольку, похоже, это не имеет значения):

 package sandbox.pdfa;

import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.FontFactory;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class PdfUaSpike {

    static public void main(String args[]) throws IOException, DocumentException {
        final String DEST = "results/pdfa/pdfua.pdf";
        File file = new File(DEST);
        file.getParentFile().mkdirs();
        new PdfUaSpike().createPdf(DEST).showExtractedText(DEST);
    }

    public PdfUaSpike createPdf(String dest) throws IOException, DocumentException {
        Document document = new Document();
        PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
        writer.setPdfVersion(PdfWriter.VERSION_1_7);
        writer.setTagged();
        writer.setViewerPreferences(PdfWriter.DisplayDocTitle);
        document.addLanguage("en-US");
        document.addTitle("English pangram");
        writer.createXmpMetadata();
        document.open();

        Font font = FontFactory.getFont(FontFactory.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED, 20);

        {
            Paragraph p = new Paragraph();
            p.setFont(font);

            String sampleText = IntStream.range(0, 3)
                    .mapToObj(i -> "The quick brown fox jumps over the lazy dog. ")
                    .collect(Collectors.joining());

            p.add(sampleText);
            document.add(p);
        }

        document.close();

        return this;
    }

    private void showExtractedText(String path) throws IOException {
        System.out.println("Notice that spaces before linebreaks have been removed:"   System.lineSeparator());
        String extractedText = PdfTextExtractor.getTextFromPage(new PdfReader(path), 1);
        System.out.println(extractedText);
    }

}
  

Зависимости для этого примера:

 com.itextpdf:itextpdf:jar:5.5.10:compile
com.itextpdf:itext-pdfa:jar:5.5.10:compile
  

При тестировании PDF, экспортированного из Word, в документе отображаются пробелы перед разрывами строк, и это отлично работает в программах чтения с экрана.

Есть ли какой-либо способ настроить iText, чтобы также сохранять пробелы перед разрывами строк?

Файл iText PDF создан в Linux и протестирован в Windows.

Ответ №1:

По предположению, одна часть вашего стека создает документы с разрывами строк Unix (LF), а другая пытается «исправить» разрывы строк Windows (CR LF), слепо удаляя байт перед LF, не проверяя, является ли это CR в первую очередь.