Skip to content

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

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

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

Conversation

@edugomz

@edugomz edugomz commented Aug 24, 2026

Copy link
Copy Markdown

Fixes #4851

Continues #4865 with the requested changes addressed:

  • Table is now derived from Unicode's East_Asian_Width=W/F data instead of Emoji_Presentation, so regional indicators (flag halves) aren't individually double-counted - 🇺🇸 still measures 2 columns, not 4
  • display_width_of() remains FMT_CONSTEXPR

Testing

Regression tests added to test/format-test.cc: the #4851 example, multiple/mixed emoji, precision truncation, alignment, newly-covered ranges, and a regional indicator (flag) pair.

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 requested a review from vitaut as a code owner August 24, 2026 18:31

@vitaut vitaut left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standard width rules are not just East_Asian_Width=W/F; [format.string.std] also explicitly includes 1F300–1F5FF and 1F900–1F9FF.

Comment thread include/fmt/format.h
(cp >= 0x1f300 && cp <= 0x1f64f) ||
// Supplemental Symbols and Pictographs:
(cp >= 0x1f900 && cp <= 0x1f9ff))));
FMT_CONSTEXPR auto display_width_of(uint32_t cp) noexcept -> size_t {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think inline is needed here.

@vitaut vitaut mentioned this pull request Aug 25, 2026
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

2 participants