Merge upstream/main into fix/update-without-prev-is-refused

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pq7HyCHD1R3rywQBPCHXZA
This commit is contained in:
mtlcl410andClaude Opus 5.5 committed 2026-11-08 00:25:48 +08:00
commit 4e522cd067
66 files changed
+4904 -850

No files matched your search

+5
View File
@@ -175,6 +175,11 @@ impl PageText {
.collect()
}
/// Index of the first glyph whose box holds a view-space point: the text under the pointer.
pub fn glyph_at(&self, x: f32, y: f32) -> Option<usize> {
self.glyphs.iter().position(|g| x >= g.rect[0] && x <= g.rect[2] && y >= g.rect[1] && y <= g.rect[3])
}
/// Index of the glyph nearest to a view-space point (for selection anchors).
///
/// A glyph whose drawn em box (`quad`) holds the point wins. Skewed or turned text has bounding
+15
View File
@@ -1965,3 +1965,18 @@ fn text_outside_the_crop_box_is_clipped() {
assert!(text.is_empty(), "expected no glyphs on {crop:?}, got {:?}", text.plain_text());
}
}
/// The glyph under a point is the first whose box holds it, edges included; between glyphs, none.
#[test]
fn the_glyph_at_a_point_is_the_first_whose_box_holds_it() {
let text = PageText {
glyphs: vec![em_box("a", 0.0, 0.0, 10.0, 10.0), em_box("b", 8.0, 0.0, 20.0, 10.0)],
line_of: vec![0, 0],
space_before: vec![false, false],
};
assert_eq!(text.glyph_at(5.0, 5.0), Some(0));
assert_eq!(text.glyph_at(9.0, 5.0), Some(0), "the first of overlapping boxes");
assert_eq!(text.glyph_at(20.0, 10.0), Some(1), "an edge is in");
assert_eq!(text.glyph_at(25.0, 5.0), None);
assert_eq!(PageText::default().glyph_at(0.0, 0.0), None);
}