Skip to content

Fix inconsistent display width for emoji outside East Asian Wide ranges - #4865

Open
edugomz wants to merge 3 commits into
fmtlib:mainfrom
edugomz:fix-emoji-display-width
Open

Fix inconsistent display width for emoji outside East Asian Wide ranges#4865
edugomz wants to merge 3 commits into
fmtlib:mainfrom
edugomz:fix-emoji-display-width

Conversation

@edugomz

@edugomz edugomz commented Jul 23, 2026

Copy link
Copy Markdown

Fixes #4851

Problem

  • display_width_of() only counted East Asian Wide/Fullwidth code points and two hand-picked emoji ranges (U+1F300-1F64F, U+1F900-1F9FF) as 2 columns wide
  • Emoji outside those ranges (e.g. ❌ U+274C, ✅ U+2705, in the Dingbats block) were measured as 1 column, even though most terminals render them double-width
  • Result: inconsistent {:^N} padding vs. CJK text
fmt::println("|{:^20}|", "");
fmt::println("|{:^20}|", "");
|         ❌          |
|         我         |

Fix

  • Replaced the boolean-expression range check with a sorted range table, looked up via binary search
  • Table = original East Asian Wide/Fullwidth blocks + full Emoji_Presentation set from Unicode's emoji-data.txt (fetched from unicode.org, not hand-transcribed)

Testing

Added regression tests (test/format-test.cc) for:

  • exact example from Inconsistent widths when UTF8 characters are used #4851
  • multiple emoji back to back
  • mixed emoji/CJK/ASCII content
  • precision truncation at a display-width boundary
  • alignment/fill variants
  • newly-covered ranges (Transport, Symbols Extended-A)
  • regional indicator (flag) pairs — documents current per-code-point behavior since fmt has no grapheme clustering

Full suite passes: 147/147 format-test, 21/21 ctest binaries.

edugomz added 3 commits July 24, 2026 00:10
fmt::detail::display_width_of() only treated East Asian Wide/Fullwidth
code points and two hand-picked emoji ranges as two columns wide, so
emoji outside those ranges (e.g. the Dingbats block: cross mark U+274C,
white heavy check mark U+2705) were measured as one column even though
most terminals render them double-width. This produced visibly
inconsistent padding under {:^N} compared to CJK text (fixes fmtlib#4851).

Replaced the ad hoc boolean expression with a sorted table of ranges
(East Asian Wide/Fullwidth plus the full Emoji_Presentation set from
Unicode's emoji-data.txt) looked up via binary search, and added
regression tests covering the original report plus edge cases:
multiple emoji, mixed emoji/CJK/ASCII content, precision truncation,
alignment/fill variants, newly covered emoji ranges, and regional
indicator (flag) pairs.
@edugomz
edugomz marked this pull request as ready for review July 28, 2026 19:16
@edugomz
edugomz requested a review from vitaut as a code owner July 28, 2026 19:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Inconsistent widths when UTF8 characters are used

1 participant