mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-27 23:38:11 +08:00
Rename gradient type to gradient form (#4405)
* Rename gradient type to gradient form * Update the demo art for the gradient form rename * Say form not type in the Gradient Form node's doc comment
This commit is contained in:
@@ -23,7 +23,7 @@ use graphene_std::transform::{ReferencePoint, ScaleType};
|
|||||||
use graphene_std::vector::misc::{
|
use graphene_std::vector::misc::{
|
||||||
ArcType, BooleanOperation, BoxCorners, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType,
|
ArcType, BooleanOperation, BoxCorners, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType,
|
||||||
};
|
};
|
||||||
use graphene_std::vector::style::{DashPattern, FillChoice, GradientRamp, GradientSpread, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};
|
use graphene_std::vector::style::{DashPattern, FillChoice, GradientForm, GradientRamp, GradientSpread, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin};
|
||||||
use graphene_std::vector::{QRCodeErrorCorrectionLevel, Vector};
|
use graphene_std::vector::{QRCodeErrorCorrectionLevel, Vector};
|
||||||
use graphene_std::{Artboard, Color, Graphic};
|
use graphene_std::{Artboard, Color, Graphic};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
@@ -216,7 +216,7 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
|
|||||||
List<DVec2>,
|
List<DVec2>,
|
||||||
List<DAffine2>,
|
List<DAffine2>,
|
||||||
List<BlendMode>,
|
List<BlendMode>,
|
||||||
List<GradientType>,
|
List<GradientForm>,
|
||||||
List<GradientSpread>,
|
List<GradientSpread>,
|
||||||
List<DashPattern>,
|
List<DashPattern>,
|
||||||
List<BoxCorners>,
|
List<BoxCorners>,
|
||||||
@@ -269,7 +269,7 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
|
|||||||
DVec2,
|
DVec2,
|
||||||
DAffine2,
|
DAffine2,
|
||||||
BlendMode,
|
BlendMode,
|
||||||
GradientType,
|
GradientForm,
|
||||||
GradientSpread,
|
GradientSpread,
|
||||||
DashPattern,
|
DashPattern,
|
||||||
BoxCorners,
|
BoxCorners,
|
||||||
@@ -1007,7 +1007,7 @@ macro_rules! impl_table_item_layout_for_choice_enum {
|
|||||||
}
|
}
|
||||||
impl_table_item_layout_for_choice_enum!(
|
impl_table_item_layout_for_choice_enum!(
|
||||||
BlendMode,
|
BlendMode,
|
||||||
GradientType,
|
GradientForm,
|
||||||
GradientSpread,
|
GradientSpread,
|
||||||
StrokeJoin,
|
StrokeJoin,
|
||||||
StrokeAlign,
|
StrokeAlign,
|
||||||
@@ -1219,7 +1219,7 @@ macro_rules! known_item_types {
|
|||||||
DashPattern,
|
DashPattern,
|
||||||
BoxCorners,
|
BoxCorners,
|
||||||
BlendMode,
|
BlendMode,
|
||||||
GradientType,
|
GradientForm,
|
||||||
GradientSpread,
|
GradientSpread,
|
||||||
StrokeJoin,
|
StrokeJoin,
|
||||||
StrokeAlign,
|
StrokeAlign,
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use graphene_std::raster::BlendMode;
|
|||||||
use graphene_std::raster_types::Image;
|
use graphene_std::raster_types::Image;
|
||||||
use graphene_std::subpath::Subpath;
|
use graphene_std::subpath::Subpath;
|
||||||
use graphene_std::text::{Font, TypesettingConfig};
|
use graphene_std::text::{Font, TypesettingConfig};
|
||||||
use graphene_std::vector::style::{GradientSpread, GradientType, Stroke};
|
use graphene_std::vector::style::{GradientForm, GradientSpread, Stroke};
|
||||||
use graphene_std::vector::{Gradient, PointId, VectorModificationType};
|
use graphene_std::vector::{Gradient, PointId, VectorModificationType};
|
||||||
|
|
||||||
#[impl_message(Message, DocumentMessage, GraphOperation)]
|
#[impl_message(Message, DocumentMessage, GraphOperation)]
|
||||||
@@ -24,7 +24,7 @@ pub enum GraphOperationMessage {
|
|||||||
layer: LayerNodeIdentifier,
|
layer: LayerNodeIdentifier,
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
gradient: Gradient,
|
gradient: Gradient,
|
||||||
gradient_type: GradientType,
|
gradient_form: GradientForm,
|
||||||
gradient_spread: GradientSpread,
|
gradient_spread: GradientSpread,
|
||||||
transform: DAffine2,
|
transform: DAffine2,
|
||||||
},
|
},
|
||||||
@@ -49,9 +49,9 @@ pub enum GraphOperationMessage {
|
|||||||
layer: LayerNodeIdentifier,
|
layer: LayerNodeIdentifier,
|
||||||
transform: DAffine2,
|
transform: DAffine2,
|
||||||
},
|
},
|
||||||
GradientTypeSet {
|
GradientFormSet {
|
||||||
layer: LayerNodeIdentifier,
|
layer: LayerNodeIdentifier,
|
||||||
gradient_type: GradientType,
|
gradient_form: GradientForm,
|
||||||
},
|
},
|
||||||
GradientSpreadSet {
|
GradientSpreadSet {
|
||||||
layer: LayerNodeIdentifier,
|
layer: LayerNodeIdentifier,
|
||||||
|
|||||||
+9
-9
@@ -14,7 +14,7 @@ use graph_craft::document::{NodeId, NodeInput};
|
|||||||
use graphene_std::list::List;
|
use graphene_std::list::List;
|
||||||
use graphene_std::renderer::convert_usvg_path::convert_usvg_path;
|
use graphene_std::renderer::convert_usvg_path::convert_usvg_path;
|
||||||
use graphene_std::text::{Font, TypesettingConfig};
|
use graphene_std::text::{Font, TypesettingConfig};
|
||||||
use graphene_std::vector::style::{Gradient, GradientSpread, GradientStop, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
use graphene_std::vector::style::{Gradient, GradientForm, GradientSpread, GradientStop, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
||||||
use graphene_std::{Artboard, Color};
|
use graphene_std::{Artboard, Color};
|
||||||
|
|
||||||
#[derive(ExtractField)]
|
#[derive(ExtractField)]
|
||||||
@@ -43,12 +43,12 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
|
|||||||
GraphOperationMessage::FillGradientSet {
|
GraphOperationMessage::FillGradientSet {
|
||||||
layer,
|
layer,
|
||||||
gradient,
|
gradient,
|
||||||
gradient_type,
|
gradient_form,
|
||||||
gradient_spread,
|
gradient_spread,
|
||||||
transform,
|
transform,
|
||||||
} => {
|
} => {
|
||||||
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
|
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
|
||||||
modify_inputs.fill_gradient_set(gradient, gradient_type, gradient_spread, transform);
|
modify_inputs.fill_gradient_set(gradient, gradient_form, gradient_spread, transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GraphOperationMessage::BlendingFillSet { layer, fill } => {
|
GraphOperationMessage::BlendingFillSet { layer, fill } => {
|
||||||
@@ -76,9 +76,9 @@ impl MessageHandler<GraphOperationMessage, GraphOperationMessageContext<'_>> for
|
|||||||
modify_inputs.gradient_transform_set(transform);
|
modify_inputs.gradient_transform_set(transform);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GraphOperationMessage::GradientTypeSet { layer, gradient_type } => {
|
GraphOperationMessage::GradientFormSet { layer, gradient_form } => {
|
||||||
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
|
if let Some(mut modify_inputs) = ModifyInputsContext::new_with_layer(layer, network_interface, responses) {
|
||||||
modify_inputs.gradient_type_set(gradient_type);
|
modify_inputs.gradient_form_set(gradient_form);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GraphOperationMessage::GradientSpreadSet { layer, gradient_spread } => {
|
GraphOperationMessage::GradientSpreadSet { layer, gradient_spread } => {
|
||||||
@@ -824,7 +824,7 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, g
|
|||||||
let direction = end - start;
|
let direction = end - start;
|
||||||
let transform = DAffine2::from_cols(direction, direction.perp(), start);
|
let transform = DAffine2::from_cols(direction, direction.perp(), start);
|
||||||
|
|
||||||
let gradient_type = GradientType::Linear;
|
let gradient_form = GradientForm::Linear;
|
||||||
|
|
||||||
let gradient = match graphite_gradient_stops.get(linear.id()) {
|
let gradient = match graphite_gradient_stops.get(linear.id()) {
|
||||||
Some(graphite_stops) => graphite_stops.clone(),
|
Some(graphite_stops) => graphite_stops.clone(),
|
||||||
@@ -838,7 +838,7 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, g
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
let gradient_spread = convert_gradient_spread(linear.spread_method());
|
let gradient_spread = convert_gradient_spread(linear.spread_method());
|
||||||
modify_inputs.fill_gradient_set(gradient, gradient_type, gradient_spread, transform);
|
modify_inputs.fill_gradient_set(gradient, gradient_form, gradient_spread, transform);
|
||||||
}
|
}
|
||||||
usvg::Paint::RadialGradient(radial) => {
|
usvg::Paint::RadialGradient(radial) => {
|
||||||
let gradient_transform = usvg_transform(radial.transform());
|
let gradient_transform = usvg_transform(radial.transform());
|
||||||
@@ -848,7 +848,7 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, g
|
|||||||
let direction = end - start;
|
let direction = end - start;
|
||||||
let transform = DAffine2::from_cols(direction, direction.perp(), start);
|
let transform = DAffine2::from_cols(direction, direction.perp(), start);
|
||||||
|
|
||||||
let gradient_type = GradientType::Radial;
|
let gradient_form = GradientForm::Radial;
|
||||||
|
|
||||||
let gradient = match graphite_gradient_stops.get(radial.id()) {
|
let gradient = match graphite_gradient_stops.get(radial.id()) {
|
||||||
Some(graphite_stops) => graphite_stops.clone(),
|
Some(graphite_stops) => graphite_stops.clone(),
|
||||||
@@ -863,7 +863,7 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, g
|
|||||||
};
|
};
|
||||||
let gradient_spread = convert_gradient_spread(radial.spread_method());
|
let gradient_spread = convert_gradient_spread(radial.spread_method());
|
||||||
|
|
||||||
modify_inputs.fill_gradient_set(gradient, gradient_type, gradient_spread, transform);
|
modify_inputs.fill_gradient_set(gradient, gradient_form, gradient_spread, transform);
|
||||||
}
|
}
|
||||||
usvg::Paint::Pattern(_) => warn!("SVG patterns are not currently supported"),
|
usvg::Paint::Pattern(_) => warn!("SVG patterns are not currently supported"),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use graphene_std::raster::BlendMode;
|
|||||||
use graphene_std::raster_types::Image;
|
use graphene_std::raster_types::Image;
|
||||||
use graphene_std::subpath::Subpath;
|
use graphene_std::subpath::Subpath;
|
||||||
use graphene_std::text::{Font, TypesettingConfig};
|
use graphene_std::text::{Font, TypesettingConfig};
|
||||||
use graphene_std::vector::style::{GradientSpread, GradientType, Stroke};
|
use graphene_std::vector::style::{GradientForm, GradientSpread, Stroke};
|
||||||
use graphene_std::vector::{Gradient, GradientRamp, PointId, Vector, VectorModification, VectorModificationType};
|
use graphene_std::vector::{Gradient, GradientRamp, PointId, Vector, VectorModification, VectorModificationType};
|
||||||
use graphene_std::{Artboard, Color, Graphic};
|
use graphene_std::{Artboard, Color, Graphic};
|
||||||
|
|
||||||
@@ -404,7 +404,7 @@ impl<'a> ModifyInputsContext<'a> {
|
|||||||
self.set_input_with_refresh(input_connector, NodeInput::value(fill_value, false), false);
|
self.set_input_with_refresh(input_connector, NodeInput::value(fill_value, false), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_gradient_set(&mut self, gradient: Gradient, gradient_type: GradientType, gradient_spread: GradientSpread, transform: DAffine2) {
|
pub fn fill_gradient_set(&mut self, gradient: Gradient, gradient_form: GradientForm, gradient_spread: GradientSpread, transform: DAffine2) {
|
||||||
let Some(fill_node_id) = self.existing_proto_node_id(graphene_std::vector_nodes::fill::IDENTIFIER, true) else {
|
let Some(fill_node_id) = self.existing_proto_node_id(graphene_std::vector_nodes::fill::IDENTIFIER, true) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
@@ -443,8 +443,8 @@ impl<'a> ModifyInputsContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.set_input_with_refresh(
|
self.set_input_with_refresh(
|
||||||
InputConnector::node(fill_node_id, graphene_std::vector::fill::GradientTypeInput),
|
InputConnector::node(fill_node_id, graphene_std::vector::fill::GradientFormInput),
|
||||||
NodeInput::value(TaggedValue::GradientType(gradient_type), false),
|
NodeInput::value(TaggedValue::GradientForm(gradient_form), false),
|
||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -661,20 +661,20 @@ impl<'a> ModifyInputsContext<'a> {
|
|||||||
self.responses.add(NodeGraphMessage::RunDocumentGraph);
|
self.responses.add(NodeGraphMessage::RunDocumentGraph);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the gradient type to the last 'Gradient Type' node in the chain, inserting one only when the value differs
|
/// Write the Gradient Form to the last 'Gradient Form' node in the chain, inserting one only when the value differs
|
||||||
/// from the default (`Linear`).
|
/// from the default (`Linear`).
|
||||||
pub fn gradient_type_set(&mut self, gradient_type: GradientType) {
|
pub fn gradient_form_set(&mut self, gradient_form: GradientForm) {
|
||||||
let Some(output_layer) = self.get_output_layer() else { return };
|
let Some(output_layer) = self.get_output_layer() else { return };
|
||||||
|
|
||||||
let target_input = gradient_chain_target_input(output_layer, self.network_interface);
|
let target_input = gradient_chain_target_input(output_layer, self.network_interface);
|
||||||
let identifier = graphene_std::math_nodes::gradient_type::IDENTIFIER;
|
let identifier = graphene_std::math_nodes::gradient_form::IDENTIFIER;
|
||||||
let create_if_nonexistent = gradient_type != GradientType::default();
|
let create_if_nonexistent = gradient_form != GradientForm::default();
|
||||||
let Some(node_id) = self.existing_proto_node_id_at(&target_input, identifier, create_if_nonexistent) else {
|
let Some(node_id) = self.existing_proto_node_id_at(&target_input, identifier, create_if_nonexistent) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let input_connector = InputConnector::node(node_id, graphene_std::math_nodes::gradient_type::GradientTypeInput);
|
let input_connector = InputConnector::node(node_id, graphene_std::math_nodes::gradient_form::GradientFormInput);
|
||||||
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::GradientType(gradient_type), false), false);
|
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::GradientForm(gradient_form), false), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write the gradient spread to the last 'Gradient Spread' node in the chain, inserting one only when the value differs
|
/// Write the gradient spread to the last 'Gradient Spread' node in the chain, inserting one only when the value differs
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ use graphene_std::vector::misc::{
|
|||||||
ArcType, BoxCorners, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType,
|
ArcType, BoxCorners, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType,
|
||||||
};
|
};
|
||||||
use graphene_std::vector::style::{
|
use graphene_std::vector::style::{
|
||||||
FillChoice, Gradient, GradientRamp, GradientSpread, GradientStops, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, build_transform_with_y_preservation,
|
FillChoice, Gradient, GradientForm, GradientRamp, GradientSpread, GradientStops, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, build_transform_with_y_preservation,
|
||||||
};
|
};
|
||||||
use graphene_std::vector::{QRCodeErrorCorrectionLevel, VectorModification};
|
use graphene_std::vector::{QRCodeErrorCorrectionLevel, VectorModification};
|
||||||
use graphene_std::{NodeParameter, ParameterRef};
|
use graphene_std::{NodeParameter, ParameterRef};
|
||||||
@@ -292,7 +292,7 @@ pub(crate) fn property_from_type(
|
|||||||
// =========================
|
// =========================
|
||||||
// AUTO-GENERATED ENUM TYPES
|
// AUTO-GENERATED ENUM TYPES
|
||||||
// =========================
|
// =========================
|
||||||
Some(x) if id_is::<GradientType>(x) => enum_choice::<GradientType>().for_socket(default_info).property_row(),
|
Some(x) if id_is::<GradientForm>(x) => enum_choice::<GradientForm>().for_socket(default_info).property_row(),
|
||||||
Some(x) if id_is::<GradientSpread>(x) => enum_choice::<GradientSpread>().for_socket(default_info).property_row(),
|
Some(x) if id_is::<GradientSpread>(x) => enum_choice::<GradientSpread>().for_socket(default_info).property_row(),
|
||||||
Some(x) if id_is::<RealTimeMode>(x) => enum_choice::<RealTimeMode>().for_socket(default_info).property_row(),
|
Some(x) if id_is::<RealTimeMode>(x) => enum_choice::<RealTimeMode>().for_socket(default_info).property_row(),
|
||||||
Some(x) if id_is::<RedGreenBlue>(x) => enum_choice::<RedGreenBlue>().for_socket(default_info).property_row(),
|
Some(x) if id_is::<RedGreenBlue>(x) => enum_choice::<RedGreenBlue>().for_socket(default_info).property_row(),
|
||||||
@@ -2402,7 +2402,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
Solid(Option<Color>),
|
Solid(Option<Color>),
|
||||||
Gradient {
|
Gradient {
|
||||||
gradient: Gradient,
|
gradient: Gradient,
|
||||||
gradient_type: GradientType,
|
gradient_form: GradientForm,
|
||||||
gradient_spread: GradientSpread,
|
gradient_spread: GradientSpread,
|
||||||
transform: DAffine2,
|
transform: DAffine2,
|
||||||
/// Whether the transform input holds a plain value (so the "Reverse Direction" button may write to it) rather than a wire.
|
/// Whether the transform input holds a plain value (so the "Reverse Direction" button may write to it) rather than a wire.
|
||||||
@@ -2432,7 +2432,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
}) {
|
}) {
|
||||||
Some(gradient) => ResolvedFill::Gradient {
|
Some(gradient) => ResolvedFill::Gradient {
|
||||||
gradient: gradient.stops,
|
gradient: gradient.stops,
|
||||||
gradient_type: gradient.gradient_type,
|
gradient_form: gradient.gradient_form,
|
||||||
gradient_spread: gradient.gradient_spread,
|
gradient_spread: gradient.gradient_spread,
|
||||||
transform: gradient.transform,
|
transform: gradient.transform,
|
||||||
transform_is_value: gradient.transform_is_value,
|
transform_is_value: gradient.transform_is_value,
|
||||||
@@ -2584,7 +2584,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
widgets.push(fill_type_switch);
|
widgets.push(fill_type_switch);
|
||||||
|
|
||||||
if let ResolvedFill::Gradient {
|
if let ResolvedFill::Gradient {
|
||||||
gradient_type,
|
gradient_form,
|
||||||
transform,
|
transform,
|
||||||
transform_is_value,
|
transform_is_value,
|
||||||
..
|
..
|
||||||
@@ -2603,7 +2603,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
|
|
||||||
let reverse_direction_button = IconButton::new(if orientation_rightward { "ReverseRadialGradientToRight" } else { "ReverseRadialGradientToLeft" }, 24)
|
let reverse_direction_button = IconButton::new(if orientation_rightward { "ReverseRadialGradientToRight" } else { "ReverseRadialGradientToLeft" }, 24)
|
||||||
.tooltip_label("Reverse Direction")
|
.tooltip_label("Reverse Direction")
|
||||||
.tooltip_description(graph_modification_utils::reverse_direction_tooltip_description(gradient_type))
|
.tooltip_description(graph_modification_utils::reverse_direction_tooltip_description(gradient_form))
|
||||||
.on_update(move |_| Message::Batched {
|
.on_update(move |_| Message::Batched {
|
||||||
messages: Box::new([
|
messages: Box::new([
|
||||||
NodeGraphMessage::SetInputValue {
|
NodeGraphMessage::SetInputValue {
|
||||||
@@ -2627,19 +2627,19 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
add_blank_assist(&mut row);
|
add_blank_assist(&mut row);
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries = [GradientType::Linear, GradientType::Radial]
|
let entries = [GradientForm::Linear, GradientForm::Radial]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&gradient_type| {
|
.map(|&gradient_form| {
|
||||||
RadioEntryData::new(format!("{:?}", gradient_type))
|
RadioEntryData::new(format!("{:?}", gradient_form))
|
||||||
.label(format!("{:?}", gradient_type))
|
.label(format!("{:?}", gradient_form))
|
||||||
.on_update(update_value(move |_| TaggedValue::GradientType(gradient_type), node_id, GradientTypeInput))
|
.on_update(update_value(move |_| TaggedValue::GradientForm(gradient_form), node_id, GradientFormInput))
|
||||||
.on_commit(commit_value)
|
.on_commit(commit_value)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
row.extend_from_slice(&[
|
row.extend_from_slice(&[
|
||||||
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
|
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
|
||||||
RadioInput::new(entries).selected_index(Some(gradient_type as u32)).widget_instance(),
|
RadioInput::new(entries).selected_index(Some(gradient_form as u32)).widget_instance(),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
widgets.push(LayoutGroup::row(row));
|
widgets.push(LayoutGroup::row(row));
|
||||||
|
|||||||
@@ -269,6 +269,10 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
|||||||
node: graphene_std::math_nodes::footprint_value::IDENTIFIER,
|
node: graphene_std::math_nodes::footprint_value::IDENTIFIER,
|
||||||
aliases: &["graphene_math_nodes::FootprintValueNode", "graphene_core::ops::FootprintValueNode"],
|
aliases: &["graphene_math_nodes::FootprintValueNode", "graphene_core::ops::FootprintValueNode"],
|
||||||
},
|
},
|
||||||
|
NodeReplacement {
|
||||||
|
node: graphene_std::math_nodes::gradient_form::IDENTIFIER,
|
||||||
|
aliases: &["math_nodes::GradientTypeNode"],
|
||||||
|
},
|
||||||
NodeReplacement {
|
NodeReplacement {
|
||||||
node: graphene_std::math_nodes::gradient_spread::IDENTIFIER,
|
node: graphene_std::math_nodes::gradient_spread::IDENTIFIER,
|
||||||
aliases: &["math_nodes::SpreadMethodNode"],
|
aliases: &["math_nodes::SpreadMethodNode"],
|
||||||
@@ -1673,7 +1677,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Upgrade the legacy 4-input Fill node (content, fill: Fill, _backup_color, _backup_gradient: Gradient) to the value-model
|
// Upgrade the legacy 4-input Fill node (content, fill: Fill, _backup_color, _backup_gradient: Gradient) to the value-model
|
||||||
// 7-input shape (content, fill: generic paint list, _backup_color, _backup_gradient, _gradient_type, _has_transform, _transform).
|
// 7-input shape (content, fill: generic paint list, _backup_color, _backup_gradient, _gradient_form, _has_transform, _transform).
|
||||||
if reference == DefinitionIdentifier::ProtoNode(graphene_std::vector_nodes::fill::IDENTIFIER) && inputs_count == 4 {
|
if reference == DefinitionIdentifier::ProtoNode(graphene_std::vector_nodes::fill::IDENTIFIER) && inputs_count == 4 {
|
||||||
let mut node_template = resolve_document_node_type(&reference)?.default_node_template();
|
let mut node_template = resolve_document_node_type(&reference)?.default_node_template();
|
||||||
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
|
document.network_interface.replace_implementation(node_id, network_path, &mut node_template);
|
||||||
@@ -1702,7 +1706,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
if let graphic_types::migrations::legacy::LegacyFill::Gradient(gradient) = old_fill {
|
if let graphic_types::migrations::legacy::LegacyFill::Gradient(gradient) = old_fill {
|
||||||
document.network_interface.set_input(
|
document.network_interface.set_input(
|
||||||
&InputConnector::node_at_index(*node_id, 4),
|
&InputConnector::node_at_index(*node_id, 4),
|
||||||
NodeInput::value(TaggedValue::GradientType(gradient.gradient_type), false),
|
NodeInput::value(TaggedValue::GradientForm(gradient.gradient_type), false),
|
||||||
network_path,
|
network_path,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1754,7 +1758,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
) {
|
) {
|
||||||
document.network_interface.set_input(
|
document.network_interface.set_input(
|
||||||
&InputConnector::node_at_index(*node_id, 4),
|
&InputConnector::node_at_index(*node_id, 4),
|
||||||
NodeInput::value(TaggedValue::GradientType(g.gradient_type), false),
|
NodeInput::value(TaggedValue::GradientForm(g.gradient_type), false),
|
||||||
network_path,
|
network_path,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use graphene_std::subpath::Subpath;
|
|||||||
use graphene_std::text::{Font, TypesettingConfig};
|
use graphene_std::text::{Font, TypesettingConfig};
|
||||||
use graphene_std::vector::misc::ManipulatorPointId;
|
use graphene_std::vector::misc::ManipulatorPointId;
|
||||||
use graphene_std::vector::style::{FillChoice, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, initial_gradient_transform_for_bounding_box};
|
use graphene_std::vector::style::{FillChoice, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, initial_gradient_transform_for_bounding_box};
|
||||||
use graphene_std::vector::{Gradient, GradientSpread, GradientType, PointId, SegmentId, VectorModificationType};
|
use graphene_std::vector::{Gradient, GradientForm, GradientSpread, PointId, SegmentId, VectorModificationType};
|
||||||
use graphene_std::{NodeParameter, ParameterRef};
|
use graphene_std::{NodeParameter, ParameterRef};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
@@ -381,11 +381,11 @@ pub fn gradient_space_transform(layer: LayerNodeIdentifier, network_interface: &
|
|||||||
metadata.transform_to_viewport(layer)
|
metadata.transform_to_viewport(layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tooltip description for a "Reverse Direction" gradient button, phrased for the given gradient type.
|
/// Tooltip description for a "Reverse Direction" gradient button, phrased for the given Gradient Form.
|
||||||
pub fn reverse_direction_tooltip_description(gradient_type: GradientType) -> &'static str {
|
pub fn reverse_direction_tooltip_description(gradient_form: GradientForm) -> &'static str {
|
||||||
match gradient_type {
|
match gradient_form {
|
||||||
GradientType::Radial => "Reverse which end the gradient radiates from.",
|
GradientForm::Radial => "Reverse which end the gradient radiates from.",
|
||||||
GradientType::Linear => "Swap the start and end points of the gradient line.",
|
GradientForm::Linear => "Swap the start and end points of the gradient line.",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,7 +659,7 @@ pub fn set_stroke_weight_for_selected_layers(weight: f64, document: &DocumentMes
|
|||||||
/// A Fill node's decoded gradient inputs, with the transform kept in its raw form (not yet baked into `start`/`end`).
|
/// A Fill node's decoded gradient inputs, with the transform kept in its raw form (not yet baked into `start`/`end`).
|
||||||
pub struct FillNodeGradient {
|
pub struct FillNodeGradient {
|
||||||
pub stops: Gradient,
|
pub stops: Gradient,
|
||||||
pub gradient_type: GradientType,
|
pub gradient_form: GradientForm,
|
||||||
pub gradient_spread: GradientSpread,
|
pub gradient_spread: GradientSpread,
|
||||||
pub transform: DAffine2,
|
pub transform: DAffine2,
|
||||||
/// Whether the transform input holds a plain value (so it may be written to) rather than a wire.
|
/// Whether the transform input holds a plain value (so it may be written to) rather than a wire.
|
||||||
@@ -675,9 +675,9 @@ pub fn read_fill_node_gradient(fill_node: &DocumentNode, bounding_box: impl FnOn
|
|||||||
};
|
};
|
||||||
let gradient_spread = ramp.gradient_spread;
|
let gradient_spread = ramp.gradient_spread;
|
||||||
let stops = Gradient::from(ramp);
|
let stops = Gradient::from(ramp);
|
||||||
let gradient_type = match fill_node.input(fill::GradientTypeInput).and_then(|input| input.as_value()) {
|
let gradient_form = match fill_node.input(fill::GradientFormInput).and_then(|input| input.as_value()) {
|
||||||
Some(&TaggedValue::GradientType(value)) => value,
|
Some(&TaggedValue::GradientForm(value)) => value,
|
||||||
_ => GradientType::default(),
|
_ => GradientForm::default(),
|
||||||
};
|
};
|
||||||
let has_transform = matches!(fill_node.input(fill::HasTransformInput).and_then(|input| input.as_value()), Some(&TaggedValue::Bool(true)));
|
let has_transform = matches!(fill_node.input(fill::HasTransformInput).and_then(|input| input.as_value()), Some(&TaggedValue::Bool(true)));
|
||||||
let transform_input = fill_node.input(fill::TransformInput).and_then(|input| input.as_value());
|
let transform_input = fill_node.input(fill::TransformInput).and_then(|input| input.as_value());
|
||||||
@@ -689,7 +689,7 @@ pub fn read_fill_node_gradient(fill_node: &DocumentNode, bounding_box: impl FnOn
|
|||||||
|
|
||||||
Some(FillNodeGradient {
|
Some(FillNodeGradient {
|
||||||
stops,
|
stops,
|
||||||
gradient_type,
|
gradient_form,
|
||||||
gradient_spread,
|
gradient_spread,
|
||||||
transform,
|
transform,
|
||||||
transform_is_value: transform_input.is_some(),
|
transform_is_value: transform_input.is_some(),
|
||||||
@@ -824,9 +824,9 @@ pub fn set_fill_for_selected_layers(fill_choice: FillChoice, document: &Document
|
|||||||
use graphene_std::vector::fill;
|
use graphene_std::vector::fill;
|
||||||
let fill_parameters = NodeGraphLayer::new(layer, &document.network_interface).find_node_parameters(fill::IDENTIFIER);
|
let fill_parameters = NodeGraphLayer::new(layer, &document.network_interface).find_node_parameters(fill::IDENTIFIER);
|
||||||
|
|
||||||
let gradient_type = match fill_parameters.as_ref().and_then(|parameters| parameters.value(fill::GradientTypeInput)) {
|
let gradient_form = match fill_parameters.as_ref().and_then(|parameters| parameters.value(fill::GradientFormInput)) {
|
||||||
Some(TaggedValue::GradientType(value)) => *value,
|
Some(TaggedValue::GradientForm(value)) => *value,
|
||||||
_ => GradientType::default(),
|
_ => GradientForm::default(),
|
||||||
};
|
};
|
||||||
let has_transform = matches!(fill_parameters.as_ref().and_then(|parameters| parameters.value(fill::HasTransformInput)), Some(TaggedValue::Bool(true)));
|
let has_transform = matches!(fill_parameters.as_ref().and_then(|parameters| parameters.value(fill::HasTransformInput)), Some(TaggedValue::Bool(true)));
|
||||||
let transform = match (has_transform, fill_parameters.as_ref().and_then(|parameters| parameters.value(fill::TransformInput))) {
|
let transform = match (has_transform, fill_parameters.as_ref().and_then(|parameters| parameters.value(fill::TransformInput))) {
|
||||||
@@ -838,7 +838,7 @@ pub fn set_fill_for_selected_layers(fill_choice: FillChoice, document: &Document
|
|||||||
responses.add(GraphOperationMessage::FillGradientSet {
|
responses.add(GraphOperationMessage::FillGradientSet {
|
||||||
layer,
|
layer,
|
||||||
gradient: Gradient::from(ramp),
|
gradient: Gradient::from(ramp),
|
||||||
gradient_type,
|
gradient_form,
|
||||||
gradient_spread: ramp.gradient_spread,
|
gradient_spread: ramp.gradient_spread,
|
||||||
transform,
|
transform,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use glam::DMat2;
|
|||||||
use graph_craft::document::value::TaggedValue;
|
use graph_craft::document::value::TaggedValue;
|
||||||
use graphene_std::color::SRGBA8;
|
use graphene_std::color::SRGBA8;
|
||||||
use graphene_std::raster::color::Color;
|
use graphene_std::raster::color::Color;
|
||||||
use graphene_std::vector::style::{FillChoice, Gradient, GradientRamp, GradientSpread, GradientStop, GradientType, build_transform_with_y_preservation};
|
use graphene_std::vector::style::{FillChoice, Gradient, GradientForm, GradientRamp, GradientSpread, GradientStop, build_transform_with_y_preservation};
|
||||||
|
|
||||||
#[derive(Default, ExtractField)]
|
#[derive(Default, ExtractField)]
|
||||||
pub struct GradientTool {
|
pub struct GradientTool {
|
||||||
@@ -27,7 +27,7 @@ pub struct GradientTool {
|
|||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct GradientOptions {
|
pub struct GradientOptions {
|
||||||
gradient_type: GradientType,
|
gradient_form: GradientForm,
|
||||||
gradient_spread: GradientSpread,
|
gradient_spread: GradientSpread,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ pub enum GradientToolMessage {
|
|||||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
||||||
#[derive(PartialEq, Eq, Clone, Debug, Hash, serde::Serialize, serde::Deserialize)]
|
#[derive(PartialEq, Eq, Clone, Debug, Hash, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum GradientOptionsUpdate {
|
pub enum GradientOptionsUpdate {
|
||||||
Type(GradientType),
|
Form(GradientForm),
|
||||||
ReverseStops,
|
ReverseStops,
|
||||||
ReverseDirection,
|
ReverseDirection,
|
||||||
}
|
}
|
||||||
@@ -82,14 +82,14 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionMessageContext<'a>> for Grad
|
|||||||
fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque<Message>, context: &mut ToolActionMessageContext<'a>) {
|
fn process_message(&mut self, message: ToolMessage, responses: &mut VecDeque<Message>, context: &mut ToolActionMessageContext<'a>) {
|
||||||
match message {
|
match message {
|
||||||
ToolMessage::Gradient(GradientToolMessage::UpdateOptions { options }) => match options {
|
ToolMessage::Gradient(GradientToolMessage::UpdateOptions { options }) => match options {
|
||||||
GradientOptionsUpdate::Type(gradient_type) => {
|
GradientOptionsUpdate::Form(gradient_form) => {
|
||||||
self.options.gradient_type = gradient_type;
|
self.options.gradient_form = gradient_form;
|
||||||
apply_gradient_update(
|
apply_gradient_update(
|
||||||
&mut self.data,
|
&mut self.data,
|
||||||
context,
|
context,
|
||||||
responses,
|
responses,
|
||||||
|(_gradient, appearance)| appearance.gradient_type != gradient_type,
|
|(_gradient, appearance)| appearance.gradient_form != gradient_form,
|
||||||
|(_gradient, appearance)| appearance.gradient_type = gradient_type,
|
|(_gradient, appearance)| appearance.gradient_form = gradient_form,
|
||||||
);
|
);
|
||||||
responses.add(ToolMessage::UpdateHints);
|
responses.add(ToolMessage::UpdateHints);
|
||||||
responses.add(ToolMessage::UpdateCursor);
|
responses.add(ToolMessage::UpdateCursor);
|
||||||
@@ -167,8 +167,8 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionMessageContext<'a>> for Grad
|
|||||||
|
|
||||||
let mut needs_refresh = false;
|
let mut needs_refresh = false;
|
||||||
if let Some((_gradient, appearance)) = ¤t_gradient {
|
if let Some((_gradient, appearance)) = ¤t_gradient {
|
||||||
if self.options.gradient_type != appearance.gradient_type {
|
if self.options.gradient_form != appearance.gradient_form {
|
||||||
self.options.gradient_type = appearance.gradient_type;
|
self.options.gradient_form = appearance.gradient_form;
|
||||||
needs_refresh = true;
|
needs_refresh = true;
|
||||||
}
|
}
|
||||||
if self.options.gradient_spread != appearance.gradient_spread {
|
if self.options.gradient_spread != appearance.gradient_spread {
|
||||||
@@ -230,21 +230,21 @@ impl LayoutHolder for GradientTool {
|
|||||||
fn layout(&self) -> Layout {
|
fn layout(&self) -> Layout {
|
||||||
let mut widgets: Vec<WidgetInstance> = Vec::new();
|
let mut widgets: Vec<WidgetInstance> = Vec::new();
|
||||||
|
|
||||||
let gradient_type = RadioInput::new(vec![
|
let gradient_form = RadioInput::new(vec![
|
||||||
RadioEntryData::new("Linear").label("Linear").tooltip_label("Linear Gradient").on_update(move |_| {
|
RadioEntryData::new("Linear").label("Linear").tooltip_label("Linear Gradient").on_update(move |_| {
|
||||||
GradientToolMessage::UpdateOptions {
|
GradientToolMessage::UpdateOptions {
|
||||||
options: GradientOptionsUpdate::Type(GradientType::Linear),
|
options: GradientOptionsUpdate::Form(GradientForm::Linear),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}),
|
}),
|
||||||
RadioEntryData::new("Radial").label("Radial").tooltip_label("Radial Gradient").on_update(move |_| {
|
RadioEntryData::new("Radial").label("Radial").tooltip_label("Radial Gradient").on_update(move |_| {
|
||||||
GradientToolMessage::UpdateOptions {
|
GradientToolMessage::UpdateOptions {
|
||||||
options: GradientOptionsUpdate::Type(GradientType::Radial),
|
options: GradientOptionsUpdate::Form(GradientForm::Radial),
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
.selected_index(Some((self.options.gradient_type == GradientType::Radial) as u32))
|
.selected_index(Some((self.options.gradient_form == GradientForm::Radial) as u32))
|
||||||
.widget_instance();
|
.widget_instance();
|
||||||
|
|
||||||
// Display priority: the selected layer's stops, then any user-customized tool default, then the working colors
|
// Display priority: the selected layer's stops, then any user-customized tool default, then the working colors
|
||||||
@@ -296,7 +296,7 @@ impl LayoutHolder for GradientTool {
|
|||||||
};
|
};
|
||||||
let reverse_direction = IconButton::new(reverse_direction_icon, 24)
|
let reverse_direction = IconButton::new(reverse_direction_icon, 24)
|
||||||
.tooltip_label("Reverse Direction")
|
.tooltip_label("Reverse Direction")
|
||||||
.tooltip_description(reverse_direction_tooltip_description(self.options.gradient_type))
|
.tooltip_description(reverse_direction_tooltip_description(self.options.gradient_form))
|
||||||
.disabled(!self.data.has_selected_gradient)
|
.disabled(!self.data.has_selected_gradient)
|
||||||
.on_update(|_| {
|
.on_update(|_| {
|
||||||
GradientToolMessage::UpdateOptions {
|
GradientToolMessage::UpdateOptions {
|
||||||
@@ -311,7 +311,7 @@ impl LayoutHolder for GradientTool {
|
|||||||
Separator::new(SeparatorStyle::Related).widget_instance(),
|
Separator::new(SeparatorStyle::Related).widget_instance(),
|
||||||
reverse_stops,
|
reverse_stops,
|
||||||
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
|
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
|
||||||
gradient_type,
|
gradient_form,
|
||||||
Separator::new(SeparatorStyle::Related).widget_instance(),
|
Separator::new(SeparatorStyle::Related).widget_instance(),
|
||||||
reverse_direction,
|
reverse_direction,
|
||||||
]);
|
]);
|
||||||
@@ -362,7 +362,7 @@ fn resolve_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkI
|
|||||||
return Some((
|
return Some((
|
||||||
gradient.stops,
|
gradient.stops,
|
||||||
GradientAppearance {
|
GradientAppearance {
|
||||||
gradient_type: gradient.gradient_type,
|
gradient_form: gradient.gradient_form,
|
||||||
gradient_spread: gradient.gradient_spread,
|
gradient_spread: gradient.gradient_spread,
|
||||||
transform: gradient.transform,
|
transform: gradient.transform,
|
||||||
},
|
},
|
||||||
@@ -381,7 +381,7 @@ fn resolve_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkI
|
|||||||
#[derive(Clone, Copy, Debug, Default)]
|
#[derive(Clone, Copy, Debug, Default)]
|
||||||
struct GradientAppearance {
|
struct GradientAppearance {
|
||||||
transform: DAffine2,
|
transform: DAffine2,
|
||||||
gradient_type: GradientType,
|
gradient_form: GradientForm,
|
||||||
gradient_spread: GradientSpread,
|
gradient_spread: GradientSpread,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,11 +392,11 @@ fn read_gradient_chain_state(layer: LayerNodeIdentifier, network_interface: &Nod
|
|||||||
let walk_from = network_interface.upstream_output_connector(&target_input, &[]).and_then(|out| out.node_id()).unwrap_or(layer.to_node());
|
let walk_from = network_interface.upstream_output_connector(&target_input, &[]).and_then(|out| out.node_id()).unwrap_or(layer.to_node());
|
||||||
|
|
||||||
let transform_reference = DefinitionIdentifier::ProtoNode(graphene_std::transform_nodes::transform::IDENTIFIER);
|
let transform_reference = DefinitionIdentifier::ProtoNode(graphene_std::transform_nodes::transform::IDENTIFIER);
|
||||||
let gradient_type_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_type::IDENTIFIER);
|
let gradient_form_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_form::IDENTIFIER);
|
||||||
let gradient_spread_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_spread::IDENTIFIER);
|
let gradient_spread_reference = DefinitionIdentifier::ProtoNode(graphene_std::math_nodes::gradient_spread::IDENTIFIER);
|
||||||
|
|
||||||
let mut transforms_downstream_to_upstream: Vec<DAffine2> = Vec::new();
|
let mut transforms_downstream_to_upstream: Vec<DAffine2> = Vec::new();
|
||||||
let mut gradient_type: Option<GradientType> = None;
|
let mut gradient_form: Option<GradientForm> = None;
|
||||||
let mut gradient_spread: Option<GradientSpread> = None;
|
let mut gradient_spread: Option<GradientSpread> = None;
|
||||||
|
|
||||||
for node_id in network_interface
|
for node_id in network_interface
|
||||||
@@ -411,11 +411,11 @@ fn read_gradient_chain_state(layer: LayerNodeIdentifier, network_interface: &Nod
|
|||||||
|
|
||||||
if reference == transform_reference {
|
if reference == transform_reference {
|
||||||
transforms_downstream_to_upstream.push(read_transform_node_value(&document_node.inputs));
|
transforms_downstream_to_upstream.push(read_transform_node_value(&document_node.inputs));
|
||||||
} else if reference == gradient_type_reference
|
} else if reference == gradient_form_reference
|
||||||
&& gradient_type.is_none()
|
&& gradient_form.is_none()
|
||||||
&& let Some(TaggedValue::GradientType(value)) = document_node.inputs.get(1).and_then(|input| input.as_value())
|
&& let Some(TaggedValue::GradientForm(value)) = document_node.inputs.get(1).and_then(|input| input.as_value())
|
||||||
{
|
{
|
||||||
gradient_type = Some(*value);
|
gradient_form = Some(*value);
|
||||||
} else if reference == gradient_spread_reference
|
} else if reference == gradient_spread_reference
|
||||||
&& gradient_spread.is_none()
|
&& gradient_spread.is_none()
|
||||||
&& let Some(TaggedValue::GradientSpread(value)) = document_node.inputs.get(1).and_then(|input| input.as_value())
|
&& let Some(TaggedValue::GradientSpread(value)) = document_node.inputs.get(1).and_then(|input| input.as_value())
|
||||||
@@ -429,7 +429,7 @@ fn read_gradient_chain_state(layer: LayerNodeIdentifier, network_interface: &Nod
|
|||||||
|
|
||||||
GradientAppearance {
|
GradientAppearance {
|
||||||
transform: composed_transform,
|
transform: composed_transform,
|
||||||
gradient_type: gradient_type.unwrap_or_default(),
|
gradient_form: gradient_form.unwrap_or_default(),
|
||||||
gradient_spread: gradient_spread.unwrap_or_default(),
|
gradient_spread: gradient_spread.unwrap_or_default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,7 +552,7 @@ impl SelectedGradient {
|
|||||||
responses: &mut VecDeque<Message>,
|
responses: &mut VecDeque<Message>,
|
||||||
snap_rotate: bool,
|
snap_rotate: bool,
|
||||||
lock_angle: bool,
|
lock_angle: bool,
|
||||||
gradient_type: GradientType,
|
gradient_form: GradientForm,
|
||||||
drag_start: DVec2,
|
drag_start: DVec2,
|
||||||
snap_data: SnapData,
|
snap_data: SnapData,
|
||||||
snap_manager: &mut SnapManager,
|
snap_manager: &mut SnapManager,
|
||||||
@@ -565,7 +565,7 @@ impl SelectedGradient {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.appearance.gradient_type = gradient_type;
|
self.appearance.gradient_form = gradient_form;
|
||||||
|
|
||||||
let anchor_point = || {
|
let anchor_point = || {
|
||||||
let (start, end) = self.viewport_handle_positions();
|
let (start, end) = self.viewport_handle_positions();
|
||||||
@@ -765,7 +765,7 @@ impl SelectedGradient {
|
|||||||
responses.add(GraphOperationMessage::FillGradientSet {
|
responses.add(GraphOperationMessage::FillGradientSet {
|
||||||
layer,
|
layer,
|
||||||
gradient: self.gradient.clone(),
|
gradient: self.gradient.clone(),
|
||||||
gradient_type: self.appearance.gradient_type,
|
gradient_form: self.appearance.gradient_form,
|
||||||
gradient_spread: self.appearance.gradient_spread,
|
gradient_spread: self.appearance.gradient_spread,
|
||||||
transform: self.appearance.transform,
|
transform: self.appearance.transform,
|
||||||
});
|
});
|
||||||
@@ -797,9 +797,9 @@ fn dispatch_gradient_chain_writes(layer: LayerNodeIdentifier, gradient: &Gradien
|
|||||||
layer,
|
layer,
|
||||||
transform: appearance.transform,
|
transform: appearance.transform,
|
||||||
});
|
});
|
||||||
responses.add(GraphOperationMessage::GradientTypeSet {
|
responses.add(GraphOperationMessage::GradientFormSet {
|
||||||
layer,
|
layer,
|
||||||
gradient_type: appearance.gradient_type,
|
gradient_form: appearance.gradient_form,
|
||||||
});
|
});
|
||||||
responses.add(GraphOperationMessage::GradientSpreadSet {
|
responses.add(GraphOperationMessage::GradientSpreadSet {
|
||||||
layer,
|
layer,
|
||||||
@@ -808,9 +808,9 @@ fn dispatch_gradient_chain_writes(layer: LayerNodeIdentifier, gradient: &Gradien
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl GradientTool {
|
impl GradientTool {
|
||||||
/// Get the gradient type of the selected gradient (if it exists)
|
/// Get the Gradient Form of the selected gradient (if it exists)
|
||||||
pub fn selected_gradient(&self) -> Option<GradientType> {
|
pub fn selected_gradient(&self) -> Option<GradientForm> {
|
||||||
self.data.selected_gradient.as_ref().map(|selected| selected.appearance.gradient_type)
|
self.data.selected_gradient.as_ref().map(|selected| selected.appearance.gradient_form)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1482,7 +1482,7 @@ impl Fsm for GradientToolFsmState {
|
|||||||
]),
|
]),
|
||||||
GradientAppearance {
|
GradientAppearance {
|
||||||
transform: DAffine2::IDENTITY,
|
transform: DAffine2::IDENTITY,
|
||||||
gradient_type: tool_options.gradient_type,
|
gradient_form: tool_options.gradient_form,
|
||||||
gradient_spread: tool_options.gradient_spread,
|
gradient_spread: tool_options.gradient_spread,
|
||||||
},
|
},
|
||||||
GradientSource::Direct,
|
GradientSource::Direct,
|
||||||
@@ -1533,7 +1533,7 @@ impl Fsm for GradientToolFsmState {
|
|||||||
responses,
|
responses,
|
||||||
input.keyboard.get(constrain_axis as usize),
|
input.keyboard.get(constrain_axis as usize),
|
||||||
input.keyboard.get(lock_angle as usize),
|
input.keyboard.get(lock_angle as usize),
|
||||||
selected_gradient.appearance.gradient_type,
|
selected_gradient.appearance.gradient_form,
|
||||||
drag_start_viewport,
|
drag_start_viewport,
|
||||||
snap_data,
|
snap_data,
|
||||||
&mut tool_data.snap_manager,
|
&mut tool_data.snap_manager,
|
||||||
@@ -1835,7 +1835,7 @@ fn apply_gradient_update(
|
|||||||
responses.add(GraphOperationMessage::FillGradientSet {
|
responses.add(GraphOperationMessage::FillGradientSet {
|
||||||
layer,
|
layer,
|
||||||
gradient,
|
gradient,
|
||||||
gradient_type: appearance.gradient_type,
|
gradient_form: appearance.gradient_form,
|
||||||
gradient_spread: appearance.gradient_spread,
|
gradient_spread: appearance.gradient_spread,
|
||||||
transform: appearance.transform,
|
transform: appearance.transform,
|
||||||
});
|
});
|
||||||
@@ -1882,7 +1882,7 @@ fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessa
|
|||||||
responses.add(GraphOperationMessage::FillGradientSet {
|
responses.add(GraphOperationMessage::FillGradientSet {
|
||||||
layer,
|
layer,
|
||||||
gradient: new_gradient.clone(),
|
gradient: new_gradient.clone(),
|
||||||
gradient_type: appearance.gradient_type,
|
gradient_form: appearance.gradient_form,
|
||||||
gradient_spread,
|
gradient_spread,
|
||||||
transform: appearance.transform,
|
transform: appearance.transform,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -167,15 +167,7 @@ macro_rules! tagged_value {
|
|||||||
Self::DashPattern(lengths) => Box::new(DashPattern::from(lengths)),
|
Self::DashPattern(lengths) => Box::new(DashPattern::from(lengths)),
|
||||||
Self::BoxCorners(values) => Box::new(BoxCorners::from(values)),
|
Self::BoxCorners(values) => Box::new(BoxCorners::from(values)),
|
||||||
Self::Color(color) => Box::new(List::<Color>::new_from_element(color)),
|
Self::Color(color) => Box::new(List::<Color>::new_from_element(color)),
|
||||||
Self::GradientRamp(ramp) => {
|
Self::GradientRamp(ramp) => Box::new(List::new_from_item(core_types::list::Item::<Gradient>::from(ramp))),
|
||||||
// The ramp's gradient spread rides the served list as its attribute, as `Item<Gradient>::from` does on master.
|
|
||||||
let gradient_spread = ramp.gradient_spread;
|
|
||||||
let mut list = List::<Gradient>::new_from_element(Gradient::from(ramp));
|
|
||||||
if !gradient_spread.is_default() {
|
|
||||||
list.set_attribute(graphic_types::vector_types::ATTR_GRADIENT_SPREAD, 0, gradient_spread);
|
|
||||||
}
|
|
||||||
Box::new(list)
|
|
||||||
}
|
|
||||||
Self::BrushStrokes(strokes) => {
|
Self::BrushStrokes(strokes) => {
|
||||||
let list: List<BrushStroke> = strokes.into_iter().map(core_types::list::Item::new_from_element).collect();
|
let list: List<BrushStroke> = strokes.into_iter().map(core_types::list::Item::new_from_element).collect();
|
||||||
Box::new(list)
|
Box::new(list)
|
||||||
@@ -221,15 +213,7 @@ macro_rules! tagged_value {
|
|||||||
Self::DashPattern(lengths) => Arc::new(DashPattern::from(lengths)),
|
Self::DashPattern(lengths) => Arc::new(DashPattern::from(lengths)),
|
||||||
Self::BoxCorners(values) => Arc::new(BoxCorners::from(values)),
|
Self::BoxCorners(values) => Arc::new(BoxCorners::from(values)),
|
||||||
Self::Color(color) => Arc::new(List::<Color>::new_from_element(color)),
|
Self::Color(color) => Arc::new(List::<Color>::new_from_element(color)),
|
||||||
Self::GradientRamp(ramp) => {
|
Self::GradientRamp(ramp) => Arc::new(List::new_from_item(core_types::list::Item::<Gradient>::from(ramp))),
|
||||||
// The ramp's gradient spread rides the served list as its attribute, as `Item<Gradient>::from` does on master.
|
|
||||||
let gradient_spread = ramp.gradient_spread;
|
|
||||||
let mut list = List::<Gradient>::new_from_element(Gradient::from(ramp));
|
|
||||||
if !gradient_spread.is_default() {
|
|
||||||
list.set_attribute(graphic_types::vector_types::ATTR_GRADIENT_SPREAD, 0, gradient_spread);
|
|
||||||
}
|
|
||||||
Arc::new(list)
|
|
||||||
}
|
|
||||||
Self::BrushStrokes(strokes) => {
|
Self::BrushStrokes(strokes) => {
|
||||||
let list: List<BrushStroke> = strokes.into_iter().map(core_types::list::Item::new_from_element).collect();
|
let list: List<BrushStroke> = strokes.into_iter().map(core_types::list::Item::new_from_element).collect();
|
||||||
Arc::new(list)
|
Arc::new(list)
|
||||||
@@ -626,7 +610,8 @@ tagged_value! {
|
|||||||
StrokeJoin(vector::style::StrokeJoin),
|
StrokeJoin(vector::style::StrokeJoin),
|
||||||
StrokeAlign(vector::style::StrokeAlign),
|
StrokeAlign(vector::style::StrokeAlign),
|
||||||
PaintOrder(vector::style::PaintOrder),
|
PaintOrder(vector::style::PaintOrder),
|
||||||
GradientType(vector::style::GradientType),
|
#[serde(alias = "GradientType")] // TODO: Eventually remove this document upgrade code
|
||||||
|
GradientForm(vector::style::GradientForm),
|
||||||
#[serde(alias = "GradientSpreadMethod")] // TODO: Eventually remove this document upgrade code
|
#[serde(alias = "GradientSpreadMethod")] // TODO: Eventually remove this document upgrade code
|
||||||
GradientSpread(vector::style::GradientSpread),
|
GradientSpread(vector::style::GradientSpread),
|
||||||
ReferencePoint(vector::ReferencePoint),
|
ReferencePoint(vector::ReferencePoint),
|
||||||
|
|||||||
@@ -1164,7 +1164,7 @@ impl<T: CacheHash> CacheHash for List<T> {
|
|||||||
self.element.cache_hash(state);
|
self.element.cache_hash(state);
|
||||||
|
|
||||||
// Hash every attribute attribute (key + values) rather than just the well-known ones, so changes to user-defined keys
|
// Hash every attribute attribute (key + values) rather than just the well-known ones, so changes to user-defined keys
|
||||||
// (e.g., gradient_type, gradient_spread) invalidate downstream graph caches as expected
|
// (e.g., gradient_form, gradient_spread) invalidate downstream graph caches as expected
|
||||||
for (key, attribute) in &self.attributes.attributes {
|
for (key, attribute) in &self.attributes.attributes {
|
||||||
std::hash::Hash::hash(key.as_str(), state);
|
std::hash::Hash::hash(key.as_str(), state);
|
||||||
attribute.cache_hash_dyn(state);
|
attribute.cache_hash_dyn(state);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ pub mod migrations {
|
|||||||
pub struct LegacyGradient {
|
pub struct LegacyGradient {
|
||||||
#[serde(deserialize_with = "crate::migrations::migrate_to_gradient_ramp")]
|
#[serde(deserialize_with = "crate::migrations::migrate_to_gradient_ramp")]
|
||||||
pub stops: GradientRamp,
|
pub stops: GradientRamp,
|
||||||
pub gradient_type: vector::style::GradientType,
|
pub gradient_type: vector::style::GradientForm,
|
||||||
pub start: DVec2,
|
pub start: DVec2,
|
||||||
pub end: DVec2,
|
pub end: DVec2,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -54,7 +54,7 @@ pub mod migrations {
|
|||||||
|
|
||||||
// The legacy radial drew as a circle in the layer's own space; bake the adjustment that, composed with the
|
// The legacy radial drew as a circle in the layer's own space; bake the adjustment that, composed with the
|
||||||
// endpoint frame, makes the new pipeline reproduce that circle through the (possibly non-uniform) layer transform.
|
// endpoint frame, makes the new pipeline reproduce that circle through the (possibly non-uniform) layer transform.
|
||||||
let radial_invertible = self.gradient_type == vector::style::GradientType::Radial
|
let radial_invertible = self.gradient_type == vector::style::GradientForm::Radial
|
||||||
&& layer_transform.is_finite()
|
&& layer_transform.is_finite()
|
||||||
&& layer_transform.matrix2.determinant().recip().is_finite()
|
&& layer_transform.matrix2.determinant().recip().is_finite()
|
||||||
&& direction.length_squared() > 1e-20;
|
&& direction.length_squared() > 1e-20;
|
||||||
|
|||||||
@@ -7,8 +7,8 @@ use core_types::list::List;
|
|||||||
use core_types::uuid::generate_uuid;
|
use core_types::uuid::generate_uuid;
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphic_types::Graphic;
|
use graphic_types::Graphic;
|
||||||
use graphic_types::vector_types::gradient::GradientType;
|
use graphic_types::vector_types::gradient::GradientForm;
|
||||||
use graphic_types::vector_types::markers::{GradientSpread as GradientSpreadAttr, GradientType as GradientTypeAttr};
|
use graphic_types::vector_types::markers::{GradientForm as GradientFormAttr, GradientSpread as GradientSpreadAttr};
|
||||||
use graphic_types::vector_types::vector::style::{PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
use graphic_types::vector_types::vector::style::{PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
use vector_types::Gradient;
|
use vector_types::Gradient;
|
||||||
@@ -108,7 +108,7 @@ pub fn render_gradient_paint<S: core_types::lane::LaneSource<Element = Gradient>
|
|||||||
|
|
||||||
{
|
{
|
||||||
let Some(stops) = source.element(0) else { return 0 };
|
let Some(stops) = source.element(0) else { return 0 };
|
||||||
let gradient_type: GradientType = source.attr::<GradientTypeAttr>(0);
|
let gradient_form: GradientForm = source.attr::<GradientFormAttr>(0);
|
||||||
let local_gradient_transform: DAffine2 = source.attr::<Transform>(0);
|
let local_gradient_transform: DAffine2 = source.attr::<Transform>(0);
|
||||||
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(0);
|
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(0);
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ pub fn render_gradient_paint<S: core_types::lane::LaneSource<Element = Gradient>
|
|||||||
|
|
||||||
let document_transform = item_transform * local_gradient_transform;
|
let document_transform = item_transform * local_gradient_transform;
|
||||||
|
|
||||||
let placement = gradient_placement(document_transform, gradient_type);
|
let placement = gradient_placement(document_transform, gradient_form);
|
||||||
let gradient_transform = format_transform_matrix(element_transform_inverse * placement);
|
let gradient_transform = format_transform_matrix(element_transform_inverse * placement);
|
||||||
let gradient_transform = if gradient_transform.is_empty() {
|
let gradient_transform = if gradient_transform.is_empty() {
|
||||||
String::new()
|
String::new()
|
||||||
@@ -157,15 +157,15 @@ pub fn render_gradient_paint<S: core_types::lane::LaneSource<Element = Gradient>
|
|||||||
|
|
||||||
let gradient_id = generate_uuid();
|
let gradient_id = generate_uuid();
|
||||||
|
|
||||||
match gradient_type {
|
match gradient_form {
|
||||||
GradientType::Linear => {
|
GradientForm::Linear => {
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
svg_defs,
|
svg_defs,
|
||||||
r#"<linearGradient id="{}" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="1" y2="0"{gradient_spread}{gradient_transform}>{}</linearGradient>"#,
|
r#"<linearGradient id="{}" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="1" y2="0"{gradient_spread}{gradient_transform}>{}</linearGradient>"#,
|
||||||
gradient_id, stop
|
gradient_id, stop
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
GradientType::Radial => {
|
GradientForm::Radial => {
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
svg_defs,
|
svg_defs,
|
||||||
r#"<radialGradient id="{}" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1"{gradient_spread}{gradient_transform}>{}</radialGradient>"#,
|
r#"<radialGradient id="{}" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1"{gradient_spread}{gradient_transform}>{}</radialGradient>"#,
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ use graphene_resource::Resource;
|
|||||||
use graphic_types::graphic::{PaintColumns, PaintOverlay, PaintReach, has_paint, is_paint_present, paint_graphics, set_paint_attribute, vector_can_reduce_to_clip_path};
|
use graphic_types::graphic::{PaintColumns, PaintOverlay, PaintReach, has_paint, is_paint_present, paint_graphics, set_paint_attribute, vector_can_reduce_to_clip_path};
|
||||||
use graphic_types::markers::{EditorMergedLayers, Fill, Stroke};
|
use graphic_types::markers::{EditorMergedLayers, Fill, Stroke};
|
||||||
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster, Texture};
|
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster, Texture};
|
||||||
use graphic_types::vector_types::gradient::{Gradient, GradientType};
|
use graphic_types::vector_types::gradient::{Gradient, GradientForm};
|
||||||
use graphic_types::vector_types::markers::{GradientSpread as GradientSpreadAttr, GradientType as GradientTypeAttr};
|
use graphic_types::vector_types::markers::{GradientForm as GradientFormAttr, GradientSpread as GradientSpreadAttr};
|
||||||
use graphic_types::vector_types::subpath::Subpath;
|
use graphic_types::vector_types::subpath::Subpath;
|
||||||
use graphic_types::vector_types::vector::click_target::{ClickTarget, FreePoint};
|
use graphic_types::vector_types::vector::click_target::{ClickTarget, FreePoint};
|
||||||
use graphic_types::vector_types::vector::style::{PaintOrder, RenderMode, StrokeAlign, StrokeCap, StrokeJoin};
|
use graphic_types::vector_types::vector::style::{PaintOrder, RenderMode, StrokeAlign, StrokeCap, StrokeJoin};
|
||||||
@@ -385,10 +385,10 @@ pub(crate) fn transform_is_invertible(transform: DAffine2) -> bool {
|
|||||||
/// non-uniform transform makes an ellipse), while linear is reduced to the equivalent non-sheared gradient line (the
|
/// non-uniform transform makes an ellipse), while linear is reduced to the equivalent non-sheared gradient line (the
|
||||||
/// axis projected onto the band normal) so the iso-color bands keep following a sheared transform, which Vello can
|
/// axis projected onto the band normal) so the iso-color bands keep following a sheared transform, which Vello can
|
||||||
/// represent since it stores only two endpoints.
|
/// represent since it stores only two endpoints.
|
||||||
pub(crate) fn gradient_placement(transform: DAffine2, gradient_type: GradientType) -> DAffine2 {
|
pub(crate) fn gradient_placement(transform: DAffine2, gradient_form: GradientForm) -> DAffine2 {
|
||||||
match gradient_type {
|
match gradient_form {
|
||||||
GradientType::Radial => transform,
|
GradientForm::Radial => transform,
|
||||||
GradientType::Linear => {
|
GradientForm::Linear => {
|
||||||
let axis = transform.matrix2.x_axis;
|
let axis = transform.matrix2.x_axis;
|
||||||
let band_normal = transform.matrix2.y_axis.perp();
|
let band_normal = transform.matrix2.y_axis.perp();
|
||||||
let line = if band_normal.length_squared() > 0. { axis.project_onto(band_normal) } else { axis };
|
let line = if band_normal.length_squared() > 0. { axis.project_onto(band_normal) } else { axis };
|
||||||
@@ -428,23 +428,23 @@ fn peniko_color_stops(gradient: &Gradient) -> peniko::ColorStops {
|
|||||||
fn create_peniko_gradient_brush<S: LaneSource<Element = Gradient>>(gradient_list: &S, multiplied_transform: &DAffine2) -> Option<(peniko::Brush, DAffine2)> {
|
fn create_peniko_gradient_brush<S: LaneSource<Element = Gradient>>(gradient_list: &S, multiplied_transform: &DAffine2) -> Option<(peniko::Brush, DAffine2)> {
|
||||||
let stops = gradient_list.element(0)?;
|
let stops = gradient_list.element(0)?;
|
||||||
|
|
||||||
let gradient_type: GradientType = gradient_list.attr::<GradientTypeAttr>(0);
|
let gradient_form: GradientForm = gradient_list.attr::<GradientFormAttr>(0);
|
||||||
let gradient_transform: DAffine2 = gradient_list.attr::<Transform>(0);
|
let gradient_transform: DAffine2 = gradient_list.attr::<Transform>(0);
|
||||||
let gradient_spread: GradientSpread = gradient_list.attr::<GradientSpreadAttr>(0);
|
let gradient_spread: GradientSpread = gradient_list.attr::<GradientSpreadAttr>(0);
|
||||||
|
|
||||||
let peniko_stops = peniko_color_stops(stops);
|
let peniko_stops = peniko_color_stops(stops);
|
||||||
|
|
||||||
// The unit gradient is placed by the desheared frame so a non-uniform transform produces the intended ellipse
|
// The unit gradient is placed by the desheared frame so a non-uniform transform produces the intended ellipse
|
||||||
let (start, end, gradient_to_device) = (DVec2::ZERO, DVec2::X, gradient_placement(multiplied_transform * gradient_transform, gradient_type));
|
let (start, end, gradient_to_device) = (DVec2::ZERO, DVec2::X, gradient_placement(multiplied_transform * gradient_transform, gradient_form));
|
||||||
|
|
||||||
let brush = peniko::Brush::Gradient(peniko::Gradient {
|
let brush = peniko::Brush::Gradient(peniko::Gradient {
|
||||||
kind: match gradient_type {
|
kind: match gradient_form {
|
||||||
GradientType::Linear => peniko::LinearGradientPosition {
|
GradientForm::Linear => peniko::LinearGradientPosition {
|
||||||
start: to_point(start),
|
start: to_point(start),
|
||||||
end: to_point(end),
|
end: to_point(end),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
GradientType::Radial => peniko::RadialGradientPosition {
|
GradientForm::Radial => peniko::RadialGradientPosition {
|
||||||
start_center: to_point(start),
|
start_center: to_point(start),
|
||||||
start_radius: 0.,
|
start_radius: 0.,
|
||||||
end_center: to_point(start),
|
end_center: to_point(start),
|
||||||
@@ -2328,7 +2328,7 @@ fn render_gradient_svg<S: LaneSource<Element = Gradient>>(source: &S, render: &m
|
|||||||
let opacity_attr: f64 = source.attr::<Opacity>(index);
|
let opacity_attr: f64 = source.attr::<Opacity>(index);
|
||||||
let opacity_fill_attr: f64 = source.attr::<OpacityFill>(index);
|
let opacity_fill_attr: f64 = source.attr::<OpacityFill>(index);
|
||||||
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(index);
|
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(index);
|
||||||
let gradient_type: GradientType = source.attr::<GradientTypeAttr>(index);
|
let gradient_form: GradientForm = source.attr::<GradientFormAttr>(index);
|
||||||
let tag = if thumbnail_rect.is_some() { "rect" } else { "polyline" };
|
let tag = if thumbnail_rect.is_some() { "rect" } else { "polyline" };
|
||||||
render.leaf_tag(tag, |attributes| {
|
render.leaf_tag(tag, |attributes| {
|
||||||
if let Some((min, size)) = thumbnail_rect {
|
if let Some((min, size)) = thumbnail_rect {
|
||||||
@@ -2373,14 +2373,14 @@ fn render_gradient_svg<S: LaneSource<Element = Gradient>>(source: &S, render: &m
|
|||||||
};
|
};
|
||||||
|
|
||||||
// The unit gradient line is the +X unit vector in local space, before the item's transform is applied
|
// The unit gradient line is the +X unit vector in local space, before the item's transform is applied
|
||||||
match gradient_type {
|
match gradient_form {
|
||||||
GradientType::Linear => {
|
GradientForm::Linear => {
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
&mut attributes.0.svg_defs,
|
&mut attributes.0.svg_defs,
|
||||||
r#"<linearGradient id="{gradient_id}" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="1" y2="0"{spread_method_attribute}{gradient_transform_attribute}>{stop_string}</linearGradient>"#
|
r#"<linearGradient id="{gradient_id}" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="1" y2="0"{spread_method_attribute}{gradient_transform_attribute}>{stop_string}</linearGradient>"#
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
GradientType::Radial => {
|
GradientForm::Radial => {
|
||||||
let _ = write!(
|
let _ = write!(
|
||||||
&mut attributes.0.svg_defs,
|
&mut attributes.0.svg_defs,
|
||||||
r#"<radialGradient id="{gradient_id}" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1"{spread_method_attribute}{gradient_transform_attribute}>{stop_string}</radialGradient>"#
|
r#"<radialGradient id="{gradient_id}" gradientUnits="userSpaceOnUse" cx="0" cy="0" r="1"{spread_method_attribute}{gradient_transform_attribute}>{stop_string}</radialGradient>"#
|
||||||
@@ -2412,7 +2412,7 @@ fn render_gradient_vello<S: LaneSource<Element = Gradient>>(source: &S, scene: &
|
|||||||
for index in 0..source.lane_count() {
|
for index in 0..source.lane_count() {
|
||||||
let Some(gradient) = source.element(index) else { continue };
|
let Some(gradient) = source.element(index) else { continue };
|
||||||
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(index);
|
let gradient_spread: GradientSpread = source.attr::<GradientSpreadAttr>(index);
|
||||||
let gradient_type: GradientType = source.attr::<GradientTypeAttr>(index);
|
let gradient_form: GradientForm = source.attr::<GradientFormAttr>(index);
|
||||||
let transform: DAffine2 = source.attr::<Transform>(index);
|
let transform: DAffine2 = source.attr::<Transform>(index);
|
||||||
let blend_mode_attr: BlendMode = source.attr::<BlendModeAttr>(index);
|
let blend_mode_attr: BlendMode = source.attr::<BlendModeAttr>(index);
|
||||||
let opacity_attr: f64 = source.attr::<Opacity>(index);
|
let opacity_attr: f64 = source.attr::<Opacity>(index);
|
||||||
@@ -2432,13 +2432,13 @@ fn render_gradient_vello<S: LaneSource<Element = Gradient>>(source: &S, scene: &
|
|||||||
|
|
||||||
// The unit gradient line is the +X unit vector in local space, before the item's transform is applied.
|
// The unit gradient line is the +X unit vector in local space, before the item's transform is applied.
|
||||||
// For radial, the unit-radius circle at the origin scales out to the line's length once the brush transform applies.
|
// For radial, the unit-radius circle at the origin scales out to the line's length once the brush transform applies.
|
||||||
let kind = match gradient_type {
|
let kind = match gradient_form {
|
||||||
GradientType::Linear => peniko::LinearGradientPosition {
|
GradientForm::Linear => peniko::LinearGradientPosition {
|
||||||
start: to_point(DVec2::ZERO),
|
start: to_point(DVec2::ZERO),
|
||||||
end: to_point(DVec2::X),
|
end: to_point(DVec2::X),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
GradientType::Radial => peniko::RadialGradientPosition {
|
GradientForm::Radial => peniko::RadialGradientPosition {
|
||||||
start_center: to_point(DVec2::ZERO),
|
start_center: to_point(DVec2::ZERO),
|
||||||
start_radius: 0.,
|
start_radius: 0.,
|
||||||
end_center: to_point(DVec2::ZERO),
|
end_center: to_point(DVec2::ZERO),
|
||||||
@@ -2454,7 +2454,7 @@ fn render_gradient_vello<S: LaneSource<Element = Gradient>>(source: &S, scene: &
|
|||||||
interpolation_alpha_space: peniko::InterpolationAlphaSpace::Premultiplied,
|
interpolation_alpha_space: peniko::InterpolationAlphaSpace::Premultiplied,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let brush_transform = kurbo::Affine::new(gradient_placement(gradient_transform, gradient_type).to_cols_array());
|
let brush_transform = kurbo::Affine::new(gradient_placement(gradient_transform, gradient_form).to_cols_array());
|
||||||
let rect = kurbo::Rect::from_origin_size(kurbo::Point::ZERO, kurbo::Size::new(1., 1.));
|
let rect = kurbo::Rect::from_origin_size(kurbo::Point::ZERO, kurbo::Size::new(1., 1.));
|
||||||
|
|
||||||
let mut layer = false;
|
let mut layer = false;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use glam::{DAffine2, DVec2};
|
|||||||
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, graphene_hash::CacheHash, DynAny, node_macro::ChoiceType)]
|
#[derive(Default, PartialEq, Eq, Clone, Copy, Debug, Hash, graphene_hash::CacheHash, DynAny, node_macro::ChoiceType)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
#[widget(Radio)]
|
#[widget(Radio)]
|
||||||
pub enum GradientType {
|
pub enum GradientForm {
|
||||||
#[default]
|
#[default]
|
||||||
Linear,
|
Linear,
|
||||||
Radial,
|
Radial,
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ pub mod vector;
|
|||||||
|
|
||||||
// Re-export commonly used types at the crate root
|
// Re-export commonly used types at the crate root
|
||||||
pub use core_types as gcore;
|
pub use core_types as gcore;
|
||||||
pub use gradient::{Gradient, GradientRamp, GradientSpread, GradientStop, GradientType};
|
pub use gradient::{Gradient, GradientForm, GradientRamp, GradientSpread, GradientStop};
|
||||||
pub use markers::{ATTR_EDITOR_CLICK_TARGET, ATTR_GRADIENT_SPREAD, ATTR_GRADIENT_TYPE};
|
pub use markers::{ATTR_EDITOR_CLICK_TARGET, ATTR_GRADIENT_FORM, ATTR_GRADIENT_SPREAD};
|
||||||
pub use math::{QuadExt, RectExt};
|
pub use math::{QuadExt, RectExt};
|
||||||
pub use subpath::Subpath;
|
pub use subpath::Subpath;
|
||||||
pub use vector::Vector;
|
pub use vector::Vector;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ core_types::attribute! {
|
|||||||
/// Gradient's spread behavior past its endpoints (`Pad`, `Reflect`, or `Repeat`).
|
/// Gradient's spread behavior past its endpoints (`Pad`, `Reflect`, or `Repeat`).
|
||||||
pub GradientSpread("gradient_spread"): crate::gradient::GradientSpread;
|
pub GradientSpread("gradient_spread"): crate::gradient::GradientSpread;
|
||||||
/// Gradient's shape (`Linear` or `Radial`).
|
/// Gradient's shape (`Linear` or `Radial`).
|
||||||
pub GradientType("gradient_type"): crate::gradient::GradientType;
|
pub GradientForm("gradient_form"): crate::gradient::GradientForm;
|
||||||
/// Optional `Vector` that overrides the item's own geometry for click-target generation.
|
/// Optional `Vector` that overrides the item's own geometry for click-target generation.
|
||||||
/// Used by the 'Text' node for per-glyph bounding-box rectangles so glyphs are selectable
|
/// Used by the 'Text' node for per-glyph bounding-box rectangles so glyphs are selectable
|
||||||
/// by clicking anywhere within their bounds, not just the filled letterform. An absent
|
/// by clicking anywhere within their bounds, not just the filled letterform. An absent
|
||||||
@@ -19,11 +19,11 @@ core_types::attribute! {
|
|||||||
// named write or read reaches this crate's enums like any other plain value.
|
// named write or read reaches this crate's enums like any other plain value.
|
||||||
core_types::named_value! {
|
core_types::named_value! {
|
||||||
for crate::gradient::GradientSpread;
|
for crate::gradient::GradientSpread;
|
||||||
for crate::gradient::GradientType;
|
for crate::gradient::GradientForm;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ATTR_GRADIENT_SPREAD: &str = GradientSpread::NAME;
|
pub const ATTR_GRADIENT_SPREAD: &str = GradientSpread::NAME;
|
||||||
pub const ATTR_GRADIENT_TYPE: &str = GradientType::NAME;
|
pub const ATTR_GRADIENT_FORM: &str = GradientForm::NAME;
|
||||||
pub const ATTR_EDITOR_CLICK_TARGET: &str = EditorClickTarget::NAME;
|
pub const ATTR_EDITOR_CLICK_TARGET: &str = EditorClickTarget::NAME;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -34,7 +34,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn the_census_carries_this_crates_names() {
|
fn the_census_carries_this_crates_names() {
|
||||||
assert_eq!(info("gradient_type").unwrap().value_type, TypeId::of::<crate::gradient::GradientType>());
|
assert_eq!(info("gradient_form").unwrap().value_type, TypeId::of::<crate::gradient::GradientForm>());
|
||||||
assert_eq!(info("gradient_spread").unwrap().value_type, TypeId::of::<crate::gradient::GradientSpread>());
|
assert_eq!(info("gradient_spread").unwrap().value_type, TypeId::of::<crate::gradient::GradientSpread>());
|
||||||
assert_eq!(info("editor:click_target").unwrap().value_type, TypeId::of::<Option<&'static crate::Vector>>());
|
assert_eq!(info("editor:click_target").unwrap().value_type, TypeId::of::<Option<&'static crate::Vector>>());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use graphic_types::graphic::{Graphic, GraphicLevel, RowStep, TryFromGraphic, wal
|
|||||||
use graphic_types::markers::{EditorMergedLayers, Fill, Stroke as StrokeAttr};
|
use graphic_types::markers::{EditorMergedLayers, Fill, Stroke as StrokeAttr};
|
||||||
use graphic_types::{ATTR_FILL, ATTR_STROKE, Vector};
|
use graphic_types::{ATTR_FILL, ATTR_STROKE, Vector};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
use vector_types::gradient::{GradientSpread, GradientType as GradientTypeValue};
|
use vector_types::gradient::{GradientForm as GradientFormValue, GradientSpread};
|
||||||
use vector_types::{Gradient, ReferencePoint};
|
use vector_types::{Gradient, ReferencePoint};
|
||||||
|
|
||||||
fn arena_exhausted() -> Interrupt {
|
fn arena_exhausted() -> Interrupt {
|
||||||
@@ -253,8 +253,8 @@ attribute_reads! {
|
|||||||
read_color_attribute: Color => Color;
|
read_color_attribute: Color => Color;
|
||||||
/// Reads a named `BlendMode` attribute, such as `blend_mode`.
|
/// Reads a named `BlendMode` attribute, such as `blend_mode`.
|
||||||
read_blend_mode_attribute: core_types::blending::BlendMode => core_types::blending::BlendMode;
|
read_blend_mode_attribute: core_types::blending::BlendMode => core_types::blending::BlendMode;
|
||||||
/// Reads a named gradient-shape attribute, such as `gradient_type`.
|
/// Reads a named gradient-shape attribute, such as `gradient_form`.
|
||||||
read_gradient_type_attribute: GradientTypeValue => GradientTypeValue;
|
read_gradient_form_attribute: GradientFormValue => GradientFormValue;
|
||||||
/// Reads a named gradient-spread attribute, such as `gradient_spread`.
|
/// Reads a named gradient-spread attribute, such as `gradient_spread`.
|
||||||
read_gradient_spread_attribute: GradientSpread => GradientSpread;
|
read_gradient_spread_attribute: GradientSpread => GradientSpread;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use math_parser::value::{Number, Value};
|
|||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use std::ops::{Add, Mul, Rem, Sub};
|
use std::ops::{Add, Mul, Rem, Sub};
|
||||||
use vector_types::Gradient;
|
use vector_types::Gradient;
|
||||||
use vector_types::markers::{GradientSpread as GradientSpreadAttr, GradientType as GradientTypeAttr};
|
use vector_types::markers::{GradientForm as GradientFormAttr, GradientSpread as GradientSpreadAttr};
|
||||||
|
|
||||||
/// The struct that stores the context for the maths parser.
|
/// The struct that stores the context for the maths parser.
|
||||||
/// This is currently just limited to supplying `a` and `b` until we add better node graph support and UI for variadic inputs.
|
/// This is currently just limited to supplying `a` and `b` until we add better node graph support and UI for variadic inputs.
|
||||||
@@ -1202,10 +1202,10 @@ fn gradient_value(_: impl Ctx, _primary: (), #[default(Color::BLACK, Color::WHIT
|
|||||||
gradient
|
gradient
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the type (linear or radial) of each gradient in the input list.
|
/// Sets the form (linear or radial) of each gradient in the input list.
|
||||||
#[node_macro::node(category("Gradient"))]
|
#[node_macro::node(category("Gradient"))]
|
||||||
fn gradient_type(_: impl Ctx, gradient: Gradient, gradient_type: vector_types::GradientType) -> (Gradient, Attr<GradientTypeAttr>) {
|
fn gradient_form(_: impl Ctx, gradient: Gradient, gradient_form: vector_types::GradientForm) -> (Gradient, Attr<GradientFormAttr>) {
|
||||||
(gradient, Attr(gradient_type))
|
(gradient, Attr(gradient_form))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets how each gradient in the input list extends past its endpoints: Pad, Reflect, or Repeat.
|
/// Sets how each gradient in the input list extends past its endpoints: Pad, Reflect, or Repeat.
|
||||||
|
|||||||
@@ -8,11 +8,11 @@ use graphic_types::graphic::{GraphicLevel, PaintColumns, PaintReach, bake_paint_
|
|||||||
use graphic_types::markers::{EditorMergedLayers, Fill, Stroke};
|
use graphic_types::markers::{EditorMergedLayers, Fill, Stroke};
|
||||||
use graphic_types::raster_types::{CPU, GPU, Raster};
|
use graphic_types::raster_types::{CPU, GPU, Raster};
|
||||||
use graphic_types::vector_types::Gradient;
|
use graphic_types::vector_types::Gradient;
|
||||||
use graphic_types::vector_types::gradient::{GradientSpread, GradientType};
|
use graphic_types::vector_types::gradient::{GradientForm, GradientSpread};
|
||||||
use graphic_types::vector_types::subpath::{ManipulatorGroup, Subpath};
|
use graphic_types::vector_types::subpath::{ManipulatorGroup, Subpath};
|
||||||
use graphic_types::vector_types::vector::PointId;
|
use graphic_types::vector_types::vector::PointId;
|
||||||
use graphic_types::vector_types::vector::algorithms::merge_by_distance::MergeByDistanceExt;
|
use graphic_types::vector_types::vector::algorithms::merge_by_distance::MergeByDistanceExt;
|
||||||
use graphic_types::vector_types::{ATTR_GRADIENT_SPREAD, ATTR_GRADIENT_TYPE};
|
use graphic_types::vector_types::{ATTR_GRADIENT_FORM, ATTR_GRADIENT_SPREAD};
|
||||||
use graphic_types::{ATTR_FILL, ATTR_STROKE, Graphic, IntoGraphicList, Vector};
|
use graphic_types::{ATTR_FILL, ATTR_STROKE, Graphic, IntoGraphicList, Vector};
|
||||||
use linesweeper::topology::Topology;
|
use linesweeper::topology::Topology;
|
||||||
use linesweeper::{BinaryOp, FillRule, binary_op};
|
use linesweeper::{BinaryOp, FillRule, binary_op};
|
||||||
@@ -288,8 +288,8 @@ fn gradient_paint_row(stops: Gradient, mut attributes: core_types::list::ItemAtt
|
|||||||
if let Some(transform) = attributes.remove::<DAffine2>(ATTR_TRANSFORM) {
|
if let Some(transform) = attributes.remove::<DAffine2>(ATTR_TRANSFORM) {
|
||||||
gradient_paint.set_attribute(ATTR_TRANSFORM, 0, transform);
|
gradient_paint.set_attribute(ATTR_TRANSFORM, 0, transform);
|
||||||
}
|
}
|
||||||
if let Some(gradient_type) = attributes.remove::<GradientType>(ATTR_GRADIENT_TYPE) {
|
if let Some(gradient_form) = attributes.remove::<GradientForm>(ATTR_GRADIENT_FORM) {
|
||||||
gradient_paint.set_attribute(ATTR_GRADIENT_TYPE, 0, gradient_type);
|
gradient_paint.set_attribute(ATTR_GRADIENT_FORM, 0, gradient_form);
|
||||||
}
|
}
|
||||||
if let Some(spread_method) = attributes.remove::<GradientSpread>(ATTR_GRADIENT_SPREAD) {
|
if let Some(spread_method) = attributes.remove::<GradientSpread>(ATTR_GRADIENT_SPREAD) {
|
||||||
gradient_paint.set_attribute(ATTR_GRADIENT_SPREAD, 0, spread_method);
|
gradient_paint.set_attribute(ATTR_GRADIENT_SPREAD, 0, spread_method);
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ use kurbo::{Affine, BezPath, DEFAULT_ACCURACY, Line, ParamCurve, ParamCurveArcle
|
|||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use vector_types::ATTR_GRADIENT_TYPE;
|
use vector_types::ATTR_GRADIENT_FORM;
|
||||||
use vector_types::GradientType;
|
use vector_types::GradientForm;
|
||||||
use vector_types::gradient::{build_transform_with_y_preservation, initial_gradient_transform_for_bounding_box};
|
use vector_types::gradient::{build_transform_with_y_preservation, initial_gradient_transform_for_bounding_box};
|
||||||
use vector_types::subpath::{BezierHandles, ManipulatorGroup};
|
use vector_types::subpath::{BezierHandles, ManipulatorGroup};
|
||||||
use vector_types::vector::algorithms::bezpath_algorithms::{self, TValue, eval_pathseg_euclidean, evaluate_bezpath, split_bezpath, tangent_on_bezpath};
|
use vector_types::vector::algorithms::bezpath_algorithms::{self, TValue, eval_pathseg_euclidean, evaluate_bezpath, split_bezpath, tangent_on_bezpath};
|
||||||
@@ -276,15 +276,15 @@ fn park_paint<'e>(arena: &'e core_types::arena::Arena, paint: List<Graphic<'stat
|
|||||||
|
|
||||||
/// The gradient defaulting the legacy fill performed, applied to the nested
|
/// The gradient defaulting the legacy fill performed, applied to the nested
|
||||||
/// stops list the paint table wraps.
|
/// stops list the paint table wraps.
|
||||||
fn default_gradient_paint(paint: &mut List<Graphic>, bounds: Option<[DVec2; 2]>, gradient_type: GradientType, transform: Option<DAffine2>) {
|
fn default_gradient_paint(paint: &mut List<Graphic>, bounds: Option<[DVec2; 2]>, gradient_type: GradientForm, transform: Option<DAffine2>) {
|
||||||
let has_type = paint.iter_attribute_values::<GradientType>(ATTR_GRADIENT_TYPE).is_some();
|
let has_type = paint.iter_attribute_values::<GradientForm>(ATTR_GRADIENT_FORM).is_some();
|
||||||
let has_transform = paint.iter_attribute_values::<DAffine2>(ATTR_TRANSFORM).is_some();
|
let has_transform = paint.iter_attribute_values::<DAffine2>(ATTR_TRANSFORM).is_some();
|
||||||
for index in 0..paint.len() {
|
for index in 0..paint.len() {
|
||||||
if !matches!(paint.element(index), Some(Graphic::Gradient(_))) {
|
if !matches!(paint.element(index), Some(Graphic::Gradient(_))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if !has_type {
|
if !has_type {
|
||||||
paint.set_attribute(ATTR_GRADIENT_TYPE, index, gradient_type);
|
paint.set_attribute(ATTR_GRADIENT_FORM, index, gradient_type);
|
||||||
}
|
}
|
||||||
if !has_transform {
|
if !has_transform {
|
||||||
let transform = transform.unwrap_or_else(|| {
|
let transform = transform.unwrap_or_else(|| {
|
||||||
@@ -320,13 +320,13 @@ fn fill<'e>(
|
|||||||
#[default(Color::BLACK)]
|
#[default(Color::BLACK)]
|
||||||
fill: IList<Graphic<'static>>,
|
fill: IList<Graphic<'static>>,
|
||||||
_backup_color: IList<Color>,
|
_backup_color: IList<Color>,
|
||||||
#[default(Color::BLACK, Color::WHITE)] _backup_gradient: IList<Gradient>,
|
_backup_gradient: IList<Gradient>,
|
||||||
_gradient_type: GradientType,
|
_gradient_form: GradientForm,
|
||||||
_has_transform: bool,
|
_has_transform: bool,
|
||||||
_transform: DAffine2,
|
_transform: DAffine2,
|
||||||
) -> Result<(Vector, Attr<'e, Fill>), Interrupt> {
|
) -> Result<(Vector, Attr<'e, Fill>), Interrupt> {
|
||||||
let mut paint = paint_table(fill);
|
let mut paint = paint_table(fill);
|
||||||
default_gradient_paint(&mut paint, element.bounding_box(), _gradient_type, _has_transform.then_some(_transform));
|
default_gradient_paint(&mut paint, element.bounding_box(), _gradient_form, _has_transform.then_some(_transform));
|
||||||
let parked = park_paint(ctx.arena(), paint)?;
|
let parked = park_paint(ctx.arena(), paint)?;
|
||||||
Ok((element, Attr(Some(parked))))
|
Ok((element, Attr(Some(parked))))
|
||||||
}
|
}
|
||||||
@@ -340,8 +340,8 @@ fn fill_graphic_leveled<'e>(
|
|||||||
(element, _content_fill): (Graphic<'static>, Attr<Fill>),
|
(element, _content_fill): (Graphic<'static>, Attr<Fill>),
|
||||||
#[default(Color::BLACK)] fill: IList<Graphic<'static>>,
|
#[default(Color::BLACK)] fill: IList<Graphic<'static>>,
|
||||||
_backup_color: IList<Color>,
|
_backup_color: IList<Color>,
|
||||||
#[default(Color::BLACK, Color::WHITE)] _backup_gradient: IList<Gradient>,
|
_backup_gradient: IList<Gradient>,
|
||||||
_gradient_type: GradientType,
|
_gradient_form: GradientForm,
|
||||||
_has_transform: bool,
|
_has_transform: bool,
|
||||||
_transform: DAffine2,
|
_transform: DAffine2,
|
||||||
) -> Result<(Graphic<'static>, Attr<'e, Fill>), Interrupt> {
|
) -> Result<(Graphic<'static>, Attr<'e, Fill>), Interrupt> {
|
||||||
@@ -350,7 +350,7 @@ fn fill_graphic_leveled<'e>(
|
|||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let mut paint = paint_table(fill);
|
let mut paint = paint_table(fill);
|
||||||
default_gradient_paint(&mut paint, bounds, _gradient_type, _has_transform.then_some(_transform));
|
default_gradient_paint(&mut paint, bounds, _gradient_form, _has_transform.then_some(_transform));
|
||||||
let parked = park_paint(ctx.arena(), paint)?;
|
let parked = park_paint(ctx.arena(), paint)?;
|
||||||
Ok((element, Attr(Some(parked))))
|
Ok((element, Attr(Some(parked))))
|
||||||
}
|
}
|
||||||
@@ -1312,55 +1312,49 @@ fn points_to_polyline(_: impl Ctx, mut points: Vector, #[default(true)] closed:
|
|||||||
fn relax_points(
|
fn relax_points(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
/// A vector path or point cloud to relax.
|
/// A vector path or point cloud to relax.
|
||||||
source: Vector,
|
mut source: Vector,
|
||||||
/// The number of relaxation steps to apply. A fractional value runs the whole steps and then blends partway toward one more step, so the amount of relaxation can be animated smoothly.
|
/// The number of relaxation steps to apply. A fractional value runs the whole steps and then blends partway toward one more step, so the amount of relaxation can be animated smoothly.
|
||||||
#[default(1.)]
|
#[default(1.)]
|
||||||
#[hard(0..1000)]
|
#[hard(0..1000)]
|
||||||
iterations: f64,
|
iterations: f64,
|
||||||
) -> Vector {
|
) -> Vector {
|
||||||
let mut vector = source;
|
let relaxed = crate::voronoi::relax_sites(source.point_domain.positions(), iterations);
|
||||||
|
for ((_, position), new_position) in source.point_domain.positions_mut().zip(relaxed) {
|
||||||
let relaxed = crate::voronoi::relax_sites(vector.point_domain.positions(), iterations);
|
|
||||||
for ((_, position), new_position) in vector.point_domain.positions_mut().zip(relaxed) {
|
|
||||||
*position = new_position;
|
*position = new_position;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector
|
source
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a Voronoi diagram from the anchor points. Each point claims the region of space closest to it, and those regions tessellate the plane. Cells around the outside are clipped to the convex hull of the points so the diagram stays finite.
|
/// Builds a Voronoi diagram from the anchor points. Each point claims the region of space closest to it, and those regions tessellate the plane. Cells around the outside are clipped to the convex hull of the points so the diagram stays finite.
|
||||||
///
|
///
|
||||||
/// When Connect Cells is off, every cell becomes its own closed, fillable subpath. When on, the cells share their common points and segments, forming a single connected mesh with no fillable regions.
|
/// When Connect Cells is off, every cell becomes its own closed, fillable subpath. When on, the cells share their common points and segments, forming a single connected mesh with no fillable regions.
|
||||||
#[node_macro::node(category("Vector"), path(core_types::vector))]
|
#[node_macro::node(category("Vector"), path(core_types::vector))]
|
||||||
fn voronoi_cells(_: impl Ctx, source: Vector, connect_cells: bool) -> Vector {
|
fn voronoi_cells(_: impl Ctx, mut source: Vector, connect_cells: bool) -> Vector {
|
||||||
let mut vector = source;
|
let sites = source.point_domain.positions().to_vec();
|
||||||
|
|
||||||
let sites = vector.point_domain.positions().to_vec();
|
|
||||||
let cells = crate::voronoi::voronoi_cells(&sites);
|
let cells = crate::voronoi::voronoi_cells(&sites);
|
||||||
if !cells.is_empty() {
|
if !cells.is_empty() {
|
||||||
replace_with_polygons(&mut vector, cells, connect_cells);
|
replace_with_polygons(&mut source, cells, connect_cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector
|
source
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a Delaunay triangulation connecting the anchor points. It is the geometric dual of the **Voronoi** node: a mesh of triangles in which no point lies inside any triangle's circumscribed circle.
|
/// Builds a Delaunay triangulation connecting the anchor points. It is the geometric dual of the **Voronoi** node: a mesh of triangles in which no point lies inside any triangle's circumscribed circle.
|
||||||
///
|
///
|
||||||
/// When Connect Cells is off, every triangle becomes its own closed, fillable subpath. When on, the triangles share their common points and segments, forming a single connected mesh with no fillable regions.
|
/// When Connect Cells is off, every triangle becomes its own closed, fillable subpath. When on, the triangles share their common points and segments, forming a single connected mesh with no fillable regions.
|
||||||
#[node_macro::node(category("Vector"), path(core_types::vector))]
|
#[node_macro::node(category("Vector"), path(core_types::vector))]
|
||||||
fn triangulate(_: impl Ctx, source: Vector, connect_cells: bool) -> Vector {
|
fn triangulate(_: impl Ctx, mut source: Vector, connect_cells: bool) -> Vector {
|
||||||
let mut vector = source;
|
let sites = source.point_domain.positions().to_vec();
|
||||||
|
|
||||||
let sites = vector.point_domain.positions().to_vec();
|
|
||||||
let triangles = crate::voronoi::delaunay_triangles(&sites);
|
let triangles = crate::voronoi::delaunay_triangles(&sites);
|
||||||
if !triangles.is_empty() {
|
if !triangles.is_empty() {
|
||||||
// `delaunator` emits triangle vertices clockwise; reverse to `[a, c, b]` so triangles wind counter-clockwise to
|
// `delaunator` emits triangle vertices clockwise; reverse to `[a, c, b]` so triangles wind counter-clockwise to
|
||||||
// match the Voronoi cells and the rest of the framework's fill winding.
|
// match the Voronoi cells and the rest of the framework's fill winding.
|
||||||
let polygons = triangles.iter().map(|&[a, b, c]| vec![sites[a], sites[c], sites[b]]).collect();
|
let polygons = triangles.iter().map(|&[a, b, c]| vec![sites[a], sites[c], sites[b]]).collect();
|
||||||
replace_with_polygons(&mut vector, polygons, connect_cells);
|
replace_with_polygons(&mut source, polygons, connect_cells);
|
||||||
}
|
}
|
||||||
|
|
||||||
vector
|
source
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces a vector's geometry (points, segments, and regions) with the given closed polygons, preserving its style.
|
/// Replaces a vector's geometry (points, segments, and regions) with the given closed polygons, preserving its style.
|
||||||
@@ -3979,6 +3973,7 @@ mod test {
|
|||||||
// contour returns to approximately, not exactly, its start; that near-coincident point must close, not duplicate).
|
// contour returns to approximately, not exactly, its start; that near-coincident point must close, not duplicate).
|
||||||
let delaunay = super::triangulate(&(), vector_from_points(&SQUARE_WITH_CENTER), false);
|
let delaunay = super::triangulate(&(), vector_from_points(&SQUARE_WITH_CENTER), false);
|
||||||
let (result, _) = super::offset_path(&(), (delaunay, Attr(DAffine2::IDENTITY)), 0.5, StrokeJoin::Miter, 4.);
|
let (result, _) = super::offset_path(&(), (delaunay, Attr(DAffine2::IDENTITY)), 0.5, StrokeJoin::Miter, 4.);
|
||||||
|
|
||||||
let mut subpaths = 0;
|
let mut subpaths = 0;
|
||||||
for (group, closed) in result.stroke_manipulator_groups() {
|
for (group, closed) in result.stroke_manipulator_groups() {
|
||||||
subpaths += 1;
|
subpaths += 1;
|
||||||
@@ -4130,7 +4125,6 @@ mod test {
|
|||||||
assert_eq!(manipulator_groups_anchors[i], expected_bounding_box[i]);
|
assert_eq!(manipulator_groups_anchors[i], expected_bounding_box[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sample_polyline() {
|
fn sample_polyline() {
|
||||||
let path = BezPath::from_vec(vec![PathEl::MoveTo(Point::ZERO), PathEl::CurveTo(Point::ZERO, Point::new(100., 0.), Point::new(100., 0.))]);
|
let path = BezPath::from_vec(vec![PathEl::MoveTo(Point::ZERO), PathEl::CurveTo(Point::ZERO, Point::new(100., 0.), Point::new(100., 0.))]);
|
||||||
|
|||||||
Reference in New Issue
Block a user