Skip to content

Справочник API: Shaper (Формирование текста)

Класс Shaper отвечает за Формирование текста (Text Shaping): процесс преобразования строки символов Юникода в набор позиционированных глифов из шрифта.

Обзор

Формирование текста необходимо для:

  • Лигатур: Преобразования "f" + "i" в единый глиф "fi".
  • Кернинга: Корректировки расстояния между определенными парами символов (например, "AV").
  • Сложных систем письма: Обработки арабского, деванагари или тайского языков, где форма глифов меняется в зависимости от соседних символов.
  • Двунаправленного текста (BiDi): Обработки смешанного текста слева направо (латиница) и справа налево (арабский/иврит).

Базовое формирование

Чтобы просто получить TextBlob (набор позиционированных глифов) для отрисовки, используйте метод shape().

java
try (Shaper shaper = Shaper.make()) {
    Font font = new Font(typeface, 24);
    
    // Простое формирование (без ограничения по ширине)
    TextBlob blob = shaper.shape("Hello, Skija!", font);
    
    canvas.drawTextBlob(blob, 20, 50, paint);
}

Перенос строк и многострочное формирование

Shaper также может рассчитывать разрывы строк на основе максимальной ширины.

java
float maxWidth = 300f;
TextBlob multiLineBlob = shaper.shape(
    "This is a long sentence that will be wrapped by the shaper.",
    font,
    maxWidth
);

// Примечание: Результирующий TextBlob содержит все строки, корректно позиционированные относительно друг друга.
canvas.drawTextBlob(multiLineBlob, 20, 100, paint);

Параметры формирования

Вы можете управлять поведением формирования (например, направлением текста) с помощью ShapingOptions.

java
ShapingOptions options = ShapingOptions.DEFAULT.withLeftToRight(false); // RTL (справа налево)
TextBlob blob = shaper.shape("مرحبا", font, options, Float.POSITIVE_INFINITY, Point.ZERO);

Расширенное формирование (RunHandler)

Если вам нужен полный контроль над процессом формирования (например, для реализации собственного выделения текста или пользовательской многостилевой верстки), вы можете использовать RunHandler.

java
shaper.shape(text, font, ShapingOptions.DEFAULT, maxWidth, new RunHandler() {
    @Override
    public void beginLine() { ... }

    @Override
    public void runInfo(RunInfo info) {
        // Получить информацию о текущем сегменте глифов
        System.out.println("Glyph count: " + info.getGlyphCount());
    }

    @Override
    public void commitRunInfo() { ... }

    @Override
    public Point commitLine() { return Point.ZERO; }

    // ... другие методы ...
});

Производительность

  • Кэширование: Формирование текста — это вычислительно дорогая операция (с использованием HarfBuzz). Если ваш текст статичен, сформируйте его один раз и сохраните полученный TextBlob.
  • Экземпляр Shaper: Создание Shaper включает инициализацию HarfBuzz. Рекомендуется создать один экземпляр Shaper и повторно использовать его в вашем приложении (обычно его можно безопасно переиспользовать, но проверьте потокобезопасность при использовании нескольких потоков).

Shaper vs. Paragraph

  • Используйте Shaper для высокопроизводительных, однородных по стилю блоков текста или когда вам нужен низкоуровневый доступ к глифам.
  • Используйте Paragraph для форматированного текста (разные цвета/шрифты в одном блоке), сложных UI-макетов и стандартного поведения текстового редактора.