Skip to content

Commit d51dd5b

Browse files
committed
Implement fill overlay
1 parent 23eb599 commit d51dd5b

1 file changed

Lines changed: 95 additions & 24 deletions

File tree

editor/src/messages/portfolio/document/overlays/utility_types_vello.rs

Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,8 @@ impl OverlayContext {
378378
}
379379

380380
pub fn text(&self, text: &str, font_color: &str, background_color: Option<&str>, transform: DAffine2, padding: f64, pivot: [Pivot; 2]) {
381-
self.internal().text(text, font_color, background_color, transform, padding, pivot);
381+
let mut internal = self.internal();
382+
internal.text(text, font_color, background_color, transform, padding, pivot);
382383
}
383384

384385
pub fn translation_box(&mut self, translation: DVec2, quad: Quad, typed_string: Option<String>) {
@@ -972,34 +973,104 @@ impl OverlayContextInternal {
972973
/// Fills the area inside the path with a pattern. Assumes `color` is in gamma space.
973974
/// Used by the fill tool to show the area to be filled.
974975
fn fill_path_pattern(&mut self, subpaths: impl Iterator<Item = impl Borrow<Subpath<PointId>>>, transform: DAffine2, color: &Color) {
975-
// TODO: Implement pattern fill in Vello
976-
// For now, just fill with a semi-transparent version of the color
976+
const PATTERN_WIDTH: u32 = 4;
977+
const PATTERN_HEIGHT: u32 = 4;
978+
979+
// Create a 4x4 pixel pattern with colored pixels at (0,0) and (2,2)
980+
// This matches the Canvas2D checkerboard pattern
981+
let mut data = vec![0u8; (PATTERN_WIDTH * PATTERN_HEIGHT * 4) as usize];
982+
let rgba = color.to_rgba8_srgb();
983+
984+
// Set pixels at (0,0) and (2,2) to the specified color
985+
let pixels = [(0, 0), (2, 2)];
986+
for &(x, y) in &pixels {
987+
let index = ((y * PATTERN_WIDTH + x) * 4) as usize;
988+
data[index..index + 4].copy_from_slice(&rgba);
989+
}
990+
991+
let image = peniko::Image {
992+
data: data.into(),
993+
format: peniko::ImageFormat::Rgba8,
994+
width: PATTERN_WIDTH,
995+
height: PATTERN_HEIGHT,
996+
x_extend: peniko::Extend::Repeat,
997+
y_extend: peniko::Extend::Repeat,
998+
alpha: 1.0,
999+
quality: peniko::ImageQuality::default(),
1000+
};
1001+
9771002
let path = self.push_path(subpaths, transform);
978-
let semi_transparent_color = color.with_alpha(0.5);
979-
980-
self.scene.fill(
981-
peniko::Fill::NonZero,
982-
self.get_transform(),
983-
peniko::Color::from_rgba8(
984-
(semi_transparent_color.r() * 255.) as u8,
985-
(semi_transparent_color.g() * 255.) as u8,
986-
(semi_transparent_color.b() * 255.) as u8,
987-
(semi_transparent_color.a() * 255.) as u8,
988-
),
1003+
let brush = peniko::Brush::Image(image);
1004+
1005+
self.scene.fill(peniko::Fill::NonZero, self.get_transform(), &brush, None, &path);
1006+
}
1007+
1008+
fn get_width(&self, text: &str) -> f64 {
1009+
// Basic text width estimation that matches the text() function implementation
1010+
// This uses the same character width estimation for consistency
1011+
// Note: This is primarily used for manual positioning calculations, but ideally
1012+
// the pivot system in text() should handle centering automatically
1013+
const CHAR_WIDTH: f64 = 7.0; // Approximate character width at 12px font size
1014+
text.len() as f64 * CHAR_WIDTH
1015+
}
1016+
1017+
fn text(&mut self, text: &str, font_color: &str, background_color: Option<&str>, transform: DAffine2, padding: f64, pivot: [Pivot; 2]) {
1018+
// For now, implement a basic text rendering approach
1019+
// This is a simplified version that can be enhanced later with full font support
1020+
1021+
// Calculate approximate text dimensions (basic estimation)
1022+
let char_width = 7.0; // Approximate character width at 12px font size
1023+
let char_height = 12.0; // Font size
1024+
let text_width = text.len() as f64 * char_width;
1025+
let text_height = char_height;
1026+
1027+
// Calculate position based on pivot
1028+
let mut position = DVec2::ZERO;
1029+
match pivot[0] {
1030+
Pivot::Start => position.x = padding,
1031+
Pivot::Middle => position.x = -text_width / 2.0,
1032+
Pivot::End => position.x = -padding - text_width,
1033+
}
1034+
match pivot[1] {
1035+
Pivot::Start => position.y = padding + text_height,
1036+
Pivot::Middle => position.y = text_height / 2.0,
1037+
Pivot::End => position.y = -padding,
1038+
}
1039+
1040+
let text_transform = transform * DAffine2::from_translation(position);
1041+
let device_transform = self.get_transform();
1042+
let combined_transform = kurbo::Affine::new(text_transform.to_cols_array());
1043+
let vello_transform = device_transform * combined_transform;
1044+
1045+
// Draw background if specified
1046+
if let Some(bg_color) = background_color {
1047+
let bg_rect = kurbo::Rect::new(
1048+
-padding,
1049+
-padding,
1050+
text_width + padding,
1051+
text_height + padding
1052+
);
1053+
self.scene.fill(
1054+
peniko::Fill::NonZero,
1055+
vello_transform,
1056+
Self::parse_color(bg_color),
1057+
None,
1058+
&bg_rect,
1059+
);
1060+
}
1061+
1062+
// For now, draw a simple rectangle to represent text
1063+
// TODO: Implement proper font rendering using vello's text capabilities
1064+
let text_rect = kurbo::Rect::new(0.0, 0.0, text_width, text_height);
1065+
self.scene.stroke(
1066+
&kurbo::Stroke::new(1.0),
1067+
vello_transform,
1068+
Self::parse_color(font_color),
9891069
None,
990-
&path,
1070+
&text_rect,
9911071
);
9921072
}
9931073

994-
fn get_width(&self, _text: &str) -> f64 {
995-
// TODO: Implement proper text measurement in Vello
996-
0.
997-
}
998-
999-
fn text(&self, _text: &str, _font_color: &str, _background_color: Option<&str>, _transform: DAffine2, _padding: f64, _pivot: [Pivot; 2]) {
1000-
// TODO: Implement text rendering in Vello
1001-
}
1002-
10031074
fn translation_box(&mut self, translation: DVec2, quad: Quad, typed_string: Option<String>) {
10041075
if translation.x.abs() > 1e-3 {
10051076
self.dashed_line(quad.top_left(), quad.top_right(), None, None, Some(2.), Some(2.), Some(0.5));

0 commit comments

Comments
 (0)