Move drawing and hit detection to buffer
This commit is contained in:
parent
a242d817e9
commit
021782b92b
3 changed files with 135 additions and 181 deletions
|
|
@ -116,9 +116,6 @@ where
|
||||||
|
|
||||||
let buffer = self.buffer.lock().unwrap();
|
let buffer = self.buffer.lock().unwrap();
|
||||||
|
|
||||||
let font_size = buffer.metrics().font_size;
|
|
||||||
let line_height = buffer.metrics().line_height;
|
|
||||||
|
|
||||||
let instant = Instant::now();
|
let instant = Instant::now();
|
||||||
|
|
||||||
if let Some(background_color) = appearance.background_color {
|
if let Some(background_color) = appearance.background_color {
|
||||||
|
|
@ -133,93 +130,28 @@ where
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let line_x = layout.bounds().x as i32;
|
let buffer_x = layout.bounds().x;
|
||||||
let mut line_y = layout.bounds().y as i32 + font_size;
|
let buffer_y = layout.bounds().y;
|
||||||
let mut start_line_opt = None;
|
buffer.draw(text_color_u32, |x, y, w, h, color| {
|
||||||
let mut end_line = TextLineIndex::new(0);
|
let a = (color >> 24) as u8;
|
||||||
for (line_i, line) in buffer
|
if a > 0 {
|
||||||
.layout_lines()
|
let r = (color >> 16) as u8;
|
||||||
.iter()
|
let g = (color >> 8) as u8;
|
||||||
.skip(buffer.scroll() as usize)
|
let b = color as u8;
|
||||||
.take(buffer.lines() as usize)
|
renderer.fill_quad(
|
||||||
.enumerate()
|
renderer::Quad {
|
||||||
{
|
bounds: Rectangle::new(
|
||||||
end_line = line.line_i;
|
Point::new(buffer_x + x as f32, buffer_y + y as f32),
|
||||||
if start_line_opt == None {
|
Size::new(w as f32, h as f32)
|
||||||
start_line_opt = Some(end_line);
|
),
|
||||||
|
border_radius: 0.0,
|
||||||
|
border_width: 0.0,
|
||||||
|
border_color: Color::TRANSPARENT,
|
||||||
|
},
|
||||||
|
Color::from_rgba8(r, g, b, a as f32 / 255.0),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
if buffer.cursor.line == line_i + buffer.scroll() as usize {
|
|
||||||
if buffer.cursor.glyph >= line.glyphs.len() {
|
|
||||||
let x = match line.glyphs.last() {
|
|
||||||
Some(glyph) => glyph.x + glyph.w,
|
|
||||||
None => 0.0,
|
|
||||||
};
|
|
||||||
|
|
||||||
renderer.fill_quad(
|
|
||||||
renderer::Quad {
|
|
||||||
bounds: Rectangle::new(
|
|
||||||
Point::new(line_x as f32 + x, (line_y - font_size) as f32),
|
|
||||||
Size::new((font_size / 2) as f32, line_height as f32)
|
|
||||||
),
|
|
||||||
border_radius: 0.0,
|
|
||||||
border_width: 0.0,
|
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
},
|
|
||||||
Color::from_rgba8(0xFF, 0xFF, 0xFF, 0.125),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let glyph = &line.glyphs[buffer.cursor.glyph];
|
|
||||||
renderer.fill_quad(
|
|
||||||
renderer::Quad {
|
|
||||||
bounds: Rectangle::new(
|
|
||||||
Point::new(line_x as f32 + glyph.x, (line_y - font_size) as f32),
|
|
||||||
Size::new(glyph.w, line_height as f32)
|
|
||||||
),
|
|
||||||
border_radius: 0.0,
|
|
||||||
border_width: 0.0,
|
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
},
|
|
||||||
Color::from_rgba8(0xFF, 0xFF, 0xFF, 0.125),
|
|
||||||
);
|
|
||||||
|
|
||||||
let text_line = &buffer.text_lines()[line.line_i.get()];
|
|
||||||
log::info!(
|
|
||||||
"{}, {}: '{}' ('{}'): '{}'",
|
|
||||||
glyph.start,
|
|
||||||
glyph.end,
|
|
||||||
glyph.font.info.family,
|
|
||||||
glyph.font.info.post_script_name,
|
|
||||||
&text_line[glyph.start..glyph.end],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
line.draw(text_color_u32, |x, y, data| {
|
|
||||||
let a = (data >> 24) as u8;
|
|
||||||
if a > 0 {
|
|
||||||
let r = (data >> 16) as u8;
|
|
||||||
let g = (data >> 8) as u8;
|
|
||||||
let b = data as u8;
|
|
||||||
let bounds = Rectangle::new(
|
|
||||||
Point::new((line_x + x) as f32, (line_y + y) as f32),
|
|
||||||
Size::new(1.0, 1.0)
|
|
||||||
);
|
|
||||||
let color = Color::from_rgba8(r, g, b, a as f32 / 255.0);
|
|
||||||
renderer.fill_quad(
|
|
||||||
renderer::Quad {
|
|
||||||
bounds,
|
|
||||||
border_radius: 0.0,
|
|
||||||
border_width: 0.0,
|
|
||||||
border_color: Color::TRANSPARENT,
|
|
||||||
},
|
|
||||||
color
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
line_y += line_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Draw scrollbar
|
// Draw scrollbar
|
||||||
|
|
|
||||||
|
|
@ -96,71 +96,27 @@ fn main() {
|
||||||
let mut mouse_x = -1;
|
let mut mouse_x = -1;
|
||||||
let mut mouse_y = -1;
|
let mut mouse_y = -1;
|
||||||
let mut mouse_left = false;
|
let mut mouse_left = false;
|
||||||
let mut rehit = false;
|
|
||||||
loop {
|
loop {
|
||||||
let font_size = buffer.metrics().font_size;
|
let font_size = buffer.metrics().font_size;
|
||||||
let line_height = buffer.metrics().line_height;
|
let line_height = buffer.metrics().line_height;
|
||||||
|
|
||||||
if rehit {
|
|
||||||
let instant = Instant::now();
|
|
||||||
|
|
||||||
let mut new_cursor_opt = None;
|
|
||||||
|
|
||||||
let mut line_y = line_height;
|
|
||||||
for (line_i, line) in buffer
|
|
||||||
.layout_lines()
|
|
||||||
.iter()
|
|
||||||
.skip(buffer.scroll() as usize)
|
|
||||||
.enumerate()
|
|
||||||
{
|
|
||||||
if line_y >= window.height() as i32 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if mouse_left
|
|
||||||
&& mouse_y >= line_y - font_size
|
|
||||||
&& mouse_y < line_y - font_size + line_height
|
|
||||||
{
|
|
||||||
let new_cursor_line = line_i + buffer.scroll() as usize;
|
|
||||||
let mut new_cursor_glyph = line.glyphs.len();
|
|
||||||
for (glyph_i, glyph) in line.glyphs.iter().enumerate() {
|
|
||||||
if mouse_x >= line_x + glyph.x as i32
|
|
||||||
&& mouse_x <= line_x + (glyph.x + glyph.w) as i32
|
|
||||||
{
|
|
||||||
new_cursor_glyph = glyph_i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
new_cursor_opt = Some(TextCursor::new(new_cursor_line, new_cursor_glyph));
|
|
||||||
}
|
|
||||||
|
|
||||||
line_y += line_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(new_cursor) = new_cursor_opt {
|
|
||||||
if new_cursor != buffer.cursor {
|
|
||||||
buffer.cursor = new_cursor;
|
|
||||||
buffer.redraw = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rehit = false;
|
|
||||||
|
|
||||||
let duration = instant.elapsed();
|
|
||||||
log::debug!("rehit: {:?}", duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
if buffer.redraw {
|
if buffer.redraw {
|
||||||
let instant = Instant::now();
|
let instant = Instant::now();
|
||||||
|
|
||||||
window.set(bg_color);
|
window.set(bg_color);
|
||||||
|
|
||||||
let mut line_y = line_height;
|
buffer.draw(font_color.data, |x, y, w, h, color| {
|
||||||
|
window.rect(line_x + x, y, w, h, Color { data: color });
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut line_y = font_size;
|
||||||
let mut start_line_opt = None;
|
let mut start_line_opt = None;
|
||||||
let mut end_line = TextLineIndex::new(0);
|
let mut end_line = TextLineIndex::new(0);
|
||||||
for (line_i, line) in buffer
|
for (line_i, line) in buffer
|
||||||
.layout_lines()
|
.layout_lines()
|
||||||
.iter()
|
.iter()
|
||||||
.skip(buffer.scroll() as usize)
|
.skip(buffer.scroll() as usize)
|
||||||
|
.take(buffer.lines() as usize)
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
if line_y >= window.height() as i32 {
|
if line_y >= window.height() as i32 {
|
||||||
|
|
@ -172,45 +128,6 @@ fn main() {
|
||||||
start_line_opt = Some(end_line);
|
start_line_opt = Some(end_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
if buffer.cursor.line == line_i + buffer.scroll() as usize {
|
|
||||||
if buffer.cursor.glyph >= line.glyphs.len() {
|
|
||||||
let x = match line.glyphs.last() {
|
|
||||||
Some(glyph) => glyph.x + glyph.w,
|
|
||||||
None => 0.0,
|
|
||||||
};
|
|
||||||
window.rect(
|
|
||||||
line_x + x as i32,
|
|
||||||
line_y - font_size,
|
|
||||||
(font_size / 2) as u32,
|
|
||||||
line_height as u32,
|
|
||||||
Color::rgba(0xFF, 0xFF, 0xFF, 0x20),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
let glyph = &line.glyphs[buffer.cursor.glyph];
|
|
||||||
window.rect(
|
|
||||||
line_x + glyph.x as i32,
|
|
||||||
line_y - font_size,
|
|
||||||
glyph.w as u32,
|
|
||||||
line_height as u32,
|
|
||||||
Color::rgba(0xFF, 0xFF, 0xFF, 0x20),
|
|
||||||
);
|
|
||||||
|
|
||||||
let text_line = &buffer.text_lines()[line.line_i.get()];
|
|
||||||
log::info!(
|
|
||||||
"{}, {}: '{}' ('{}'): '{}'",
|
|
||||||
glyph.start,
|
|
||||||
glyph.end,
|
|
||||||
glyph.font.info.family,
|
|
||||||
glyph.font.info.post_script_name,
|
|
||||||
&text_line[glyph.start..glyph.end],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
line.draw(font_color.data, |x, y, color| {
|
|
||||||
window.pixel(line_x + x, line_y + y, Color { data: color });
|
|
||||||
});
|
|
||||||
|
|
||||||
line_y += line_height;
|
line_y += line_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -286,14 +203,20 @@ fn main() {
|
||||||
mouse_x = event.x;
|
mouse_x = event.x;
|
||||||
mouse_y = event.y;
|
mouse_y = event.y;
|
||||||
if mouse_left {
|
if mouse_left {
|
||||||
rehit = true;
|
buffer.action(TextAction::Click {
|
||||||
|
x: mouse_x - line_x,
|
||||||
|
y: mouse_y
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EventOption::Button(event) => {
|
EventOption::Button(event) => {
|
||||||
if event.left != mouse_left {
|
if event.left != mouse_left {
|
||||||
mouse_left = event.left;
|
mouse_left = event.left;
|
||||||
if mouse_left {
|
if mouse_left {
|
||||||
rehit = true;
|
buffer.action(TextAction::Click {
|
||||||
|
x: mouse_x - line_x,
|
||||||
|
y: mouse_y
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
101
src/buffer.rs
101
src/buffer.rs
|
|
@ -385,7 +385,7 @@ impl<'a> TextBuffer<'a> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
TextAction::Click { x, y } => {
|
TextAction::Click { x, y } => {
|
||||||
|
self.click(x, y);
|
||||||
},
|
},
|
||||||
TextAction::Scroll(lines) => {
|
TextAction::Scroll(lines) => {
|
||||||
self.scroll += lines;
|
self.scroll += lines;
|
||||||
|
|
@ -394,4 +394,103 @@ impl<'a> TextBuffer<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn click(&mut self, mouse_x: i32, mouse_y: i32) {
|
||||||
|
let instant = Instant::now();
|
||||||
|
|
||||||
|
let font_size = self.metrics.font_size;
|
||||||
|
let line_height = self.metrics.line_height;
|
||||||
|
|
||||||
|
let mut new_cursor_opt = None;
|
||||||
|
|
||||||
|
let mut line_y = font_size;
|
||||||
|
for (line_i, line) in self.layout_lines.iter()
|
||||||
|
.skip(cmp::max(0, self.scroll()) as usize)
|
||||||
|
.take(cmp::max(0, self.lines()) as usize)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if mouse_y >= line_y - font_size
|
||||||
|
&& mouse_y < line_y - font_size + line_height
|
||||||
|
{
|
||||||
|
let new_cursor_line = line_i + self.scroll() as usize;
|
||||||
|
let mut new_cursor_glyph = line.glyphs.len();
|
||||||
|
for (glyph_i, glyph) in line.glyphs.iter().enumerate() {
|
||||||
|
if mouse_x >= glyph.x as i32
|
||||||
|
&& mouse_x <= (glyph.x + glyph.w) as i32
|
||||||
|
{
|
||||||
|
new_cursor_glyph = glyph_i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new_cursor_opt = Some(TextCursor::new(new_cursor_line, new_cursor_glyph));
|
||||||
|
}
|
||||||
|
|
||||||
|
line_y += line_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(new_cursor) = new_cursor_opt {
|
||||||
|
if new_cursor != self.cursor {
|
||||||
|
self.cursor = new_cursor;
|
||||||
|
self.redraw = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let duration = instant.elapsed();
|
||||||
|
log::debug!("click({}, {}): {:?}", mouse_x, mouse_y, duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw the buffer
|
||||||
|
pub fn draw<F>(&self, color: u32, mut f: F)
|
||||||
|
where F: FnMut(i32, i32, u32, u32, u32)
|
||||||
|
{
|
||||||
|
let font_size = self.metrics.font_size;
|
||||||
|
let line_height = self.metrics.line_height;
|
||||||
|
|
||||||
|
let mut line_y = font_size;
|
||||||
|
for (line_i, line) in self.layout_lines.iter()
|
||||||
|
.skip(cmp::max(0, self.scroll()) as usize)
|
||||||
|
.take(cmp::max(0, self.lines()) as usize)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
if self.cursor.line == line_i + self.scroll() as usize {
|
||||||
|
if self.cursor.glyph >= line.glyphs.len() {
|
||||||
|
let x = match line.glyphs.last() {
|
||||||
|
Some(glyph) => glyph.x + glyph.w,
|
||||||
|
None => 0.0,
|
||||||
|
};
|
||||||
|
f(
|
||||||
|
x as i32,
|
||||||
|
line_y - font_size,
|
||||||
|
(font_size / 2) as u32,
|
||||||
|
line_height as u32,
|
||||||
|
0x20FFFFFF,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let glyph = &line.glyphs[self.cursor.glyph];
|
||||||
|
f(
|
||||||
|
glyph.x as i32,
|
||||||
|
line_y - font_size,
|
||||||
|
glyph.w as u32,
|
||||||
|
line_height as u32,
|
||||||
|
0x20FFFFFF,
|
||||||
|
);
|
||||||
|
|
||||||
|
let text_line = &self.text_lines()[line.line_i.get()];
|
||||||
|
log::info!(
|
||||||
|
"{}, {}: '{}' ('{}'): '{}'",
|
||||||
|
glyph.start,
|
||||||
|
glyph.end,
|
||||||
|
glyph.font.info.family,
|
||||||
|
glyph.font.info.post_script_name,
|
||||||
|
&text_line[glyph.start..glyph.end],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line.draw(color, |x, y, color| {
|
||||||
|
f(x, line_y + y, 1, 1, color);
|
||||||
|
});
|
||||||
|
|
||||||
|
line_y += line_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue