Merge pull request #9059 from penpot/azazeln28-fix-caret-dimensions

🐛 Fix caret dimensions
This commit is contained in:
Elena Torró 2026-04-21 13:41:07 +02:00 committed by GitHub
commit 04f29a0d72
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 31 additions and 21 deletions

View File

@ -1,9 +1,17 @@
use crate::render::options::RenderOptions;
use crate::shapes::{Shape, TextContent, Type, VerticalAlign}; use crate::shapes::{Shape, TextContent, Type, VerticalAlign};
use crate::state::{TextEditorState, TextSelection}; use crate::state::{TextEditorState, TextSelection};
use crate::view::Viewbox;
use skia_safe::textlayout::{RectHeightStyle, RectWidthStyle}; use skia_safe::textlayout::{RectHeightStyle, RectWidthStyle};
use skia_safe::{BlendMode, Canvas, Paint, Rect}; use skia_safe::{BlendMode, Canvas, Paint, Rect};
pub fn render_overlay(canvas: &Canvas, editor_state: &TextEditorState, shape: &Shape) { pub fn render_overlay(
canvas: &Canvas,
viewbox: &Viewbox,
options: &RenderOptions,
editor_state: &TextEditorState,
shape: &Shape,
) {
if !editor_state.has_focus { if !editor_state.has_focus {
return; return;
} }
@ -13,17 +21,24 @@ pub fn render_overlay(canvas: &Canvas, editor_state: &TextEditorState, shape: &S
}; };
canvas.save(); canvas.save();
let zoom = viewbox.zoom * options.dpr();
canvas.scale((zoom, zoom));
canvas.translate((-viewbox.area.left, -viewbox.area.top));
if editor_state.selection.is_selection() { if editor_state.selection.is_selection() {
render_selection(canvas, editor_state, text_content, shape); render_selection(canvas, editor_state, text_content, shape);
} }
if editor_state.cursor_visible { if editor_state.cursor_visible {
render_cursor(canvas, editor_state, text_content, shape); render_cursor(canvas, zoom, editor_state, text_content, shape);
} }
canvas.restore(); canvas.restore();
} }
fn render_cursor( fn render_cursor(
canvas: &Canvas, canvas: &Canvas,
zoom: f32,
editor_state: &TextEditorState, editor_state: &TextEditorState,
text_content: &TextContent, text_content: &TextContent,
shape: &Shape, shape: &Shape,
@ -32,6 +47,9 @@ fn render_cursor(
return; return;
}; };
let mut cursor_rect = Rect::new_empty();
cursor_rect.set_xywh(rect.x(), rect.y(), 1.5 / zoom, rect.height());
let mut paint = Paint::default(); let mut paint = Paint::default();
paint.set_color(editor_state.theme.cursor_color); paint.set_color(editor_state.theme.cursor_color);
paint.set_anti_alias(true); paint.set_anti_alias(true);
@ -39,7 +57,7 @@ fn render_cursor(
let shape_matrix = shape.get_matrix(); let shape_matrix = shape.get_matrix();
canvas.save(); canvas.save();
canvas.concat(&shape_matrix); canvas.concat(&shape_matrix);
canvas.draw_rect(rect, &paint); canvas.draw_rect(cursor_rect, &paint);
canvas.restore(); canvas.restore();
} }
@ -160,7 +178,7 @@ fn calculate_cursor_rect(
return Some(Rect::from_xywh( return Some(Rect::from_xywh(
cursor_x, cursor_x,
y_offset + cursor_y, y_offset + cursor_y,
editor_state.theme.cursor_width, 1.0, // cursor_width
cursor_height, cursor_height,
)); ));
} }

View File

@ -100,7 +100,6 @@ pub enum TextEditorEvent {
/// FIXME: It should be better to get these constants from the frontend through the API. /// FIXME: It should be better to get these constants from the frontend through the API.
const SELECTION_COLOR: Color = Color::from_argb(127, 0, 209, 184); const SELECTION_COLOR: Color = Color::from_argb(127, 0, 209, 184);
const CURSOR_WIDTH: f32 = 1.5;
const CURSOR_COLOR: Color = Color::BLACK; const CURSOR_COLOR: Color = Color::BLACK;
const CURSOR_BLINK_INTERVAL_MS: f64 = 530.0; const CURSOR_BLINK_INTERVAL_MS: f64 = 530.0;
@ -257,7 +256,6 @@ impl TextEditorStyles {
pub struct TextEditorTheme { pub struct TextEditorTheme {
pub selection_color: Color, pub selection_color: Color,
pub cursor_width: f32,
pub cursor_color: Color, pub cursor_color: Color,
} }
@ -340,7 +338,6 @@ impl TextEditorState {
Self { Self {
theme: TextEditorTheme { theme: TextEditorTheme {
selection_color: SELECTION_COLOR, selection_color: SELECTION_COLOR,
cursor_width: CURSOR_WIDTH,
cursor_color: CURSOR_COLOR, cursor_color: CURSOR_COLOR,
}, },
selection: TextSelection::new(), selection: TextSelection::new(),

View File

@ -32,16 +32,11 @@ pub enum CursorDirection {
// ============================================================================ // ============================================================================
#[no_mangle] #[no_mangle]
pub extern "C" fn text_editor_apply_theme( pub extern "C" fn text_editor_apply_theme(selection_color: u32, cursor_color: u32) {
selection_color: u32,
cursor_width: f32,
cursor_color: u32,
) {
with_state_mut!(state, { with_state_mut!(state, {
// NOTE: In the future could be interesting to fill al this data from // NOTE: In the future could be interesting to fill al this data from
// a structure pointer. // a structure pointer.
state.text_editor_state.theme.selection_color = Color::new(selection_color); state.text_editor_state.theme.selection_color = Color::new(selection_color);
state.text_editor_state.theme.cursor_width = cursor_width;
state.text_editor_state.theme.cursor_color = Color::new(cursor_color); state.text_editor_state.theme.cursor_color = Color::new(cursor_color);
}) })
} }
@ -912,13 +907,14 @@ pub extern "C" fn text_editor_render_overlay() {
}; };
let canvas = state.render_state.surfaces.canvas(SurfaceId::Target); let canvas = state.render_state.surfaces.canvas(SurfaceId::Target);
canvas.save();
let viewbox = state.render_state.viewbox; let viewbox = state.render_state.viewbox;
let zoom = viewbox.zoom * state.render_state.options.dpr(); text_editor_render::render_overlay(
canvas.scale((zoom, zoom)); canvas,
canvas.translate((-viewbox.area.left, -viewbox.area.top)); &viewbox,
text_editor_render::render_overlay(canvas, &state.text_editor_state, shape); &state.render_state.options,
canvas.restore(); &state.text_editor_state,
shape,
);
state.render_state.flush_and_submit(); state.render_state.flush_and_submit();
}); });
} }
@ -1103,12 +1099,11 @@ fn get_cursor_rect(
(pos.position as f32, height) (pos.position as f32, height)
}; };
let cursor_width = 2.0;
let selrect = shape.selrect(); let selrect = shape.selrect();
let base_x = selrect.x(); let base_x = selrect.x();
let base_y = selrect.y() + y_offset; let base_y = selrect.y() + y_offset;
return Some(Rect::from_xywh(base_x + x, base_y, cursor_width, height)); return Some(Rect::from_xywh(base_x + x, base_y, 1.0, height));
} }
y_offset += laid_out_para.height(); y_offset += laid_out_para.height();
} }