Skip to content

Commit 9db0789

Browse files
author
vidy
committed
Add test for concat_text method
1 parent 51bd665 commit 9db0789

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

examples/text.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,10 @@ fn main() {
1818
}
1919
}
2020
}
21-
for line in flow.lines {
22-
for w in line.words {
23-
println!("{}", w.text);
24-
}
25-
}
21+
// for line in flow.lines {
22+
// for w in line.words {
23+
// println!("{}", w.text);
24+
// }
25+
// }
2626
// }
2727
}

src/text.rs

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ use crate::{util::avg, flow::{Word, Rect}};
77

88
pub fn concat_text<'a, E: Encoder + 'a>(out: &mut String, items: impl Iterator<Item=&'a TextSpan<E>> + Clone) -> Vec<Word> {
99
let mut words: Vec<Word> = vec![];
10-
// dbg!(items.clone().map(|s| s).collect::<Vec<_>>());
11-
// gaps between each char
10+
11+
// Calculate gaps between each char, the unit is em, relative to the font size.
1212
let gaps = items.clone()
1313
.flat_map(|s| {
14+
// the transform matrix is from em space to device space
15+
// so we need to invert it
1416
let tr_inv = s.transform.matrix.inverse();
1517
let pos = (tr_inv * s.transform.vector).x();
18+
1619
s.chars.iter()
1720
.filter(|c| !s.text[c.offset..].chars().next().unwrap().is_whitespace())
1821
.map(move |c| (c.pos + pos, c.pos + pos + c.width, s.font_size))
@@ -26,6 +29,7 @@ pub fn concat_text<'a, E: Encoder + 'a>(out: &mut String, items: impl Iterator<I
2629
let space_gap = (0.5 * font_size).min(2.0 * avg(gaps).unwrap_or(0.0)); //2.0 * gaps[gaps.len()/2];
2730

2831
let mut end = 0.; // trailing edge of the last char
32+
// out中最后一个字符是否是空格
2933
let mut trailing_space = out.chars().last().map(|c| c.is_whitespace()).unwrap_or(true);
3034
let mut word_start_pos = 0.0;
3135
let mut word_start_idx = out.len();
@@ -38,16 +42,19 @@ pub fn concat_text<'a, E: Encoder + 'a>(out: &mut String, items: impl Iterator<I
3842
let mut pos = 0; // byte index of last char into span.text
3943
let tr_inv = span.transform.matrix.inverse();
4044
let x_off = (tr_inv * span.transform.vector).x();
45+
4146
for c in span.chars.iter() {
42-
47+
// current string of TextChar
4348
let s = &span.text[pos..c.offset];
4449
if c.offset > 0 {
4550
let is_whitespace = s.chars().all(|c| c.is_whitespace());
51+
// 在不为空格的时候, 将 s 写入 out.
4652
if !trailing_space || !is_whitespace {
4753
out.extend(s.nfkc());
4854
}
4955
trailing_space = is_whitespace;
5056
}
57+
// 在 s 不为空格,且有gap 的时候,记录一个 word.
5158
if !trailing_space && c.pos + x_off > end + space_gap {
5259
words.push(Word {
5360
text: out[word_start_idx..].into(),
@@ -80,6 +87,7 @@ pub fn concat_text<'a, E: Encoder + 'a>(out: &mut String, items: impl Iterator<I
8087
y_max = y_max.max(span.rect.max_y());
8188
}
8289
}
90+
8391
trailing_space = span.text[pos..].chars().all(|c| c.is_whitespace());
8492

8593
out.extend(span.text[pos..].nfkc());
@@ -95,4 +103,51 @@ pub fn concat_text<'a, E: Encoder + 'a>(out: &mut String, items: impl Iterator<I
95103
});
96104

97105
words
106+
}
107+
108+
#[cfg(test)]
109+
mod tests {
110+
use pathfinder_geometry::{rect::RectF, transform2d::Transform2F};
111+
use pdf_render::{font::OutlineBuilder, Fill, TextChar};
112+
113+
use super::*;
114+
115+
#[test]
116+
fn test_concat_text() {
117+
let text_span: TextSpan<OutlineBuilder> = TextSpan {
118+
rect: RectF::from_points(Vector2F::new(56.8, 55.85077), Vector2F::new(136.26399, 67.85077)),
119+
width: 79.464,
120+
bbox: None,
121+
font_size: 12.0,
122+
font: None,
123+
text: "hello world".to_string(),
124+
chars: vec![
125+
TextChar { offset: 0, pos: 0.0, width: 7.224001 },
126+
TextChar { offset: 1, pos: 7.224001, width: 7.224001 },
127+
TextChar { offset: 2, pos: 14.448002, width: 7.224001 },
128+
TextChar { offset: 3, pos: 21.672003, width: 7.224001 },
129+
TextChar { offset: 4, pos: 28.896004, width: 7.224001 },
130+
TextChar { offset: 5, pos: 36.120003, width: 7.224001 },
131+
TextChar { offset: 6, pos: 43.344, width: 7.224001 },
132+
TextChar { offset: 7, pos: 50.568, width: 7.224001 },
133+
TextChar { offset: 8, pos: 57.792, width: 7.224001 },
134+
TextChar { offset: 9, pos: 65.016, width: 7.224001 },
135+
TextChar { offset: 10, pos: 72.24, width: 7.224001 },
136+
],
137+
color: Fill::Solid(0.0, 0.5019608, 0.0),
138+
alpha: 1.0,
139+
transform: Transform2F::row_major(1.0, 0.0, 56.8, 0.0, 1.0, 67.85077),
140+
mode: pdf::content::TextMode::Fill,
141+
op_nr: 18,
142+
};
143+
144+
let mut output = String::new();
145+
let words = concat_text(&mut output, vec![&text_span].into_iter());
146+
147+
// Assert the concatenated text
148+
assert_eq!(output, "hello world");
149+
150+
// Assert the words
151+
assert_eq!(words.len(), 2); // Expect two words: "hello" and "world"
152+
}
98153
}

0 commit comments

Comments
 (0)