Короче говоря
Причина этой проблемы заключается в том, что подпрограмма, которая объединяет извлеченные фрагменты текста в один String
для применения регулярного выражения, не вставляет ни одного индикатора для разрыва строки.Таким образом, в этом String
за последней буквой из одной строки сразу же следует первая буква следующей, которая скрывает границу слова.Поведение можно исправить, добавив соответствующий символ к String
в случае разрыва строки.
Проблемный код
Подпрограмма, которая объединяет извлеченные фрагменты текста в один String
это CharacterRenderInfo.mapString(List<CharacterRenderInfo>)
в упаковке com.itextpdf.kernel.pdf.canvas.parser.listener
.В случае просто горизонтального разрыва эта подпрограмма вставляет символ пробела, но в случае вертикального смещения, то есть разрыва строки, она не добавляет ничего дополнительного к StringBuilder
, в котором генерируется представление String
:
if (chunk.sameLine(lastChunk)) {
// we only insert a blank space if the trailing character of the previous string wasn't a space, and the leading character of the current string isn't a space
if (chunk.getLocation().isAtWordBoundary(lastChunk.getLocation()) && !chunk.getText().startsWith(" ") && !chunk.getText().endsWith(" ")) {
sb.append(' ');
}
indexMap.put(sb.length(), i);
sb.append(chunk.getText());
} else {
indexMap.put(sb.length(), i);
sb.append(chunk.getText());
}
Возможное исправление
В случае разрыва строки можно расширить приведенный выше код для вставки символа новой строки:
if (chunk.sameLine(lastChunk)) {
// we only insert a blank space if the trailing character of the previous string wasn't a space, and the leading character of the current string isn't a space
if (chunk.getLocation().isAtWordBoundary(lastChunk.getLocation()) && !chunk.getText().startsWith(" ") && !chunk.getText().endsWith(" ")) {
sb.append(' ');
}
indexMap.put(sb.length(), i);
sb.append(chunk.getText());
} else {
sb.append('\n');
indexMap.put(sb.length(), i);
sb.append(chunk.getText());
}
Этот CharacterRenderInfo.mapString
метод вызывается только изRegexBasedLocationExtractionStrategy
метод getResultantLocations()
(пакет com.itextpdf.kernel.pdf.canvas.parser.listener
) и только для упомянутой задачи, т.е. применения рассматриваемого регулярного выражения.Таким образом, если разрешить ему надлежащим образом разрешить распознавание границ слов, это не должно нарушать ничего, но действительно должно рассматриваться как исправление.
Можно просто добавить другой символ для переноса строки, например, простой пробел ' '
, еслиНельзя рассматривать вертикальные разрывы иначе, чем горизонтальные.Поэтому для общего исправления можно рассмотреть вопрос о том, чтобы сделать этот символ настраиваемым свойством стратегии.
Версии
Я тестировал с iText 7.1.4-SNAPSHOT и PDFSweep 2.0.3-SNAPSHOT.