From ecbb2c8c42a51b53ee8279e81fc527b6079b897d Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Wed, 7 Oct 2026 17:49:05 -0400 Subject: [PATCH] =?UTF-8?q?Type:=20the=20Japanese=E2=80=93Latin=20quarter?= =?UTF-8?q?=20em=20leaves=20Hangul=20alone=20and=20counts=20=E3=80=85=20?= =?UTF-8?q?=E3=80=86=20=E3=80=87=20as=20letters=20(#370=20follow-up)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- crates/text/src/layout.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/text/src/layout.rs b/crates/text/src/layout.rs index 8ad1fe1e..f436eca0 100644 --- a/crates/text/src/layout.rs +++ b/crates/text/src/layout.rs @@ -269,10 +269,14 @@ fn compress_punctuation(sg: &mut [SGlyph]) -> Vec { const WAKAN_AKI: f64 = 0.25; /// A Japanese character for the space next to Latin text: kana and kanji (and full-width -/// letters), not punctuation or symbols. +/// letters, and the iteration and abbreviation marks 々 〆 〇), not punctuation or symbols, nor +/// Hangul (Korean sets a word space instead). fn is_japanese_letter(c: char) -> bool { + if matches!(c, '々' | '〆' | '〇') { + return true; + } is_cjk(c) - && !matches!(c as u32, 0x3000..=0x303F | 0xFF01..=0xFF0F | 0xFF1A..=0xFF20 | 0xFF3B..=0xFF40 | 0xFF5B..=0xFF65) + && !matches!(c as u32, 0x3000..=0x303F | 0xAC00..=0xD7AF | 0xFF01..=0xFF0F | 0xFF1A..=0xFF20 | 0xFF3B..=0xFF40 | 0xFF5B..=0xFF65) && c != '・' && punct(c).is_none() } @@ -763,6 +767,17 @@ fn kinsoku_between(before: char, after: Option) -> bool { !no_line_end(before) && after.is_none_or(|c| !no_line_start(c)) } +#[cfg(test)] +#[test] +fn japanese_letters_for_the_latin_space_are_kana_kanji_and_marks_not_hangul_or_punctuation() { + for c in ['あ', 'カ', '漢', '々', '〆', '〇', 'A'] { + assert!(is_japanese_letter(c), "{c}"); + } + for c in ['한', '。', '「', '・', '、', 'a'] { + assert!(!is_japanese_letter(c), "{c}"); + } +} + #[cfg(test)] #[test] fn kinsoku_keeps_closing_marks_off_line_starts_and_opening_ones_off_line_ends() {