GlyphLookup.fromShape constructor
GlyphLookup.fromShape(
- TextShapeResult shape,
- int codeUnitCount, {
- 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);
}