mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-01 04:08:13 +08:00
Add support for setting the spread method for gradient fills (#3953)
* Add spread method support for gradients * Add GradientSpreadMethod enum (Pad, Repeat, Reflect) to vector-types * Add radio buttons to gradient tool and fill properties panel * Convert spread method when importing SVGs via usvg * Sync backup gradient input when changing spread method * Table<GradientStops> rendering is not yet updated for spread method * Sync gradient tool options with layer's gradient * Sync gradient_type and spread_method from the selected layer's existing gradient to the tool options bar when switching to the gradient tool * Refactor has_gradient_on_selected_layers to reuse a new get_gradient_on_selected_layer helper * Swap Reflect and Repeat order in UI radio buttons * Fix alignment of the radio buttons in right panel * Fix the position of the radio buttons in the tool * Rename SpreadMethod to SetSpreadMethod * Move default spread method omission logic
This commit is contained in:
+25
-3
@@ -15,7 +15,7 @@ use graphene_std::renderer::Quad;
|
||||
use graphene_std::renderer::convert_usvg_path::convert_usvg_path;
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::{Font, TypesettingConfig};
|
||||
use graphene_std::vector::style::{Fill, Gradient, GradientStop, GradientStops, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
||||
use graphene_std::vector::style::{Fill, Gradient, GradientSpreadMethod, GradientStop, GradientStops, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
||||
|
||||
#[derive(ExtractField)]
|
||||
pub struct GraphOperationMessageContext<'a> {
|
||||
@@ -765,6 +765,14 @@ fn apply_usvg_stroke(stroke: &usvg::Stroke, modify_inputs: &mut ModifyInputsCont
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_spread_method(spread_method: usvg::SpreadMethod) -> GradientSpreadMethod {
|
||||
match spread_method {
|
||||
usvg::SpreadMethod::Pad => GradientSpreadMethod::Pad,
|
||||
usvg::SpreadMethod::Reflect => GradientSpreadMethod::Reflect,
|
||||
usvg::SpreadMethod::Repeat => GradientSpreadMethod::Repeat,
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, bounds_transform: DAffine2, graphite_gradient_stops: &HashMap<String, GradientStops>) {
|
||||
modify_inputs.fill_set(match &fill.paint() {
|
||||
usvg::Paint::Color(color) => Fill::solid(usvg_color(*color, fill.opacity().get())),
|
||||
@@ -787,8 +795,15 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, b
|
||||
GradientStops::new(stops)
|
||||
}
|
||||
};
|
||||
let spread_method = convert_spread_method(linear.spread_method());
|
||||
|
||||
Fill::Gradient(Gradient { start, end, gradient_type, stops })
|
||||
Fill::Gradient(Gradient {
|
||||
start,
|
||||
end,
|
||||
gradient_type,
|
||||
stops,
|
||||
spread_method,
|
||||
})
|
||||
}
|
||||
usvg::Paint::RadialGradient(radial) => {
|
||||
let gradient_transform = usvg_transform(radial.transform());
|
||||
@@ -810,8 +825,15 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, b
|
||||
GradientStops::new(stops)
|
||||
}
|
||||
};
|
||||
let spread_method = convert_spread_method(radial.spread_method());
|
||||
|
||||
Fill::Gradient(Gradient { start, end, gradient_type, stops })
|
||||
Fill::Gradient(Gradient {
|
||||
start,
|
||||
end,
|
||||
gradient_type,
|
||||
stops,
|
||||
spread_method,
|
||||
})
|
||||
}
|
||||
usvg::Paint::Pattern(_) => {
|
||||
warn!("SVG patterns are not currently supported");
|
||||
|
||||
@@ -27,7 +27,7 @@ use graphene_std::transform::{Footprint, ReferencePoint, ScaleType, Transform};
|
||||
use graphene_std::vector::QRCodeErrorCorrectionLevel;
|
||||
use graphene_std::vector::misc::BooleanOperation;
|
||||
use graphene_std::vector::misc::{ArcType, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType};
|
||||
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientStops, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};
|
||||
use graphene_std::vector::style::{Fill, FillChoice, FillType, GradientSpreadMethod, GradientStops, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};
|
||||
|
||||
pub(crate) fn string_properties(text: &str) -> Vec<LayoutGroup> {
|
||||
let widget = TextLabel::new(text).widget_instance();
|
||||
@@ -2006,6 +2006,55 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
||||
]);
|
||||
|
||||
widgets.push(LayoutGroup::row(row));
|
||||
|
||||
let mut spread_methods_row: Vec<WidgetInstance> = vec![TextLabel::new("").widget_instance(), Separator::new(SeparatorStyle::Unrelated).widget_instance()];
|
||||
|
||||
let spread_method_entries = [GradientSpreadMethod::Pad, GradientSpreadMethod::Reflect, GradientSpreadMethod::Repeat]
|
||||
.iter()
|
||||
.map(|&spread_method| {
|
||||
let gradient_for_input = gradient_for_closure.clone();
|
||||
let gradient_for_backup = gradient_for_closure.clone();
|
||||
|
||||
let set_input_value = update_value(
|
||||
move |_: &()| {
|
||||
let mut new_gradient = gradient_for_input.clone();
|
||||
new_gradient.spread_method = spread_method;
|
||||
TaggedValue::Fill(Fill::Gradient(new_gradient))
|
||||
},
|
||||
node_id,
|
||||
FillInput::<Color>::INDEX,
|
||||
);
|
||||
|
||||
let set_backup_value = update_value(
|
||||
move |_: &()| {
|
||||
let mut new_gradient = gradient_for_backup.clone();
|
||||
new_gradient.spread_method = spread_method;
|
||||
TaggedValue::Gradient(new_gradient)
|
||||
},
|
||||
node_id,
|
||||
BackupGradientInput::INDEX,
|
||||
);
|
||||
|
||||
RadioEntryData::new(format!("{:?}", spread_method))
|
||||
.label(format!("{:?}", spread_method))
|
||||
.on_update(move |_| Message::Batched {
|
||||
messages: Box::new([
|
||||
set_input_value(&()),
|
||||
set_backup_value(&()),
|
||||
GradientToolMessage::UpdateOptions {
|
||||
options: GradientOptionsUpdate::SetSpreadMethod(spread_method),
|
||||
}
|
||||
.into(),
|
||||
]),
|
||||
})
|
||||
.on_commit(commit_value)
|
||||
})
|
||||
.collect();
|
||||
|
||||
add_blank_assist(&mut spread_methods_row);
|
||||
spread_methods_row.extend_from_slice(&[RadioInput::new(spread_method_entries).selected_index(Some(gradient.spread_method as u32)).widget_instance()]);
|
||||
|
||||
widgets.push(LayoutGroup::row(spread_methods_row));
|
||||
}
|
||||
|
||||
widgets
|
||||
|
||||
Reference in New Issue
Block a user