isWideGrapheme function
Returns true if the given grapheme cluster is a double-width (wide) character.
Optimization Note - Zero-Allocation Fast-Path:
- For single BMP characters (length == 1), checks if the code unit is >= 0x1100 (the lowest wide character in Unicode is Hangul Jamo U+1100). If < 0x1100, exits in a single CPU comparison without any heap allocations.
- For multi-code-unit graphemes, scans code units directly for Variation Selector-16 (0xFE0F), Combining Enclosing Keycap (0x20E3), or Zero-Width Joiner (0x200D), which force 2-column emoji presentation.
- For SMP characters (surrogate pairs), decodes the first code point via bitwise math. This implementation achieves zero Runes/Iterator allocations in hot render loops.
Implementation
bool isWideGrapheme(String grapheme) {
final len = grapheme.length;
if (len == 0) return false;
final cu0 = grapheme.codeUnitAt(0);
// Fast-path: single BMP character
if (len == 1) {
return cu0 >= 0x1100 && isWideCodePoint(cu0);
}
// Extract first code point (decode surrogate pair if SMP)
var firstRune = cu0;
if (cu0 >= 0xD800 && cu0 <= 0xDBFF && len >= 2) {
final cu1 = grapheme.codeUnitAt(1);
if (cu1 >= 0xDC00 && cu1 <= 0xDFFF) {
firstRune = 0x10000 + ((cu0 & 0x3FF) << 10) + (cu1 & 0x3FF);
}
}
// Multi-code-unit cluster:
// 1. Combining Enclosing Keycap (0x20E3): makes keycap sequences (e.g. 1๏ธโฃ, #๏ธโฃ) wide (2 cells).
// 2. Variation Selector-16 (0xFE0F): forces emoji presentation (wide) for symbols/pictographs (firstRune >= 0x2000).
// 3. Zero-Width Joiner (0x200D): joins emoji sequences (e.g. ๐ฉโ๐ป, ๐จโ๐ฉโ๐งโ๐ฆ, ๐ฑโ๐ค) into a single wide emoji.
// Only applies to emoji sequences where firstRune >= 0x2000 (not Latin letters with ZWJ).
for (var i = 1; i < len; i++) {
final cu = grapheme.codeUnitAt(i);
if (cu == 0x20E3) return true;
if ((cu == 0xFE0F || cu == 0x200D) && firstRune >= 0x2000) return true;
}
return isWideCodePoint(firstRune);
}