GlyphLookup.fromShape constructor

GlyphLookup.fromShape(
  1. TextShapeResult shape,
  2. int codeUnitCount, {
  3. String? text,
})

Build a GlyphLookup from shaped text.

codeUnitCount is the number of indices in the target index space. When text is provided, textIndices from shaping (which are codepoint indices) are mapped to UTF-16 code unit indices, so the resulting GlyphLookup works in UTF-16 space. When text is null, textIndices are used as-is (suitable for callers already in codepoint space).

Implementation

factory GlyphLookup.fromShape(
  TextShapeResult shape,
  int codeUnitCount, {
  String? text,
}) {
  // Build codepoint index -> UTF-16 code unit index mapping when text has
  // non-BMP characters (surrogate pairs).
  List<int>? cpToUtf16;
  if (text != null && text.runes.length != text.length) {
    cpToUtf16 = List<int>.filled(text.runes.length + 1, text.length);
    int utf16Index = 0;
    int cpIndex = 0;
    for (final rune in text.runes) {
      cpToUtf16[cpIndex++] = utf16Index;
      utf16Index += rune > 0xFFFF ? 2 : 1;
    }
    cpToUtf16[cpIndex] = utf16Index;
  }

  var glyphIndices = List<int>.filled(codeUnitCount + 1, 0);
  // Build a mapping of code units to glyph indices.
  int glyphIndex = 0;
  int lastTextIndex = 0;
  for (final paragraph in shape.paragraphs) {
    for (final run in paragraph.runs) {
      for (int i = 0; i < run.glyphCount; i++) {
        var textIndex = run.textIndexAt(i);
        // Convert codepoint index to UTF-16 code unit index if needed.
        if (cpToUtf16 != null) {
          textIndex = textIndex < cpToUtf16.length
              ? cpToUtf16[textIndex]
              : codeUnitCount;
        }
        for (int j = lastTextIndex; j < textIndex; j++) {
          glyphIndices[j] = glyphIndex - 1;
        }
        lastTextIndex = textIndex;
        glyphIndex++;
      }
    }
  }
  for (int i = lastTextIndex; i < codeUnitCount; i++) {
    glyphIndices[i] = glyphIndex - 1;
  }
  // Store a fake unreachable glyph at the end to allow selecting the last
  // one.
  glyphIndices[codeUnitCount] =
      codeUnitCount == 0 ? 0 : glyphIndices[codeUnitCount - 1] + 1;
  return GlyphLookup(glyphIndices, cpToUtf16);
}