1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! Single-paragraph shape → wrap → paint pipeline.
//!
//! - `shape`: bidi/UAX-14 segmentation + per-word native shaping ([`ShapedWord`]).
//! - `wrap`: greedy first-fit and visual-line assembly into [`ShapedLine`].
//! - `paint`: paint-time post-processors (alignment offset, ellipsis truncation).
//!
//! The two-stage pipeline ([`shape_words`] + [`wrap_shaped_words`]) lets callers
//! re-fit on a width change without re-shaping. [`greedy_wrap`] chains both for
//! the one-shot path, and [`shape_line_bidi`] runs the single-line variant
//! through the same segment → reorder pipeline.
use crate;
use crateTextError;
use crate;
pub use ;
pub use ;
pub use wrap_shaped_words;
pub use shape_words_in;
pub use ;
/// Wrap text into multiple lines using greedy first-fit algorithm.
///
/// Breaks at UAX #14 opportunities (after spaces, between CJK ideographs, after
/// hyphens, …), so space-less scripts wrap. Each returned `ShapedLine` has its
/// `y_offset_lpx` set to the vertical position relative to the paragraph origin.
///
/// # Behavior
///
/// - Words with no interior break opportunity wider than `max_width_lpx` are
/// placed on their own line without character-level breaking (may overflow
/// visually).
/// - Every ASCII space is preserved (one glyph per space byte); a run is
/// absorbed at a soft wrap but kept visible at the end of the text.
/// - Tabs (U+0009) advance the pen to the next tab stop (`4 × space_advance`).
/// - Empty input returns an empty `Vec`.
///
/// # Performance
///
/// Each word is shaped exactly once. Accumulated glyphs are joined with a
/// space-advance offset rather than re-shaping the full line string. As a
/// result cross-word kerning pairs that span the space boundary are not
/// captured — this is an acceptable tradeoff for O(W) vs O(W+L) shaping
/// calls (W = words, L = lines).
///
/// # Arguments
///
/// * `backend` - Text backend for shaping
/// * `font` - Font to use
/// * `text` - Input text to wrap
/// * `max_width_lpx` - Maximum line width in logical pixels
/// Shape a single line through the bidi segment + reorder pipeline, producing a
/// run-bearing [`ShapedLine`] (the same path [`greedy_wrap`] / `shape_document`
/// use, minus the wrap fit).
///
/// Unlike the raw native `shape_line`, this resolves UAX #9 level-runs, shapes
/// each per its resolved direction, reorders into visual order, and populates
/// `runs` so the run-aware caret / hit-test math works on mixed / RTL text. On
/// pure-LTR / CJK input every item is level 0, so `assemble_visual_line` takes
/// its fast path: `runs` stays empty and glyph placement is byte-identical to
/// the pre-bidi single-line shaper (caret geometry then uses the original LTR
/// pen walk). The trade-off is that LTR text loses whole-line cross-word
/// kerning — consistent with the rest of the system, which shapes per segment.
///
/// Clusters are line-relative (the caller passes the line text as the whole
/// string); empty input yields a zero-glyph line carrying the font metrics.