Correctly apply transforms to vector data and strokes (#1977)

* Fix adding a layer to a transformed group

* Fix assorted transform issues

* Default stroke transform

* Fix bench

* Transform gradient

* Gradient fix

* Add gradient reversal buttons to Fill node in the Properties panel

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
James Lindsay
2024-09-15 22:26:11 +00:00
committed by GitHub
co-authored by Keavon Chambers
parent 2fa8773092
commit dd4a97b09f
19 changed files with 152 additions and 59 deletions
@@ -266,7 +266,7 @@ fn import_usvg_node(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node,
let bounds_transform = DAffine2::from_scale_angle_translation(bounds[1] - bounds[0], 0., bounds[0]);
apply_usvg_fill(path.fill(), modify_inputs, transform * usvg_transform(node.abs_transform()), bounds_transform);
apply_usvg_stroke(path.stroke(), modify_inputs);
apply_usvg_stroke(path.stroke(), modify_inputs, transform * usvg_transform(node.abs_transform()));
}
usvg::Node::Image(_image) => {
warn!("Skip image")
@@ -279,7 +279,7 @@ fn import_usvg_node(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node,
}
}
fn apply_usvg_stroke(stroke: Option<&usvg::Stroke>, modify_inputs: &mut ModifyInputsContext) {
fn apply_usvg_stroke(stroke: Option<&usvg::Stroke>, modify_inputs: &mut ModifyInputsContext, transform: DAffine2) {
if let Some(stroke) = stroke {
if let usvg::Paint::Color(color) = &stroke.paint() {
modify_inputs.stroke_set(Stroke {
@@ -299,6 +299,7 @@ fn apply_usvg_stroke(stroke: Option<&usvg::Stroke>, modify_inputs: &mut ModifyIn
usvg::LineJoin::Bevel => LineJoin::Bevel,
},
line_join_miter_limit: stroke.miterlimit().get() as f64,
transform,
})
} else {
warn!("Skip non-solid stroke")
@@ -2597,7 +2597,28 @@ pub fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context:
let fill_type_switch = {
let mut row = vec![TextLabel::new("").widget_holder()];
add_blank_assist(&mut row);
match fill {
Fill::Solid(_) | Fill::None => add_blank_assist(&mut row),
Fill::Gradient(gradient) => {
let reverse_button = IconButton::new("Reverse", 24)
.tooltip("Reverse the gradient color stops")
.on_update(update_value(
{
let gradient = gradient.clone();
move |_| {
let mut gradient = gradient.clone();
gradient.stops = gradient.stops.reversed();
TaggedValue::Fill(Fill::Gradient(gradient))
}
},
node_id,
fill_index,
))
.widget_holder();
row.push(Separator::new(SeparatorType::Unrelated).widget_holder());
row.push(reverse_button);
}
}
let entries = vec![
RadioEntryData::new("solid")
@@ -2619,9 +2640,35 @@ pub fn fill_properties(document_node: &DocumentNode, node_id: NodeId, _context:
};
widgets.push(fill_type_switch);
if let Fill::Gradient(gradient) = fill {
if let Fill::Gradient(gradient) = fill.clone() {
let mut row = vec![TextLabel::new("").widget_holder()];
add_blank_assist(&mut row);
match gradient.gradient_type {
GradientType::Linear => add_blank_assist(&mut row),
GradientType::Radial => {
let orientation = if (gradient.end.x - gradient.start.x).abs() > f64::EPSILON * 1e6 {
gradient.end.x > gradient.start.x
} else {
(gradient.start.x + gradient.start.y) < (gradient.end.x + gradient.end.y)
};
let reverse_radial_gradient_button = IconButton::new(if orientation { "ReverseRadialGradientToRight" } else { "ReverseRadialGradientToLeft" }, 24)
.tooltip("Reverse which end the gradient radiates from")
.on_update(update_value(
{
let gradient = gradient.clone();
move |_| {
let mut gradient = gradient.clone();
std::mem::swap(&mut gradient.start, &mut gradient.end);
TaggedValue::Fill(Fill::Gradient(gradient))
}
},
node_id,
fill_index,
))
.widget_holder();
row.push(Separator::new(SeparatorType::Unrelated).widget_holder());
row.push(reverse_radial_gradient_button);
}
}
let new_gradient1 = gradient.clone();
let new_gradient2 = gradient.clone();