Use layout_runs for hit detection
This commit is contained in:
parent
b6bd72335c
commit
0336e0c5e9
1 changed files with 69 additions and 82 deletions
151
src/buffer.rs
151
src/buffer.rs
|
|
@ -762,103 +762,90 @@ impl<'a> TextBuffer<'a> {
|
||||||
let font_size = self.metrics.font_size;
|
let font_size = self.metrics.font_size;
|
||||||
let line_height = self.metrics.line_height;
|
let line_height = self.metrics.line_height;
|
||||||
|
|
||||||
let mut line_y = font_size;
|
let mut new_cursor = self.cursor;
|
||||||
let mut layout_i = 0;
|
|
||||||
for (line_i, line) in self.lines.iter().enumerate() {
|
|
||||||
let layout = match line.layout_opt.as_ref() {
|
|
||||||
Some(some) => some,
|
|
||||||
None => break,
|
|
||||||
};
|
|
||||||
|
|
||||||
for layout_line in layout {
|
for run in self.layout_runs() {
|
||||||
let scrolled = layout_i < self.scroll;
|
let line_y = run.line_y;
|
||||||
layout_i += 1;
|
|
||||||
|
|
||||||
if scrolled {
|
if mouse_y >= line_y - font_size
|
||||||
continue;
|
&& mouse_y < line_y - font_size + line_height
|
||||||
}
|
{
|
||||||
|
let mut new_cursor_glyph = run.glyphs.len();
|
||||||
|
let mut new_cursor_char = 0;
|
||||||
|
'hit: for (glyph_i, glyph) in run.glyphs.iter().enumerate() {
|
||||||
|
if mouse_x >= glyph.x as i32
|
||||||
|
&& mouse_x <= (glyph.x + glyph.w) as i32
|
||||||
|
{
|
||||||
|
new_cursor_glyph = glyph_i;
|
||||||
|
|
||||||
if line_y > self.height {
|
let cluster = &run.text[glyph.start..glyph.end];
|
||||||
return;
|
let total = cluster.grapheme_indices(true).count();
|
||||||
}
|
let mut egc_x = glyph.x;
|
||||||
|
let egc_w = glyph.w / (total as f32);
|
||||||
|
for (egc_i, egc) in cluster.grapheme_indices(true) {
|
||||||
|
if mouse_x >= egc_x as i32
|
||||||
|
&& mouse_x <= (egc_x + egc_w) as i32
|
||||||
|
{
|
||||||
|
new_cursor_char = egc_i;
|
||||||
|
|
||||||
if mouse_y >= line_y - font_size
|
let right_half = mouse_x >= (egc_x + egc_w / 2.0) as i32;
|
||||||
&& mouse_y < line_y - font_size + line_height
|
if right_half != glyph.rtl {
|
||||||
{
|
// If clicking on last half of glyph, move cursor past glyph
|
||||||
let mut new_cursor_glyph = layout_line.glyphs.len();
|
new_cursor_char += egc.len();
|
||||||
let mut new_cursor_char = 0;
|
|
||||||
'hit: for (glyph_i, glyph) in layout_line.glyphs.iter().enumerate() {
|
|
||||||
if mouse_x >= glyph.x as i32
|
|
||||||
&& mouse_x <= (glyph.x + glyph.w) as i32
|
|
||||||
{
|
|
||||||
new_cursor_glyph = glyph_i;
|
|
||||||
|
|
||||||
let cluster = &line.text[glyph.start..glyph.end];
|
|
||||||
let total = cluster.grapheme_indices(true).count();
|
|
||||||
let mut egc_x = glyph.x;
|
|
||||||
let egc_w = glyph.w / (total as f32);
|
|
||||||
for (egc_i, egc) in cluster.grapheme_indices(true) {
|
|
||||||
if mouse_x >= egc_x as i32
|
|
||||||
&& mouse_x <= (egc_x + egc_w) as i32
|
|
||||||
{
|
|
||||||
new_cursor_char = egc_i;
|
|
||||||
|
|
||||||
let right_half = mouse_x >= (egc_x + egc_w / 2.0) as i32;
|
|
||||||
if right_half != glyph.rtl {
|
|
||||||
// If clicking on last half of glyph, move cursor past glyph
|
|
||||||
new_cursor_char += egc.len();
|
|
||||||
}
|
|
||||||
break 'hit;
|
|
||||||
}
|
}
|
||||||
egc_x += egc_w;
|
break 'hit;
|
||||||
}
|
}
|
||||||
|
egc_x += egc_w;
|
||||||
let right_half = mouse_x >= (glyph.x + glyph.w / 2.0) as i32;
|
|
||||||
if right_half != glyph.rtl {
|
|
||||||
// If clicking on last half of glyph, move cursor past glyph
|
|
||||||
new_cursor_char = cluster.len();
|
|
||||||
}
|
|
||||||
break 'hit;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let mut new_cursor = TextCursor::new(TextLineIndex::new(line_i), 0);
|
let right_half = mouse_x >= (glyph.x + glyph.w / 2.0) as i32;
|
||||||
|
if right_half != glyph.rtl {
|
||||||
match layout_line.glyphs.get(new_cursor_glyph) {
|
// If clicking on last half of glyph, move cursor past glyph
|
||||||
Some(glyph) => {
|
new_cursor_char = cluster.len();
|
||||||
// Position at glyph
|
|
||||||
new_cursor.index = glyph.start + new_cursor_char;
|
|
||||||
},
|
|
||||||
None => if let Some(glyph) = layout_line.glyphs.last() {
|
|
||||||
// Position at end of line
|
|
||||||
new_cursor.index = glyph.end;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_cursor != self.cursor {
|
|
||||||
self.cursor = new_cursor;
|
|
||||||
self.redraw = true;
|
|
||||||
|
|
||||||
if let Some(glyph) = layout_line.glyphs.get(new_cursor_glyph) {
|
|
||||||
let font_opt = self.font_matches.get_font(&glyph.cache_key.font_id);
|
|
||||||
let text_glyph = &line.text[glyph.start..glyph.end];
|
|
||||||
log::debug!(
|
|
||||||
"{}, {}: '{}' ('{}'): '{}' ({:?})",
|
|
||||||
self.cursor.line.get(),
|
|
||||||
self.cursor.index,
|
|
||||||
font_opt.map_or("?", |font| font.info.family.as_str()),
|
|
||||||
font_opt.map_or("?", |font| font.info.post_script_name.as_str()),
|
|
||||||
text_glyph,
|
|
||||||
text_glyph
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
break 'hit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
line_y += line_height;
|
new_cursor.line = run.line_i;
|
||||||
|
new_cursor.index = 0;
|
||||||
|
|
||||||
|
match run.glyphs.get(new_cursor_glyph) {
|
||||||
|
Some(glyph) => {
|
||||||
|
// Position at glyph
|
||||||
|
new_cursor.index = glyph.start + new_cursor_char;
|
||||||
|
},
|
||||||
|
None => if let Some(glyph) = run.glyphs.last() {
|
||||||
|
// Position at end of line
|
||||||
|
new_cursor.index = glyph.end;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if new_cursor != self.cursor {
|
||||||
|
if let Some(glyph) = run.glyphs.get(new_cursor_glyph) {
|
||||||
|
let font_opt = self.font_matches.get_font(&glyph.cache_key.font_id);
|
||||||
|
let text_glyph = &run.text[glyph.start..glyph.end];
|
||||||
|
log::debug!(
|
||||||
|
"{}, {}: '{}' ('{}'): '{}' ({:?})",
|
||||||
|
self.cursor.line.get(),
|
||||||
|
self.cursor.index,
|
||||||
|
font_opt.map_or("?", |font| font.info.family.as_str()),
|
||||||
|
font_opt.map_or("?", |font| font.info.post_script_name.as_str()),
|
||||||
|
text_glyph,
|
||||||
|
text_glyph
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if new_cursor != self.cursor {
|
||||||
|
self.cursor = new_cursor;
|
||||||
|
self.redraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
let duration = instant.elapsed();
|
let duration = instant.elapsed();
|
||||||
log::trace!("click({}, {}): {:?}", mouse_x, mouse_y, duration);
|
log::trace!("click({}, {}): {:?}", mouse_x, mouse_y, duration);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue