2 Commits

Author SHA1 Message Date
5ca9dfabb8 Rename painting module to handwriting 2025-06-15 12:53:23 +02:00
1df81509df Add some comments to the handwriting code 2025-06-15 12:52:13 +02:00
3 changed files with 26 additions and 11 deletions

View File

@ -12,7 +12,7 @@ use egui::{
use crate::{ use crate::{
custom_code_block::{MdItem, iter_lines_and_code_blocks}, custom_code_block::{MdItem, iter_lines_and_code_blocks},
painting::{self, Handwriting, HandwritingStyle}, handwriting::{self, Handwriting, HandwritingStyle},
preferences::Preferences, preferences::Preferences,
text_editor::MdTextEdit, text_editor::MdTextEdit,
}; };
@ -287,7 +287,7 @@ impl From<&str> for FileEditor {
match item { match item {
MdItem::Line(line) => push_text(buffer, line), MdItem::Line(line) => push_text(buffer, line),
MdItem::CodeBlock { key, content, span } => match key { MdItem::CodeBlock { key, content, span } => match key {
painting::CODE_BLOCK_KEY => match Handwriting::from_str(span) { handwriting::CODE_BLOCK_KEY => match Handwriting::from_str(span) {
Ok(handwriting) => { Ok(handwriting) => {
if let Some(BufferItem::Text(text_edit)) = buffer.last_mut() { if let Some(BufferItem::Text(text_edit)) = buffer.last_mut() {
if text_edit.text.ends_with('\n') { if text_edit.text.ends_with('\n') {

View File

@ -219,8 +219,8 @@ impl Handwriting {
self.height = self.desired_height; self.height = self.desired_height;
} }
let size = Vec2::new(ui.available_width(), self.height); let desired_size = Vec2::new(ui.available_width(), self.height);
let (response, painter) = ui.allocate_painter(size, Sense::drag()); let (response, painter) = ui.allocate_painter(desired_size, Sense::drag());
let mut response = response let mut response = response
//.on_hover_cursor(CursorIcon::Crosshair) //.on_hover_cursor(CursorIcon::Crosshair)
@ -229,16 +229,23 @@ impl Handwriting {
let size = response.rect.size(); let size = response.rect.size();
// Calculate matrices that convert between screen-space and image-space.
// - image-space: 0,0 is the top-left of the texture.
// - screen-space: 0,0 is the top-left of the window.
// Both spaces use the same logical points, not pixels.
let to_screen = let to_screen =
emath::RectTransform::from_to(Rect::from_min_size(Pos2::ZERO, size), response.rect); emath::RectTransform::from_to(Rect::from_min_size(Pos2::ZERO, size), response.rect);
let from_screen = to_screen.inverse(); let from_screen = to_screen.inverse();
let is_drawing = response.interact_pointer_pos().is_some(); // Was the user in the process of drawing a stroke last frame?
let was_drawing = !self.current_stroke.is_empty(); let was_drawing = !self.current_stroke.is_empty();
// Is the user in the process of drawing a stroke now?
let is_drawing = response.interact_pointer_pos().is_some();
if !is_drawing { if !is_drawing {
// commit current line
if was_drawing { if was_drawing {
// commit current line
self.commit_current_line(hw_response); self.commit_current_line(hw_response);
response.mark_changed(); response.mark_changed();
} }
@ -251,6 +258,8 @@ impl Handwriting {
.map(|p| p.y + HANDWRITING_BOTTOM_PADDING) .map(|p| p.y + HANDWRITING_BOTTOM_PADDING)
.fold(HANDWRITING_MIN_HEIGHT, |max, y| max.max(y)); .fold(HANDWRITING_MIN_HEIGHT, |max, y| max.max(y));
// Change the height of the handwriting item.
// We don't do this mid-stroke, only when the user e.g. lifts the pen.
if self.desired_height != lines_max_y { if self.desired_height != lines_max_y {
self.desired_height = lines_max_y; self.desired_height = lines_max_y;
response.mark_changed(); response.mark_changed();
@ -285,6 +294,7 @@ impl Handwriting {
.collect::<Vec<_>>() .collect::<Vec<_>>()
}); });
// Process input events and turn them into strokes
for event in events { for event in events {
let last_canvas_pos = self.current_stroke.last(); let last_canvas_pos = self.current_stroke.last();
@ -371,6 +381,7 @@ impl Handwriting {
} }
} }
// Draw the horizontal ruled lines
(1..) (1..)
.map(|n| n as f32 * HANDWRITING_LINE_SPACING) .map(|n| n as f32 * HANDWRITING_LINE_SPACING)
.take_while(|&y| y < size.y) .take_while(|&y| y < size.y)
@ -383,9 +394,12 @@ impl Handwriting {
painter.add(shape); painter.add(shape);
}); });
// Get the dimensions of the image
let mesh_rect = response let mesh_rect = response
.rect .rect
.with_max_y(response.rect.min.y + self.desired_height); .with_max_y(response.rect.min.y + self.desired_height);
// These are the values that, if changed, would require the mesh to be re-rendered.
let new_context = MeshContext { let new_context = MeshContext {
ui_theme: ui.ctx().theme(), ui_theme: ui.ctx().theme(),
pixels_per_point: ui.pixels_per_point(), pixels_per_point: ui.pixels_per_point(),
@ -393,24 +407,25 @@ impl Handwriting {
stroke: style.stroke, stroke: style.stroke,
}; };
// Figure out if we need to re-rasterize the mesh.
if Some(&new_context) != self.last_mesh_ctx.as_ref() { if Some(&new_context) != self.last_mesh_ctx.as_ref() {
self.refresh_texture = true; self.refresh_texture = true;
} }
if self.refresh_texture { if self.refresh_texture {
// rasterize the entire texture from scratch // ...if we do, rasterize the entire texture from scratch
self.refresh_texture(style, new_context, ui); self.refresh_texture(style, new_context, ui);
self.unblitted_lines.clear(); self.unblitted_lines.clear();
} else if !self.unblitted_lines.is_empty() { } else if !self.unblitted_lines.is_empty() {
// only rasterize the new lines onto the existing texture // ...if we don't, we can get away with only rasterizing the *new* lines onto the
// existing texture.
for [from, to] in std::mem::take(&mut self.unblitted_lines) { for [from, to] in std::mem::take(&mut self.unblitted_lines) {
self.draw_line_to_texture(from, to, &new_context, ui); self.draw_line_to_texture(from, to, &new_context, ui);
} }
self.unblitted_lines.clear(); self.unblitted_lines.clear();
} }
//painter.add(self.mesh.clone()); // Draw the texture
if let Some(texture) = &self.texture { if let Some(texture) = &self.texture {
let texture = SizedTexture::new(texture.id(), texture.size_vec2()); let texture = SizedTexture::new(texture.id(), texture.size_vec2());
let shape = RectShape { let shape = RectShape {

View File

@ -5,7 +5,7 @@ pub mod constants;
pub mod custom_code_block; pub mod custom_code_block;
pub mod easy_mark; pub mod easy_mark;
pub mod file_editor; pub mod file_editor;
pub mod painting; pub mod handwriting;
pub mod preferences; pub mod preferences;
pub mod rasterizer; pub mod rasterizer;
pub mod text_editor; pub mod text_editor;