///|
/// Wrap using discretionary word-internal hyphens. Providers receive UAX #29
/// word segments; offsets must be interior UTF-8 bytes on grapheme boundaries.
/// Invalid/duplicate offsets are ignored. A visible ASCII hyphen is inserted
/// only at a selected break and never changes source or start/end offsets.
pub fn[H : @hyphen.Hyphenator] wrap_hyphenated(
s : String,
max_width : Int,
hyphenator : H,
algorithm? : WrapAlgorithm = Greedy,
opts? : WrapOptions = WrapOptions::new(),
optimal? : OptimalOptions = OptimalOptions::new(),
) -> Array[Line] {
let points : Map[Int, Bool] = Map([])
let text = @text.scan(s)
for span in @segment.segments(s, @segment.Word) {
let (offset, end) = span
let start_scalar = match text.bytes.binary_search(offset) {
Ok(i) => i
Err(_) => continue
}
let end_scalar = match text.bytes.binary_search(end) {
Ok(i) => i
Err(_) => continue
}
let word = s[text.units[start_scalar]:text.units[end_scalar]].to_owned()
let size = end - offset
for point in hyphenator.positions(word) {
if point > 0 && point < size {
points.set(offset + point, true)
}
}
}
match algorithm {
Greedy => greedy_points(s, max_width, opts, points)
Optimal => optimal_points(s, max_width, opts, optimal, points)
}
}