LineBreakMeasurer выдает результат, отличный от MS Word / LibreOffice


В приложении swing мне нужно предусмотреть текстовое обертывание строки, например, при вводе ее в текстовый процессор, такой как MS Word или LibreOffice. Предоставление той же ширины отображаемой области, того же шрифта (лицо и размер) и той же строки, что и ниже:

  • отображаемая ширина области: 179 мм (в a .doc-файл, настройка портретной страницы формата А4-ширина = 210 мм, поле слева = 20 мм, справа = 11 мм; абзац отформатирован с нулевыми полями)
  • шрифт Times New Roman, размер 14
  • Тестовая строка: Tadf fdas fdas daebjnbvx dasf opqwe dsa: dfa fdsa ewqnbcmv caqw vstrt vsip d asfd eacc

И результат:

  • как в MS Word, так и в LibreOffice эта тестовая строка отображается в одной строке, обтекание текста не происходит.
  • Мой отчет программы bellow обтекание текста происходит, 2 строки

    Строка 1: Tadf fdas fdas daebjnbvx dasf opqwe dsa: dfa fdsa ewqnbcmv caqw vstrt vsip d asfd

    Строка 2: eacc

Так ли это можно ли добиться такого же эффекта обтекания текста, как MS Word в swing? Что может быть не так в коде?

Ниже моя программа

public static List<String> wrapText(String text, float maxWidth,
        Graphics2D g, Font displayFont) {
    // Normalize the graphics context so that 1 point is exactly
    // 1/72 inch and thus fonts will display at the correct sizes:
    GraphicsConfiguration gc = g.getDeviceConfiguration();
    g.transform(gc.getNormalizingTransform());

    AttributedCharacterIterator paragraph = new AttributedString(text).getIterator();
    Font backupFont = g.getFont();
    g.setFont(displayFont);
    LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(
            paragraph, BreakIterator.getWordInstance(), g.getFontRenderContext());
    // Set position to the index of the first character in the paragraph.
    lineMeasurer.setPosition(paragraph.getBeginIndex());

    List<String> lines = new ArrayList<String>();
    int beginIndex = 0;
    // Get lines until the entire paragraph has been displayed.
    while (lineMeasurer.getPosition() < paragraph.getEndIndex()) {
        lineMeasurer.nextLayout(maxWidth);
        lines.add(text.substring(beginIndex, lineMeasurer.getPosition()));
        beginIndex = lineMeasurer.getPosition();
    }

    g.setFont(backupFont);
    return lines;
}

public static void main(String[] args) throws Exception {
    JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JTextPane txtp = new JTextPane();
    frame.add(txtp);
    frame.setSize(200,200);
    frame.setVisible(true);
    Font displayFont = new Font("Times New Roman", Font.PLAIN, 14);

    float textWith = (179 * 0.0393701f) // from Millimeter to Inch
                        * 72f;           // From Inch to Pixel (User space)
    List<String> lines = wrapText(
            "Tadf fdas fdas daebjnbvx dasf opqwe dsa: dfa fdsa ewqnbcmv caqw vstrt vsip d asfd eacc",
            textWith,
            (Graphics2D) txtp.getGraphics(),
            displayFont);
    for (int i = 0; i < lines.size(); i++) {
        System.out.print("Line " + (i + 1) + ": ");
        System.out.println(lines.get(i));
    }
    frame.dispose();
}
1 2

1 ответ:

+1 к вопросу

Из моего опыта работы с текстовыми редакторами невозможно достичь точно такого же измерения.

Вы можете попробовать играть с DPI там по умолчанию DPI=72 и 96 на windows.

Также вы можете попробовать поиграть со всеми подсказками рендеринга графики-сглаживанием текста и т. д.