mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-29 06:28:12 +08:00
Rename GradientStops to Gradient and the legacy Gradient/Fill structs to LegacyGradient/LegacyFill
This commit is contained in:
@@ -5,7 +5,7 @@ use crate::messages::prelude::*;
|
|||||||
use graphene_std::Color;
|
use graphene_std::Color;
|
||||||
use graphene_std::color::SRGBA8;
|
use graphene_std::color::SRGBA8;
|
||||||
use graphene_std::core_types::misc::parse_css_color;
|
use graphene_std::core_types::misc::parse_css_color;
|
||||||
use graphene_std::vector::style::{FillChoice, FillChoiceUI, GradientStops, GradientStopsUI};
|
use graphene_std::vector::style::{FillChoice, FillChoiceUI, Gradient, GradientUI};
|
||||||
|
|
||||||
/// Bounds for a midpoint position (relative to the interval between two adjacent gradient stops).
|
/// Bounds for a midpoint position (relative to the interval between two adjacent gradient stops).
|
||||||
const MIN_MIDPOINT: f64 = 0.01;
|
const MIN_MIDPOINT: f64 = 0.01;
|
||||||
@@ -28,7 +28,7 @@ pub struct ColorPickerMessageHandler {
|
|||||||
old_is_none: bool,
|
old_is_none: bool,
|
||||||
|
|
||||||
// When set, the picker is editing a gradient: the visual pickers and inputs target the active stop's color.
|
// When set, the picker is editing a gradient: the visual pickers and inputs target the active stop's color.
|
||||||
gradient: Option<GradientStops>,
|
gradient: Option<Gradient>,
|
||||||
active_marker_index: Option<u32>,
|
active_marker_index: Option<u32>,
|
||||||
active_marker_is_midpoint: bool,
|
active_marker_is_midpoint: bool,
|
||||||
|
|
||||||
@@ -430,7 +430,7 @@ impl ColorPickerMessageHandler {
|
|||||||
// For gradient editing, the markers' handle colors mirror their gradient stop colors
|
// For gradient editing, the markers' handle colors mirror their gradient stop colors
|
||||||
let markers = gradient.iter().map(|stop| SpectrumMarker::new(stop.position, stop.midpoint, stop.color)).collect();
|
let markers = gradient.iter().map(|stop| SpectrumMarker::new(stop.position, stop.midpoint, stop.color)).collect();
|
||||||
let mut row_widgets = vec![
|
let mut row_widgets = vec![
|
||||||
SpectrumInput::new(GradientStopsUI::from(gradient))
|
SpectrumInput::new(GradientUI::from(gradient))
|
||||||
.markers(markers)
|
.markers(markers)
|
||||||
.active_marker_index(self.active_marker_index)
|
.active_marker_index(self.active_marker_index)
|
||||||
.active_marker_is_midpoint(self.active_marker_is_midpoint)
|
.active_marker_is_midpoint(self.active_marker_is_midpoint)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use derivative::*;
|
|||||||
use graphene_std::Color;
|
use graphene_std::Color;
|
||||||
use graphene_std::color::SRGBA8;
|
use graphene_std::color::SRGBA8;
|
||||||
use graphene_std::transform::ReferencePoint;
|
use graphene_std::transform::ReferencePoint;
|
||||||
use graphene_std::vector::style::{FillChoiceUI, GradientStopsUI};
|
use graphene_std::vector::style::{FillChoiceUI, GradientUI};
|
||||||
use graphite_proc_macros::WidgetBuilder;
|
use graphite_proc_macros::WidgetBuilder;
|
||||||
|
|
||||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
#[cfg_attr(feature = "wasm", derive(tsify::Tsify))]
|
||||||
@@ -531,7 +531,7 @@ pub struct SpectrumInput {
|
|||||||
// Content
|
// Content
|
||||||
/// The colored gradient drawn behind the markers (display-only, caller-owned).
|
/// The colored gradient drawn behind the markers (display-only, caller-owned).
|
||||||
#[widget_builder(constructor)]
|
#[widget_builder(constructor)]
|
||||||
pub track: GradientStopsUI,
|
pub track: GradientUI,
|
||||||
/// CSS `linear-gradient(...)` string for the track strip's `background-image`. Auto-populated from `track` at layout-send time.
|
/// CSS `linear-gradient(...)` string for the track strip's `background-image`. Auto-populated from `track` at layout-send time.
|
||||||
#[serde(rename = "trackCSS")]
|
#[serde(rename = "trackCSS")]
|
||||||
#[widget_builder(skip)]
|
#[widget_builder(skip)]
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use glam::{Affine2, DAffine2, Vec2};
|
|||||||
use graph_craft::document::NodeId;
|
use graph_craft::document::NodeId;
|
||||||
use graphene_std::blending::BlendMode;
|
use graphene_std::blending::BlendMode;
|
||||||
use graphene_std::color::SRGBA8;
|
use graphene_std::color::SRGBA8;
|
||||||
use graphene_std::gradient::GradientStops;
|
use graphene_std::gradient::Gradient;
|
||||||
use graphene_std::list::List;
|
use graphene_std::list::List;
|
||||||
use graphene_std::raster_types::{CPU, GPU, Raster};
|
use graphene_std::raster_types::{CPU, GPU, Raster};
|
||||||
use graphene_std::vector::Vector;
|
use graphene_std::vector::Vector;
|
||||||
@@ -192,7 +192,7 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
|
|||||||
List<Raster<CPU>>,
|
List<Raster<CPU>>,
|
||||||
List<Raster<GPU>>,
|
List<Raster<GPU>>,
|
||||||
List<Color>,
|
List<Color>,
|
||||||
List<GradientStops>,
|
List<Gradient>,
|
||||||
List<String>,
|
List<String>,
|
||||||
List<f64>,
|
List<f64>,
|
||||||
List<u8>,
|
List<u8>,
|
||||||
@@ -201,7 +201,7 @@ fn generate_layout(introspected_data: &Arc<dyn std::any::Any + Send + Sync + 'st
|
|||||||
List<BlendMode>,
|
List<BlendMode>,
|
||||||
List<GradientType>,
|
List<GradientType>,
|
||||||
List<GradientSpreadMethod>,
|
List<GradientSpreadMethod>,
|
||||||
GradientStops,
|
Gradient,
|
||||||
f64,
|
f64,
|
||||||
u32,
|
u32,
|
||||||
u64,
|
u64,
|
||||||
@@ -543,7 +543,7 @@ impl TableItemLayout for Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableItemLayout for GradientStops {
|
impl TableItemLayout for Gradient {
|
||||||
fn type_name() -> &'static str {
|
fn type_name() -> &'static str {
|
||||||
"Gradient"
|
"Gradient"
|
||||||
}
|
}
|
||||||
@@ -911,12 +911,12 @@ macro_rules! known_item_types {
|
|||||||
List<Raster<CPU>>,
|
List<Raster<CPU>>,
|
||||||
List<Raster<GPU>>,
|
List<Raster<GPU>>,
|
||||||
List<Color>,
|
List<Color>,
|
||||||
List<GradientStops>,
|
List<Gradient>,
|
||||||
List<String>,
|
List<String>,
|
||||||
List<NodeId>,
|
List<NodeId>,
|
||||||
List<f64>,
|
List<f64>,
|
||||||
List<u8>,
|
List<u8>,
|
||||||
GradientStops,
|
Gradient,
|
||||||
Color,
|
Color,
|
||||||
NodeId,
|
NodeId,
|
||||||
DAffine2,
|
DAffine2,
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ pub struct DocumentMessageHandler {
|
|||||||
/// network path, the node itself, and its original relative gradient. The deferred migration removes each entry as its bake lands.
|
/// network path, the node itself, and its original relative gradient. The deferred migration removes each entry as its bake lands.
|
||||||
/// Transient migration state, but persisted in the saved document so unfinished bakes retry on the next open instead of losing placement.
|
/// Transient migration state, but persisted in the saved document so unfinished bakes retry on the next open instead of losing placement.
|
||||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
pub(crate) pending_gradient_bbox_bake: Vec<(Vec<NodeId>, NodeId, graphic_types::migrations::legacy::Gradient)>,
|
pub(crate) pending_gradient_bbox_bake: Vec<(Vec<NodeId>, NodeId, graphic_types::migrations::legacy::LegacyGradient)>,
|
||||||
|
|
||||||
// =============================================
|
// =============================================
|
||||||
// Fields omitted from the saved document format
|
// Fields omitted from the saved document format
|
||||||
@@ -4007,7 +4007,7 @@ mod document_message_handler_tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn pending_gradient_bakes_round_trip_through_serialization() {
|
fn pending_gradient_bakes_round_trip_through_serialization() {
|
||||||
let document = DocumentMessageHandler {
|
let document = DocumentMessageHandler {
|
||||||
pending_gradient_bbox_bake: vec![(vec![NodeId(7)], NodeId(42), graphic_types::migrations::legacy::Gradient::default())],
|
pending_gradient_bbox_bake: vec![(vec![NodeId(7)], NodeId(42), graphic_types::migrations::legacy::LegacyGradient::default())],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ 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::{GradientSpreadMethod, GradientType, Stroke};
|
use graphene_std::vector::style::{GradientSpreadMethod, GradientType, Stroke};
|
||||||
use graphene_std::vector::{GradientStops, PointId, VectorModificationType};
|
use graphene_std::vector::{Gradient, PointId, VectorModificationType};
|
||||||
|
|
||||||
#[impl_message(Message, DocumentMessage, GraphOperation)]
|
#[impl_message(Message, DocumentMessage, GraphOperation)]
|
||||||
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
@@ -22,7 +22,7 @@ pub enum GraphOperationMessage {
|
|||||||
},
|
},
|
||||||
FillGradientSet {
|
FillGradientSet {
|
||||||
layer: LayerNodeIdentifier,
|
layer: LayerNodeIdentifier,
|
||||||
gradient: GradientStops,
|
gradient: Gradient,
|
||||||
gradient_type: GradientType,
|
gradient_type: GradientType,
|
||||||
spread_method: GradientSpreadMethod,
|
spread_method: GradientSpreadMethod,
|
||||||
transform: DAffine2,
|
transform: DAffine2,
|
||||||
@@ -33,7 +33,7 @@ pub enum GraphOperationMessage {
|
|||||||
},
|
},
|
||||||
GradientStopsSet {
|
GradientStopsSet {
|
||||||
layer: LayerNodeIdentifier,
|
layer: LayerNodeIdentifier,
|
||||||
stops: GradientStops,
|
stops: Gradient,
|
||||||
},
|
},
|
||||||
GradientTransformSet {
|
GradientTransformSet {
|
||||||
layer: LayerNodeIdentifier,
|
layer: LayerNodeIdentifier,
|
||||||
|
|||||||
+10
-17
@@ -13,7 +13,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::{GradientSpreadMethod, GradientStop, GradientStops, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
use graphene_std::vector::style::{Gradient, GradientSpreadMethod, GradientStop, GradientType, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
||||||
use graphene_std::{Artboard, Color};
|
use graphene_std::{Artboard, Color};
|
||||||
|
|
||||||
#[derive(ExtractField)]
|
#[derive(ExtractField)]
|
||||||
@@ -508,8 +508,8 @@ const GRAPHITE_NAMESPACE: &str = "https://graphite.art";
|
|||||||
/// Pre-parses the raw SVG XML to extract gradient stops that have `graphite:midpoint` attributes.
|
/// Pre-parses the raw SVG XML to extract gradient stops that have `graphite:midpoint` attributes.
|
||||||
/// Graphite exports gradients with midpoint curve data by writing interpolated approximation stops
|
/// Graphite exports gradients with midpoint curve data by writing interpolated approximation stops
|
||||||
/// alongside the real stops. Real stops are tagged with `graphite:midpoint` attributes.
|
/// alongside the real stops. Real stops are tagged with `graphite:midpoint` attributes.
|
||||||
/// Returns a map from gradient element `id` to `GradientStops` containing only the real stops.
|
/// Returns a map from gradient element `id` to `Gradient` containing only the real stops.
|
||||||
fn extract_graphite_gradient_stops(svg: &str) -> HashMap<String, GradientStops> {
|
fn extract_graphite_gradient_stops(svg: &str) -> HashMap<String, Gradient> {
|
||||||
let mut result = HashMap::new();
|
let mut result = HashMap::new();
|
||||||
|
|
||||||
// Quick check: if the SVG doesn't reference `graphite:midpoint` at all, skip parsing
|
// Quick check: if the SVG doesn't reference `graphite:midpoint` at all, skip parsing
|
||||||
@@ -555,7 +555,7 @@ fn extract_graphite_gradient_stops(svg: &str) -> HashMap<String, GradientStops>
|
|||||||
}
|
}
|
||||||
|
|
||||||
if has_any_midpoint && !real_stops.is_empty() {
|
if has_any_midpoint && !real_stops.is_empty() {
|
||||||
result.insert(gradient_id, GradientStops::new(real_stops));
|
result.insert(gradient_id, Gradient::new(real_stops));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -579,14 +579,7 @@ fn parse_hex_stop_color(hex: &str, opacity: f32) -> Option<Color> {
|
|||||||
/// interact with any existing layers in the parent stack. All descendant layers use a lightweight
|
/// interact with any existing layers in the parent stack. All descendant layers use a lightweight
|
||||||
/// O(n) import path that skips collision detection and instead calculates positions directly from
|
/// O(n) import path that skips collision detection and instead calculates positions directly from
|
||||||
/// the known tree structure.
|
/// the known tree structure.
|
||||||
fn import_usvg_node(
|
fn import_usvg_node(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node, id: NodeId, parent: LayerNodeIdentifier, insert_index: usize, graphite_gradient_stops: &HashMap<String, Gradient>) {
|
||||||
modify_inputs: &mut ModifyInputsContext,
|
|
||||||
node: &usvg::Node,
|
|
||||||
id: NodeId,
|
|
||||||
parent: LayerNodeIdentifier,
|
|
||||||
insert_index: usize,
|
|
||||||
graphite_gradient_stops: &HashMap<String, GradientStops>,
|
|
||||||
) {
|
|
||||||
let layer = modify_inputs.create_layer(id);
|
let layer = modify_inputs.create_layer(id);
|
||||||
|
|
||||||
modify_inputs.network_interface.move_layer_to_stack(layer, parent, insert_index, &[]);
|
modify_inputs.network_interface.move_layer_to_stack(layer, parent, insert_index, &[]);
|
||||||
@@ -649,7 +642,7 @@ fn import_usvg_node_inner(
|
|||||||
id: NodeId,
|
id: NodeId,
|
||||||
parent: LayerNodeIdentifier,
|
parent: LayerNodeIdentifier,
|
||||||
insert_index: usize,
|
insert_index: usize,
|
||||||
graphite_gradient_stops: &HashMap<String, GradientStops>,
|
graphite_gradient_stops: &HashMap<String, Gradient>,
|
||||||
group_extents_map: &mut HashMap<LayerNodeIdentifier, Vec<u32>>,
|
group_extents_map: &mut HashMap<LayerNodeIdentifier, Vec<u32>>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let layer = modify_inputs.create_layer(id);
|
let layer = modify_inputs.create_layer(id);
|
||||||
@@ -692,7 +685,7 @@ fn import_usvg_node_inner(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Helper to apply path data (vector geometry, fill, stroke, transform) to a layer.
|
/// Helper to apply path data (vector geometry, fill, stroke, transform) to a layer.
|
||||||
fn import_usvg_path(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node, path: &usvg::Path, layer: LayerNodeIdentifier, graphite_gradient_stops: &HashMap<String, GradientStops>) {
|
fn import_usvg_path(modify_inputs: &mut ModifyInputsContext, node: &usvg::Node, path: &usvg::Path, layer: LayerNodeIdentifier, graphite_gradient_stops: &HashMap<String, Gradient>) {
|
||||||
let subpaths = convert_usvg_path(path);
|
let subpaths = convert_usvg_path(path);
|
||||||
|
|
||||||
// Skip creating a Transform node entirely when the SVG-native transform is identity.
|
// Skip creating a Transform node entirely when the SVG-native transform is identity.
|
||||||
@@ -807,7 +800,7 @@ fn convert_spread_method(spread_method: usvg::SpreadMethod) -> GradientSpreadMet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, graphite_gradient_stops: &HashMap<String, GradientStops>) {
|
fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, graphite_gradient_stops: &HashMap<String, Gradient>) {
|
||||||
match &fill.paint() {
|
match &fill.paint() {
|
||||||
usvg::Paint::Color(color) => modify_inputs.fill_color_set(Some(usvg_color(*color, fill.opacity().get()))),
|
usvg::Paint::Color(color) => modify_inputs.fill_color_set(Some(usvg_color(*color, fill.opacity().get()))),
|
||||||
usvg::Paint::LinearGradient(linear) => {
|
usvg::Paint::LinearGradient(linear) => {
|
||||||
@@ -827,7 +820,7 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, g
|
|||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
color: usvg_color(stop.color(), stop.opacity().get()),
|
color: usvg_color(stop.color(), stop.opacity().get()),
|
||||||
});
|
});
|
||||||
GradientStops::new(stops)
|
Gradient::new(stops)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let spread_method = convert_spread_method(linear.spread_method());
|
let spread_method = convert_spread_method(linear.spread_method());
|
||||||
@@ -851,7 +844,7 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, g
|
|||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
color: usvg_color(stop.color(), stop.opacity().get()),
|
color: usvg_color(stop.color(), stop.opacity().get()),
|
||||||
});
|
});
|
||||||
GradientStops::new(stops)
|
Gradient::new(stops)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let spread_method = convert_spread_method(radial.spread_method());
|
let spread_method = convert_spread_method(radial.spread_method());
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ 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::{GradientSpreadMethod, GradientType, Stroke};
|
use graphene_std::vector::style::{GradientSpreadMethod, GradientType, Stroke};
|
||||||
use graphene_std::vector::{GradientStops, PointId, Vector, VectorModification, VectorModificationType};
|
use graphene_std::vector::{Gradient, PointId, Vector, VectorModification, VectorModificationType};
|
||||||
use graphene_std::{Artboard, Color, Graphic, NodeInputDecleration};
|
use graphene_std::{Artboard, Color, Graphic, NodeInputDecleration};
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(PartialEq, Clone, Copy, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
@@ -464,7 +464,7 @@ impl<'a> ModifyInputsContext<'a> {
|
|||||||
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::Color(color), false), false);
|
self.set_input_with_refresh(input_connector, NodeInput::value(TaggedValue::Color(color), false), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fill_gradient_set(&mut self, gradient: GradientStops, gradient_type: GradientType, spread_method: GradientSpreadMethod, transform: DAffine2) {
|
pub fn fill_gradient_set(&mut self, gradient: Gradient, gradient_type: GradientType, spread_method: GradientSpreadMethod, 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;
|
||||||
};
|
};
|
||||||
@@ -563,7 +563,7 @@ impl<'a> ModifyInputsContext<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write the gradient stops to the 'Gradient Value' node feeding the layer.
|
/// Write the gradient stops to the 'Gradient Value' node feeding the layer.
|
||||||
pub fn gradient_stops_set(&mut self, stops: GradientStops) {
|
pub fn gradient_stops_set(&mut self, stops: Gradient) {
|
||||||
let Some(output_layer) = self.get_output_layer() else { return };
|
let Some(output_layer) = self.get_output_layer() else { return };
|
||||||
|
|
||||||
let gradient_value_id = match get_upstream_gradient_value_node_id(output_layer, self.network_interface) {
|
let gradient_value_id = match get_upstream_gradient_value_node_id(output_layer, self.network_interface) {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ use graphene_std::transform::{Footprint, ReferencePoint, ScaleType, Transform};
|
|||||||
use graphene_std::vector::misc::BooleanOperation;
|
use graphene_std::vector::misc::BooleanOperation;
|
||||||
use graphene_std::vector::misc::{ArcType, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType};
|
use graphene_std::vector::misc::{ArcType, CentroidType, ExtrudeJoiningAlgorithm, GridType, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, SpiralType};
|
||||||
use graphene_std::vector::style::{
|
use graphene_std::vector::style::{
|
||||||
FillChoice, FillChoiceUI, GradientSpreadMethod, GradientStops, GradientStopsUI, GradientType, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, build_transform_with_y_preservation,
|
FillChoice, FillChoiceUI, Gradient, GradientSpreadMethod, GradientType, GradientUI, PaintOrder, StrokeAlign, StrokeCap, StrokeJoin, build_transform_with_y_preservation,
|
||||||
};
|
};
|
||||||
use graphene_std::vector::{QRCodeErrorCorrectionLevel, VectorModification};
|
use graphene_std::vector::{QRCodeErrorCorrectionLevel, VectorModification};
|
||||||
|
|
||||||
@@ -254,11 +254,11 @@ pub(crate) fn property_from_type(
|
|||||||
// ==========
|
// ==========
|
||||||
Some(x) if x == TypeId::of::<List<f64>>() => array_of_number_widget(default_info, TextInput::default()).into(),
|
Some(x) if x == TypeId::of::<List<f64>>() => array_of_number_widget(default_info, TextInput::default()).into(),
|
||||||
Some(x) if x == TypeId::of::<List<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
|
Some(x) if x == TypeId::of::<List<Color>>() => color_widget(default_info, ColorInput::default().allow_none(true)),
|
||||||
Some(x) if x == TypeId::of::<List<GradientStops>>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
Some(x) if x == TypeId::of::<List<Gradient>>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
||||||
Some(x) if x == TypeId::of::<List<BrushStroke>>() => brush_strokes_widget(default_info).into(),
|
Some(x) if x == TypeId::of::<List<BrushStroke>>() => brush_strokes_widget(default_info).into(),
|
||||||
// Leveled wires type by their element; each element keeps its list form's widget.
|
// Leveled wires type by their element; each element keeps its list form's widget.
|
||||||
Some(x) if x == TypeId::of::<Color>() => color_widget(default_info, ColorInput::default().allow_none(true)),
|
Some(x) if x == TypeId::of::<Color>() => color_widget(default_info, ColorInput::default().allow_none(true)),
|
||||||
Some(x) if x == TypeId::of::<GradientStops>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
Some(x) if x == TypeId::of::<Gradient>() => color_widget(default_info, ColorInput::default().allow_none(false)),
|
||||||
Some(x) if x == TypeId::of::<BrushStroke>() => brush_strokes_widget(default_info).into(),
|
Some(x) if x == TypeId::of::<BrushStroke>() => brush_strokes_widget(default_info).into(),
|
||||||
// ============
|
// ============
|
||||||
// STRUCT TYPES
|
// STRUCT TYPES
|
||||||
@@ -1190,7 +1190,7 @@ pub fn color_widget(parameter_widgets_info: ParameterWidgetsInfo, color_button:
|
|||||||
color_button
|
color_button
|
||||||
.value(FillChoiceUI::from(&FillChoice::Gradient(stops.clone())))
|
.value(FillChoiceUI::from(&FillChoice::Gradient(stops.clone())))
|
||||||
.on_update(update_value(
|
.on_update(update_value(
|
||||||
|input: &ColorInput| TaggedValue::Gradient(input.value.as_gradient().map(GradientStops::from).unwrap_or_default()),
|
|input: &ColorInput| TaggedValue::Gradient(input.value.as_gradient().map(Gradient::from).unwrap_or_default()),
|
||||||
node_id,
|
node_id,
|
||||||
index,
|
index,
|
||||||
))
|
))
|
||||||
@@ -1267,8 +1267,8 @@ pub fn query_assign_colors_randomize(node_id: NodeId, context: &NodePropertiesCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 2-stop black-to-white gradient track for spectrum sliders that map a value to a grayscale axis.
|
/// 2-stop black-to-white gradient track for spectrum sliders that map a value to a grayscale axis.
|
||||||
fn bw_track() -> GradientStops {
|
fn bw_track() -> Gradient {
|
||||||
GradientStops {
|
Gradient {
|
||||||
position: vec![0., 1.],
|
position: vec![0., 1.],
|
||||||
midpoint: vec![0.5, 0.5],
|
midpoint: vec![0.5, 0.5],
|
||||||
color: vec![Color::BLACK, Color::WHITE],
|
color: vec![Color::BLACK, Color::WHITE],
|
||||||
@@ -1276,8 +1276,8 @@ fn bw_track() -> GradientStops {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 3-stop black-to-color-to-white gradient track for spectrum sliders that map a value to a hue's full luminance range.
|
/// 3-stop black-to-color-to-white gradient track for spectrum sliders that map a value to a hue's full luminance range.
|
||||||
fn color_track(color: Color) -> GradientStops {
|
fn color_track(color: Color) -> Gradient {
|
||||||
GradientStops {
|
Gradient {
|
||||||
position: vec![0., 0.5, 1.],
|
position: vec![0., 0.5, 1.],
|
||||||
midpoint: vec![0.5; 3],
|
midpoint: vec![0.5; 3],
|
||||||
color: vec![Color::BLACK, color, Color::WHITE],
|
color: vec![Color::BLACK, color, Color::WHITE],
|
||||||
@@ -1312,7 +1312,7 @@ pub(crate) fn brightness_contrast_properties(node_id: NodeId, context: &mut Node
|
|||||||
|
|
||||||
let contrast_min = if use_classic_value { -100. } else { -50. };
|
let contrast_min = if use_classic_value { -100. } else { -50. };
|
||||||
let zero_position = -contrast_min / (100. - contrast_min);
|
let zero_position = -contrast_min / (100. - contrast_min);
|
||||||
let contrast_track = GradientStops {
|
let contrast_track = Gradient {
|
||||||
position: vec![0., zero_position, 1.],
|
position: vec![0., zero_position, 1.],
|
||||||
midpoint: vec![0.5; 3],
|
midpoint: vec![0.5; 3],
|
||||||
color: vec![Color::from_rgbf32_unchecked(0.5, 0.5, 0.5), Color::BLACK, Color::from_rgbf32_unchecked(0.5, 0.5, 0.5)],
|
color: vec![Color::from_rgbf32_unchecked(0.5, 0.5, 0.5), Color::BLACK, Color::from_rgbf32_unchecked(0.5, 0.5, 0.5)],
|
||||||
@@ -1409,7 +1409,7 @@ fn build_shared_spectrum_section(node_id: NodeId, context: &mut NodePropertiesCo
|
|||||||
|
|
||||||
// Build the shared spectrum widget (placed on the first non-exposed row)
|
// Build the shared spectrum widget (placed on the first non-exposed row)
|
||||||
let spectrum_widget = (!spectrum_markers.is_empty()).then(|| {
|
let spectrum_widget = (!spectrum_markers.is_empty()).then(|| {
|
||||||
SpectrumInput::new(GradientStopsUI::from(&bw_track()))
|
SpectrumInput::new(GradientUI::from(&bw_track()))
|
||||||
.markers(spectrum_markers)
|
.markers(spectrum_markers)
|
||||||
.show_midpoints(false)
|
.show_midpoints(false)
|
||||||
.allow_insert(false)
|
.allow_insert(false)
|
||||||
@@ -1502,13 +1502,13 @@ pub(crate) fn hue_saturation_properties(node_id: NodeId, context: &mut NodePrope
|
|||||||
let saturated_current_hue = Color::from_hsva(marker_hue, 1., 1., 1.);
|
let saturated_current_hue = Color::from_hsva(marker_hue, 1., 1., 1.);
|
||||||
|
|
||||||
// Hue: cyclic rainbow
|
// Hue: cyclic rainbow
|
||||||
let hue_track = GradientStops {
|
let hue_track = Gradient {
|
||||||
position: vec![0., 1. / 6., 2. / 6., 3. / 6., 4. / 6., 5. / 6., 1.],
|
position: vec![0., 1. / 6., 2. / 6., 3. / 6., 4. / 6., 5. / 6., 1.],
|
||||||
midpoint: vec![0.5; 7],
|
midpoint: vec![0.5; 7],
|
||||||
color: vec![Color::RED, Color::YELLOW, Color::GREEN, Color::CYAN, Color::BLUE, Color::MAGENTA, Color::RED],
|
color: vec![Color::RED, Color::YELLOW, Color::GREEN, Color::CYAN, Color::BLUE, Color::MAGENTA, Color::RED],
|
||||||
};
|
};
|
||||||
// Saturation: gray to the fully saturated current hue
|
// Saturation: gray to the fully saturated current hue
|
||||||
let saturation_track = GradientStops {
|
let saturation_track = Gradient {
|
||||||
position: vec![0., 1.],
|
position: vec![0., 1.],
|
||||||
midpoint: vec![0.5, 0.5],
|
midpoint: vec![0.5, 0.5],
|
||||||
color: vec![Color::from_rgbf32_unchecked(0.5, 0.5, 0.5), saturated_current_hue],
|
color: vec![Color::from_rgbf32_unchecked(0.5, 0.5, 0.5), saturated_current_hue],
|
||||||
@@ -1558,7 +1558,7 @@ fn spectrum_slider_row(
|
|||||||
node_id: NodeId,
|
node_id: NodeId,
|
||||||
context: &mut NodePropertiesContext,
|
context: &mut NodePropertiesContext,
|
||||||
input_index: usize,
|
input_index: usize,
|
||||||
track: GradientStops,
|
track: Gradient,
|
||||||
handle_color: Color,
|
handle_color: Color,
|
||||||
value_min: f64,
|
value_min: f64,
|
||||||
value_max: f64,
|
value_max: f64,
|
||||||
@@ -1583,7 +1583,7 @@ fn spectrum_slider_row(
|
|||||||
|
|
||||||
let position_to_value = move |position: f64| value_min + position * value_range;
|
let position_to_value = move |position: f64| value_min + position * value_range;
|
||||||
row.push(
|
row.push(
|
||||||
SpectrumInput::new(GradientStopsUI::from(&track))
|
SpectrumInput::new(GradientUI::from(&track))
|
||||||
.markers(vec![SpectrumMarker::new(position, 0.5, handle_color)])
|
.markers(vec![SpectrumMarker::new(position, 0.5, handle_color)])
|
||||||
.show_midpoints(false)
|
.show_midpoints(false)
|
||||||
.allow_insert(false)
|
.allow_insert(false)
|
||||||
@@ -1643,7 +1643,7 @@ pub(crate) fn threshold_properties(node_id: NodeId, context: &mut NodeProperties
|
|||||||
pub(crate) fn vibrance_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
pub(crate) fn vibrance_properties(node_id: NodeId, context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||||
use graphene_std::raster::vibrance::*;
|
use graphene_std::raster::vibrance::*;
|
||||||
|
|
||||||
let track = GradientStops {
|
let track = Gradient {
|
||||||
position: vec![0., 1.],
|
position: vec![0., 1.],
|
||||||
midpoint: vec![0.5, 0.5],
|
midpoint: vec![0.5, 0.5],
|
||||||
color: vec![Color::from_rgbf32_unchecked(0.5, 0.5, 0.5), Color::RED],
|
color: vec![Color::from_rgbf32_unchecked(0.5, 0.5, 0.5), Color::RED],
|
||||||
@@ -2451,7 +2451,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
enum ResolvedFill {
|
enum ResolvedFill {
|
||||||
Solid(Option<Color>),
|
Solid(Option<Color>),
|
||||||
Gradient {
|
Gradient {
|
||||||
gradient: GradientStops,
|
gradient: Gradient,
|
||||||
gradient_type: GradientType,
|
gradient_type: GradientType,
|
||||||
spread_method: GradientSpreadMethod,
|
spread_method: GradientSpreadMethod,
|
||||||
transform: DAffine2,
|
transform: DAffine2,
|
||||||
@@ -2487,7 +2487,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
ResolvedFill::Other
|
ResolvedFill::Other
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(ty) if ty == &concrete!(List<GradientStops>) => {
|
Some(ty) if ty == &concrete!(List<Gradient>) => {
|
||||||
// Read this node's own inputs rather than the layer's nearest Fill, which may be a different node when Fills are chained
|
// Read this node's own inputs rather than the layer's nearest Fill, which may be a different node when Fills are chained
|
||||||
if let Ok(document_node) = get_document_node(node_id, context)
|
if let Ok(document_node) = get_document_node(node_id, context)
|
||||||
&& let Some(gradient) = graph_modification_utils::read_fill_node_gradient(document_node, || {
|
&& let Some(gradient) = graph_modification_utils::read_fill_node_gradient(document_node, || {
|
||||||
@@ -2515,11 +2515,11 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
};
|
};
|
||||||
let backup_stops = match document_node.inputs[BackupGradientInput::INDEX].as_value() {
|
let backup_stops = match document_node.inputs[BackupGradientInput::INDEX].as_value() {
|
||||||
Some(TaggedValue::Gradient(stops)) => stops.clone(),
|
Some(TaggedValue::Gradient(stops)) => stops.clone(),
|
||||||
_ => GradientStops::default(),
|
_ => Gradient::default(),
|
||||||
};
|
};
|
||||||
(backup_color, backup_stops)
|
(backup_color, backup_stops)
|
||||||
}
|
}
|
||||||
Err(_) => (None, GradientStops::default()),
|
Err(_) => (None, Gradient::default()),
|
||||||
};
|
};
|
||||||
|
|
||||||
match &fill {
|
match &fill {
|
||||||
@@ -2545,7 +2545,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
FillChoiceUI::None
|
FillChoiceUI::None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ResolvedFill::Gradient { gradient: stops, .. } => FillChoiceUI::Gradient(GradientStopsUI::from(stops)),
|
ResolvedFill::Gradient { gradient: stops, .. } => FillChoiceUI::Gradient(GradientUI::from(stops)),
|
||||||
ResolvedFill::Other => FillChoiceUI::None,
|
ResolvedFill::Other => FillChoiceUI::None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2566,7 +2566,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
let gradient_set_messages = move |gradient: GradientStops| Message::Batched {
|
let gradient_set_messages = move |gradient: Gradient| Message::Batched {
|
||||||
messages: Box::new([
|
messages: Box::new([
|
||||||
NodeGraphMessage::SetInputValue {
|
NodeGraphMessage::SetInputValue {
|
||||||
node_id,
|
node_id,
|
||||||
@@ -2594,7 +2594,7 @@ pub(crate) fn fill_properties(node_id: NodeId, context: &mut NodePropertiesConte
|
|||||||
solid_set_messages(color)
|
solid_set_messages(color)
|
||||||
}
|
}
|
||||||
FillChoiceUI::Gradient(gradient_stops_ui) => {
|
FillChoiceUI::Gradient(gradient_stops_ui) => {
|
||||||
let gradient = GradientStops::from(gradient_stops_ui);
|
let gradient = Gradient::from(gradient_stops_ui);
|
||||||
gradient_set_messages(gradient)
|
gradient_set_messages(gradient)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ const TEXT_REPLACEMENTS: &[(&str, &str)] = &[
|
|||||||
("\"OptionalF64\":", "\"F64\":"),
|
("\"OptionalF64\":", "\"F64\":"),
|
||||||
("\"path_bool_nodes::BooleanOperation\"", "\"vector_types::vector::misc::BooleanOperation\""),
|
("\"path_bool_nodes::BooleanOperation\"", "\"vector_types::vector::misc::BooleanOperation\""),
|
||||||
("\"core_types::table::Table<", "\"core_types::list::List<"),
|
("\"core_types::table::Table<", "\"core_types::list::List<"),
|
||||||
|
// The `GradientStops` type was renamed to `Gradient`; stale stored output names are cleared so the display falls back to the live type name
|
||||||
|
("\"output_names\":[\"GradientStops\"]", "\"output_names\":[\"\"]"),
|
||||||
|
("vector_types::gradient::GradientStops", "vector_types::gradient::Gradient"),
|
||||||
];
|
];
|
||||||
|
|
||||||
pub struct NodeReplacement<'a> {
|
pub struct NodeReplacement<'a> {
|
||||||
@@ -1622,21 +1625,21 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
// Content: no change
|
// Content: no change
|
||||||
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
|
document.network_interface.set_input(&InputConnector::node(*node_id, 0), old_inputs[0].clone(), network_path);
|
||||||
|
|
||||||
// Fill: a literal Fill value is decomposed, and a wired input (`List<GradientStops> / List<Color>`) is kept as-is
|
// Fill: a literal Fill value is decomposed, and a wired input (`List<Gradient> / List<Color>`) is kept as-is
|
||||||
match old_inputs[1].as_value() {
|
match old_inputs[1].as_value() {
|
||||||
Some(TaggedValue::LegacyFill(old_fill)) => {
|
Some(TaggedValue::LegacyFill(old_fill)) => {
|
||||||
let exposed = old_inputs[1].is_exposed();
|
let exposed = old_inputs[1].is_exposed();
|
||||||
let fill_value = match old_fill {
|
let fill_value = match old_fill {
|
||||||
graphic_types::migrations::legacy::Fill::None => TaggedValue::Color(None),
|
graphic_types::migrations::legacy::LegacyFill::None => TaggedValue::Color(None),
|
||||||
graphic_types::migrations::legacy::Fill::Solid(color) => TaggedValue::Color(Some(*color)),
|
graphic_types::migrations::legacy::LegacyFill::Solid(color) => TaggedValue::Color(Some(*color)),
|
||||||
graphic_types::migrations::legacy::Fill::Gradient(gradient) => TaggedValue::Gradient(gradient.stops.clone()),
|
graphic_types::migrations::legacy::LegacyFill::Gradient(gradient) => TaggedValue::Gradient(gradient.stops.clone()),
|
||||||
};
|
};
|
||||||
document
|
document
|
||||||
.network_interface
|
.network_interface
|
||||||
.set_input(&InputConnector::node(*node_id, 1), NodeInput::value(fill_value, exposed), network_path);
|
.set_input(&InputConnector::node(*node_id, 1), NodeInput::value(fill_value, exposed), network_path);
|
||||||
|
|
||||||
// Gradient metadata (4, 5, 6): applies only to a literal gradient, solids/none keep the template defaults
|
// Gradient metadata (4, 5, 6): applies only to a literal gradient, solids/none keep the template defaults
|
||||||
if let graphic_types::migrations::legacy::Fill::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(*node_id, 4),
|
&InputConnector::node(*node_id, 4),
|
||||||
NodeInput::value(TaggedValue::GradientType(gradient.gradient_type), false),
|
NodeInput::value(TaggedValue::GradientType(gradient.gradient_type), false),
|
||||||
@@ -1661,7 +1664,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Wired/exposed fill keeps the connection.
|
// Wired/exposed fill keeps the connection.
|
||||||
// The generic paint connector accepts the existing `List<Color>`/`List<GradientStops>` paint sources directly.
|
// The generic paint connector accepts the existing `List<Color>`/`List<Gradient>` paint sources directly.
|
||||||
_ => {
|
_ => {
|
||||||
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
|
document.network_interface.set_input(&InputConnector::node(*node_id, 1), old_inputs[1].clone(), network_path);
|
||||||
}
|
}
|
||||||
@@ -1680,7 +1683,7 @@ fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId],
|
|||||||
if matches!(
|
if matches!(
|
||||||
old_inputs[1].as_value(),
|
old_inputs[1].as_value(),
|
||||||
Some(TaggedValue::LegacyFill(
|
Some(TaggedValue::LegacyFill(
|
||||||
graphic_types::migrations::legacy::Fill::None | graphic_types::migrations::legacy::Fill::Solid(_)
|
graphic_types::migrations::legacy::LegacyFill::None | graphic_types::migrations::legacy::LegacyFill::Solid(_)
|
||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
document
|
document
|
||||||
|
|||||||
@@ -15,7 +15,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::{GradientSpreadMethod, GradientStops, GradientType, PointId, SegmentId, VectorModificationType};
|
use graphene_std::vector::{Gradient, GradientSpreadMethod, GradientType, PointId, SegmentId, VectorModificationType};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
/// Returns the ID of the first Spline node in the horizontal flow which is not followed by a `Path` node, or `None` if none exists.
|
/// Returns the ID of the first Spline node in the horizontal flow which is not followed by a `Path` node, or `None` if none exists.
|
||||||
@@ -309,7 +309,7 @@ pub fn get_fill_input_node_id(layer: LayerNodeIdentifier, network_interface: &No
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the gradient stops of a layer, if any.
|
/// Get the gradient stops of a layer, if any.
|
||||||
pub fn get_gradient_stops(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<GradientStops> {
|
pub fn get_gradient_stops(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<Gradient> {
|
||||||
// Try to find the gradient stops value that is created by a Fill node first
|
// Try to find the gradient stops value that is created by a Fill node first
|
||||||
if let Some(fill_node_id) = get_fill_node_id_with_direct_fill_input(layer, network_interface) {
|
if let Some(fill_node_id) = get_fill_node_id_with_direct_fill_input(layer, network_interface) {
|
||||||
return network_interface
|
return network_interface
|
||||||
@@ -328,7 +328,7 @@ pub fn get_gradient_stops(layer: LayerNodeIdentifier, network_interface: &NodeNe
|
|||||||
Some(stops.clone())
|
Some(stops.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Compute the transform from a gradient's local space to viewport space for the given layer. For a `List<GradientStops>`
|
/// Compute the transform from a gradient's local space to viewport space for the given layer. For a `List<Gradient>`
|
||||||
/// layer this is the layer's incoming footprint transform; for a Fill-owned gradient value it composes the layer's viewport
|
/// layer this is the layer's incoming footprint transform; for a Fill-owned gradient value it composes the layer's viewport
|
||||||
/// transform with the [0,1]² → bounding-box mapping.
|
/// transform with the [0,1]² → bounding-box mapping.
|
||||||
pub fn gradient_space_transform(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> glam::DAffine2 {
|
pub fn gradient_space_transform(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> glam::DAffine2 {
|
||||||
@@ -625,7 +625,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: GradientStops,
|
pub stops: Gradient,
|
||||||
pub gradient_type: GradientType,
|
pub gradient_type: GradientType,
|
||||||
pub spread_method: GradientSpreadMethod,
|
pub spread_method: GradientSpreadMethod,
|
||||||
pub transform: DAffine2,
|
pub transform: DAffine2,
|
||||||
|
|||||||
@@ -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, FillChoiceUI, GradientSpreadMethod, GradientStop, GradientStops, GradientStopsUI, GradientType, build_transform_with_y_preservation};
|
use graphene_std::vector::style::{FillChoice, FillChoiceUI, Gradient, GradientSpreadMethod, GradientStop, GradientType, GradientUI, build_transform_with_y_preservation};
|
||||||
|
|
||||||
#[derive(Default, ExtractField)]
|
#[derive(Default, ExtractField)]
|
||||||
pub struct GradientTool {
|
pub struct GradientTool {
|
||||||
@@ -53,7 +53,7 @@ pub enum GradientToolMessage {
|
|||||||
CommitTransactionForColorStop,
|
CommitTransactionForColorStop,
|
||||||
CloseStopColorPicker,
|
CloseStopColorPicker,
|
||||||
UpdateStopColor { color: Color },
|
UpdateStopColor { color: Color },
|
||||||
UpdateStops { stops: GradientStopsUI },
|
UpdateStops { stops: GradientUI },
|
||||||
UpdateOptions { options: GradientOptionsUpdate },
|
UpdateOptions { options: GradientOptionsUpdate },
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ impl<'a> MessageHandler<ToolMessage, &mut ToolActionMessageContext<'a>> for Grad
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ToolMessage::Gradient(GradientToolMessage::UpdateStops { stops }) => {
|
ToolMessage::Gradient(GradientToolMessage::UpdateStops { stops }) => {
|
||||||
apply_stops_update(&mut self.data, context, responses, GradientStops::from(&stops));
|
apply_stops_update(&mut self.data, context, responses, Gradient::from(&stops));
|
||||||
}
|
}
|
||||||
ToolMessage::Gradient(GradientToolMessage::CloseStopColorPicker) => {
|
ToolMessage::Gradient(GradientToolMessage::CloseStopColorPicker) => {
|
||||||
if self.data.color_picker_transaction_open {
|
if self.data.color_picker_transaction_open {
|
||||||
@@ -264,7 +264,7 @@ impl LayoutHolder for GradientTool {
|
|||||||
.or_else(|| self.data.default_gradient_stops.clone())
|
.or_else(|| self.data.default_gradient_stops.clone())
|
||||||
.map(FillChoice::Gradient)
|
.map(FillChoice::Gradient)
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
FillChoice::Gradient(GradientStops::new([
|
FillChoice::Gradient(Gradient::new([
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
@@ -389,7 +389,7 @@ enum GradientSource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the gradient with appearance information from Fill node values, or the chain connected to Fill node / layer.
|
/// Get the gradient with appearance information from Fill node values, or the chain connected to Fill node / layer.
|
||||||
fn resolve_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<(GradientStops, GradientAppearance, GradientSource)> {
|
fn resolve_gradient(layer: LayerNodeIdentifier, network_interface: &NodeNetworkInterface) -> Option<(Gradient, GradientAppearance, GradientSource)> {
|
||||||
if let Some(stops) = get_gradient_stops(layer, network_interface) {
|
if let Some(stops) = get_gradient_stops(layer, network_interface) {
|
||||||
// A Fill node holding a direct gradient value decodes through the shared reader
|
// A Fill node holding a direct gradient value decodes through the shared reader
|
||||||
if let Some(fill_id) = get_fill_node_id_with_direct_fill_input(layer, network_interface) {
|
if let Some(fill_id) = get_fill_node_id_with_direct_fill_input(layer, network_interface) {
|
||||||
@@ -521,15 +521,15 @@ struct SelectedGradient {
|
|||||||
dragging: GradientDragTarget,
|
dragging: GradientDragTarget,
|
||||||
/// Transform from the geometry's local gradient space to viewport space.
|
/// Transform from the geometry's local gradient space to viewport space.
|
||||||
gradient_space_transform: DAffine2,
|
gradient_space_transform: DAffine2,
|
||||||
gradient: GradientStops,
|
gradient: Gradient,
|
||||||
appearance: GradientAppearance,
|
appearance: GradientAppearance,
|
||||||
initial_gradient: GradientStops,
|
initial_gradient: Gradient,
|
||||||
/// Transform from unit [0, 1] line to the geometry's local gradient space, the snapshot from `GradientAppearance.transform`.
|
/// Transform from unit [0, 1] line to the geometry's local gradient space, the snapshot from `GradientAppearance.transform`.
|
||||||
initial_gradient_transform: DAffine2,
|
initial_gradient_transform: DAffine2,
|
||||||
is_gradient_chain: bool,
|
is_gradient_chain: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_insertion(start: DVec2, end: DVec2, stops: &GradientStops, mouse: DVec2) -> Option<f64> {
|
fn calculate_insertion(start: DVec2, end: DVec2, stops: &Gradient, mouse: DVec2) -> Option<f64> {
|
||||||
let distance = (end - start).angle_to(mouse - start).sin() * (mouse - start).length();
|
let distance = (end - start).angle_to(mouse - start).sin() * (mouse - start).length();
|
||||||
let projection = ((end - start).angle_to(mouse - start)).cos() * start.distance(mouse) / start.distance(end);
|
let projection = ((end - start).angle_to(mouse - start)).cos() * start.distance(mouse) / start.distance(end);
|
||||||
|
|
||||||
@@ -568,7 +568,7 @@ fn calculate_insertion(start: DVec2, end: DVec2, stops: &GradientStops, mouse: D
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SelectedGradient {
|
impl SelectedGradient {
|
||||||
pub fn new(gradient: GradientStops, appearance: GradientAppearance, source: GradientSource, layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> Self {
|
pub fn new(gradient: Gradient, appearance: GradientAppearance, source: GradientSource, layer: LayerNodeIdentifier, document: &DocumentMessageHandler) -> Self {
|
||||||
let gradient_space_transform = gradient_space_transform(layer, document);
|
let gradient_space_transform = gradient_space_transform(layer, document);
|
||||||
Self {
|
Self {
|
||||||
layer: Some(layer),
|
layer: Some(layer),
|
||||||
@@ -820,7 +820,7 @@ impl SelectedGradient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Send the four per-attribute graph operations that mirror the in-memory `Gradient` onto the chain feeding the layer.
|
/// Send the four per-attribute graph operations that mirror the in-memory `Gradient` onto the chain feeding the layer.
|
||||||
fn dispatch_gradient_chain_writes(layer: LayerNodeIdentifier, gradient: &GradientStops, appearance: GradientAppearance, responses: &mut VecDeque<Message>) {
|
fn dispatch_gradient_chain_writes(layer: LayerNodeIdentifier, gradient: &Gradient, appearance: GradientAppearance, responses: &mut VecDeque<Message>) {
|
||||||
responses.add(GraphOperationMessage::GradientStopsSet { layer, stops: gradient.clone() });
|
responses.add(GraphOperationMessage::GradientStopsSet { layer, stops: gradient.clone() });
|
||||||
responses.add(GraphOperationMessage::GradientTransformSet {
|
responses.add(GraphOperationMessage::GradientTransformSet {
|
||||||
layer,
|
layer,
|
||||||
@@ -868,11 +868,11 @@ struct GradientToolData {
|
|||||||
has_selected_gradient: bool,
|
has_selected_gradient: bool,
|
||||||
/// Cached stops of the currently selected layer's gradient, mirrored into the control-bar widget.
|
/// Cached stops of the currently selected layer's gradient, mirrored into the control-bar widget.
|
||||||
/// Independent of any in-progress drag (which uses `selected_gradient`) so it stays current after selection changes too.
|
/// Independent of any in-progress drag (which uses `selected_gradient`) so it stays current after selection changes too.
|
||||||
current_gradient_stops: Option<GradientStops>,
|
current_gradient_stops: Option<Gradient>,
|
||||||
/// User-customized default gradient stop colors: used when nothing that has a gradient is selected.
|
/// User-customized default gradient stop colors: used when nothing that has a gradient is selected.
|
||||||
/// `None` means to follow the working colors.
|
/// `None` means to follow the working colors.
|
||||||
/// Cleared on tool deactivation so each fresh activation starts from the working colors again.
|
/// Cleared on tool deactivation so each fresh activation starts from the working colors again.
|
||||||
default_gradient_stops: Option<GradientStops>,
|
default_gradient_stops: Option<Gradient>,
|
||||||
/// Cached viewport-space orientation (true = predominantly rightward) of the selected gradient line.
|
/// Cached viewport-space orientation (true = predominantly rightward) of the selected gradient line.
|
||||||
/// Used to refresh the control bar's "Reverse Direction" icon only when the line's apparent direction flips.
|
/// Used to refresh the control bar's "Reverse Direction" icon only when the line's apparent direction flips.
|
||||||
gradient_orientation_rightward: bool,
|
gradient_orientation_rightward: bool,
|
||||||
@@ -1496,7 +1496,7 @@ impl Fsm for GradientToolFsmState {
|
|||||||
// Generate a new gradient running primary → secondary so the default working colors
|
// Generate a new gradient running primary → secondary so the default working colors
|
||||||
// (primary = black, secondary = white) produce the expected black-to-white gradient
|
// (primary = black, secondary = white) produce the expected black-to-white gradient
|
||||||
None => (
|
None => (
|
||||||
GradientStops::new([
|
Gradient::new([
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
@@ -1738,7 +1738,7 @@ impl Fsm for GradientToolFsmState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_stop_at_point(gradient: &mut GradientStops, point: DVec2, unit_to_viewport: DAffine2) -> Option<usize> {
|
fn insert_stop_at_point(gradient: &mut Gradient, point: DVec2, unit_to_viewport: DAffine2) -> Option<usize> {
|
||||||
let (start, end) = gradient_handle_positions(unit_to_viewport);
|
let (start, end) = gradient_handle_positions(unit_to_viewport);
|
||||||
let t = ((end - start).angle_to(point - start)).cos() * start.distance(point) / start.distance(end);
|
let t = ((end - start).angle_to(point - start)).cos() * start.distance(point) / start.distance(end);
|
||||||
(0. ..=1.).contains(&t).then(|| gradient.insert_stop(t))
|
(0. ..=1.).contains(&t).then(|| gradient.insert_stop(t))
|
||||||
@@ -1831,8 +1831,8 @@ fn apply_gradient_update(
|
|||||||
data: &mut GradientToolData,
|
data: &mut GradientToolData,
|
||||||
context: &mut ToolActionMessageContext,
|
context: &mut ToolActionMessageContext,
|
||||||
responses: &mut VecDeque<Message>,
|
responses: &mut VecDeque<Message>,
|
||||||
condition: impl Fn((&GradientStops, &GradientAppearance)) -> bool,
|
condition: impl Fn((&Gradient, &GradientAppearance)) -> bool,
|
||||||
update: impl Fn((&mut GradientStops, &mut GradientAppearance)),
|
update: impl Fn((&mut Gradient, &mut GradientAppearance)),
|
||||||
) {
|
) {
|
||||||
let selected_layers: Vec<_> = context
|
let selected_layers: Vec<_> = context
|
||||||
.document
|
.document
|
||||||
@@ -1888,7 +1888,7 @@ fn apply_gradient_update(
|
|||||||
/// Set new gradient stops on every selected layer's gradient. Unlike `apply_gradient_update`, this doesn't open its own
|
/// Set new gradient stops on every selected layer's gradient. Unlike `apply_gradient_update`, this doesn't open its own
|
||||||
/// transaction so it can be called repeatedly during a color picker drag and have all the changes coalesced into a
|
/// transaction so it can be called repeatedly during a color picker drag and have all the changes coalesced into a
|
||||||
/// single undo entry by the surrounding 'on_commit' callback.
|
/// single undo entry by the surrounding 'on_commit' callback.
|
||||||
fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessageContext, responses: &mut VecDeque<Message>, new_gradient: GradientStops) {
|
fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessageContext, responses: &mut VecDeque<Message>, new_gradient: Gradient) {
|
||||||
let selected_layers: Vec<_> = context
|
let selected_layers: Vec<_> = context
|
||||||
.document
|
.document
|
||||||
.network_interface
|
.network_interface
|
||||||
@@ -1933,7 +1933,7 @@ fn apply_stops_update(data: &mut GradientToolData, context: &mut ToolActionMessa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Find the first selected visible layer that has a gradient and return both the layer ID and its resolved gradient.
|
/// Find the first selected visible layer that has a gradient and return both the layer ID and its resolved gradient.
|
||||||
fn current_layer_and_gradient(document: &DocumentMessageHandler) -> (Option<LayerNodeIdentifier>, Option<(GradientStops, GradientAppearance)>) {
|
fn current_layer_and_gradient(document: &DocumentMessageHandler) -> (Option<LayerNodeIdentifier>, Option<(Gradient, GradientAppearance)>) {
|
||||||
for layer in document.network_interface.selected_nodes().selected_visible_layers(&document.network_interface) {
|
for layer in document.network_interface.selected_nodes().selected_visible_layers(&document.network_interface) {
|
||||||
if let Some((gradient, appearance, _source)) = resolve_gradient(layer, &document.network_interface) {
|
if let Some((gradient, appearance, _source)) = resolve_gradient(layer, &document.network_interface) {
|
||||||
return (Some(layer), Some((gradient, appearance)));
|
return (Some(layer), Some((gradient, appearance)));
|
||||||
@@ -1942,7 +1942,7 @@ fn current_layer_and_gradient(document: &DocumentMessageHandler) -> (Option<Laye
|
|||||||
(None, None)
|
(None, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_gradient_on_selected_layer(document: &DocumentMessageHandler) -> Option<(GradientStops, GradientAppearance, GradientSource)> {
|
fn get_gradient_on_selected_layer(document: &DocumentMessageHandler) -> Option<(Gradient, GradientAppearance, GradientSource)> {
|
||||||
document
|
document
|
||||||
.network_interface
|
.network_interface
|
||||||
.selected_nodes()
|
.selected_nodes()
|
||||||
@@ -2015,18 +2015,18 @@ mod test_gradient {
|
|||||||
use graphene_std::NodeInputDecleration;
|
use graphene_std::NodeInputDecleration;
|
||||||
use graphene_std::color::SRGBA8;
|
use graphene_std::color::SRGBA8;
|
||||||
use graphene_std::vector::style::{GradientSpreadMethod, build_transform_with_y_preservation};
|
use graphene_std::vector::style::{GradientSpreadMethod, build_transform_with_y_preservation};
|
||||||
use graphene_std::vector::{GradientStop, GradientStops, fill};
|
use graphene_std::vector::{Gradient, GradientStop, fill};
|
||||||
|
|
||||||
use super::gradient_space_transform;
|
use super::gradient_space_transform;
|
||||||
|
|
||||||
struct ResolvedGradient {
|
struct ResolvedGradient {
|
||||||
stops: GradientStops,
|
stops: Gradient,
|
||||||
spread_method: GradientSpreadMethod,
|
spread_method: GradientSpreadMethod,
|
||||||
transform: DAffine2,
|
transform: DAffine2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResolvedGradient {
|
impl ResolvedGradient {
|
||||||
fn new(stops: GradientStops, appearance: super::GradientAppearance) -> Self {
|
fn new(stops: Gradient, appearance: super::GradientAppearance) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stops,
|
stops,
|
||||||
spread_method: appearance.spread_method,
|
spread_method: appearance.spread_method,
|
||||||
@@ -2146,7 +2146,7 @@ mod test_gradient {
|
|||||||
.handle_message(NodeGraphMessage::SetInputValue {
|
.handle_message(NodeGraphMessage::SetInputValue {
|
||||||
node_id: gradient_node_id,
|
node_id: gradient_node_id,
|
||||||
input_index: 1,
|
input_index: 1,
|
||||||
value: Box::new(TaggedValue::Gradient(GradientStops::new([
|
value: Box::new(TaggedValue::Gradient(Gradient::new([
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
@@ -2183,7 +2183,7 @@ mod test_gradient {
|
|||||||
.handle_message(NodeGraphMessage::SetInputValue {
|
.handle_message(NodeGraphMessage::SetInputValue {
|
||||||
node_id: gradient_node_id,
|
node_id: gradient_node_id,
|
||||||
input_index: 1,
|
input_index: 1,
|
||||||
value: Box::new(TaggedValue::Gradient(GradientStops::new([
|
value: Box::new(TaggedValue::Gradient(Gradient::new([
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
@@ -2654,7 +2654,7 @@ mod test_gradient {
|
|||||||
// Create original transform for the control geometry and apply it
|
// Create original transform for the control geometry and apply it
|
||||||
let initial_start = DVec2::new(10., 50.);
|
let initial_start = DVec2::new(10., 50.);
|
||||||
let initial_end = DVec2::new(200., 50.);
|
let initial_end = DVec2::new(200., 50.);
|
||||||
let stops = GradientStops::new([
|
let stops = Gradient::new([
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
@@ -2725,7 +2725,7 @@ mod test_gradient {
|
|||||||
let layer = create_gradient_list_layer(&mut editor).await;
|
let layer = create_gradient_list_layer(&mut editor).await;
|
||||||
|
|
||||||
// Set up a 3-stop gradient with distinct colors
|
// Set up a 3-stop gradient with distinct colors
|
||||||
let original_stops = GradientStops::new([
|
let original_stops = Gradient::new([
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
@@ -2826,7 +2826,7 @@ mod test_gradient {
|
|||||||
.handle_message(NodeGraphMessage::SetInputValue {
|
.handle_message(NodeGraphMessage::SetInputValue {
|
||||||
node_id: gradient_value_id,
|
node_id: gradient_value_id,
|
||||||
input_index: 1,
|
input_index: 1,
|
||||||
value: Box::new(TaggedValue::Gradient(GradientStops::new([
|
value: Box::new(TaggedValue::Gradient(Gradient::new([
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ struct ExecutionContext {
|
|||||||
/// Set when this execution is a gradient-migration measurement run, carrying the "Fill" node (addressed by its enclosing
|
/// Set when this execution is a gradient-migration measurement run, carrying the "Fill" node (addressed by its enclosing
|
||||||
/// network path) and its original relative gradient. The evaluated geometry is read back from the inspect result to size the
|
/// network path) and its original relative gradient. The evaluated geometry is read back from the inspect result to size the
|
||||||
/// gradient; such runs never touch the visible artwork. Carrying the entry keeps a stale re-dispatched response paired with the fill it measured.
|
/// gradient; such runs never touch the visible artwork. Carrying the entry keeps a stale re-dispatched response paired with the fill it measured.
|
||||||
measure_fill: Option<(Vec<NodeId>, NodeId, graphic_types::migrations::legacy::Gradient)>,
|
measure_fill: Option<(Vec<NodeId>, NodeId, graphic_types::migrations::legacy::LegacyGradient)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Eventually remove this document upgrade code
|
// TODO: Eventually remove this document upgrade code
|
||||||
@@ -94,7 +94,7 @@ struct ExecutionContext {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct GradientMigration {
|
struct GradientMigration {
|
||||||
document_id: DocumentId,
|
document_id: DocumentId,
|
||||||
remaining: VecDeque<(Vec<NodeId>, NodeId, graphic_types::migrations::legacy::Gradient)>,
|
remaining: VecDeque<(Vec<NodeId>, NodeId, graphic_types::migrations::legacy::LegacyGradient)>,
|
||||||
resolution: UVec2,
|
resolution: UVec2,
|
||||||
scale: f64,
|
scale: f64,
|
||||||
}
|
}
|
||||||
@@ -507,7 +507,7 @@ impl NodeGraphExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Snapshot the queue but leave `pending_gradient_bbox_bake` populated, so subsequent render requests keep deferring here (and hit the guard above); each entry is removed from the document as its bake lands.
|
// Snapshot the queue but leave `pending_gradient_bbox_bake` populated, so subsequent render requests keep deferring here (and hit the guard above); each entry is removed from the document as its bake lands.
|
||||||
let remaining: VecDeque<(Vec<NodeId>, NodeId, graphic_types::migrations::legacy::Gradient)> = document.pending_gradient_bbox_bake.iter().cloned().collect();
|
let remaining: VecDeque<(Vec<NodeId>, NodeId, graphic_types::migrations::legacy::LegacyGradient)> = document.pending_gradient_bbox_bake.iter().cloned().collect();
|
||||||
let Some((first_network_path, first_fill, first_gradient)) = remaining.front().cloned() else {
|
let Some((first_network_path, first_fill, first_gradient)) = remaining.front().cloned() else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
@@ -534,7 +534,7 @@ impl NodeGraphExecutor {
|
|||||||
document_id: DocumentId,
|
document_id: DocumentId,
|
||||||
network_path: Vec<NodeId>,
|
network_path: Vec<NodeId>,
|
||||||
fill_node_id: NodeId,
|
fill_node_id: NodeId,
|
||||||
gradient: graphic_types::migrations::legacy::Gradient,
|
gradient: graphic_types::migrations::legacy::LegacyGradient,
|
||||||
resolution: UVec2,
|
resolution: UVec2,
|
||||||
scale: f64,
|
scale: f64,
|
||||||
responses: &mut VecDeque<Message>,
|
responses: &mut VecDeque<Message>,
|
||||||
@@ -603,7 +603,7 @@ impl NodeGraphExecutor {
|
|||||||
&mut self,
|
&mut self,
|
||||||
document: &mut DocumentMessageHandler,
|
document: &mut DocumentMessageHandler,
|
||||||
document_id: DocumentId,
|
document_id: DocumentId,
|
||||||
bake_target: (Vec<NodeId>, NodeId, graphic_types::migrations::legacy::Gradient),
|
bake_target: (Vec<NodeId>, NodeId, graphic_types::migrations::legacy::LegacyGradient),
|
||||||
inspect_result: Option<InspectResult>,
|
inspect_result: Option<InspectResult>,
|
||||||
responses: &mut VecDeque<Message>,
|
responses: &mut VecDeque<Message>,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
import ColorPicker from "/src/components/floating-menus/ColorPicker.svelte";
|
import ColorPicker from "/src/components/floating-menus/ColorPicker.svelte";
|
||||||
import LayoutCol from "/src/components/layout/LayoutCol.svelte";
|
import LayoutCol from "/src/components/layout/LayoutCol.svelte";
|
||||||
import { contrastingOutlineFactor, fillChoiceUIColor, fillChoiceUIGradientStops } from "/src/utility-functions/colors";
|
import { contrastingOutlineFactor, fillChoiceUIColor, fillChoiceUIGradient } from "/src/utility-functions/colors";
|
||||||
import type { FillChoiceUI, MenuDirection, ActionShortcut } from "/wrapper/pkg/graphite_wasm_wrapper";
|
import type { FillChoiceUI, MenuDirection, ActionShortcut } from "/wrapper/pkg/graphite_wasm_wrapper";
|
||||||
|
|
||||||
const dispatch = createEventDispatcher<{ value: FillChoiceUI; startHistoryTransaction: undefined }>();
|
const dispatch = createEventDispatcher<{ value: FillChoiceUI; startHistoryTransaction: undefined }>();
|
||||||
@@ -29,10 +29,10 @@
|
|||||||
|
|
||||||
$: outlineFactor = contrastingOutlineFactor(value, "--color-3-darkgray", 0.01);
|
$: outlineFactor = contrastingOutlineFactor(value, "--color-3-darkgray", 0.01);
|
||||||
$: outlined = outlineFactor > 0.0001;
|
$: outlined = outlineFactor > 0.0001;
|
||||||
$: gradientStops = fillChoiceUIGradientStops(value);
|
$: gradient = fillChoiceUIGradient(value);
|
||||||
$: solidColor = fillChoiceUIColor(value);
|
$: solidColor = fillChoiceUIColor(value);
|
||||||
$: none = value === "None";
|
$: none = value === "None";
|
||||||
$: transparency = gradientStops ? gradientStops.color.some((color) => color.alpha < 255) : solidColor ? solidColor.alpha < 255 : false;
|
$: transparency = gradient ? gradient.color.some((color) => color.alpha < 255) : solidColor ? solidColor.alpha < 255 : false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<LayoutCol
|
<LayoutCol
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { FillChoiceUI, GradientStopsUI, SRGBA8 } from "/wrapper/pkg/graphite_wasm_wrapper";
|
import type { FillChoiceUI, GradientUI, SRGBA8 } from "/wrapper/pkg/graphite_wasm_wrapper";
|
||||||
|
|
||||||
// Channels can have any range (0-1, 0-255, 0-100, 0-360) in the context they are being used in, these are just containers for the numbers
|
// Channels can have any range (0-1, 0-255, 0-100, 0-360) in the context they are being used in, these are just containers for the numbers
|
||||||
export type HSV = { h: number; s: number; v: number };
|
export type HSV = { h: number; s: number; v: number };
|
||||||
@@ -167,12 +167,12 @@ export function contrastingOutlineFactor(value: FillChoiceUI, proximityColor: st
|
|||||||
return (1 - Math.min(distance / proximityRange, 1)) * (1 - sRgba8ToHSV(color).s);
|
return (1 - Math.min(distance / proximityRange, 1)) * (1 - sRgba8ToHSV(color).s);
|
||||||
};
|
};
|
||||||
|
|
||||||
const gradientStops = fillChoiceUIGradientStops(value);
|
const gradient = fillChoiceUIGradient(value);
|
||||||
if (gradientStops) {
|
if (gradient) {
|
||||||
if (gradientStops.color.length === 0) return 0;
|
if (gradient.color.length === 0) return 0;
|
||||||
|
|
||||||
const first = contrast(gradientStops.color[0]);
|
const first = contrast(gradient.color[0]);
|
||||||
const last = contrast(gradientStops.color[gradientStops.color.length - 1]);
|
const last = contrast(gradient.color[gradient.color.length - 1]);
|
||||||
|
|
||||||
return Math.min(first, last);
|
return Math.min(first, last);
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ export function contrastingOutlineFactor(value: FillChoiceUI, proximityColor: st
|
|||||||
|
|
||||||
// GRADIENT UTILITY FUNCTIONS
|
// GRADIENT UTILITY FUNCTIONS
|
||||||
|
|
||||||
export function isGradientStopsUI(value: unknown): value is GradientStopsUI {
|
export function isGradientUI(value: unknown): value is GradientUI {
|
||||||
return typeof value === "object" && value !== null && "position" in value && "midpoint" in value && "color" in value;
|
return typeof value === "object" && value !== null && "position" in value && "midpoint" in value && "color" in value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,7 +193,7 @@ export function fillChoiceUIColor(value: FillChoiceUI): SRGBA8 | undefined {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fillChoiceUIGradientStops(value: FillChoiceUI): GradientStopsUI | undefined {
|
export function fillChoiceUIGradient(value: FillChoiceUI): GradientUI | undefined {
|
||||||
if (typeof value === "object" && "Gradient" in value) return value.Gradient;
|
if (typeof value === "object" && "Gradient" in value) return value.Gradient;
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -201,6 +201,6 @@ export function fillChoiceUIGradientStops(value: FillChoiceUI): GradientStopsUI
|
|||||||
export function parseFillChoiceUI(value: unknown): FillChoiceUI {
|
export function parseFillChoiceUI(value: unknown): FillChoiceUI {
|
||||||
if (value === "None" || value === undefined || value === null) return "None";
|
if (value === "None" || value === undefined || value === null) return "None";
|
||||||
if (typeof value === "object" && value !== null && "Solid" in value && isSRgba8(value.Solid)) return { Solid: value.Solid };
|
if (typeof value === "object" && value !== null && "Solid" in value && isSRgba8(value.Solid)) return { Solid: value.Solid };
|
||||||
if (typeof value === "object" && value !== null && "Gradient" in value && isGradientStopsUI(value.Gradient)) return { Gradient: value.Gradient };
|
if (typeof value === "object" && value !== null && "Gradient" in value && isGradientUI(value.Gradient)) return { Gradient: value.Gradient };
|
||||||
return "None";
|
return "None";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ pub use dyn_any::StaticType;
|
|||||||
pub use glam::{DAffine2, DVec2, IVec2, UVec2};
|
pub use glam::{DAffine2, DVec2, IVec2, UVec2};
|
||||||
use graphene_application_io::resource::ResourceHash;
|
use graphene_application_io::resource::ResourceHash;
|
||||||
use graphic_types::raster_types::{CPU, Image, Raster};
|
use graphic_types::raster_types::{CPU, Image, Raster};
|
||||||
use graphic_types::vector_types::vector::style::GradientStops;
|
use graphic_types::vector_types::vector::style::Gradient;
|
||||||
use graphic_types::vector_types::vector::{self, ReferencePoint};
|
use graphic_types::vector_types::vector::{self, ReferencePoint};
|
||||||
use graphic_types::{Artboard, Graphic, Vector};
|
use graphic_types::{Artboard, Graphic, Vector};
|
||||||
use rendering::RenderMetadata;
|
use rendering::RenderMetadata;
|
||||||
@@ -67,11 +67,11 @@ macro_rules! tagged_value {
|
|||||||
#[serde(deserialize_with = "core_types::misc::migrate_to_optional_color")] // TODO: Eventually remove this migration document upgrade code
|
#[serde(deserialize_with = "core_types::misc::migrate_to_optional_color")] // TODO: Eventually remove this migration document upgrade code
|
||||||
#[serde(alias = "ColorTable", alias = "OptionalColor", alias = "ColorNotInTable")]
|
#[serde(alias = "ColorTable", alias = "OptionalColor", alias = "ColorNotInTable")]
|
||||||
Color(Option<Color>),
|
Color(Option<Color>),
|
||||||
/// Stored compactly as a `GradientStops`, materializes as a single-row `List<GradientStops>` at runtime via `to_dynany`/`to_any`. Aliases recover legacy on-disk shapes.
|
/// Stored compactly as a `Gradient`, materializes as a single-row `List<Gradient>` at runtime via `to_dynany`/`to_any`. Aliases recover legacy on-disk shapes.
|
||||||
/// (Old documents that stored a full `Gradient` struct under this same `"Gradient"` tag are routed to `LegacyGradient` by `deserialize_tagged_value_with_legacy_migration`.)
|
/// (Old documents that stored a full `Gradient` struct under this same `"Gradient"` tag are routed to `LegacyGradient` by `deserialize_tagged_value_with_legacy_migration`.)
|
||||||
#[serde(deserialize_with = "graphic_types::vector_types::gradient::migrate_to_gradient_stops")] // TODO: Eventually remove this migration document upgrade code
|
#[serde(deserialize_with = "graphic_types::vector_types::gradient::migrate_to_gradient")] // TODO: Eventually remove this migration document upgrade code
|
||||||
#[serde(alias = "GradientTable", alias = "GradientPositions", alias = "GradientStops")]
|
#[serde(alias = "GradientTable", alias = "GradientPositions", alias = "GradientStops")]
|
||||||
Gradient(GradientStops),
|
Gradient(Gradient),
|
||||||
/// Stored compactly as a `Vec<BrushStroke>`, materializes as `List<BrushStroke>` at runtime via `to_dynany`/`to_any`. Aliases recover legacy on-disk shapes.
|
/// Stored compactly as a `Vec<BrushStroke>`, materializes as `List<BrushStroke>` at runtime via `to_dynany`/`to_any`. Aliases recover legacy on-disk shapes.
|
||||||
#[serde(deserialize_with = "brush_nodes::migrations::migrate_to_brush_strokes")] // TODO: Eventually remove this migration document upgrade code
|
#[serde(deserialize_with = "brush_nodes::migrations::migrate_to_brush_strokes")] // TODO: Eventually remove this migration document upgrade code
|
||||||
#[serde(alias = "BrushStrokeTable")]
|
#[serde(alias = "BrushStrokeTable")]
|
||||||
@@ -160,7 +160,7 @@ macro_rules! tagged_value {
|
|||||||
let list: List<Color> = color.into_iter().map(core_types::list::Item::new_from_element).collect();
|
let list: List<Color> = color.into_iter().map(core_types::list::Item::new_from_element).collect();
|
||||||
Box::new(list)
|
Box::new(list)
|
||||||
}
|
}
|
||||||
Self::Gradient(stops) => Box::new(List::<GradientStops>::new_from_element(stops)),
|
Self::Gradient(stops) => Box::new(List::<Gradient>::new_from_element(stops)),
|
||||||
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)
|
||||||
@@ -207,7 +207,7 @@ macro_rules! tagged_value {
|
|||||||
let list: List<Color> = color.into_iter().map(core_types::list::Item::new_from_element).collect();
|
let list: List<Color> = color.into_iter().map(core_types::list::Item::new_from_element).collect();
|
||||||
Arc::new(list)
|
Arc::new(list)
|
||||||
}
|
}
|
||||||
Self::Gradient(stops) => Arc::new(List::<GradientStops>::new_from_element(stops)),
|
Self::Gradient(stops) => Arc::new(List::<Gradient>::new_from_element(stops)),
|
||||||
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)
|
||||||
@@ -248,7 +248,7 @@ macro_rules! tagged_value {
|
|||||||
}
|
}
|
||||||
Self::F64Array(_) => concrete!(f64),
|
Self::F64Array(_) => concrete!(f64),
|
||||||
Self::Color(_) => concrete!(Color),
|
Self::Color(_) => concrete!(Color),
|
||||||
Self::Gradient(_) => concrete!(GradientStops),
|
Self::Gradient(_) => concrete!(Gradient),
|
||||||
Self::BrushStrokes(_) => concrete!(BrushStroke),
|
Self::BrushStrokes(_) => concrete!(BrushStroke),
|
||||||
// =======================
|
// =======================
|
||||||
// AUTO-GENERATED VARIANTS
|
// AUTO-GENERATED VARIANTS
|
||||||
@@ -297,7 +297,7 @@ macro_rules! tagged_value {
|
|||||||
}
|
}
|
||||||
Self::F64Array(_) => leveled::<f64>(),
|
Self::F64Array(_) => leveled::<f64>(),
|
||||||
Self::Color(_) => leveled::<Color>(),
|
Self::Color(_) => leveled::<Color>(),
|
||||||
Self::Gradient(_) => leveled::<GradientStops>(),
|
Self::Gradient(_) => leveled::<Gradient>(),
|
||||||
Self::BrushStrokes(_) => leveled::<BrushStroke>(),
|
Self::BrushStrokes(_) => leveled::<BrushStroke>(),
|
||||||
$( Self::$identifier(_) => scalar::<$ty>(), )*
|
$( Self::$identifier(_) => scalar::<$ty>(), )*
|
||||||
Self::RenderOutput(_) => scalar::<RenderOutput>(),
|
Self::RenderOutput(_) => scalar::<RenderOutput>(),
|
||||||
@@ -443,14 +443,14 @@ macro_rules! tagged_value {
|
|||||||
if name == core_types::normalize_type_name(std::any::type_name::<()>()) { return Some(TaggedValue::None) }
|
if name == core_types::normalize_type_name(std::any::type_name::<()>()) { return Some(TaggedValue::None) }
|
||||||
// List-wrapped types need a single-item default with the element's default, not an empty list
|
// List-wrapped types need a single-item default with the element's default, not an empty list
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<List<Color>>()) { return Some(TaggedValue::Color(Some(Color::default()))) }
|
if name == core_types::normalize_type_name(std::any::type_name::<List<Color>>()) { return Some(TaggedValue::Color(Some(Color::default()))) }
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<List<GradientStops>>()) { return Some(TaggedValue::Gradient(GradientStops::default())) }
|
if name == core_types::normalize_type_name(std::any::type_name::<List<Gradient>>()) { return Some(TaggedValue::Gradient(Gradient::default())) }
|
||||||
$( if name == core_types::normalize_type_name(std::any::type_name::<$ty>()) { return Some(TaggedValue::$identifier(Default::default())) } )*
|
$( if name == core_types::normalize_type_name(std::any::type_name::<$ty>()) { return Some(TaggedValue::$identifier(Default::default())) } )*
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<List<f64>>()) { return Some(TaggedValue::F64Array(Vec::new())) }
|
if name == core_types::normalize_type_name(std::any::type_name::<List<f64>>()) { return Some(TaggedValue::F64Array(Vec::new())) }
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<List<BrushStroke>>()) { return Some(TaggedValue::BrushStrokes(Vec::new())) }
|
if name == core_types::normalize_type_name(std::any::type_name::<List<BrushStroke>>()) { return Some(TaggedValue::BrushStrokes(Vec::new())) }
|
||||||
// Leveled inputs type by their element; each element name maps to the
|
// Leveled inputs type by their element; each element name maps to the
|
||||||
// same tagged default as its legacy list form.
|
// same tagged default as its legacy list form.
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<Color>()) { return Some(TaggedValue::Color(Some(Color::default()))) }
|
if name == core_types::normalize_type_name(std::any::type_name::<Color>()) { return Some(TaggedValue::Color(Some(Color::default()))) }
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<GradientStops>()) { return Some(TaggedValue::Gradient(GradientStops::default())) }
|
if name == core_types::normalize_type_name(std::any::type_name::<Gradient>()) { return Some(TaggedValue::Gradient(Gradient::default())) }
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<BrushStroke>()) { return Some(TaggedValue::BrushStrokes(Vec::new())) }
|
if name == core_types::normalize_type_name(std::any::type_name::<BrushStroke>()) { return Some(TaggedValue::BrushStrokes(Vec::new())) }
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<Graphic>()) { return Some(TaggedValue::TypeDefault(core_types::descriptor!(List<Graphic>))) }
|
if name == core_types::normalize_type_name(std::any::type_name::<Graphic>()) { return Some(TaggedValue::TypeDefault(core_types::descriptor!(List<Graphic>))) }
|
||||||
if name == core_types::normalize_type_name(std::any::type_name::<Artboard>()) { return Some(TaggedValue::TypeDefault(core_types::descriptor!(List<Artboard>))) }
|
if name == core_types::normalize_type_name(std::any::type_name::<Artboard>()) { return Some(TaggedValue::TypeDefault(core_types::descriptor!(List<Artboard>))) }
|
||||||
@@ -540,7 +540,7 @@ tagged_value! {
|
|||||||
DAffine2(DAffine2),
|
DAffine2(DAffine2),
|
||||||
OptionalDAffine2(Option<DAffine2>),
|
OptionalDAffine2(Option<DAffine2>),
|
||||||
#[serde(alias = "FillGradient")]
|
#[serde(alias = "FillGradient")]
|
||||||
LegacyGradient(graphic_types::migrations::legacy::Gradient),
|
LegacyGradient(graphic_types::migrations::legacy::LegacyGradient),
|
||||||
Font(Font),
|
Font(Font),
|
||||||
Footprint(Footprint),
|
Footprint(Footprint),
|
||||||
VectorModification(Box<VectorModification>),
|
VectorModification(Box<VectorModification>),
|
||||||
@@ -550,7 +550,7 @@ tagged_value! {
|
|||||||
// ENUM TYPES
|
// ENUM TYPES
|
||||||
// ==========
|
// ==========
|
||||||
#[serde(alias = "Fill")]
|
#[serde(alias = "Fill")]
|
||||||
LegacyFill(graphic_types::migrations::legacy::Fill),
|
LegacyFill(graphic_types::migrations::legacy::LegacyFill),
|
||||||
BlendMode(core_types::blending::BlendMode),
|
BlendMode(core_types::blending::BlendMode),
|
||||||
LuminanceCalculation(raster_nodes::adjustments::LuminanceCalculation),
|
LuminanceCalculation(raster_nodes::adjustments::LuminanceCalculation),
|
||||||
QRCodeErrorCorrectionLevel(vector_nodes::generator_nodes::QRCodeErrorCorrectionLevel),
|
QRCodeErrorCorrectionLevel(vector_nodes::generator_nodes::QRCodeErrorCorrectionLevel),
|
||||||
@@ -648,11 +648,11 @@ impl TaggedValue {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_gradient(input: &str) -> Option<GradientStops> {
|
fn to_gradient(input: &str) -> Option<Gradient> {
|
||||||
// String syntax: (e.g. "000000ff, ff0000ff")
|
// String syntax: (e.g. "000000ff, ff0000ff")
|
||||||
let stops = input.split(',').filter_map(|s| to_color(s.trim())).collect::<Vec<_>>();
|
let stops = input.split(',').filter_map(|s| to_color(s.trim())).collect::<Vec<_>>();
|
||||||
if stops.len() == 1 {
|
if stops.len() == 1 {
|
||||||
Some(GradientStops::new(vec![
|
Some(Gradient::new(vec![
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
@@ -666,7 +666,7 @@ impl TaggedValue {
|
|||||||
]))
|
]))
|
||||||
} else if stops.len() >= 2 {
|
} else if stops.len() >= 2 {
|
||||||
let step = 1. / (stops.len() - 1) as f64;
|
let step = 1. / (stops.len() - 1) as f64;
|
||||||
Some(GradientStops::new(stops.into_iter().enumerate().map(|(i, color)| GradientStop {
|
Some(Gradient::new(stops.into_iter().enumerate().map(|(i, color)| GradientStop {
|
||||||
position: i as f64 * step,
|
position: i as f64 * step,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
color,
|
color,
|
||||||
@@ -726,7 +726,7 @@ impl TaggedValue {
|
|||||||
() if ty == TypeId::of::<List<Color>>() => to_color(string).map(|color| TaggedValue::Color(Some(color)))?,
|
() if ty == TypeId::of::<List<Color>>() => to_color(string).map(|color| TaggedValue::Color(Some(color)))?,
|
||||||
// The Fill and Stroke nodes' paint connectors default to `List<Graphic>`, their first registered implementation row
|
// The Fill and Stroke nodes' paint connectors default to `List<Graphic>`, their first registered implementation row
|
||||||
() if ty == TypeId::of::<List<Graphic>>() => to_color(string).map(|color| TaggedValue::Color(Some(color)))?,
|
() if ty == TypeId::of::<List<Graphic>>() => to_color(string).map(|color| TaggedValue::Color(Some(color)))?,
|
||||||
() if ty == TypeId::of::<List<GradientStops>>() => to_gradient(string).map(TaggedValue::Gradient)?,
|
() if ty == TypeId::of::<List<Gradient>>() => to_gradient(string).map(TaggedValue::Gradient)?,
|
||||||
() if ty == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
|
() if ty == TypeId::of::<ReferencePoint>() => to_reference_point(string).map(TaggedValue::ReferencePoint)?,
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
@@ -794,10 +794,10 @@ pub fn deserialize_tagged_value_with_legacy_migration<'de, D: serde::Deserialize
|
|||||||
}
|
}
|
||||||
return Ok(MemoHash::new(TaggedValue::TypeDefault(descriptor!(List<Vector>))));
|
return Ok(MemoHash::new(TaggedValue::TypeDefault(descriptor!(List<Vector>))));
|
||||||
}
|
}
|
||||||
// The `Gradient` tag was reused: it used to carry a full `Gradient` struct (now `LegacyGradient`), and now carries an `Option<GradientStops>`.
|
// The `Gradient` tag was reused: it used to carry a full `Gradient` struct (now `LegacyGradient`), and now carries an `Option<Gradient>`.
|
||||||
// Disambiguate by payload shape: a Gradient struct has `start`/`end` keys; a `GradientStops` has none of those (it has `position`/`midpoint`/`color`).
|
// Disambiguate by payload shape: a Gradient struct has `start`/`end` keys; a `Gradient` has none of those (it has `position`/`midpoint`/`color`).
|
||||||
"Gradient" if content.as_object().is_some_and(|c| c.contains_key("start") && c.contains_key("end")) => {
|
"Gradient" if content.as_object().is_some_and(|c| c.contains_key("start") && c.contains_key("end")) => {
|
||||||
let gradient: graphic_types::migrations::legacy::Gradient = serde_json::from_value(content.clone()).map_err(serde::de::Error::custom)?;
|
let gradient: graphic_types::migrations::legacy::LegacyGradient = serde_json::from_value(content.clone()).map_err(serde::de::Error::custom)?;
|
||||||
return Ok(MemoHash::new(TaggedValue::LegacyGradient(gradient)));
|
return Ok(MemoHash::new(TaggedValue::LegacyGradient(gradient)));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, Vec<RegistryEntry>> {
|
|||||||
"List<Raster<CPU>>",
|
"List<Raster<CPU>>",
|
||||||
"List<Raster<GPU>>",
|
"List<Raster<GPU>>",
|
||||||
"List<Color>",
|
"List<Color>",
|
||||||
"List<GradientStops>",
|
"List<Gradient>",
|
||||||
"List<String>",
|
"List<String>",
|
||||||
])
|
])
|
||||||
.map(|(entry, target)| (ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::ConvertNode<{target}>")), entry)),
|
.map(|(entry, target)| (ProtoNodeIdentifier::with_owned_string(format!("graphene_core::ops::ConvertNode<{target}>")), entry)),
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ pub trait BoundingBox {
|
|||||||
/// Returns the bounding box to use when sizing this value's thumbnail in the Layers panel.
|
/// Returns the bounding box to use when sizing this value's thumbnail in the Layers panel.
|
||||||
///
|
///
|
||||||
/// Diverges from `bounding_box` for types where the rendering bounds wouldn't make a useful thumbnail frame.
|
/// Diverges from `bounding_box` for types where the rendering bounds wouldn't make a useful thumbnail frame.
|
||||||
/// For instance, `GradientStops` is `Infinite` for rendering but returns the line's AABB here, so a `List<Graphic>`
|
/// For instance, `Gradient` is `Infinite` for rendering but returns the line's AABB here, so a `List<Graphic>`
|
||||||
/// group of a gradient and a vector frames around the vector's geometry rather than infinity.
|
/// group of a gradient and a vector frames around the vector's geometry rather than infinity.
|
||||||
/// Types with no meaningful contribution (e.g., `Color`) return `Infinite` from both; the runtime substitutes a
|
/// Types with no meaningful contribution (e.g., `Color`) return `Infinite` from both; the runtime substitutes a
|
||||||
/// small fallback rectangle at the end if no finite bounds remain after combining.
|
/// small fallback rectangle at the end if no finite bounds remain after combining.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use core_types::node::Node;
|
|||||||
use core_types::record::{Group, GroupItem, LevelStatus, materialize_level};
|
use core_types::record::{Group, GroupItem, LevelStatus, materialize_level};
|
||||||
use core_types::uuid::NodeId;
|
use core_types::uuid::NodeId;
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use vector_types::GradientStops;
|
use vector_types::Gradient;
|
||||||
|
|
||||||
/// The outcome of materializing a leveled wire into a group.
|
/// The outcome of materializing a leveled wire into a group.
|
||||||
// The group is the render path's success payload; boxing it would add a heap allocation per materialized level.
|
// The group is the render path's success payload; boxing it would add a heap allocation per materialized level.
|
||||||
@@ -93,7 +93,7 @@ pub fn batch_to_legacy(layout: &core_types::record::Layout, batch: core_types::n
|
|||||||
.or_else(|| typed::<Raster<CPU>>(&item))
|
.or_else(|| typed::<Raster<CPU>>(&item))
|
||||||
.or_else(|| typed::<Raster<GPU>>(&item))
|
.or_else(|| typed::<Raster<GPU>>(&item))
|
||||||
.or_else(|| typed::<Color>(&item))
|
.or_else(|| typed::<Color>(&item))
|
||||||
.or_else(|| typed::<GradientStops>(&item))
|
.or_else(|| typed::<Gradient>(&item))
|
||||||
.or_else(|| typed::<String>(&item))
|
.or_else(|| typed::<String>(&item))
|
||||||
.or_else(|| typed::<f64>(&item))
|
.or_else(|| typed::<f64>(&item))
|
||||||
.or_else(|| typed::<u64>(&item))
|
.or_else(|| typed::<u64>(&item))
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use crate::markers::{ATTR_FILL, ATTR_STROKE};
|
|||||||
use core_types::Color;
|
use core_types::Color;
|
||||||
use core_types::list::{Item, List};
|
use core_types::list::{Item, List};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
use vector_types::{GradientStops, Vector};
|
use vector_types::{Gradient, Vector};
|
||||||
|
|
||||||
/// One typed run as an owned list, elements cloned and every attribute copied
|
/// One typed run as an owned list, elements cloned and every attribute copied
|
||||||
/// through its erased read. Content keeps its native form; the legacy
|
/// through its erased read. Content keeps its native form; the legacy
|
||||||
@@ -69,7 +69,7 @@ pub fn group_to_legacy_graphic(group: &core_types::record::Group) -> Graphic<'st
|
|||||||
.or_else(|| run_to_legacy_list::<Raster<CPU>>(item).map(|list| detable_items(list, Graphic::RasterCPU)))
|
.or_else(|| run_to_legacy_list::<Raster<CPU>>(item).map(|list| detable_items(list, Graphic::RasterCPU)))
|
||||||
.or_else(|| run_to_legacy_list::<Raster<GPU>>(item).map(|list| detable_items(list, Graphic::RasterGPU)))
|
.or_else(|| run_to_legacy_list::<Raster<GPU>>(item).map(|list| detable_items(list, Graphic::RasterGPU)))
|
||||||
.or_else(|| run_to_legacy_list::<Color>(item).map(|list| detable_items(list, Graphic::Color)))
|
.or_else(|| run_to_legacy_list::<Color>(item).map(|list| detable_items(list, Graphic::Color)))
|
||||||
.or_else(|| run_to_legacy_list::<GradientStops>(item).map(|list| detable_items(list, Graphic::Gradient)))
|
.or_else(|| run_to_legacy_list::<Gradient>(item).map(|list| detable_items(list, Graphic::Gradient)))
|
||||||
.or_else(|| run_to_legacy_list::<String>(item).map(|list| detable_items(list, Graphic::Text)));
|
.or_else(|| run_to_legacy_list::<String>(item).map(|list| detable_items(list, Graphic::Text)));
|
||||||
if let Some(typed) = typed {
|
if let Some(typed) = typed {
|
||||||
return Graphic::Graphic(typed);
|
return Graphic::Graphic(typed);
|
||||||
@@ -93,7 +93,7 @@ pub fn group_to_legacy_list(group: &core_types::record::Group) -> List<Graphic<'
|
|||||||
.or_else(|| run_to_legacy_list::<Raster<CPU>>(item).map(|list| detable_items(list, Graphic::RasterCPU)))
|
.or_else(|| run_to_legacy_list::<Raster<CPU>>(item).map(|list| detable_items(list, Graphic::RasterCPU)))
|
||||||
.or_else(|| run_to_legacy_list::<Raster<GPU>>(item).map(|list| detable_items(list, Graphic::RasterGPU)))
|
.or_else(|| run_to_legacy_list::<Raster<GPU>>(item).map(|list| detable_items(list, Graphic::RasterGPU)))
|
||||||
.or_else(|| run_to_legacy_list::<Color>(item).map(|list| detable_items(list, Graphic::Color)))
|
.or_else(|| run_to_legacy_list::<Color>(item).map(|list| detable_items(list, Graphic::Color)))
|
||||||
.or_else(|| run_to_legacy_list::<GradientStops>(item).map(|list| detable_items(list, Graphic::Gradient)))
|
.or_else(|| run_to_legacy_list::<Gradient>(item).map(|list| detable_items(list, Graphic::Gradient)))
|
||||||
.or_else(|| run_to_legacy_list::<String>(item).map(|list| detable_items(list, Graphic::Text)))
|
.or_else(|| run_to_legacy_list::<String>(item).map(|list| detable_items(list, Graphic::Text)))
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ use core_types::{ATTR_CLIPPING_MASK, ATTR_EDITOR_LAYER_PATH, ATTR_OPACITY, ATTR_
|
|||||||
use dyn_any::DynAny;
|
use dyn_any::DynAny;
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
use vector_types::GradientStops;
|
use vector_types::Gradient;
|
||||||
pub use vector_types::Vector;
|
pub use vector_types::Vector;
|
||||||
|
|
||||||
/// The possible forms of graphical content that can be rendered by the Render node into either an image or SVG syntax.
|
/// The possible forms of graphical content that can be rendered by the Render node into either an image or SVG syntax.
|
||||||
@@ -38,7 +38,7 @@ pub enum Graphic<'e> {
|
|||||||
RasterCPU(Raster<CPU>),
|
RasterCPU(Raster<CPU>),
|
||||||
RasterGPU(Raster<GPU>),
|
RasterGPU(Raster<GPU>),
|
||||||
Color(Color),
|
Color(Color),
|
||||||
Gradient(GradientStops),
|
Gradient(Gradient),
|
||||||
Text(String),
|
Text(String),
|
||||||
Group(core_types::record::Group<'e>),
|
Group(core_types::record::Group<'e>),
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ into_graphic_element! {
|
|||||||
RasterCPU: Raster<CPU>;
|
RasterCPU: Raster<CPU>;
|
||||||
RasterGPU: Raster<GPU>;
|
RasterGPU: Raster<GPU>;
|
||||||
Color: Color;
|
Color: Color;
|
||||||
Gradient: GradientStops;
|
Gradient: Gradient;
|
||||||
Text: String;
|
Text: String;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,9 +146,9 @@ impl From<Color> for Graphic<'_> {
|
|||||||
}
|
}
|
||||||
// Note: List<Color> -> Option<Color> is in gcore (Color is defined there)
|
// Note: List<Color> -> Option<Color> is in gcore (Color is defined there)
|
||||||
|
|
||||||
// GradientStops
|
// Gradient
|
||||||
impl From<GradientStops> for Graphic<'_> {
|
impl From<Gradient> for Graphic<'_> {
|
||||||
fn from(gradient: GradientStops) -> Self {
|
fn from(gradient: Gradient) -> Self {
|
||||||
Graphic::Gradient(gradient)
|
Graphic::Gradient(gradient)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,7 +251,7 @@ impl TryFromGraphic for Color {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFromGraphic for GradientStops {
|
impl TryFromGraphic for Gradient {
|
||||||
fn try_from_graphic(graphic: Graphic) -> Option<List<Self>> {
|
fn try_from_graphic(graphic: Graphic) -> Option<List<Self>> {
|
||||||
if let Graphic::Gradient(t) = graphic { Some(List::new_from_element(t)) } else { None }
|
if let Graphic::Gradient(t) = graphic { Some(List::new_from_element(t)) } else { None }
|
||||||
}
|
}
|
||||||
@@ -306,7 +306,7 @@ impl IntoGraphicList for List<Color> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoGraphicList for List<GradientStops> {
|
impl IntoGraphicList for List<Gradient> {
|
||||||
fn into_graphic_list(self) -> List<Graphic<'static>> {
|
fn into_graphic_list(self) -> List<Graphic<'static>> {
|
||||||
detable_items(self, Graphic::Gradient)
|
detable_items(self, Graphic::Gradient)
|
||||||
}
|
}
|
||||||
@@ -612,7 +612,7 @@ mod graphic_is_opaque_tests {
|
|||||||
Graphic::Color(color)
|
Graphic::Color(color)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gradient_graphic(gradient: GradientStops) -> Graphic<'static> {
|
fn gradient_graphic(gradient: Gradient) -> Graphic<'static> {
|
||||||
Graphic::Gradient(gradient)
|
Graphic::Gradient(gradient)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,7 +638,7 @@ mod graphic_is_opaque_tests {
|
|||||||
fn gradient_with_all_opaque_stops_is_opaque() {
|
fn gradient_with_all_opaque_stops_is_opaque() {
|
||||||
let color_1 = Color::from_rgbaf32(1., 0., 0., 1.).unwrap();
|
let color_1 = Color::from_rgbaf32(1., 0., 0., 1.).unwrap();
|
||||||
let color_2 = Color::from_rgbaf32(1., 0., 0., 1.).unwrap();
|
let color_2 = Color::from_rgbaf32(1., 0., 0., 1.).unwrap();
|
||||||
let gradient = GradientStops::new(vec![
|
let gradient = Gradient::new(vec![
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
@@ -658,7 +658,7 @@ mod graphic_is_opaque_tests {
|
|||||||
fn gradient_with_transparent_stop_is_not_opaque() {
|
fn gradient_with_transparent_stop_is_not_opaque() {
|
||||||
let color_1 = Color::from_rgbaf32(1., 0., 0., 0.5).unwrap();
|
let color_1 = Color::from_rgbaf32(1., 0., 0., 0.5).unwrap();
|
||||||
let color_2 = Color::from_rgbaf32(1., 0., 0., 1.).unwrap();
|
let color_2 = Color::from_rgbaf32(1., 0., 0., 1.).unwrap();
|
||||||
let gradient = GradientStops::new(vec![
|
let gradient = Gradient::new(vec![
|
||||||
GradientStop {
|
GradientStop {
|
||||||
position: 0.,
|
position: 0.,
|
||||||
midpoint: 0.5,
|
midpoint: 0.5,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use core_types::uuid::NodeId;
|
|||||||
use core_types::{ATTR_EDITOR_LAYER_PATH, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TRANSFORM, Color};
|
use core_types::{ATTR_EDITOR_LAYER_PATH, ATTR_OPACITY, ATTR_OPACITY_FILL, ATTR_TRANSFORM, Color};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
use vector_types::{GradientStops, Vector};
|
use vector_types::{Gradient, Vector};
|
||||||
|
|
||||||
/// One run's attribute tokens, minted once so the lane loops read at an offset.
|
/// One run's attribute tokens, minted once so the lane loops read at an offset.
|
||||||
struct RunAttrs {
|
struct RunAttrs {
|
||||||
@@ -117,7 +117,7 @@ pub(in crate::graphic) fn group_bounding_box(group: &core_types::record::Group,
|
|||||||
.or_else(|| typed_run::<Raster<CPU>>(item, transform, include_stroke, thumbnail))
|
.or_else(|| typed_run::<Raster<CPU>>(item, transform, include_stroke, thumbnail))
|
||||||
.or_else(|| typed_run::<Raster<GPU>>(item, transform, include_stroke, thumbnail))
|
.or_else(|| typed_run::<Raster<GPU>>(item, transform, include_stroke, thumbnail))
|
||||||
.or_else(|| typed_run::<Color>(item, transform, include_stroke, thumbnail))
|
.or_else(|| typed_run::<Color>(item, transform, include_stroke, thumbnail))
|
||||||
.or_else(|| typed_run::<GradientStops>(item, transform, include_stroke, thumbnail))
|
.or_else(|| typed_run::<Gradient>(item, transform, include_stroke, thumbnail))
|
||||||
.or_else(|| typed_run::<String>(item, transform, include_stroke, thumbnail))
|
.or_else(|| typed_run::<String>(item, transform, include_stroke, thumbnail))
|
||||||
.unwrap_or(RenderBoundingBox::Infinite)
|
.unwrap_or(RenderBoundingBox::Infinite)
|
||||||
}
|
}
|
||||||
@@ -497,7 +497,7 @@ pub(in crate::graphic) fn group_render_complexity(group: &core_types::record::Gr
|
|||||||
.or_else(|| typed_run::<Raster<CPU>>(item))
|
.or_else(|| typed_run::<Raster<CPU>>(item))
|
||||||
.or_else(|| typed_run::<Raster<GPU>>(item))
|
.or_else(|| typed_run::<Raster<GPU>>(item))
|
||||||
.or_else(|| typed_run::<Color>(item))
|
.or_else(|| typed_run::<Color>(item))
|
||||||
.or_else(|| typed_run::<GradientStops>(item))
|
.or_else(|| typed_run::<Gradient>(item))
|
||||||
.or_else(|| typed_run::<String>(item))
|
.or_else(|| typed_run::<String>(item))
|
||||||
.unwrap_or(item.len())
|
.unwrap_or(item.len())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ pub mod migrations {
|
|||||||
use dyn_any::DynAny;
|
use dyn_any::DynAny;
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use vector_types::vector::{PointDomain, RegionDomain, SegmentDomain, misc::HandleId, style::Stroke};
|
use vector_types::vector::{PointDomain, RegionDomain, SegmentDomain, misc::HandleId, style::Stroke};
|
||||||
use vector_types::{GradientStops, Vector, vector};
|
use vector_types::{Gradient, Vector, vector};
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, graphene_hash::CacheHash, DynAny, serde::Serialize, serde::Deserialize)]
|
#[derive(Default, Debug, Clone, PartialEq, graphene_hash::CacheHash, DynAny, serde::Serialize, serde::Deserialize)]
|
||||||
pub struct Gradient {
|
pub struct LegacyGradient {
|
||||||
pub stops: GradientStops,
|
pub stops: Gradient,
|
||||||
pub gradient_type: vector::style::GradientType,
|
pub gradient_type: vector::style::GradientType,
|
||||||
pub start: DVec2,
|
pub start: DVec2,
|
||||||
pub end: DVec2,
|
pub end: DVec2,
|
||||||
@@ -39,11 +39,11 @@ pub mod migrations {
|
|||||||
pub transform: DAffine2,
|
pub transform: DAffine2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gradient {
|
impl LegacyGradient {
|
||||||
/// Converts a legacy bounding-box-relative gradient (`start`/`end` in [0,1]) into an absolute one in the geometry's local space.
|
/// Converts a legacy bounding-box-relative gradient (`start`/`end` in [0,1]) into an absolute one in the geometry's local space.
|
||||||
/// `bounding_box` maps [0,1] onto the geometry's bounding box; `layer_transform` is the layer's own transform,
|
/// `bounding_box` maps [0,1] onto the geometry's bounding box; `layer_transform` is the layer's own transform,
|
||||||
/// used to bake the elliptical adjustment that reproduces the legacy isotropic radial through a non-uniform layer.
|
/// used to bake the elliptical adjustment that reproduces the legacy isotropic radial through a non-uniform layer.
|
||||||
pub fn to_absolute(&self, bounding_box: DAffine2, layer_transform: DAffine2) -> Gradient {
|
pub fn to_absolute(&self, bounding_box: DAffine2, layer_transform: DAffine2) -> LegacyGradient {
|
||||||
let start = bounding_box.transform_point2(self.start);
|
let start = bounding_box.transform_point2(self.start);
|
||||||
let end = bounding_box.transform_point2(self.end);
|
let end = bounding_box.transform_point2(self.end);
|
||||||
let direction = end - start;
|
let direction = end - start;
|
||||||
@@ -66,7 +66,7 @@ pub mod migrations {
|
|||||||
DAffine2::IDENTITY
|
DAffine2::IDENTITY
|
||||||
};
|
};
|
||||||
|
|
||||||
Gradient {
|
LegacyGradient {
|
||||||
start,
|
start,
|
||||||
end,
|
end,
|
||||||
transform,
|
transform,
|
||||||
@@ -83,15 +83,15 @@ pub mod migrations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, graphene_hash::CacheHash, DynAny, serde::Serialize, serde::Deserialize)]
|
#[derive(Default, Debug, Clone, PartialEq, graphene_hash::CacheHash, DynAny, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum Fill {
|
pub enum LegacyFill {
|
||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
Solid(Color),
|
Solid(Color),
|
||||||
Gradient(Gradient),
|
Gradient(LegacyGradient),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The legacy `fill` field is intentionally omitted because vector payload migration only
|
/// The legacy `fill` field is intentionally omitted because vector payload migration only
|
||||||
/// recovers editable vector data. The fill/stroke paints are migrated from the the node inputs.
|
/// recovers editable vector data. The fill/stroke paints are migrated from the node inputs.
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
#[cfg_attr(test, derive(Default, serde::Serialize))]
|
#[cfg_attr(test, derive(Default, serde::Serialize))]
|
||||||
pub(super) struct PathStyle {
|
pub(super) struct PathStyle {
|
||||||
@@ -165,7 +165,7 @@ pub mod migrations {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.as_object_mut()
|
.as_object_mut()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.insert("fill".into(), serde_json::to_value(legacy::Fill::default()).unwrap());
|
.insert("fill".into(), serde_json::to_value(legacy::LegacyFill::default()).unwrap());
|
||||||
let migrated = migrate_to_optional_vector(value).unwrap().unwrap();
|
let migrated = migrate_to_optional_vector(value).unwrap().unwrap();
|
||||||
|
|
||||||
assert_eq!(migrated.stroke.unwrap().weight, 12.);
|
assert_eq!(migrated.stroke.unwrap().weight, 12.);
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use graphic_types::vector_types::gradient::GradientType;
|
|||||||
use graphic_types::vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod};
|
use graphic_types::vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod};
|
||||||
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::GradientStops;
|
use vector_types::Gradient;
|
||||||
use vector_types::gradient::GradientSpreadMethod;
|
use vector_types::gradient::GradientSpreadMethod;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq)]
|
||||||
@@ -83,7 +83,7 @@ impl RenderExt for List<Color> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderExt for List<GradientStops> {
|
impl RenderExt for List<Gradient> {
|
||||||
type Output = u64;
|
type Output = u64;
|
||||||
|
|
||||||
/// Adds the gradient def through mutating the first argument, returning the gradient ID.
|
/// Adds the gradient def through mutating the first argument, returning the gradient ID.
|
||||||
@@ -103,7 +103,7 @@ impl RenderExt for List<GradientStops> {
|
|||||||
|
|
||||||
/// Adds the gradient def through mutating `svg_defs`, returning the gradient
|
/// Adds the gradient def through mutating `svg_defs`, returning the gradient
|
||||||
/// ID, over any gradient lane source.
|
/// ID, over any gradient lane source.
|
||||||
pub fn render_gradient_paint<S: core_types::lane::LaneSource<Element = GradientStops>>(source: &S, svg_defs: &mut String, item_transform: DAffine2, element_transform: DAffine2) -> u64 {
|
pub fn render_gradient_paint<S: core_types::lane::LaneSource<Element = Gradient>>(source: &S, svg_defs: &mut String, item_transform: DAffine2, element_transform: DAffine2) -> u64 {
|
||||||
let mut stop = String::new();
|
let mut stop = String::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ 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::{GradientStops, GradientType};
|
use graphic_types::vector_types::gradient::{Gradient, GradientType};
|
||||||
use graphic_types::vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod};
|
use graphic_types::vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod};
|
||||||
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};
|
||||||
@@ -400,7 +400,7 @@ pub(crate) fn gradient_placement(transform: DAffine2, gradient_type: GradientTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_peniko_gradient_brush<S: LaneSource<Element = GradientStops>>(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_type: GradientType = gradient_list.attr::<GradientTypeAttr>(0);
|
||||||
@@ -694,7 +694,7 @@ fn collect_group_row_metadata(group: &Group, metadata: &mut RenderMetadata, elem
|
|||||||
.or_else(|| lane_zero_transform::<Raster<CPU>>(item))
|
.or_else(|| lane_zero_transform::<Raster<CPU>>(item))
|
||||||
.or_else(|| lane_zero_transform::<Raster<GPU>>(item))
|
.or_else(|| lane_zero_transform::<Raster<GPU>>(item))
|
||||||
.or_else(|| lane_zero_transform::<Color>(item))
|
.or_else(|| lane_zero_transform::<Color>(item))
|
||||||
.or_else(|| lane_zero_transform::<GradientStops>(item))
|
.or_else(|| lane_zero_transform::<Gradient>(item))
|
||||||
.or_else(|| lane_zero_transform::<String>(item));
|
.or_else(|| lane_zero_transform::<String>(item));
|
||||||
if let Some(transform) = transform {
|
if let Some(transform) = transform {
|
||||||
metadata.local_transforms.insert(element_id, transform);
|
metadata.local_transforms.insert(element_id, transform);
|
||||||
@@ -741,7 +741,7 @@ fn render_group_svg<'a>(group: &'a Group, reach: PaintReach<'a>, render: &mut Sv
|
|||||||
} else if item.typed_lanes::<Raster<GPU>>().is_some() {
|
} else if item.typed_lanes::<Raster<GPU>>().is_some() {
|
||||||
} else if let Some(run) = RunView::<Color>::new(item) {
|
} else if let Some(run) = RunView::<Color>::new(item) {
|
||||||
render_color_svg(&run, render, render_params)
|
render_color_svg(&run, render, render_params)
|
||||||
} else if let Some(run) = RunView::<GradientStops>::new(item) {
|
} else if let Some(run) = RunView::<Gradient>::new(item) {
|
||||||
render_gradient_svg(&run, render, render_params)
|
render_gradient_svg(&run, render, render_params)
|
||||||
} else if let Some(run) = RunView::<String>::new(item) {
|
} else if let Some(run) = RunView::<String>::new(item) {
|
||||||
render_text_svg(&run, render, render_params)
|
render_text_svg(&run, render, render_params)
|
||||||
@@ -763,7 +763,7 @@ fn render_group_vello<'a>(group: &'a Group, reach: PaintReach<'a>, scene: &mut S
|
|||||||
render_raster_gpu_vello(&run, scene, transform, context, render_params)
|
render_raster_gpu_vello(&run, scene, transform, context, render_params)
|
||||||
} else if let Some(run) = RunView::<Color>::new(item) {
|
} else if let Some(run) = RunView::<Color>::new(item) {
|
||||||
render_color_vello(&run, scene, render_params)
|
render_color_vello(&run, scene, render_params)
|
||||||
} else if let Some(run) = RunView::<GradientStops>::new(item) {
|
} else if let Some(run) = RunView::<Gradient>::new(item) {
|
||||||
render_gradient_vello(&run, scene, transform, render_params)
|
render_gradient_vello(&run, scene, transform, render_params)
|
||||||
} else if let Some(run) = RunView::<String>::new(item) {
|
} else if let Some(run) = RunView::<String>::new(item) {
|
||||||
render_text_vello(&run, scene, transform, render_params)
|
render_text_vello(&run, scene, transform, render_params)
|
||||||
@@ -786,7 +786,7 @@ fn collect_group_metadata<'a>(group: &'a Group, reach: PaintReach<'a>, metadata:
|
|||||||
collect_raster_metadata(&run, metadata, footprint, element_id)
|
collect_raster_metadata(&run, metadata, footprint, element_id)
|
||||||
} else if let Some(run) = RunView::<Raster<GPU>>::new(item) {
|
} else if let Some(run) = RunView::<Raster<GPU>>::new(item) {
|
||||||
collect_raster_metadata(&run, metadata, footprint, element_id)
|
collect_raster_metadata(&run, metadata, footprint, element_id)
|
||||||
} else if item.typed_lanes::<Color>().is_some() || item.typed_lanes::<GradientStops>().is_some() {
|
} else if item.typed_lanes::<Color>().is_some() || item.typed_lanes::<Gradient>().is_some() {
|
||||||
} else if let Some(run) = RunView::<String>::new(item) {
|
} else if let Some(run) = RunView::<String>::new(item) {
|
||||||
collect_text_metadata(&run, metadata, footprint, element_id)
|
collect_text_metadata(&run, metadata, footprint, element_id)
|
||||||
}
|
}
|
||||||
@@ -2282,7 +2282,7 @@ impl Render for List<Color> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_gradient_svg<S: LaneSource<Element = GradientStops>>(source: &S, render: &mut SvgRender, render_params: &RenderParams) {
|
fn render_gradient_svg<S: LaneSource<Element = Gradient>>(source: &S, render: &mut SvgRender, render_params: &RenderParams) {
|
||||||
// For thumbnails the gradient fills a finite rect at the footprint's document space bounds, with a 1-unit margin to cover the `as u32` truncation of `Footprint::resolution`.
|
// For thumbnails the gradient fills a finite rect at the footprint's document space bounds, with a 1-unit margin to cover the `as u32` truncation of `Footprint::resolution`.
|
||||||
// The viewBox crops the overshoot. Canvas rendering keeps the polyline path since Chrome rejects rects larger than ~20 million.
|
// The viewBox crops the overshoot. Canvas rendering keeps the polyline path since Chrome rejects rects larger than ~20 million.
|
||||||
let thumbnail_rect = if render_params.thumbnail {
|
let thumbnail_rect = if render_params.thumbnail {
|
||||||
@@ -2374,7 +2374,7 @@ fn render_gradient_svg<S: LaneSource<Element = GradientStops>>(source: &S, rende
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_gradient_vello<S: LaneSource<Element = GradientStops>>(source: &S, scene: &mut Scene, parent_transform: DAffine2, render_params: &RenderParams) {
|
fn render_gradient_vello<S: LaneSource<Element = Gradient>>(source: &S, scene: &mut Scene, parent_transform: DAffine2, render_params: &RenderParams) {
|
||||||
use vello::peniko;
|
use vello::peniko;
|
||||||
|
|
||||||
if let RenderMode::Outline = render_params.render_mode {
|
if let RenderMode::Outline = render_params.render_mode {
|
||||||
@@ -2458,7 +2458,7 @@ fn render_gradient_vello<S: LaneSource<Element = GradientStops>>(source: &S, sce
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for List<GradientStops> {
|
impl Render for List<Gradient> {
|
||||||
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams) {
|
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams) {
|
||||||
render_gradient_svg(self, render, render_params)
|
render_gradient_svg(self, render, render_params)
|
||||||
}
|
}
|
||||||
@@ -2926,7 +2926,7 @@ impl Render for RunView<'_, Color> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Render for RunView<'_, GradientStops> {
|
impl Render for RunView<'_, Gradient> {
|
||||||
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams) {
|
fn render_svg(&self, render: &mut SvgRender, render_params: &RenderParams) {
|
||||||
render_gradient_svg(self, render, render_params)
|
render_gradient_svg(self, render, render_params)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,10 @@ pub enum GradientType {
|
|||||||
// TODO: Someday we could switch this to a Box[T] to avoid over-allocation
|
// TODO: Someday we could switch this to a Box[T] to avoid over-allocation
|
||||||
/// A list of colors (linear, unassociated alpha) associated with positions (in the range 0 to 1) along a gradient.
|
/// A list of colors (linear, unassociated alpha) associated with positions (in the range 0 to 1) along a gradient.
|
||||||
///
|
///
|
||||||
/// Not exposed via Tsify; use [`GradientStopsUI`] at the JS boundary.
|
/// Not exposed via Tsify; use [`GradientUI`] at the JS boundary.
|
||||||
#[derive(Debug, Clone, PartialEq, graphene_hash::CacheHash, DynAny)]
|
#[derive(Debug, Clone, PartialEq, graphene_hash::CacheHash, DynAny)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||||
pub struct GradientStops {
|
pub struct Gradient {
|
||||||
/// The position of this stop, a factor from 0-1 along the length of the full gradient.
|
/// The position of this stop, a factor from 0-1 along the length of the full gradient.
|
||||||
pub position: Vec<f64>,
|
pub position: Vec<f64>,
|
||||||
/// The midpoint to the right of this stop, a factor from 0-1 along the distance to the next stop. The final stop's midpoint is ignored.
|
/// The midpoint to the right of this stop, a factor from 0-1 along the distance to the next stop. The final stop's midpoint is ignored.
|
||||||
@@ -29,18 +29,18 @@ pub struct GradientStops {
|
|||||||
pub color: Vec<Color>,
|
pub color: Vec<Color>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// JS-boundary version of [`GradientStops`] where stop colors are [`SRGBA8`] byte triples instead of linear-light [`Color`].
|
/// JS-boundary version of [`Gradient`] where stop colors are [`SRGBA8`] byte triples instead of linear-light [`Color`].
|
||||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify), tsify(from_wasm_abi))]
|
#[cfg_attr(feature = "wasm", derive(tsify::Tsify), tsify(from_wasm_abi))]
|
||||||
#[derive(Debug, Clone, PartialEq, Default, DynAny)]
|
#[derive(Debug, Clone, PartialEq, Default, DynAny)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
pub struct GradientStopsUI {
|
pub struct GradientUI {
|
||||||
pub position: Vec<f64>,
|
pub position: Vec<f64>,
|
||||||
pub midpoint: Vec<f64>,
|
pub midpoint: Vec<f64>,
|
||||||
pub color: Vec<SRGBA8>,
|
pub color: Vec<SRGBA8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&GradientStops> for GradientStopsUI {
|
impl From<&Gradient> for GradientUI {
|
||||||
fn from(s: &GradientStops) -> Self {
|
fn from(s: &Gradient) -> Self {
|
||||||
Self {
|
Self {
|
||||||
position: s.position.clone(),
|
position: s.position.clone(),
|
||||||
midpoint: s.midpoint.clone(),
|
midpoint: s.midpoint.clone(),
|
||||||
@@ -49,8 +49,8 @@ impl From<&GradientStops> for GradientStopsUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&GradientStopsUI> for GradientStops {
|
impl From<&GradientUI> for Gradient {
|
||||||
fn from(s: &GradientStopsUI) -> Self {
|
fn from(s: &GradientUI) -> Self {
|
||||||
Self {
|
Self {
|
||||||
position: s.position.clone(),
|
position: s.position.clone(),
|
||||||
midpoint: s.midpoint.clone(),
|
midpoint: s.midpoint.clone(),
|
||||||
@@ -59,7 +59,7 @@ impl From<&GradientStopsUI> for GradientStops {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientStopsUI {
|
impl GradientUI {
|
||||||
/// CSS `linear-gradient(...)` string. Stops are emitted as `#rrggbbaa` hex (already gamma-encoded bytes).
|
/// CSS `linear-gradient(...)` string. Stops are emitted as `#rrggbbaa` hex (already gamma-encoded bytes).
|
||||||
pub fn to_css_linear_gradient(&self) -> String {
|
pub fn to_css_linear_gradient(&self) -> String {
|
||||||
if self.position.len() <= 1 {
|
if self.position.len() <= 1 {
|
||||||
@@ -67,7 +67,7 @@ impl GradientStopsUI {
|
|||||||
return format!("linear-gradient(to right, #{hex} 0%, #{hex} 100%)");
|
return format!("linear-gradient(to right, #{hex} 0%, #{hex} 100%)");
|
||||||
}
|
}
|
||||||
// Sample via the midpoint-aware subdivision used for SVG/Vello stops so browser interpolation matches
|
// Sample via the midpoint-aware subdivision used for SVG/Vello stops so browser interpolation matches
|
||||||
let stops: GradientStops = self.into();
|
let stops: Gradient = self.into();
|
||||||
let pieces = stops
|
let pieces = stops
|
||||||
.interpolated_samples()
|
.interpolated_samples()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -83,7 +83,7 @@ impl GradientStopsUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Eventually remove this migration document upgrade code
|
// TODO: Eventually remove this migration document upgrade code
|
||||||
impl<'de> serde::Deserialize<'de> for GradientStops {
|
impl<'de> serde::Deserialize<'de> for Gradient {
|
||||||
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
struct NewFormat {
|
struct NewFormat {
|
||||||
@@ -117,7 +117,7 @@ impl<'de> serde::Deserialize<'de> for GradientStops {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for GradientStops {
|
impl Default for Gradient {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
position: vec![0., 1.],
|
position: vec![0., 1.],
|
||||||
@@ -127,7 +127,7 @@ impl Default for GradientStops {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderComplexity for GradientStops {
|
impl RenderComplexity for Gradient {
|
||||||
fn render_complexity(&self) -> usize {
|
fn render_complexity(&self) -> usize {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ pub struct GradientStop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct GradientStopsIter<'a> {
|
pub struct GradientStopsIter<'a> {
|
||||||
stops: &'a GradientStops,
|
stops: &'a Gradient,
|
||||||
index: usize,
|
index: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ impl<'a> Iterator for GradientStopsIter<'a> {
|
|||||||
|
|
||||||
impl ExactSizeIterator for GradientStopsIter<'_> {}
|
impl ExactSizeIterator for GradientStopsIter<'_> {}
|
||||||
|
|
||||||
impl<'a> IntoIterator for &'a GradientStops {
|
impl<'a> IntoIterator for &'a Gradient {
|
||||||
type Item = GradientStop;
|
type Item = GradientStop;
|
||||||
type IntoIter = GradientStopsIter<'a>;
|
type IntoIter = GradientStopsIter<'a>;
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ impl<'a> IntoIterator for &'a GradientStops {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoIterator for GradientStops {
|
impl IntoIterator for Gradient {
|
||||||
type Item = GradientStop;
|
type Item = GradientStop;
|
||||||
type IntoIter = std::vec::IntoIter<GradientStop>;
|
type IntoIter = std::vec::IntoIter<GradientStop>;
|
||||||
|
|
||||||
@@ -211,7 +211,7 @@ impl IntoIterator for GradientStops {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GradientStops {
|
impl Gradient {
|
||||||
pub fn new(stops: impl IntoIterator<Item = GradientStop>) -> Self {
|
pub fn new(stops: impl IntoIterator<Item = GradientStop>) -> Self {
|
||||||
let mut position = Vec::new();
|
let mut position = Vec::new();
|
||||||
let mut midpoint = Vec::new();
|
let mut midpoint = Vec::new();
|
||||||
@@ -465,7 +465,7 @@ impl GradientStops {
|
|||||||
let color = a.color.lerp(&b.color, time as f32);
|
let color = a.color.lerp(&b.color, time as f32);
|
||||||
GradientStop { position, midpoint: 0.5, color }
|
GradientStop { position, midpoint: 0.5, color }
|
||||||
});
|
});
|
||||||
GradientStops::new(stops)
|
Gradient::new(stops)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -540,19 +540,19 @@ pub fn initial_gradient_transform_for_bounding_box(bounds: [DVec2; 2]) -> DAffin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Eventually remove this migration document upgrade code
|
// TODO: Eventually remove this migration document upgrade code
|
||||||
pub fn migrate_to_gradient_stops<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<GradientStops, D::Error> {
|
pub fn migrate_to_gradient<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Gradient, D::Error> {
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
struct LegacyTable {
|
struct LegacyTable {
|
||||||
#[serde(alias = "instances", alias = "instance")]
|
#[serde(alias = "instances", alias = "instance")]
|
||||||
element: Vec<GradientStops>,
|
element: Vec<Gradient>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Deserialize)]
|
#[derive(serde::Deserialize)]
|
||||||
#[cfg_attr(feature = "serde", serde(untagged))]
|
#[cfg_attr(feature = "serde", serde(untagged))]
|
||||||
enum GradientStopsFormat {
|
enum GradientStopsFormat {
|
||||||
Stops(GradientStops),
|
Stops(Gradient),
|
||||||
List(LegacyTable),
|
List(LegacyTable),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +562,7 @@ pub fn migrate_to_gradient_stops<'de, D: serde::Deserializer<'de>>(deserializer:
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core_types::bounds::BoundingBox for GradientStops {
|
impl core_types::bounds::BoundingBox for Gradient {
|
||||||
fn bounding_box(&self, _transform: DAffine2, _include_stroke: bool) -> core_types::bounds::RenderBoundingBox {
|
fn bounding_box(&self, _transform: DAffine2, _include_stroke: bool) -> core_types::bounds::RenderBoundingBox {
|
||||||
core_types::bounds::RenderBoundingBox::Infinite
|
core_types::bounds::RenderBoundingBox::Infinite
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ 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::{GradientSpreadMethod, GradientStop, GradientStops, GradientType};
|
pub use gradient::{Gradient, GradientSpreadMethod, GradientStop, GradientType};
|
||||||
pub use markers::{ATTR_EDITOR_CLICK_TARGET, ATTR_GRADIENT_TYPE, ATTR_SPREAD_METHOD};
|
pub use markers::{ATTR_EDITOR_CLICK_TARGET, ATTR_GRADIENT_TYPE, ATTR_SPREAD_METHOD};
|
||||||
pub use math::{QuadExt, RectExt};
|
pub use math::{QuadExt, RectExt};
|
||||||
pub use subpath::Subpath;
|
pub use subpath::Subpath;
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ use std::f64::consts::{PI, TAU};
|
|||||||
|
|
||||||
/// Describes an editable fill choice, storing color or gradient stops without gradient placement metadata.
|
/// Describes an editable fill choice, storing color or gradient stops without gradient placement metadata.
|
||||||
///
|
///
|
||||||
/// Can be None, a solid [Color], or a linear/radial [GradientStops].
|
/// Can be None, a solid [Color], or a linear/radial [Gradient].
|
||||||
///
|
///
|
||||||
/// In the future we'll probably also add a pattern fill.
|
/// In the future we'll probably also add a pattern fill.
|
||||||
///
|
///
|
||||||
@@ -22,11 +22,11 @@ pub enum FillChoice {
|
|||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
Solid(Color),
|
Solid(Color),
|
||||||
Gradient(GradientStops),
|
Gradient(Gradient),
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Deprecate [`FillChoice`] and keep this, renamed, as the main widget-controlling type
|
// TODO: Deprecate [`FillChoice`] and keep this, renamed, as the main widget-controlling type
|
||||||
/// JS-boundary version of [`FillChoice`] where the solid color is [`SRGBA8`] and the gradient is [`GradientStopsUI`].
|
/// JS-boundary version of [`FillChoice`] where the solid color is [`SRGBA8`] and the gradient is [`GradientUI`].
|
||||||
#[cfg_attr(feature = "wasm", derive(tsify::Tsify), tsify(from_wasm_abi))]
|
#[cfg_attr(feature = "wasm", derive(tsify::Tsify), tsify(from_wasm_abi))]
|
||||||
#[derive(Default, Debug, Clone, PartialEq, DynAny)]
|
#[derive(Default, Debug, Clone, PartialEq, DynAny)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||||
@@ -34,7 +34,7 @@ pub enum FillChoiceUI {
|
|||||||
#[default]
|
#[default]
|
||||||
None,
|
None,
|
||||||
Solid(SRGBA8),
|
Solid(SRGBA8),
|
||||||
Gradient(GradientStopsUI),
|
Gradient(GradientUI),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<&FillChoice> for FillChoiceUI {
|
impl From<&FillChoice> for FillChoiceUI {
|
||||||
@@ -42,7 +42,7 @@ impl From<&FillChoice> for FillChoiceUI {
|
|||||||
match value {
|
match value {
|
||||||
FillChoice::None => Self::None,
|
FillChoice::None => Self::None,
|
||||||
FillChoice::Solid(color) => Self::Solid(SRGBA8::from(*color)),
|
FillChoice::Solid(color) => Self::Solid(SRGBA8::from(*color)),
|
||||||
FillChoice::Gradient(stops) => Self::Gradient(GradientStopsUI::from(stops)),
|
FillChoice::Gradient(stops) => Self::Gradient(GradientUI::from(stops)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,7 +52,7 @@ impl From<&FillChoiceUI> for FillChoice {
|
|||||||
match value {
|
match value {
|
||||||
FillChoiceUI::None => Self::None,
|
FillChoiceUI::None => Self::None,
|
||||||
FillChoiceUI::Solid(srgba) => Self::Solid(Color::from(*srgba)),
|
FillChoiceUI::Solid(srgba) => Self::Solid(Color::from(*srgba)),
|
||||||
FillChoiceUI::Gradient(stops) => Self::Gradient(GradientStops::from(stops)),
|
FillChoiceUI::Gradient(stops) => Self::Gradient(Gradient::from(stops)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ impl FillChoiceUI {
|
|||||||
Some(*c)
|
Some(*c)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_gradient(&self) -> Option<&GradientStopsUI> {
|
pub fn as_gradient(&self) -> Option<&GradientUI> {
|
||||||
let Self::Gradient(g) = self else { return None };
|
let Self::Gradient(g) = self else { return None };
|
||||||
Some(g)
|
Some(g)
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ impl FillChoice {
|
|||||||
Some(*color)
|
Some(*color)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_gradient(&self) -> Option<&GradientStops> {
|
pub fn as_gradient(&self) -> Option<&Gradient> {
|
||||||
let Self::Gradient(gradient) = self else { return None };
|
let Self::Gradient(gradient) = self else { return None };
|
||||||
Some(gradient)
|
Some(gradient)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -598,7 +598,7 @@ mod tests {
|
|||||||
async fn rasterize<T: Send + Clone>(
|
async fn rasterize<T: Send + Clone>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
_: (),
|
_: (),
|
||||||
#[implementations(List<Vector>, List<Raster<CPU>>, List<Graphic>, List<Color>, List<GradientStops>)] data: List<T>,
|
#[implementations(List<Vector>, List<Raster<CPU>>, List<Graphic>, List<Color>, List<Gradient>)] data: List<T>,
|
||||||
footprint: Footprint,
|
footprint: Footprint,
|
||||||
canvas: CanvasHandle,
|
canvas: CanvasHandle,
|
||||||
) -> (Raster<CPU>, Attr<Transform>, OwnedAttr<EditorMergedLayers>) {
|
) -> (Raster<CPU>, Attr<Transform>, OwnedAttr<EditorMergedLayers>) {
|
||||||
@@ -607,7 +607,7 @@ mod tests {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
assert!(entries.contains("fn rasterize_entries"), "a registrable record-io source must emit its entries fn");
|
assert!(entries.contains("fn rasterize_entries"), "a registrable record-io source must emit its entries fn");
|
||||||
for element in ["Vector", "Raster < CPU >", "Graphic", "Color", "GradientStops"] {
|
for element in ["Vector", "Raster < CPU >", "Graphic", "Color", "Gradient"] {
|
||||||
let row = format!("record_source_type :: < List < {element} > > ()");
|
let row = format!("record_source_type :: < List < {element} > > ()");
|
||||||
assert!(entries.contains(&row), "the implementations row {element} is missing: {entries}");
|
assert!(entries.contains(&row), "the implementations row {element} is missing: {entries}");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2186,10 +2186,10 @@ mod tests {
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
() -> List<Raster<CPU>>,
|
() -> List<Raster<CPU>>,
|
||||||
() -> List<Color>,
|
() -> List<Color>,
|
||||||
() -> List<GradientStops>,
|
() -> List<Gradient>,
|
||||||
Footprint -> List<Raster<CPU>>,
|
Footprint -> List<Raster<CPU>>,
|
||||||
Footprint -> List<Color>,
|
Footprint -> List<Color>,
|
||||||
Footprint -> List<GradientStops>,
|
Footprint -> List<Gradient>,
|
||||||
)]
|
)]
|
||||||
image: impl Node<F, Output = T>,
|
image: impl Node<F, Output = T>,
|
||||||
) -> T {
|
) -> T {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use core_types::list::List;
|
|||||||
use core_types::transform::Footprint;
|
use core_types::transform::Footprint;
|
||||||
use core_types::{CacheHash, Color, Context, Ctx, DeriveCtx, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime};
|
use core_types::{CacheHash, Color, Context, Ctx, DeriveCtx, ExtractAnimationTime, ExtractPointerPosition, ExtractRealTime};
|
||||||
use glam::{DAffine2, DVec2};
|
use glam::{DAffine2, DVec2};
|
||||||
use graphic_types::vector_types::GradientStops;
|
use graphic_types::vector_types::Gradient;
|
||||||
use graphic_types::{Artboard, Graphic, Vector};
|
use graphic_types::{Artboard, Graphic, Vector};
|
||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ fn quantize_real_time<T>(
|
|||||||
Context -> List<Raster<GPU>>,
|
Context -> List<Raster<GPU>>,
|
||||||
Context -> List<Color>,
|
Context -> List<Color>,
|
||||||
Context -> List<Artboard>,
|
Context -> List<Artboard>,
|
||||||
Context -> List<GradientStops>,
|
Context -> List<Gradient>,
|
||||||
Context -> List<String>,
|
Context -> List<String>,
|
||||||
Context -> List<f64>,
|
Context -> List<f64>,
|
||||||
Context -> (),
|
Context -> (),
|
||||||
@@ -120,7 +120,7 @@ fn quantize_animation_time<T>(
|
|||||||
Context -> List<Raster<GPU>>,
|
Context -> List<Raster<GPU>>,
|
||||||
Context -> List<Color>,
|
Context -> List<Color>,
|
||||||
Context -> List<Artboard>,
|
Context -> List<Artboard>,
|
||||||
Context -> List<GradientStops>,
|
Context -> List<Gradient>,
|
||||||
Context -> List<String>,
|
Context -> List<String>,
|
||||||
Context -> List<f64>,
|
Context -> List<f64>,
|
||||||
Context -> (),
|
Context -> (),
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use core_types::list::List;
|
|||||||
use core_types::{Color, ExtractVarArgs};
|
use core_types::{Color, ExtractVarArgs};
|
||||||
use core_types::{Ctx, ExtractIndex, ExtractIndices, ExtractPosition};
|
use core_types::{Ctx, ExtractIndex, ExtractIndices, ExtractPosition};
|
||||||
use glam::DVec2;
|
use glam::DVec2;
|
||||||
use graphic_types::vector_types::GradientStops;
|
use graphic_types::vector_types::Gradient;
|
||||||
use graphic_types::{Graphic, Vector};
|
use graphic_types::{Graphic, Vector};
|
||||||
use raster_types::{CPU, Raster};
|
use raster_types::{CPU, Raster};
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ fn read_color(ctx: impl Ctx + ExtractVarArgs) -> List<Color> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("Context"), path(graphene_core::vector))]
|
#[node_macro::node(category("Context"), path(graphene_core::vector))]
|
||||||
fn read_gradient(ctx: impl Ctx + ExtractVarArgs) -> List<GradientStops> {
|
fn read_gradient(ctx: impl Ctx + ExtractVarArgs) -> List<Gradient> {
|
||||||
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
|
let Ok(var_arg) = ctx.vararg(0) else { return Default::default() };
|
||||||
let var_arg = var_arg as &dyn std::any::Any;
|
let var_arg = var_arg as &dyn std::any::Any;
|
||||||
|
|
||||||
@@ -111,12 +111,12 @@ fn read_color_row_extent<C: Ctx + ExtractVarArgs>(_: &ReadColorRowNode, ctx: &C,
|
|||||||
|
|
||||||
/// Rank-model vararg source: the mapped row's items as lanes, elements only.
|
/// Rank-model vararg source: the mapped row's items as lanes, elements only.
|
||||||
#[node_macro::node(category("Test"), extent_raw(read_gradient_row_extent))]
|
#[node_macro::node(category("Test"), extent_raw(read_gradient_row_extent))]
|
||||||
pub fn read_gradient_row(ctx: impl Ctx + ExtractVarArgs + ExtractIndex) -> Result<IList<GradientStops>, Interrupt> {
|
pub fn read_gradient_row(ctx: impl Ctx + ExtractVarArgs + ExtractIndex) -> Result<IList<Gradient>, Interrupt> {
|
||||||
vararg_element(ctx)
|
vararg_element(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_gradient_row_extent<C: Ctx + ExtractVarArgs>(_: &ReadGradientRowNode, ctx: &C, level: u8) -> GPoll<Extent> {
|
fn read_gradient_row_extent<C: Ctx + ExtractVarArgs>(_: &ReadGradientRowNode, ctx: &C, level: u8) -> GPoll<Extent> {
|
||||||
vararg_lanes::<GradientStops>(ctx, level)
|
vararg_lanes::<Gradient>(ctx, level)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[node_macro::node(category("Context"), path(core_types::vector))]
|
#[node_macro::node(category("Context"), path(core_types::vector))]
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ use graphic_types::{ATTR_EDITOR_MERGED_LAYERS, Artboard, Vector};
|
|||||||
use raster_types::{CPU, GPU, Raster};
|
use raster_types::{CPU, GPU, Raster};
|
||||||
|
|
||||||
use vector_types::gradient::{GradientSpreadMethod, GradientType as GradientTypeValue};
|
use vector_types::gradient::{GradientSpreadMethod, GradientType as GradientTypeValue};
|
||||||
use vector_types::{GradientStop, GradientStops, ReferencePoint};
|
use vector_types::{Gradient, GradientStop, ReferencePoint};
|
||||||
|
|
||||||
/// Resolves a signed index over `total` lanes: negatives count from the end,
|
/// Resolves a signed index over `total` lanes: negatives count from the end,
|
||||||
/// out of range resolves to nothing.
|
/// out of range resolves to nothing.
|
||||||
@@ -100,7 +100,7 @@ fn omit_element_extent(list: ExtentIn<'_>, index: ValueIn<'_, f64>, level: Level
|
|||||||
pub fn extract_element<T: Clone + Default + Send + Sync + CacheHash + 'static>(
|
pub fn extract_element<T: Clone + Default + Send + Sync + CacheHash + 'static>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
/// The `List` of data to extract from.
|
/// The `List` of data to extract from.
|
||||||
#[implementations(String, f64, NodeId, Color, GradientStops, Vector, Raster<CPU>, Graphic, Artboard)]
|
#[implementations(String, f64, NodeId, Color, Gradient, Vector, Raster<CPU>, Graphic, Artboard)]
|
||||||
list: IList<T>,
|
list: IList<T>,
|
||||||
/// The index of the item to retrieve, starting from 0 for the first item. Negative indices count backwards from the end of the list, starting from -1 for the last item.
|
/// The index of the item to retrieve, starting from 0 for the first item. Negative indices count backwards from the end of the list, starting from -1 for the last item.
|
||||||
index: SignedInteger,
|
index: SignedInteger,
|
||||||
@@ -114,7 +114,7 @@ pub fn extract_element<T: Clone + Default + Send + Sync + CacheHash + 'static>(
|
|||||||
#[node_macro::node(category("General"))]
|
#[node_macro::node(category("General"))]
|
||||||
fn map<Row: Clone + Send + Sync + CacheHash + 'static, T>(
|
fn map<Row: Clone + Send + Sync + CacheHash + 'static, T>(
|
||||||
ctx: impl Ctx + DeriveCtx + ExtractIndex + InjectIndex + Copy,
|
ctx: impl Ctx + DeriveCtx + ExtractIndex + InjectIndex + Copy,
|
||||||
#[implementations(Graphic, Vector, Raster<CPU>, Color, GradientStops, String)] content: IList<Row>,
|
#[implementations(Graphic, Vector, Raster<CPU>, Color, Gradient, String)] content: IList<Row>,
|
||||||
mapped: impl Node<Context<'_>, Output = IList<T>>,
|
mapped: impl Node<Context<'_>, Output = IList<T>>,
|
||||||
) -> Result<IList<T>, Interrupt> {
|
) -> Result<IList<T>, Interrupt> {
|
||||||
let mut remaining = ctx.index();
|
let mut remaining = ctx.index();
|
||||||
@@ -429,9 +429,9 @@ fn extend_extent(base: ExtentIn<'_>, new: ExtentIn<'_>, level: LevelIn) -> GPoll
|
|||||||
#[node_macro::node(category(""))]
|
#[node_macro::node(category(""))]
|
||||||
pub fn legacy_layer_extend<T: Send + Clone>(
|
pub fn legacy_layer_extend<T: Send + Clone>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
#[implementations(List<Artboard>, List<Graphic>, List<Vector>, List<String>, List<Raster<CPU>>, List<Raster<GPU>>, List<Color>, List<GradientStops>)] base: List<T>,
|
#[implementations(List<Artboard>, List<Graphic>, List<Vector>, List<String>, List<Raster<CPU>>, List<Raster<GPU>>, List<Color>, List<Gradient>)] base: List<T>,
|
||||||
#[expose]
|
#[expose]
|
||||||
#[implementations(List<Artboard>, List<Graphic>, List<Vector>, List<String>, List<Raster<CPU>>, List<Raster<GPU>>, List<Color>, List<GradientStops>)]
|
#[implementations(List<Artboard>, List<Graphic>, List<Vector>, List<String>, List<Raster<CPU>>, List<Raster<GPU>>, List<Color>, List<Gradient>)]
|
||||||
new: List<T>,
|
new: List<T>,
|
||||||
nested_node_path: List<NodeId>,
|
nested_node_path: List<NodeId>,
|
||||||
) -> List<T> {
|
) -> List<T> {
|
||||||
@@ -458,7 +458,7 @@ pub fn legacy_layer_extend<T: Send + Clone>(
|
|||||||
#[node_macro::node(category("General"), extent(wrap_graphic_extent))]
|
#[node_macro::node(category("General"), extent(wrap_graphic_extent))]
|
||||||
pub fn wrap_graphic<'e, T: Clone + Send + Sync + core_types::CacheHash + 'static>(
|
pub fn wrap_graphic<'e, T: Clone + Send + Sync + core_types::CacheHash + 'static>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
#[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, GradientStops, String)] content: IList<T>,
|
#[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, Gradient, String)] content: IList<T>,
|
||||||
) -> Result<IList<Graphic<'e>>, Interrupt> {
|
) -> Result<IList<Graphic<'e>>, Interrupt> {
|
||||||
let item = content.as_group_item();
|
let item = content.as_group_item();
|
||||||
Ok(Graphic::Group(core_types::record::Group { row: None, content: item }))
|
Ok(Graphic::Group(core_types::record::Group { row: None, content: item }))
|
||||||
@@ -483,7 +483,7 @@ pub fn to_graphic<'e, T: graphic_types::graphic::IntoGraphicElement>(
|
|||||||
List<Raster<CPU>>,
|
List<Raster<CPU>>,
|
||||||
List<Raster<GPU>>,
|
List<Raster<GPU>>,
|
||||||
List<Color>,
|
List<Color>,
|
||||||
List<GradientStops>,
|
List<Gradient>,
|
||||||
List<String>,
|
List<String>,
|
||||||
)]
|
)]
|
||||||
content: T,
|
content: T,
|
||||||
@@ -503,14 +503,14 @@ pub fn to_graphic_element<'e, T: graphic_types::graphic::IntoGraphicElement>(
|
|||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Raster<GPU>,
|
Raster<GPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
String,
|
String,
|
||||||
List<Graphic>,
|
List<Graphic>,
|
||||||
List<Vector>,
|
List<Vector>,
|
||||||
List<Raster<CPU>>,
|
List<Raster<CPU>>,
|
||||||
List<Raster<GPU>>,
|
List<Raster<GPU>>,
|
||||||
List<Color>,
|
List<Color>,
|
||||||
List<GradientStops>,
|
List<Gradient>,
|
||||||
List<String>,
|
List<String>,
|
||||||
)]
|
)]
|
||||||
content: T,
|
content: T,
|
||||||
@@ -524,7 +524,7 @@ pub fn to_graphic_element<'e, T: graphic_types::graphic::IntoGraphicElement>(
|
|||||||
#[node_macro::node(category(""), extent(wrap_graphic_extent))]
|
#[node_macro::node(category(""), extent(wrap_graphic_extent))]
|
||||||
pub fn to_graphic_typed<'e, T: Clone + Send + Sync + core_types::CacheHash + 'static>(
|
pub fn to_graphic_typed<'e, T: Clone + Send + Sync + core_types::CacheHash + 'static>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
#[implementations(Vector, Raster<CPU>, Raster<GPU>, Color, GradientStops, String)] content: IList<T>,
|
#[implementations(Vector, Raster<CPU>, Raster<GPU>, Color, Gradient, String)] content: IList<T>,
|
||||||
) -> Result<IList<Graphic<'e>>, Interrupt> {
|
) -> Result<IList<Graphic<'e>>, Interrupt> {
|
||||||
let item = content.as_group_item();
|
let item = content.as_group_item();
|
||||||
Ok(Graphic::Group(core_types::record::Group { row: None, content: item }))
|
Ok(Graphic::Group(core_types::record::Group { row: None, content: item }))
|
||||||
@@ -548,7 +548,7 @@ fn to_graphic_unit_extent(_content: core_types::extent::ValueIn<'_, ()>, _level:
|
|||||||
#[node_macro::node(category(""))]
|
#[node_macro::node(category(""))]
|
||||||
pub fn level_to_list<T: Clone + Send + Sync + CacheHash + dyn_any::StaticTypeSized>(
|
pub fn level_to_list<T: Clone + Send + Sync + CacheHash + dyn_any::StaticTypeSized>(
|
||||||
_: impl Ctx,
|
_: impl Ctx,
|
||||||
#[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, GradientStops, String)] value: IList<T>,
|
#[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, Gradient, String)] value: IList<T>,
|
||||||
_converter: (),
|
_converter: (),
|
||||||
) -> List<T> {
|
) -> List<T> {
|
||||||
let item = value.as_group_item();
|
let item = value.as_group_item();
|
||||||
@@ -650,19 +650,19 @@ pub fn flatten_color<T: IntoGraphicList>(_: impl Ctx, #[implementations(List<Gra
|
|||||||
content.into_flattened_list()
|
content.into_flattened_list()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a `Graphic[]` into a `GradientStops[]` by deeply flattening any gradient content it contains, and discarding any non-gradient content.
|
/// Converts a `Graphic[]` into a `Gradient[]` by deeply flattening any gradient content it contains, and discarding any non-gradient content.
|
||||||
#[node_macro::node(category("General"))]
|
#[node_macro::node(category("General"))]
|
||||||
pub fn flatten_gradient<T: IntoGraphicList>(_: impl Ctx, #[implementations(List<Graphic>, List<GradientStops>)] content: T) -> List<GradientStops> {
|
pub fn flatten_gradient<T: IntoGraphicList>(_: impl Ctx, #[implementations(List<Graphic>, List<Gradient>)] content: T) -> List<Gradient> {
|
||||||
content.into_flattened_list()
|
content.into_flattened_list()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a gradient from a `Color[]`, where the colors are evenly distributed as gradient stops across the range from 0 to 1.
|
/// Constructs a gradient from a `Color[]`, where the colors are evenly distributed as gradient stops across the range from 0 to 1.
|
||||||
#[node_macro::node(category("Color"))]
|
#[node_macro::node(category("Color"))]
|
||||||
fn colors_to_gradient(_: impl Ctx, colors: IList<Color>) -> GradientStops {
|
fn colors_to_gradient(_: impl Ctx, colors: IList<Color>) -> Gradient {
|
||||||
let stop = |position: f64, color: Color| GradientStop { position, midpoint: 0.5, color };
|
let stop = |position: f64, color: Color| GradientStop { position, midpoint: 0.5, color };
|
||||||
match colors.len() {
|
match colors.len() {
|
||||||
0 => GradientStops::new(vec![stop(0., Color::BLACK), stop(1., Color::BLACK)]),
|
0 => Gradient::new(vec![stop(0., Color::BLACK), stop(1., Color::BLACK)]),
|
||||||
1 => GradientStops::new(vec![stop(0., colors.get(0)), stop(1., colors.get(0))]),
|
1 => Gradient::new(vec![stop(0., colors.get(0)), stop(1., colors.get(0))]),
|
||||||
total => GradientStops::new((0..total).map(|index| stop(index as f64 / (total - 1) as f64, colors.get(index)))),
|
total => Gradient::new((0..total).map(|index| stop(index as f64 / (total - 1) as f64, colors.get(index)))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use glam::DAffine2;
|
|||||||
use graphic_types::Vector;
|
use graphic_types::Vector;
|
||||||
use graphic_types::graphic::Graphic;
|
use graphic_types::graphic::Graphic;
|
||||||
use raster_types::{CPU, Raster};
|
use raster_types::{CPU, Raster};
|
||||||
use vector_types::{GradientStop, GradientStops};
|
use vector_types::{Gradient, GradientStop};
|
||||||
|
|
||||||
/// Whether the walk can descend into a group: the run holds `Graphic`
|
/// Whether the walk can descend into a group: the run holds `Graphic`
|
||||||
/// elements.
|
/// elements.
|
||||||
@@ -113,12 +113,12 @@ fn wrap_extent(_content: ListIn<'_, Graphic>, _level: LevelIn) -> GPoll<Extent>
|
|||||||
/// Rank-model colors-to-gradient: the color level folds into one gradient
|
/// Rank-model colors-to-gradient: the color level folds into one gradient
|
||||||
/// with evenly spaced stops.
|
/// with evenly spaced stops.
|
||||||
#[node_macro::node(category("Test"))]
|
#[node_macro::node(category("Test"))]
|
||||||
fn to_gradient(_: impl Ctx, colors: IList<Color>) -> GradientStops {
|
fn to_gradient(_: impl Ctx, colors: IList<Color>) -> Gradient {
|
||||||
let stop = |position: f64, color: Color| GradientStop { position, midpoint: 0.5, color };
|
let stop = |position: f64, color: Color| GradientStop { position, midpoint: 0.5, color };
|
||||||
match colors.len() {
|
match colors.len() {
|
||||||
0 => GradientStops::new(vec![stop(0., Color::BLACK), stop(1., Color::BLACK)]),
|
0 => Gradient::new(vec![stop(0., Color::BLACK), stop(1., Color::BLACK)]),
|
||||||
1 => GradientStops::new(vec![stop(0., colors.get(0)), stop(1., colors.get(0))]),
|
1 => Gradient::new(vec![stop(0., colors.get(0)), stop(1., colors.get(0))]),
|
||||||
total => GradientStops::new((0..total).map(|index| stop(index as f64 / (total - 1) as f64, colors.get(index)))),
|
total => Gradient::new((0..total).map(|index| stop(index as f64 / (total - 1) as f64, colors.get(index)))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ pub(crate) fn vararg_row<Row: Clone + Send + Sync + 'static>(content: core_types
|
|||||||
#[node_macro::node(category("Test"))]
|
#[node_macro::node(category("Test"))]
|
||||||
fn map<Row: Clone + Send + Sync + core_types::CacheHash + 'static, T>(
|
fn map<Row: Clone + Send + Sync + core_types::CacheHash + 'static, T>(
|
||||||
ctx: impl Ctx + DeriveCtx + ExtractIndex + InjectIndex + Copy,
|
ctx: impl Ctx + DeriveCtx + ExtractIndex + InjectIndex + Copy,
|
||||||
#[implementations(Graphic, Vector, Raster<CPU>, Color, GradientStops, String)] content: IList<Row>,
|
#[implementations(Graphic, Vector, Raster<CPU>, Color, Gradient, String)] content: IList<Row>,
|
||||||
mapped: impl Node<Context<'_>, Output = IList<T>>,
|
mapped: impl Node<Context<'_>, Output = IList<T>>,
|
||||||
) -> Result<IList<IList<T>>, Interrupt> {
|
) -> Result<IList<IList<T>>, Interrupt> {
|
||||||
let mut remaining = ctx.index();
|
let mut remaining = ctx.index();
|
||||||
@@ -159,7 +159,7 @@ fn map<Row: Clone + Send + Sync + core_types::CacheHash + 'static, T>(
|
|||||||
#[node_macro::node(category("Test"))]
|
#[node_macro::node(category("Test"))]
|
||||||
fn flat_map<Row: Clone + Send + Sync + core_types::CacheHash + 'static, T>(
|
fn flat_map<Row: Clone + Send + Sync + core_types::CacheHash + 'static, T>(
|
||||||
ctx: impl Ctx + DeriveCtx + ExtractIndex + InjectIndex + Copy,
|
ctx: impl Ctx + DeriveCtx + ExtractIndex + InjectIndex + Copy,
|
||||||
#[implementations(Graphic, Vector, Raster<CPU>, Color, GradientStops, String)] content: IList<Row>,
|
#[implementations(Graphic, Vector, Raster<CPU>, Color, Gradient, String)] content: IList<Row>,
|
||||||
mapped: impl Node<Context<'_>, Output = IList<T>>,
|
mapped: impl Node<Context<'_>, Output = IList<T>>,
|
||||||
) -> Result<IList<T>, Interrupt> {
|
) -> Result<IList<T>, Interrupt> {
|
||||||
let mut remaining = ctx.index();
|
let mut remaining = ctx.index();
|
||||||
@@ -820,14 +820,14 @@ mod tests {
|
|||||||
let ctx = ContextImpl::root(&scope);
|
let ctx = ContextImpl::root(&scope);
|
||||||
|
|
||||||
let layout = Layout::default().with_writes(1, record::element_write_hashed::<Color>(), &[]);
|
let layout = Layout::default().with_writes(1, record::element_write_hashed::<Color>(), &[]);
|
||||||
let out = Layout::default().with_writes(0, record::element_write_hashed::<GradientStops>(), &[]);
|
let out = Layout::default().with_writes(0, record::element_write_hashed::<Gradient>(), &[]);
|
||||||
let build = |colors: Vec<Color>| install_flip(ToGradientNode::new(RecordSource::new(ColorSource { layout: layout.clone(), colors }, &layout, &layout), &layout), &out);
|
let build = |colors: Vec<Color>| install_flip(ToGradientNode::new(RecordSource::new(ColorSource { layout: layout.clone(), colors }, &layout, &layout), &layout), &out);
|
||||||
let stops_of = |colors: Vec<Color>| {
|
let stops_of = |colors: Vec<Color>| {
|
||||||
let node = build(colors);
|
let node = build(colors);
|
||||||
let GPoll::Final(record) = record::capture(&node, &ctx, &frames) else {
|
let GPoll::Final(record) = record::capture(&node, &ctx, &frames) else {
|
||||||
panic!("expected a final record");
|
panic!("expected a final record");
|
||||||
};
|
};
|
||||||
record.element::<GradientStops>()
|
record.element::<Gradient>()
|
||||||
};
|
};
|
||||||
|
|
||||||
let three = stops_of(vec![Color::BLACK, Color::WHITE, Color::BLACK]);
|
let three = stops_of(vec![Color::BLACK, Color::WHITE, Color::BLACK]);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ pub mod subpath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub mod gradient {
|
pub mod gradient {
|
||||||
pub use vector_types::{GradientStop, GradientStops};
|
pub use vector_types::{Gradient, GradientStop};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod transform {
|
pub mod transform {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ use graphic_types::markers::EditorMergedLayers;
|
|||||||
use graphic_types::raster_types::Image;
|
use graphic_types::raster_types::Image;
|
||||||
use graphic_types::raster_types::{CPU, Raster};
|
use graphic_types::raster_types::{CPU, Raster};
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
use graphic_types::vector_types::gradient::GradientStops;
|
use graphic_types::vector_types::gradient::Gradient;
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
use rendering::{Render, RenderParams, RenderSvgSegmentList, SvgRender};
|
use rendering::{Render, RenderParams, RenderSvgSegmentList, SvgRender};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -212,7 +212,7 @@ async fn rasterize<T: Clone + Send + Sync + dyn_any::StaticTypeSized>(
|
|||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Graphic,
|
Graphic,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
mut data: IList<T>,
|
mut data: IList<T>,
|
||||||
footprint: Footprint,
|
footprint: Footprint,
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use graphic_types::raster_types::{CPU, Raster};
|
|||||||
use graphic_types::{Artboard, Graphic, Vector};
|
use graphic_types::{Artboard, Graphic, Vector};
|
||||||
use rendering::{Render, RenderMetadata, RenderOutputType as RenderOutputTypeRequest, RenderParams, SvgRender, SvgRenderOutput};
|
use rendering::{Render, RenderMetadata, RenderOutputType as RenderOutputTypeRequest, RenderParams, SvgRender, SvgRenderOutput};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use vector_types::GradientStops;
|
use vector_types::Gradient;
|
||||||
use wgpu_executor::RenderContext;
|
use wgpu_executor::RenderContext;
|
||||||
|
|
||||||
#[derive(Clone, dyn_any::DynAny)]
|
#[derive(Clone, dyn_any::DynAny)]
|
||||||
@@ -60,7 +60,7 @@ fn render_intermediate<T: dyn_any::StaticTypeSized + 'static + Render + WasmNotS
|
|||||||
Context -> List<Vector>,
|
Context -> List<Vector>,
|
||||||
Context -> List<Raster<CPU>>,
|
Context -> List<Raster<CPU>>,
|
||||||
Context -> List<Color>,
|
Context -> List<Color>,
|
||||||
Context -> List<GradientStops>,
|
Context -> List<Gradient>,
|
||||||
Context -> List<String>,
|
Context -> List<String>,
|
||||||
)]
|
)]
|
||||||
data: impl Node<Context<'_>, Output = T>,
|
data: impl Node<Context<'_>, Output = T>,
|
||||||
@@ -80,7 +80,7 @@ fn render_intermediate<T: dyn_any::StaticTypeSized + 'static + Render + WasmNotS
|
|||||||
#[node_macro::node(category(""))]
|
#[node_macro::node(category(""))]
|
||||||
fn render_intermediate_leveled<T: Clone + Send + Sync + core_types::CacheHash + dyn_any::StaticTypeSized + 'static>(
|
fn render_intermediate_leveled<T: Clone + Send + Sync + core_types::CacheHash + dyn_any::StaticTypeSized + 'static>(
|
||||||
ctx: impl Ctx + ExtractVarArgs + ExtractIndex + InjectIndex + Copy,
|
ctx: impl Ctx + ExtractVarArgs + ExtractIndex + InjectIndex + Copy,
|
||||||
#[implementations(Artboard, Graphic, Vector, Raster<CPU>, Color, GradientStops, String)] data: IList<T>,
|
#[implementations(Artboard, Graphic, Vector, Raster<CPU>, Color, Gradient, String)] data: IList<T>,
|
||||||
) -> Result<RenderIntermediate, Interrupt>
|
) -> Result<RenderIntermediate, Interrupt>
|
||||||
where
|
where
|
||||||
for<'a> core_types::record::RunView<'a, T>: Render,
|
for<'a> core_types::record::RunView<'a, T>: Render,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ use math_parser::value::{Number, Value};
|
|||||||
use num_traits::Pow;
|
use num_traits::Pow;
|
||||||
use rand::{Rng, SeedableRng};
|
use rand::{Rng, SeedableRng};
|
||||||
use std::ops::{Add, Div, Mul, Rem, Sub};
|
use std::ops::{Add, Div, Mul, Rem, Sub};
|
||||||
use vector_types::GradientStops;
|
use vector_types::Gradient;
|
||||||
use vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod as SpreadMethodAttr};
|
use vector_types::markers::{GradientType as GradientTypeAttr, SpreadMethod as SpreadMethodAttr};
|
||||||
|
|
||||||
/// The struct that stores the context for the maths parser.
|
/// The struct that stores the context for the maths parser.
|
||||||
@@ -819,25 +819,25 @@ fn hex_to_color(ctx: impl Ctx + ExtractIndex + InjectIndex + Copy, hex_code: Str
|
|||||||
|
|
||||||
/// Constructs a gradient value which may be set to any sequence of color stops to represent the transition between colors.
|
/// Constructs a gradient value which may be set to any sequence of color stops to represent the transition between colors.
|
||||||
#[node_macro::node(category("Value"))]
|
#[node_macro::node(category("Value"))]
|
||||||
fn gradient_value(_: impl Ctx, _primary: (), gradient: GradientStops) -> GradientStops {
|
fn gradient_value(_: impl Ctx, _primary: (), gradient: Gradient) -> Gradient {
|
||||||
gradient
|
gradient
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the type (linear or radial) of each gradient in the input list.
|
/// Sets the type (linear or radial) of each gradient in the input list.
|
||||||
#[node_macro::node(category("Color"))]
|
#[node_macro::node(category("Color"))]
|
||||||
fn gradient_type(_: impl Ctx, gradient: GradientStops, gradient_type: vector_types::GradientType) -> (GradientStops, Attr<GradientTypeAttr>) {
|
fn gradient_type(_: impl Ctx, gradient: Gradient, gradient_type: vector_types::GradientType) -> (Gradient, Attr<GradientTypeAttr>) {
|
||||||
(gradient, Attr(gradient_type))
|
(gradient, Attr(gradient_type))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
#[node_macro::node(category("Color"))]
|
#[node_macro::node(category("Color"))]
|
||||||
fn spread_method(_: impl Ctx, gradient: GradientStops, spread_method: vector_types::GradientSpreadMethod) -> (GradientStops, Attr<SpreadMethodAttr>) {
|
fn spread_method(_: impl Ctx, gradient: Gradient, spread_method: vector_types::GradientSpreadMethod) -> (Gradient, Attr<SpreadMethodAttr>) {
|
||||||
(gradient, Attr(spread_method))
|
(gradient, Attr(spread_method))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the color at the specified position along the gradient, given a position from 0 (left) to 1 (right).
|
/// Gets the color at the specified position along the gradient, given a position from 0 (left) to 1 (right).
|
||||||
#[node_macro::node(category("Color"))]
|
#[node_macro::node(category("Color"))]
|
||||||
fn sample_gradient(ctx: impl Ctx + ExtractIndex + InjectIndex + Copy, _primary: (), gradient: IList<GradientStops>, position: Fraction) -> Result<IList<Color>, Interrupt> {
|
fn sample_gradient(ctx: impl Ctx + ExtractIndex + InjectIndex + Copy, _primary: (), gradient: IList<Gradient>, position: Fraction) -> Result<IList<Color>, Interrupt> {
|
||||||
// An unwired gradient serves an empty level: no color
|
// An unwired gradient serves an empty level: no color
|
||||||
if gradient.is_empty() || ctx.index() != 0 {
|
if gradient.is_empty() || ctx.index() != 0 {
|
||||||
return Err(GraphError::past_end().into());
|
return Err(GraphError::past_end().into());
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ use glam::{DAffine2, DVec2};
|
|||||||
use graphic_types::graphic::{GraphicLevel, PaintColumns, PaintReach, bake_paint_transforms, is_paint_present, set_paint_attribute, set_paint_attribute_at};
|
use graphic_types::graphic::{GraphicLevel, PaintColumns, PaintReach, bake_paint_transforms, is_paint_present, set_paint_attribute, set_paint_attribute_at};
|
||||||
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::GradientStops;
|
use graphic_types::vector_types::Gradient;
|
||||||
use graphic_types::vector_types::gradient::{GradientSpreadMethod, GradientType};
|
use graphic_types::vector_types::gradient::{GradientSpreadMethod, GradientType};
|
||||||
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;
|
||||||
@@ -283,7 +283,7 @@ fn color_paint_row(color: Color, mut attributes: core_types::list::ItemAttribute
|
|||||||
|
|
||||||
/// A gradient row: an empty vector carrying the stops as its fill paint, the
|
/// A gradient row: an empty vector carrying the stops as its fill paint, the
|
||||||
/// gradient keys moved onto the paint.
|
/// gradient keys moved onto the paint.
|
||||||
fn gradient_paint_row(stops: GradientStops, mut attributes: core_types::list::ItemAttributeValues) -> Item<Vector> {
|
fn gradient_paint_row(stops: Gradient, mut attributes: core_types::list::ItemAttributeValues) -> Item<Vector> {
|
||||||
let mut gradient_paint = List::new_from_element(Graphic::Gradient(stops));
|
let mut gradient_paint = List::new_from_element(Graphic::Gradient(stops));
|
||||||
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);
|
||||||
@@ -409,7 +409,7 @@ fn flatten_group(out: &mut List<Vector>, group: &core_types::record::Group, comp
|
|||||||
out,
|
out,
|
||||||
(0..color.len()).filter_map(|i| Some(color_paint_row(*color.element(i)?, color.clone_item_attributes(i)))).collect(),
|
(0..color.len()).filter_map(|i| Some(color_paint_row(*color.element(i)?, color.clone_item_attributes(i)))).collect(),
|
||||||
);
|
);
|
||||||
} else if let Some(gradient) = graphic_types::graphic::run_to_list::<GradientStops>(item) {
|
} else if let Some(gradient) = graphic_types::graphic::run_to_list::<Gradient>(item) {
|
||||||
push_rows(
|
push_rows(
|
||||||
out,
|
out,
|
||||||
(0..gradient.len())
|
(0..gradient.len())
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ impl Adjust<Color> for Color {
|
|||||||
mod adjust_std {
|
mod adjust_std {
|
||||||
use super::*;
|
use super::*;
|
||||||
use raster_types::{CPU, Raster};
|
use raster_types::{CPU, Raster};
|
||||||
use vector_types::GradientStops;
|
use vector_types::Gradient;
|
||||||
|
|
||||||
impl Adjust<Color> for Raster<CPU> {
|
impl Adjust<Color> for Raster<CPU> {
|
||||||
fn adjust(&mut self, map_fn: impl Fn(&Color) -> Color) {
|
fn adjust(&mut self, map_fn: impl Fn(&Color) -> Color) {
|
||||||
@@ -22,7 +22,7 @@ mod adjust_std {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl Adjust<Color> for GradientStops {
|
impl Adjust<Color> for Gradient {
|
||||||
fn adjust(&mut self, map_fn: impl Fn(&Color) -> Color) {
|
fn adjust(&mut self, map_fn: impl Fn(&Color) -> Color) {
|
||||||
for color in self.color.iter_mut() {
|
for color in self.color.iter_mut() {
|
||||||
*color = map_fn(color);
|
*color = map_fn(color);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ use num_traits::float::Float;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use raster_types::{CPU, Raster};
|
use raster_types::{CPU, Raster};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use vector_types::GradientStops;
|
use vector_types::Gradient;
|
||||||
|
|
||||||
// TODO: Implement the following:
|
// TODO: Implement the following:
|
||||||
// Color Balance
|
// Color Balance
|
||||||
@@ -53,7 +53,7 @@ fn luminance<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context::Cac
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -78,7 +78,7 @@ fn gamma_correction<T: Adjust<Color> + Clone + Send + Sync + no_std_types::conte
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -100,7 +100,7 @@ fn extract_channel<T: Adjust<Color> + Clone + Send + Sync + no_std_types::contex
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -124,7 +124,7 @@ fn make_opaque<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context::C
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -146,7 +146,7 @@ fn brightness_contrast_classic<T: Adjust<Color> + Clone + Send + Sync + no_std_t
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -177,7 +177,7 @@ fn brightness_contrast<T: Adjust<Color> + Clone + Send + Sync + no_std_types::co
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -258,7 +258,7 @@ fn levels<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context::CacheH
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
@@ -337,7 +337,7 @@ fn black_and_white<T: Adjust<Color> + Clone + Send + Sync + no_std_types::contex
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
@@ -420,7 +420,7 @@ fn hue_saturation<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -452,7 +452,7 @@ fn invert<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context::CacheH
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -473,7 +473,7 @@ fn threshold<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context::Cac
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
@@ -519,7 +519,7 @@ fn vibrance<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context::Cach
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
@@ -721,7 +721,7 @@ fn channel_mixer<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context:
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
@@ -853,7 +853,7 @@ fn selective_color<T: Adjust<Color> + Clone + Send + Sync + no_std_types::contex
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
@@ -999,7 +999,7 @@ fn posterize<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context::Cac
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
@@ -1028,7 +1028,7 @@ fn exposure<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context::Cach
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut input: T,
|
mut input: T,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ use no_std_types::registry::types::PercentageF32;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use raster_types::{CPU, Raster};
|
use raster_types::{CPU, Raster};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use vector_types::{GradientStop, GradientStops};
|
use vector_types::{Gradient, GradientStop};
|
||||||
|
|
||||||
pub trait Blend<P: Pixel> {
|
pub trait Blend<P: Pixel> {
|
||||||
fn blend(&self, under: &Self, blend_fn: impl Fn(P, P) -> P) -> Self;
|
fn blend(&self, under: &Self, blend_fn: impl Fn(P, P) -> P) -> Self;
|
||||||
@@ -36,7 +36,7 @@ mod blend_std {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Blend<Color> for GradientStops {
|
impl Blend<Color> for Gradient {
|
||||||
fn blend(&self, under: &Self, blend_fn: impl Fn(Color, Color) -> Color) -> Self {
|
fn blend(&self, under: &Self, blend_fn: impl Fn(Color, Color) -> Color) -> Self {
|
||||||
let mut combined_stops = self.position.iter().chain(under.position.iter()).copied().collect::<Vec<_>>();
|
let mut combined_stops = self.position.iter().chain(under.position.iter()).copied().collect::<Vec<_>>();
|
||||||
combined_stops.dedup_by(|a, b| (*a - *b).abs() < 1e-6);
|
combined_stops.dedup_by(|a, b| (*a - *b).abs() < 1e-6);
|
||||||
@@ -47,7 +47,7 @@ mod blend_std {
|
|||||||
let color = blend_fn(over_color, under_color);
|
let color = blend_fn(over_color, under_color);
|
||||||
GradientStop { position, midpoint: 0.5, color }
|
GradientStop { position, midpoint: 0.5, color }
|
||||||
});
|
});
|
||||||
GradientStops::new(stops)
|
Gradient::new(stops)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,7 +111,7 @@ fn mix<T: Blend<Color> + Clone + Send + Sync + core_types::CacheHash + 'static>(
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
over: T,
|
over: T,
|
||||||
@@ -119,7 +119,7 @@ fn mix<T: Blend<Color> + Clone + Send + Sync + core_types::CacheHash + 'static>(
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
under: T,
|
under: T,
|
||||||
@@ -135,7 +135,7 @@ fn color_overlay<T: Adjust<Color> + Clone + Send + Sync + no_std_types::context:
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
#[gpu_image]
|
#[gpu_image]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
//! Not immediately shader compatible due to needing [`GradientStops`] as a param, which needs [`Vec`]
|
//! Not immediately shader compatible due to needing [`Gradient`] as a param, which needs [`Vec`]
|
||||||
|
|
||||||
use crate::adjust::Adjust;
|
use crate::adjust::Adjust;
|
||||||
use core_types::{Color, Ctx};
|
use core_types::{Color, Ctx};
|
||||||
use raster_types::{CPU, Raster};
|
use raster_types::{CPU, Raster};
|
||||||
use vector_types::GradientStops;
|
use vector_types::Gradient;
|
||||||
|
|
||||||
// Aims for interoperable compatibility with:
|
// Aims for interoperable compatibility with:
|
||||||
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27grdm%27%20%3D%20Gradient%20Map
|
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27grdm%27%20%3D%20Gradient%20Map
|
||||||
@@ -14,10 +14,10 @@ fn gradient_map<T: Adjust<Color> + Clone + Send + Sync + core_types::CacheHash +
|
|||||||
#[implementations(
|
#[implementations(
|
||||||
Raster<CPU>,
|
Raster<CPU>,
|
||||||
Color,
|
Color,
|
||||||
GradientStops,
|
Gradient,
|
||||||
)]
|
)]
|
||||||
mut image: T,
|
mut image: T,
|
||||||
gradient: IList<GradientStops>,
|
gradient: IList<Gradient>,
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
) -> T {
|
) -> T {
|
||||||
if gradient.is_empty() {
|
if gradient.is_empty() {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use glam::{DAffine2, DMat2, DVec2};
|
|||||||
use graphic_types::Graphic;
|
use graphic_types::Graphic;
|
||||||
use graphic_types::Vector;
|
use graphic_types::Vector;
|
||||||
use graphic_types::raster_types::{CPU, GPU, Raster};
|
use graphic_types::raster_types::{CPU, GPU, Raster};
|
||||||
use vector_types::GradientStops;
|
use vector_types::Gradient;
|
||||||
|
|
||||||
/// Applies the specified transform to each lane of the input, composing onto the lane's transform attribute.
|
/// Applies the specified transform to each lane of the input, composing onto the lane's transform attribute.
|
||||||
#[node_macro::node(category("Math: Transform"), extent(transform_extent))]
|
#[node_macro::node(category("Math: Transform"), extent(transform_extent))]
|
||||||
@@ -97,7 +97,7 @@ fn replace_transform<T>(_: impl Ctx + InjectFootprint, (element, _content_transf
|
|||||||
// TODO: Figure out how this node should behave once #2982 is implemented.
|
// TODO: Figure out how this node should behave once #2982 is implemented.
|
||||||
/// Obtains the transform of the first lane of the input, if present.
|
/// Obtains the transform of the first lane of the input, if present.
|
||||||
#[node_macro::node(category("Math: Transform"), path(core_types::vector))]
|
#[node_macro::node(category("Math: Transform"), path(core_types::vector))]
|
||||||
fn extract_transform<T: Clone + Send + Sync + CacheHash + 'static>(_: impl Ctx, #[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, GradientStops)] content: IList<T>) -> DAffine2 {
|
fn extract_transform<T: Clone + Send + Sync + CacheHash + 'static>(_: impl Ctx, #[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, Gradient)] content: IList<T>) -> DAffine2 {
|
||||||
match content.len() {
|
match content.len() {
|
||||||
0 => DAffine2::default(),
|
0 => DAffine2::default(),
|
||||||
_ => content.lane(0).attr::<TransformAttr>(),
|
_ => content.lane(0).attr::<TransformAttr>(),
|
||||||
|
|||||||
@@ -37,14 +37,14 @@ use vector_types::vector::misc::{
|
|||||||
CentroidType, ExtrudeJoiningAlgorithm, HandleId, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, bezpath_from_manipulator_groups,
|
CentroidType, ExtrudeJoiningAlgorithm, HandleId, InterpolationDistribution, MergeByDistanceAlgorithm, PointSpacingType, RowsOrColumns, bezpath_from_manipulator_groups,
|
||||||
bezpath_to_manipulator_groups, handles_to_segment, is_linear, point_to_dvec2, segment_to_handles,
|
bezpath_to_manipulator_groups, handles_to_segment, is_linear, point_to_dvec2, segment_to_handles,
|
||||||
};
|
};
|
||||||
use vector_types::vector::style::{GradientStops, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
use vector_types::vector::style::{Gradient, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
|
||||||
use vector_types::vector::{FillId, PointId, RegionId, SegmentDomain, SegmentId, StrokeId, VectorExt};
|
use vector_types::vector::{FillId, PointId, RegionId, SegmentDomain, SegmentId, StrokeId, VectorExt};
|
||||||
use vector_types::{ATTR_GRADIENT_TYPE, ATTR_SPREAD_METHOD};
|
use vector_types::{ATTR_GRADIENT_TYPE, ATTR_SPREAD_METHOD};
|
||||||
use vector_types::{GradientSpreadMethod, GradientType};
|
use vector_types::{GradientSpreadMethod, GradientType};
|
||||||
|
|
||||||
/// The gradient color for one assign-colors position, replaying the
|
/// The gradient color for one assign-colors position, replaying the
|
||||||
/// randomized draws up to it.
|
/// randomized draws up to it.
|
||||||
fn assign_color_at(gradient: &GradientStops, position: usize, length: usize, randomize: bool, seed: SeedValue, repeat_every: u32) -> Color {
|
fn assign_color_at(gradient: &Gradient, position: usize, length: usize, randomize: bool, seed: SeedValue, repeat_every: u32) -> Color {
|
||||||
let factor = match randomize {
|
let factor = match randomize {
|
||||||
true => {
|
true => {
|
||||||
let mut rng = rand::rngs::StdRng::seed_from_u64(seed.into());
|
let mut rng = rand::rngs::StdRng::seed_from_u64(seed.into());
|
||||||
@@ -77,7 +77,7 @@ fn assign_colors<'e>(
|
|||||||
stroke: bool,
|
stroke: bool,
|
||||||
/// The range of colors to select from.
|
/// The range of colors to select from.
|
||||||
#[widget(ParsedWidgetOverride::Custom = "assign_colors_gradient")]
|
#[widget(ParsedWidgetOverride::Custom = "assign_colors_gradient")]
|
||||||
gradient: IList<GradientStops>,
|
gradient: IList<Gradient>,
|
||||||
/// Whether to reverse the gradient.
|
/// Whether to reverse the gradient.
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
/// Whether to randomize the color selection for each element from throughout the gradient.
|
/// Whether to randomize the color selection for each element from throughout the gradient.
|
||||||
@@ -132,7 +132,7 @@ fn assign_colors_extent(
|
|||||||
content: ListIn<'_, Vector>,
|
content: ListIn<'_, Vector>,
|
||||||
_fill: ValueIn<'_, bool>,
|
_fill: ValueIn<'_, bool>,
|
||||||
_stroke: ValueIn<'_, bool>,
|
_stroke: ValueIn<'_, bool>,
|
||||||
_gradient: ListIn<'_, GradientStops>,
|
_gradient: ListIn<'_, Gradient>,
|
||||||
_reverse: ValueIn<'_, bool>,
|
_reverse: ValueIn<'_, bool>,
|
||||||
_randomize: ValueIn<'_, bool>,
|
_randomize: ValueIn<'_, bool>,
|
||||||
_seed: ValueIn<'_, SeedValue>,
|
_seed: ValueIn<'_, SeedValue>,
|
||||||
@@ -155,7 +155,7 @@ fn assign_colors_graphic<'e>(
|
|||||||
#[data] lane_offsets: std::sync::Arc<std::sync::Mutex<Option<LaneOffsets>>>,
|
#[data] lane_offsets: std::sync::Arc<std::sync::Mutex<Option<LaneOffsets>>>,
|
||||||
#[default(true)] fill: bool,
|
#[default(true)] fill: bool,
|
||||||
stroke: bool,
|
stroke: bool,
|
||||||
gradient: IList<GradientStops>,
|
gradient: IList<Gradient>,
|
||||||
reverse: bool,
|
reverse: bool,
|
||||||
randomize: bool,
|
randomize: bool,
|
||||||
seed: SeedValue,
|
seed: SeedValue,
|
||||||
@@ -247,7 +247,7 @@ fn assign_colors_graphic_extent(
|
|||||||
content: ListIn<'_, Graphic>,
|
content: ListIn<'_, Graphic>,
|
||||||
_fill: ValueIn<'_, bool>,
|
_fill: ValueIn<'_, bool>,
|
||||||
_stroke: ValueIn<'_, bool>,
|
_stroke: ValueIn<'_, bool>,
|
||||||
_gradient: ListIn<'_, GradientStops>,
|
_gradient: ListIn<'_, Gradient>,
|
||||||
_reverse: ValueIn<'_, bool>,
|
_reverse: ValueIn<'_, bool>,
|
||||||
_randomize: ValueIn<'_, bool>,
|
_randomize: ValueIn<'_, bool>,
|
||||||
_seed: ValueIn<'_, SeedValue>,
|
_seed: ValueIn<'_, SeedValue>,
|
||||||
@@ -322,7 +322,7 @@ 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>,
|
||||||
_backup_gradient: IList<GradientStops>,
|
_backup_gradient: IList<Gradient>,
|
||||||
_gradient_type: GradientType,
|
_gradient_type: GradientType,
|
||||||
_spread_method: GradientSpreadMethod,
|
_spread_method: GradientSpreadMethod,
|
||||||
_transform: Option<DAffine2>,
|
_transform: Option<DAffine2>,
|
||||||
@@ -342,7 +342,7 @@ 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>,
|
||||||
_backup_gradient: IList<GradientStops>,
|
_backup_gradient: IList<Gradient>,
|
||||||
_gradient_type: GradientType,
|
_gradient_type: GradientType,
|
||||||
_spread_method: GradientSpreadMethod,
|
_spread_method: GradientSpreadMethod,
|
||||||
_transform: Option<DAffine2>,
|
_transform: Option<DAffine2>,
|
||||||
@@ -2780,7 +2780,7 @@ fn morph_core(flattened: List<Vector>, snapshot: List<Graphic<'static>>, progres
|
|||||||
};
|
};
|
||||||
|
|
||||||
// This keeps the gradient metadata attributes, which ride the paint lane
|
// This keeps the gradient metadata attributes, which ride the paint lane
|
||||||
let gradient_paint = |metadata_source: &List<Graphic>, stops: GradientStops, transform: Option<DAffine2>| -> List<Graphic> {
|
let gradient_paint = |metadata_source: &List<Graphic>, stops: Gradient, transform: Option<DAffine2>| -> List<Graphic> {
|
||||||
let mut out = List::new_from_item(Item::from_parts(Graphic::Gradient(stops), metadata_source.clone_item_attributes(0)));
|
let mut out = List::new_from_item(Item::from_parts(Graphic::Gradient(stops), metadata_source.clone_item_attributes(0)));
|
||||||
if let Some(transform) = transform {
|
if let Some(transform) = transform {
|
||||||
out.set_attribute(ATTR_TRANSFORM, 0, transform);
|
out.set_attribute(ATTR_TRANSFORM, 0, transform);
|
||||||
@@ -3666,7 +3666,7 @@ fn point_inside(_: impl Ctx, source: IList<Vector>, point: DVec2) -> bool {
|
|||||||
// TODO: Return u32, u64, or usize instead of f64 after #1621 is resolved and has allowed us to implement automatic type conversion in the node graph for nodes with generic type inputs.
|
// TODO: Return u32, u64, or usize instead of f64 after #1621 is resolved and has allowed us to implement automatic type conversion in the node graph for nodes with generic type inputs.
|
||||||
// TODO: (Currently automatic type conversion only works for concrete types, via the Graphene preprocessor and not the full Graphene type system.)
|
// TODO: (Currently automatic type conversion only works for concrete types, via the Graphene preprocessor and not the full Graphene type system.)
|
||||||
#[node_macro::node(category("General"), path(graphene_core::vector))]
|
#[node_macro::node(category("General"), path(graphene_core::vector))]
|
||||||
fn count_elements<T: Clone + Send + Sync + CacheHash + 'static>(_: impl Ctx, #[implementations(Graphic, Artboard, Vector, Raster<CPU>, Color, GradientStops, String)] content: IList<T>) -> f64 {
|
fn count_elements<T: Clone + Send + Sync + CacheHash + 'static>(_: impl Ctx, #[implementations(Graphic, Artboard, Vector, Raster<CPU>, Color, Gradient, String)] content: IList<T>) -> f64 {
|
||||||
content.len() as f64
|
content.len() as f64
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ fn write_inputs(page: &mut std::fs::File, valid_input_types: &[Vec<core_types::T
|
|||||||
let render_color = |color| format!(r#"<span style="padding-right: 100px; border: 2px solid var(--color-fog); background: {color}"></span>"#);
|
let render_color = |color| format!(r#"<span style="padding-right: 100px; border: 2px solid var(--color-fog); background: {color}"></span>"#);
|
||||||
let default_value = match default_value {
|
let default_value = match default_value {
|
||||||
"Color::BLACK" => render_color("black"),
|
"Color::BLACK" => render_color("black"),
|
||||||
"GradientStops([(0.0, Color { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 }), (1.0, Color { red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0 })])" => {
|
"Gradient([(0.0, Color { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 }), (1.0, Color { red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0 })])" => {
|
||||||
render_color("linear-gradient(to right, black, white)")
|
render_color("linear-gradient(to right, black, white)")
|
||||||
}
|
}
|
||||||
_ => format!("`{default_value}{}`", field.unit.unwrap_or_default()),
|
_ => format!("`{default_value}{}`", field.unit.unwrap_or_default()),
|
||||||
|
|||||||
Reference in New Issue
Block a user