1use super::{RunSpecial, TextDisplay};
9use crate::conv::{to_u32, to_usize};
10use crate::fonts::{self, FontLibrary};
11use crate::shaper::{GlyphRun, PartMetrics};
12use crate::{Align, Range, Vec2};
13use smallvec::SmallVec;
14use std::num::NonZeroUsize;
15use tinyvec::TinyVec;
16use unicode_bidi::{LTR_LEVEL, Level};
17
18#[derive(Clone, Debug, Default)]
19pub struct RunPart {
20 pub text_end: u32,
21 pub glyph_run: u32,
22 pub glyph_range: Range,
23 pub offset: Vec2,
24}
25
26#[derive(Clone, Debug, Default)]
28pub struct Line {
29 text_range: Range, pub(crate) run_range: Range, pub(crate) top: f32,
32 pub(crate) bottom: f32,
33}
34
35impl Line {
36 #[inline]
38 pub fn text_range(&self) -> std::ops::Range<usize> {
39 self.text_range.to_std()
40 }
41
42 #[inline]
44 pub fn top(&self) -> f32 {
45 self.top
46 }
47
48 #[inline]
50 pub fn bottom(&self) -> f32 {
51 self.bottom
52 }
53}
54
55impl TextDisplay {
56 pub fn measure_width(&self, max_width: f32) -> f32 {
67 let mut max_line_len = 0.0f32;
68 let mut caret = 0.0;
69 let mut line_len = 0.0;
70
71 for run in self.runs.iter() {
72 let num_parts = run.num_parts();
73 let part = run.part_lengths(0..num_parts);
74
75 if part.len_no_space > 0.0 {
76 line_len = caret + part.len_no_space;
77 if line_len >= max_width {
78 return max_width;
79 }
80 }
81 caret += part.len;
82
83 if run.special == RunSpecial::HardBreak {
84 max_line_len = max_line_len.max(line_len);
85 caret = 0.0;
86 line_len = 0.0;
87 }
88 }
89
90 max_line_len.max(line_len)
91 }
92
93 pub fn measure_height(&self, wrap_width: f32, max_lines: Option<NonZeroUsize>) -> f32 {
100 #[derive(Default)]
101 struct MeasureAdder {
102 parts: Vec<usize>, lines: usize,
104 line_gap: f32,
105 vcaret: f32,
106 }
107
108 impl PartAccumulator for MeasureAdder {
109 fn num_parts(&self) -> usize {
110 self.parts.len()
111 }
112
113 fn num_lines(&self) -> usize {
114 self.lines
115 }
116
117 fn add_part(
118 &mut self,
119 _: &[GlyphRun],
120 run_index: usize,
121 _: std::ops::Range<usize>,
122 _: PartMetrics,
123 checkpoint: bool,
124 ) {
125 if checkpoint
126 && let Some(index) = self.parts.last().cloned()
127 && index == run_index
128 {
129 return;
130 }
131
132 self.parts.push(run_index);
133 }
134
135 fn add_line(
136 &mut self,
137 fonts: &FontLibrary,
138 runs: &[GlyphRun],
139 parts_end: usize,
140 _: bool,
141 ) {
142 debug_assert!(parts_end > 0);
143 let parts = &mut self.parts[..parts_end];
144
145 let mut last_run = usize::MAX;
147 let (mut ascent, mut descent, mut line_gap) = (0f32, 0f32, 0f32);
148 for run_index in parts.iter().cloned() {
149 if last_run == run_index {
150 continue;
151 }
152 last_run = run_index;
153 let run = &runs[last_run];
154
155 let scale_font = fonts.get_face(run.face_id).scale_by_dpu(run.dpu);
156 ascent = ascent.max(scale_font.ascent());
157 descent = descent.min(scale_font.descent());
158 line_gap = line_gap.max(scale_font.line_gap());
159 }
160
161 if self.lines > 0 {
162 self.vcaret += line_gap.max(self.line_gap);
163 }
164 self.vcaret += ascent - descent;
165 self.line_gap = line_gap;
166
167 self.vcaret = self.vcaret.round();
169
170 self.lines += 1;
171 self.parts.clear();
172 }
173 }
174
175 let mut adder = MeasureAdder::default();
176 let max_lines = max_lines.map(|n| n.get()).unwrap_or(0);
177 self.wrap_lines(&mut adder, wrap_width, max_lines);
178 adder.vcaret
179 }
180
181 pub fn prepare_lines(&mut self, wrap_width: f32, width_bound: f32, h_align: Align) -> f32 {
213 debug_assert!(width_bound.is_finite());
214 let mut adder = LineAdder::new(width_bound, h_align);
215
216 self.wrap_lines(&mut adder, wrap_width, 0);
217
218 self.wrapped_runs = adder.wrapped_runs;
219 self.lines = adder.lines;
220 #[cfg(feature = "num_glyphs")]
221 {
222 self.num_glyphs = adder.num_glyphs;
223 }
224 self.l_bound = adder.l_bound.min(adder.r_bound);
225 self.r_bound = adder.r_bound;
226 adder.vcaret
227 }
228
229 fn wrap_lines(
230 &self,
231 accumulator: &mut impl PartAccumulator,
232 wrap_width: f32,
233 max_lines: usize,
234 ) {
235 let fonts = fonts::library();
236
237 let mut start = (0, 0, 0);
239 let mut end = start;
240
241 let mut caret = 0.0;
242 let mut run_index = start.0;
243
244 let end_index = self.runs.len();
245 'a: while run_index < end_index {
246 let run = &self.runs[run_index];
247 let num_parts = run.num_parts();
248
249 let hard_break = run.special == RunSpecial::HardBreak;
250 let allow_break = run.special != RunSpecial::NoBreak;
251 let tab = run.special == RunSpecial::HTab;
252
253 let mut last_part = start.1;
254 let mut part_index = last_part + 1;
255 while part_index <= num_parts {
256 let mut part = run.part_lengths(last_part..part_index);
257 if tab {
258 let sf = fonts.get_face(run.face_id).scale_by_dpu(run.dpu);
266 let tab_size = sf.h_advance(sf.face().glyph_index(' ')) * 8.0;
268 let stops = (caret / tab_size).floor() + 1.0;
269 part.len = tab_size * stops - caret;
270 }
271
272 let line_len = caret + part.len_no_space;
273 if line_len > wrap_width && end.2 > 0 {
274 accumulator.add_line(fonts, &self.runs, end.2, true);
276
277 if accumulator.num_lines() == max_lines {
278 return;
279 }
280
281 end.2 = 0;
282 start = end;
283 caret = 0.0;
284 run_index = start.0;
285 continue 'a;
286 }
287 caret += part.len;
288 let checkpoint = part_index < num_parts || allow_break;
289 accumulator.add_part(
290 &self.runs,
291 run_index,
292 last_part..part_index,
293 part,
294 checkpoint,
295 );
296 if checkpoint {
297 end = (run_index, part_index, accumulator.num_parts());
298 }
299 last_part = part_index;
300 part_index += 1;
301 }
302
303 run_index += 1;
304 start.1 = 0;
305
306 if hard_break || run_index == end_index {
307 let num_parts = accumulator.num_parts();
308 if num_parts > 0 {
309 debug_assert_eq!(num_parts, end.2);
311
312 accumulator.add_line(fonts, &self.runs, num_parts, false);
313
314 if accumulator.num_lines() == max_lines {
315 return;
316 }
317 }
318
319 start = (run_index, 0, 0);
320 end = start;
321
322 caret = 0.0;
323 run_index = start.0;
324 }
325 }
326 }
327
328 pub fn apply_offset(&mut self, offset: Vec2) {
333 for run in &mut self.wrapped_runs {
334 run.offset += offset;
335 }
336 for line in &mut self.lines {
337 line.top += offset.1;
338 line.bottom += offset.1;
339 }
340 self.l_bound += offset.0;
341 self.r_bound += offset.0;
342 }
343
344 pub fn vertically_align(&mut self, bound: f32, v_align: Align) {
348 debug_assert!(bound.is_finite());
349
350 if self.lines.is_empty() {
351 return;
352 }
353
354 let top = self.lines.first().unwrap().top;
355 let bottom = self.lines.last().unwrap().bottom;
356 let height = bottom - top;
357 let new_offset = match v_align {
358 _ if height >= bound => 0.0,
359 Align::Default | Align::TL | Align::Stretch => 0.0,
360 Align::Center => 0.5 * (bound - height),
361 Align::BR => bound - height,
362 };
363 let offset = new_offset - top;
364
365 if offset != 0.0 {
366 self.apply_offset(Vec2(0.0, offset));
367 }
368 }
369}
370
371trait PartAccumulator {
372 fn num_parts(&self) -> usize;
373 fn num_lines(&self) -> usize;
374
375 fn add_part(
376 &mut self,
377 runs: &[GlyphRun],
378 run_index: usize,
379 part_range: std::ops::Range<usize>,
380 part: PartMetrics,
381 checkpoint: bool,
382 );
383
384 fn add_line(&mut self, fonts: &FontLibrary, runs: &[GlyphRun], parts_end: usize, is_wrap: bool);
385}
386
387#[derive(Clone, Debug)]
388struct PartInfo {
389 run: u32,
390 offset: f32,
391 len: f32,
392 len_no_space: f32,
393 glyph_range: Range,
394 end_space: bool,
395}
396
397#[derive(Default)]
398struct LineAdder {
399 wrapped_runs: TinyVec<[RunPart; 1]>,
400 parts: Vec<PartInfo>,
401 lines: TinyVec<[Line; 1]>,
402 line_gap: f32,
403 l_bound: f32,
404 r_bound: f32,
405 vcaret: f32,
406 #[cfg(feature = "num_glyphs")]
407 num_glyphs: u32,
408 h_align: Align,
409 width_bound: f32,
410}
411impl LineAdder {
412 fn new(width_bound: f32, h_align: Align) -> Self {
413 LineAdder {
414 parts: Vec::with_capacity(16),
415 l_bound: width_bound,
416 h_align,
417 width_bound,
418 ..Default::default()
419 }
420 }
421}
422
423impl PartAccumulator for LineAdder {
424 fn num_parts(&self) -> usize {
425 self.parts.len()
426 }
427
428 fn num_lines(&self) -> usize {
429 self.lines.len()
430 }
431
432 fn add_part(
433 &mut self,
434 runs: &[GlyphRun],
435 run_index: usize,
436 part_range: std::ops::Range<usize>,
437 part: PartMetrics,
438 checkpoint: bool,
439 ) {
440 let glyph_run = &runs[run_index];
441 let run = to_u32(run_index);
442 let glyph_range = glyph_run.to_glyph_range(part_range);
443
444 let justify = self.h_align == Align::Stretch && part.len_no_space > 0.0;
445 if checkpoint
446 && !justify
447 && let Some(info) = self.parts.last_mut()
448 && info.run == run
449 {
450 if glyph_run.level.is_ltr() {
453 info.glyph_range.end = glyph_range.end;
454 } else {
455 info.offset = part.offset;
456 info.glyph_range.start = glyph_range.start;
457 }
458 debug_assert!(info.glyph_range.start <= info.glyph_range.end);
459
460 if part.len_no_space > 0.0 {
461 info.len_no_space = info.len + part.len_no_space;
462 }
463 info.len += part.len;
464
465 return;
466 }
467
468 self.parts.push(PartInfo {
469 run,
470 offset: part.offset,
471 len: part.len,
472 len_no_space: part.len_no_space,
473 glyph_range,
474 end_space: false, });
476 }
477
478 fn add_line(
479 &mut self,
480 fonts: &FontLibrary,
481 runs: &[GlyphRun],
482 parts_end: usize,
483 is_wrap: bool,
484 ) {
485 debug_assert!(parts_end > 0);
486 let line_start = self.wrapped_runs.len();
487 let parts = &mut self.parts[..parts_end];
488
489 let mut last_run = u32::MAX;
491 let (mut ascent, mut descent, mut line_gap) = (0f32, 0f32, 0f32);
492 let mut line_level = Level::new(Level::max_implicit_depth()).unwrap();
493 let mut max_level = LTR_LEVEL;
494 for part in parts.iter() {
495 if last_run == part.run {
496 continue;
497 }
498 last_run = part.run;
499 let run = &runs[to_usize(last_run)];
500
501 let scale_font = fonts.get_face(run.face_id).scale_by_dpu(run.dpu);
502 ascent = ascent.max(scale_font.ascent());
503 descent = descent.min(scale_font.descent());
504 line_gap = line_gap.max(scale_font.line_gap());
505
506 line_level = line_level.min(run.level);
507 max_level = max_level.max(run.level);
508 }
509 let line_is_rtl = line_level.is_rtl();
510
511 if !self.lines.is_empty() {
512 self.vcaret += line_gap.max(self.line_gap);
513 }
514 self.vcaret += ascent;
515 self.line_gap = line_gap;
516
517 let line_text_start = {
518 let part = &parts[0];
519 let run = &runs[to_usize(part.run)];
520 if run.level.is_ltr() {
521 if part.glyph_range.start() < run.glyphs.len() {
522 run.glyphs[part.glyph_range.start()].index
523 } else {
524 run.range.start
525 }
526 } else {
527 let end = part.glyph_range.end();
528 if 0 < end && end < run.glyphs.len() {
529 run.glyphs[end - 1].index
530 } else {
531 run.range.start
532 }
533 }
534 };
535
536 let mut line_text_end;
539 let mut line_len = 0.0;
540 {
541 let part = &mut parts[parts.len() - 1];
542 let run = &runs[to_usize(part.run)];
543
544 if is_wrap && part.len > part.len_no_space {
545 if part.glyph_range.start < part.glyph_range.end {
551 if run.level.is_ltr() {
552 part.glyph_range.end -= 1;
553 } else {
554 part.glyph_range.start += 1;
555 }
556 }
557 }
558
559 line_text_end = run.range.end;
560 if run.level.is_ltr() {
561 if part.glyph_range.end() < run.glyphs.len() {
562 line_text_end = run.glyphs[part.glyph_range.end()].index;
563 }
564 } else {
565 let start = part.glyph_range.start();
566 if 0 < start && start < run.glyphs.len() {
567 line_text_end = run.glyphs[start - 1].index
568 }
569 }
570
571 for part in parts.iter_mut().rev() {
574 part.end_space = true;
575
576 if part.len_no_space > 0.0 {
577 break;
578 }
579 }
580 for part in parts.iter() {
581 line_len += if part.end_space {
582 part.len_no_space
583 } else {
584 part.len
585 };
586 }
587 }
588
589 {
598 let mut level = max_level;
599 while level > Level::ltr() {
600 let mut start = None;
601 for i in 0..parts.len() {
602 let part_level = runs[to_usize(parts[i].run)].level;
603 if let Some(s) = start {
604 if part_level < level {
605 parts[s..i].reverse();
606 start = None;
607 }
608 } else if part_level >= level {
609 start = Some(i);
610 }
611 }
612 if let Some(s) = start {
613 parts[s..].reverse();
614 }
615 level.lower(1).unwrap();
616 }
617 }
618
619 let spare = self.width_bound - line_len;
620 let mut is_gap = SmallVec::<[bool; 16]>::new();
621 let mut per_gap = 0.0;
622 let mut caret = match self.h_align {
623 Align::Default if line_is_rtl => spare,
624 Align::Default => 0.0,
625 Align::TL => 0.0,
626 Align::Center => 0.5 * spare,
627 Align::BR => spare,
628 Align::Stretch if is_wrap && spare > 0.0 => {
629 let len = parts.len();
630 is_gap.resize(len, false);
631 let mut num_gaps = 0;
632 for (i, part) in parts[..len - 1].iter().enumerate() {
633 let run = &runs[to_usize(part.run)];
634 let not_at_end = if run.level.is_ltr() {
635 part.glyph_range.end() < run.glyphs.len()
636 } else {
637 part.glyph_range.start > 0
638 };
639 if not_at_end || run.special != RunSpecial::NoBreak {
640 is_gap[i] = true;
641 num_gaps += 1;
642 }
643 }
644
645 let mut start = 0;
647 let mut level = runs[to_usize(parts[0].run)].level;
648 for i in 1..len {
649 let new_level = runs[to_usize(parts[i].run)].level;
650 if level != new_level {
651 if level > line_level {
652 is_gap[start..i].reverse();
653 }
654 start = i;
655 level = new_level;
656 }
657 }
658 if level > line_level {
659 is_gap[start..len - 1].reverse();
660 }
661
662 if line_level.is_rtl() {
664 is_gap.copy_within(1..len, 0);
665 }
666
667 if num_gaps == 0 {
668 match line_is_rtl {
669 false => 0.0,
670 true => spare,
671 }
672 } else {
673 per_gap = spare / (num_gaps as f32);
674 0.0
675 }
676 }
677 Align::Stretch if line_is_rtl => spare,
678 Align::Stretch => 0.0,
679 };
680
681 self.l_bound = self.l_bound.min(caret);
682 let mut end_caret = caret;
683
684 for (i, part) in parts.iter().enumerate() {
685 let run = &runs[to_usize(part.run)];
686
687 #[cfg(feature = "num_glyphs")]
688 {
689 self.num_glyphs += to_u32(part.glyph_range.len());
690 }
691
692 let mut text_end = run.range.end;
693 let mut offset = 0.0;
694 if run.level.is_ltr() {
695 if part.glyph_range.end() < run.glyphs.len() {
696 text_end = run.glyphs[part.glyph_range.end()].index;
697 }
698 } else {
699 let start = part.glyph_range.start();
700 if 0 < start && start < run.glyphs.len() {
701 text_end = run.glyphs[start - 1].index
702 }
703 offset = part.len_no_space - part.len;
704 }
705
706 let xoffset = if part.end_space {
707 end_caret - part.offset + offset
708 } else {
709 caret - part.offset
710 };
711 self.wrapped_runs.push(RunPart {
712 text_end,
713 glyph_run: part.run,
714 glyph_range: part.glyph_range,
715 offset: Vec2(xoffset, self.vcaret),
716 });
717 if part.end_space {
718 caret += part.len_no_space;
719 end_caret += part.len;
720 } else {
721 caret += part.len;
722 end_caret = caret;
723 }
724
725 if is_gap.len() > 0 && is_gap[i] {
726 caret += per_gap;
727 end_caret += per_gap;
728 }
729 }
730
731 self.r_bound = self.r_bound.max(caret);
732
733 self.wrapped_runs[line_start..].sort_by_key(|run| run.text_end);
737
738 let top = self.vcaret - ascent;
739 self.vcaret -= descent;
740 self.vcaret = self.vcaret.round();
742
743 self.lines.push(Line {
744 text_range: Range::from(line_text_start..line_text_end),
745 run_range: (line_start..self.wrapped_runs.len()).into(),
746 top,
747 bottom: self.vcaret,
748 });
749 self.parts.clear();
750 }
751}