From 74296309fe11fbcda3d74b25913af8bfc54c2f72 Mon Sep 17 00:00:00 2001 From: "zhuoxian.dzx" Date: Mon, 5 Aug 2024 01:17:22 +0800 Subject: [PATCH] fix: complex composition calculation not correct --- package.json | 2 +- src/metrics.rs | 10 ++++------ src/metrics/compose.rs | 35 ++++++++++++++++++----------------- tests/basic.rs | 36 ++++++++++++++++++++++++++++++++++-- 4 files changed, 57 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index b990e2f..0d69fa5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fontkit-rs", - "version": "0.0.11-beta.3", + "version": "0.0.11-beta.5", "description": "Toolkit used to load, match, measure, and render texts", "main": "index.js", "directories": { diff --git a/src/metrics.rs b/src/metrics.rs index 91560a3..7bc75a9 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -288,14 +288,12 @@ impl TextMetrics { if self.units == 0 { return 0.0; } - let factor = font_size / self.units as f32; let positions = self.positions.read().unwrap(); positions.iter().take(index).fold(0.0, |current, p| { - current - + p.kerning as f32 * factor - + p.metrics.advanced_x as f32 * factor - + letter_spacing - }) + current + p.kerning as f32 + p.metrics.advanced_x as f32 + }) * font_size + / self.units as f32 + + letter_spacing * (index as f32) } pub fn width_trim_start(&self, font_size: f32, letter_spacing: f32) -> f32 { diff --git a/src/metrics/compose.rs b/src/metrics/compose.rs index 9442d0f..5c7a172 100644 --- a/src/metrics/compose.rs +++ b/src/metrics/compose.rs @@ -184,7 +184,7 @@ where } is_first_line = false; let line_width = line.width(); - if width - (line_width + current_line_width) >= -0.01 { + if width - (line_width + current_line_width) >= -0.1 { // Current line fits, push all of its spans into current line current_line_width += line_width; current_line.spans.append(&mut line.spans); @@ -195,7 +195,7 @@ where // Go through spans to get the first not-fitting span let index = line.spans.iter().position(|span| { let span_width = span.width(); - if span_width + current_line_width <= width { + if span_width + current_line_width - width <= 0.1 { current_line_width += span_width; false } else { @@ -231,7 +231,6 @@ where span.letter_spacing, width - current_line_width, ); - if new_metrics.count() != 0 { failed_with_no_acception = false; } @@ -255,17 +254,23 @@ where // Add new_span to next line let mut new_line = Line { hard_break: false, - spans: vec![new_span], + spans: vec![], }; - // Check for swallowed leading space - if new_line.spans[0].metrics.value().starts_with(" ") { - new_line.spans[0].swallow_leading_space = true; + if new_span.metrics.count() != 0 { + new_line.spans.push(new_span); } for span in line.spans.into_iter().skip(1) { new_line.spans.push(span); } - lines.push_front(new_line); current_line_width = 0.0; + if new_line.spans.is_empty() { + continue; + } + // Check for swallowed leading space + if new_line.spans[0].metrics.value().starts_with(" ") { + new_line.spans[0].swallow_leading_space = true; + } + lines.push_front(new_line); } } if !current_line.spans.is_empty() { @@ -460,7 +465,7 @@ impl TextMetrics { // Textwrap cannot find a good break point, we directly drop chars loop { let span_width = self.width_until(font_size, letter_spacing, naive_break_index); - if span_width <= width || naive_break_index == 0 { + if span_width - width <= 0.1 || naive_break_index == 0 { break; } naive_break_index -= 1; @@ -563,14 +568,10 @@ impl TextMetrics { drop(positions); // Split here, create a new span let mut new_metrics = self.clone(); - if real_index == 0 { - new_metrics.positions = Arc::new(RwLock::new(vec![])); - } else { - new_metrics.positions = { - let mut p = self.positions.write().unwrap(); - Arc::new(RwLock::new(p.split_off(real_index))) - }; - } + new_metrics.positions = { + let mut p = self.positions.write().unwrap(); + Arc::new(RwLock::new(p.split_off(real_index))) + }; new_metrics } } diff --git a/tests/basic.rs b/tests/basic.rs index 6ea9ea1..61ef32f 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -54,7 +54,8 @@ pub fn test_search_font() -> Result<(), Error> { pub fn test_text_wrap() -> Result<(), Error> { let fontkit = FontKit::new(); fontkit.search_fonts_from_path("examples/AlimamaFangYuanTiVF.ttf")?; - let key = fontkit.font_keys().next().unwrap(); + let mut key = FontKey::default(); + key.family = "AlimamaFangYuanTiVF-Medium-Round".into(); let mut area = Area::<(), TextMetrics>::new(); let metrics = fontkit .measure(&key, " 傲冬黑色真皮皮衣 穿着舒适显瘦") @@ -69,6 +70,37 @@ pub fn test_text_wrap() -> Result<(), Error> { }); area.unwrap_text(); area.wrap_text(576.0)?; - assert_eq!(area.width(), 549.12); + assert_eq!(area.width(), 553.608); + Ok(()) +} + +#[test] +pub fn test_complex_text_wrap() -> Result<(), Error> { + let fontkit = FontKit::new(); + fontkit.search_fonts_from_path("examples/AlimamaFangYuanTiVF.ttf")?; + let mut key = FontKey::default(); + key.family = "AlimamaFangYuanTiVF-Medium-Round".into(); + let mut area = Area::<(), TextMetrics>::new(); + let metrics = fontkit.measure(&key, "商家").unwrap(); + let mut span = Span::default(); + span.font_key = key.clone(); + span.size = 32.0; + span.metrics = metrics; + let metrics = fontkit.measure(&key, "热卖12345678").unwrap(); + let mut span_1 = Span::default(); + span_1.font_key = key.clone(); + span_1.size = 32.0; + span_1.metrics = metrics; + area.lines.push(Line { + spans: vec![span], + hard_break: true, + }); + area.lines.push(Line { + spans: vec![span_1], + hard_break: true, + }); + area.unwrap_text(); + area.wrap_text(64.4)?; + assert_eq!(area.value_string(), "商家\n热卖\n1234\n567\n8"); Ok(()) }