Apply correct stroke styling with Vello (#1875)

* Apply correct stroke styling in vello

* Account for line end caps in clipmask size

* apply properties panel improvements

* Account for miter limit in Bbox calculation

* Fix bounding box for individual layers
This commit is contained in:
Dennis Kobert 2024-08-02 14:39:59 +02:00 committed by GitHub
parent 80cf486790
commit 390e643558
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 6 deletions

View File

@ -2132,11 +2132,22 @@ pub fn stroke_properties(document_node: &DocumentNode, node_id: NodeId, _context
let color = color_widget(document_node, node_id, color_index, "Color", ColorButton::default(), true);
let weight = number_widget(document_node, node_id, weight_index, "Weight", NumberInput::default().unit("px").min(0.), true);
let dash_lengths_val = match &document_node.inputs[dash_lengths_index].as_value() {
Some(TaggedValue::VecF64(x)) => x,
_ => &vec![],
};
let dash_lengths = vec_f64_input(document_node, node_id, dash_lengths_index, "Dash Lengths", TextInput::default().centered(true), true);
let dash_offset = number_widget(document_node, node_id, dash_offset_index, "Dash Offset", NumberInput::default().unit("px").min(0.), true);
let number_input = NumberInput::default().unit("px").disabled(dash_lengths_val.is_empty());
let dash_offset = number_widget(document_node, node_id, dash_offset_index, "Dash Offset", number_input, true);
let line_cap = line_cap_widget(document_node, node_id, line_cap_index, "Line Cap", true);
let line_join = line_join_widget(document_node, node_id, line_join_index, "Line Join", true);
let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", NumberInput::default().min(0.), true);
let line_join_val = match &document_node.inputs[line_join_index].as_value() {
Some(TaggedValue::LineJoin(x)) => x,
_ => &LineJoin::Miter,
};
let number_input = NumberInput::default().min(0.).disabled(line_join_val != &LineJoin::Miter);
let miter_limit = number_widget(document_node, node_id, miter_limit_index, "Miter Limit", number_input, true);
vec![
color,

View File

@ -327,8 +327,10 @@ impl GraphicElementRendered for VectorData {
fn bounding_box(&self, transform: DAffine2) -> Option<[DVec2; 2]> {
let stroke_width = self.style.stroke().map(|s| s.weight()).unwrap_or_default();
let miter_limit = self.style.stroke().map(|s| s.line_join_miter_limit).unwrap_or(1.);
let scale = transform.decompose_scale();
let offset = DVec2::splat(stroke_width * scale.x.max(scale.y) / 2.);
// We use the full line width here to account for different styles of line caps
let offset = DVec2::splat(stroke_width * scale.x.max(scale.y) * miter_limit);
self.bounding_box_with_transform(transform * self.transform).map(|[a, b]| [a - offset, b + offset])
}
@ -349,8 +351,7 @@ impl GraphicElementRendered for VectorData {
use crate::vector::style::GradientType;
use vello::peniko;
let multiplied_transform = transform * self.transform;
let transformed_bounds = self.bounding_box_with_transform(multiplied_transform).unwrap_or_default();
let transformed_bounds = GraphicElementRendered::bounding_box(self, transform).unwrap_or_default();
let mut layer = false;
if self.alpha_blending.opacity < 1. || self.alpha_blending.blend_mode != BlendMode::default() {
@ -424,10 +425,26 @@ impl GraphicElementRendered for VectorData {
Some(color) => peniko::Color::rgba(color.r() as f64, color.g() as f64, color.b() as f64, color.a() as f64),
None => peniko::Color::TRANSPARENT,
};
use crate::vector::style::{LineCap, LineJoin};
use vello::kurbo::{Cap, Join};
let cap = match stroke.line_cap {
LineCap::Butt => Cap::Butt,
LineCap::Round => Cap::Round,
LineCap::Square => Cap::Square,
};
let join = match stroke.line_join {
LineJoin::Miter => Join::Miter,
LineJoin::Bevel => Join::Bevel,
LineJoin::Round => Join::Round,
};
let stroke = kurbo::Stroke {
width: stroke.weight,
miter_limit: stroke.line_join_miter_limit,
..Default::default()
join,
start_cap: cap,
end_cap: cap,
dash_pattern: stroke.dash_lengths.into(),
dash_offset: stroke.dash_offset,
};
if stroke.width > 0. {
scene.stroke(&stroke, kurbo_transform, color, None, &path);