#![cfg(any(target_os = "macos", target_os = "windows"))]
use slate_framework::text_system::TextSystem;
fn compose(committed: &str, caret: usize, preedit: &str) -> String {
let mut at = caret.min(committed.len());
while at > 0 && !committed.is_char_boundary(at) {
at -= 1;
}
format!("{}{}{}", &committed[..at], preedit, &committed[at..])
}
fn text_system() -> (TextSystem, slate_framework::text_system::PlatformFont) {
let mut ts = TextSystem::new().expect("create TextSystem");
let font = ts
.load_font_from_bytes(slate_text::TEST_FONT, 14.0, 1.0)
.expect("load bundled font");
(ts, font)
}
fn wrapped(
ts: &TextSystem,
font: &slate_framework::text_system::PlatformFont,
text: &str,
w: f32,
) -> slate_text::MultilineLayout {
let doc = ts.shape_document(font, text).expect("shape document");
slate_text::wrap_document(&doc, w)
}
#[test]
fn preedit_composes_into_layout_and_widens_line() {
let (ts, font) = text_system();
let committed = wrapped(&ts, &font, "ab", 1000.0);
let display = compose("ab", 2, "你好");
assert_eq!(display, "ab你好");
let composed = wrapped(&ts, &font, &display, 1000.0);
assert_eq!(
composed.lines.len(),
1,
"short composition stays on one line"
);
let committed_w = committed.lines[0].line.width_lpx;
let composed_w = composed.lines[0].line.width_lpx;
assert!(
composed_w > committed_w,
"composed line ({composed_w}) must be wider than committed ({committed_w}) — preedit adds advance"
);
}
#[test]
fn caret_sits_after_composition() {
let (ts, font) = text_system();
let display = compose("ab", 2, "你好");
let composed = wrapped(&ts, &font, &display, 1000.0);
let display_caret = 2 + "你好".len();
let (line_idx, caret_x, _) = composed.caret_position(display_caret);
assert_eq!(line_idx, 0);
let committed = wrapped(&ts, &font, "ab", 1000.0);
let committed_end_x = committed.caret_position(2).1;
assert!(
caret_x > committed_end_x,
"caret after composition ({caret_x}) must be past committed end ({committed_end_x})"
);
assert!(caret_x <= composed.lines[0].line.width_lpx + 0.01);
}
#[test]
fn long_preedit_wraps_to_next_visual_line() {
let (ts, font) = text_system();
let committed_text = "aaaaaa";
let one_line = wrapped(&ts, &font, committed_text, 1000.0);
assert_eq!(one_line.lines.len(), 1, "committed text alone is one line");
let line_w = one_line.lines[0].line.width_lpx;
let display = compose(committed_text, committed_text.len(), "bbbbbbbbbb");
let composed = wrapped(&ts, &font, &display, line_w + 1.0);
assert!(
composed.lines.len() > 1,
"long composition past the wrap width must grow the line count (got {})",
composed.lines.len()
);
}
#[test]
fn empty_preedit_leaves_layout_unchanged() {
let (ts, font) = text_system();
let committed = wrapped(&ts, &font, "hello", 1000.0);
let display = compose("hello", 3, "");
let composed = wrapped(&ts, &font, &display, 1000.0);
assert_eq!(display, "hello");
assert_eq!(composed.lines.len(), committed.lines.len());
assert!((composed.lines[0].line.width_lpx - committed.lines[0].line.width_lpx).abs() < 0.01);
}