Можно ли обосновать текст в PDFBOX?

Есть ли какая-либо функция в PDFBOX API для выравнивания текста или мы должны делать это вручную? и если вручную, то как оправдать текст с помощью Java(логика за ним)

1 ответ

Решение

Этот старый ответ показывает, как разбить строку на подстроки, вписывающиеся в данный width, Чтобы сделать пример кода, нарисуйте подстроки таким образом, чтобы заполнить всю ширину строки, замените следующим образом (в зависимости от версии PDFBox):

PDFBox 1.8.x

Заменить последний цикл

for (String line: lines)
{
    contentStream.drawString(line);
    contentStream.moveTextPositionByAmount(0, -leading);
}

с этим более сложным:

for (String line: lines)
{
    float charSpacing = 0;
    if (line.length() > 1)
    {
        float size = fontSize * pdfFont.getStringWidth(line) / 1000;
        float free = width - size;
        if (free > 0)
        {
            charSpacing = free / (line.length() - 1);
        }
    }
    contentStream.appendRawCommands(String.format("%f Tc\n", charSpacing).replace(',', '.'));

    contentStream.drawString(line);
    contentStream.moveTextPositionByAmount(0, -leading);
}

(Из теста BreakLongString.java testBreakStringJustified для PDFBox 1.8.x)

Если вам интересно о replace(',', '.') в

contentStream.appendRawCommands(String.format("%f Tc\n", charSpacing).replace(',', '.'));

... моя локаль использует запятую в качестве разделителя десятичных дробей, и после того, как мой первый тестовый запуск привел к запятым в содержимом страницы, я немного ленив и просто добавил, что заменить, чтобы исправить вещи...

PDFBox 2.0.x

Заменить последний цикл

for (String line: lines)
{
    contentStream.showText(line);
    contentStream.newLineAtOffset(0, -leading);
}

с этим более сложным:

for (String line: lines)
{
    float charSpacing = 0;
    if (line.length() > 1)
    {
        float size = fontSize * pdfFont.getStringWidth(line) / 1000;
        float free = width - size;
        if (free > 0)
        {
            charSpacing = free / (line.length() - 1);
        }
    }
    contentStream.setCharacterSpacing(charSpacing);

    contentStream.showText(line);
    contentStream.newLineAtOffset(0, -leading);
}

(Из теста BreakLongString.java testBreakStringJustified для PDFBox 2.0.x)


Это решение просто использует дополнительный межсимвольный интервал (оператор Tc) для обоснования. Вместо этого вы можете использовать дополнительный интервал между словами (оператор Tw), который расширяет только пробелы или их комбинацию; но будьте осторожны: расстояние между словами не работает со всеми кодировками шрифтов. Для получения дополнительной информации об этих операндах см. Таблица 105 Операторы состояния текста, раздел 9.3.2 Межсимвольный интервал и раздел 9.3.3 Межсимвольный интервал в спецификации PDF ISO 32000-1

Вместо бывшего

не выровненный

теперь вы получаете

Как вы видите, есть еще один незначительный дефицит, последняя строка абзаца, очевидно, не должна быть оправдана. Поэтому в последней строке используйте 0 интервал между символами:

    contentStream.appendRawCommands("0 Tc\n"); // PDFBox 1.8.x

    contentStream.setCharacterSpacing(0); // PDFBox 2.0.x

PS Я просто наткнулся на то, что setCharacterSpacing в настоящее время (ноябрь 2016 г.) только в версии разработки 2.1.0-SNAPSHOT, но пока не в версии 2.0.x. Таким образом, в 2.0.x вам, возможно, придется вернуться к использованию appendRawCommands вместо этого, даже если он был помечен как устаревший.

Другие вопросы по тегам