Skip to content

Commit 1856315

Browse files
committed
[cg] Use piet::util for utf8/16 conversion
1 parent 041635a commit 1856315

File tree

1 file changed

+17
-15
lines changed

1 file changed

+17
-15
lines changed

piet-coregraphics/src/text.rs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use core_graphics::path::CGPath;
1010
use core_text::font::{self, CTFont};
1111

1212
use piet::kurbo::{Point, Size};
13+
use piet::util;
1314
use piet::{
1415
Error, Font, FontBuilder, HitTestMetrics, HitTestPoint, HitTestTextPosition, LineMetric, Text,
1516
TextLayout, TextLayoutBuilder,
@@ -193,7 +194,7 @@ impl TextLayout for CoreGraphicsTextLayout {
193194
let utf8_range = self.line_range(line_num).unwrap();
194195
let line_txt = self.line_text(line_num).unwrap();
195196
let rel_offset = (n - utf16_range.location) as usize;
196-
utf8_range.0 + utf8_offset_for_utf16_offset(line_txt, rel_offset)
197+
utf8_range.0 + util::count_until_utf16(line_txt, rel_offset).unwrap_or_else(|| line_txt.len())
197198
}
198199
// some other value; should never happen
199200
_ => panic!("gross violation of api contract"),
@@ -220,7 +221,7 @@ impl TextLayout for CoreGraphicsTextLayout {
220221
let text = self.line_text(line_num)?;
221222

222223
let offset_remainder = offset - self.line_offsets.get(line_num)?;
223-
let off16: usize = text[..offset_remainder].chars().map(char::len_utf16).sum();
224+
let off16: usize = util::count_utf16(&text[..offset_remainder]);
224225
let line_range = line.get_string_range();
225226
let char_idx = line_range.location + off16 as isize;
226227
let (x_pos, _) = line.get_offset_for_string_index(char_idx);
@@ -311,19 +312,6 @@ impl CoreGraphicsTextLayout {
311312
}
312313
}
313314

314-
fn utf8_offset_for_utf16_offset(text: &str, utf16_offset: usize) -> usize {
315-
let mut off16 = 0;
316-
let mut off8 = 0;
317-
for c in text.chars() {
318-
if utf16_offset == off16 {
319-
break;
320-
}
321-
off16 += c.len_utf16();
322-
off8 += c.len_utf8();
323-
}
324-
off8
325-
}
326-
327315
#[cfg(test)]
328316
#[allow(clippy::float_cmp)]
329317
mod tests {
@@ -428,4 +416,18 @@ mod tests {
428416
// just the general idea that this is the second character
429417
assert!(p1.point.x > 5.0 && p1.point.x < 15.0);
430418
}
419+
420+
#[test]
421+
fn hit_test_text_position_astral_plane() {
422+
let text = "👾🤠\n🤖🎃👾";
423+
let a_font = font::new_from_name("Helvetica", 16.0).unwrap();
424+
let layout = CoreGraphicsTextLayout::new(&CoreGraphicsFont(a_font), text, f64::INFINITY);
425+
let p0 = layout.hit_test_text_position(4).unwrap();
426+
let p1 = layout.hit_test_text_position(8).unwrap();
427+
let p2 = layout.hit_test_text_position(13).unwrap();
428+
429+
assert!(p1.point.x > p0.point.x);
430+
assert!(p1.point.y == p0.point.y);
431+
assert!(p2.point.y > p1.point.y);
432+
}
431433
}

0 commit comments

Comments
 (0)