Skip to content

Commit 32ed4bd

Browse files
author
indierusty
committed
Merge branch 'master' into merge-spline-path
2 parents ed83b84 + 6292dea commit 32ed4bd

35 files changed

+238
-186
lines changed

editor/src/messages/layout/layout_message_handler.rs

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ impl LayoutMessageHandler {
8282
let callback_message = match action {
8383
WidgetValueAction::Commit => (color_button.on_commit.callback)(&()),
8484
WidgetValueAction::Update => {
85+
// Decodes the colors in gamma, not linear
8586
let decode_color = |color: &serde_json::map::Map<String, serde_json::value::Value>| -> Option<Color> {
8687
let red = color.get("red").and_then(|x| x.as_f64()).map(|x| x as f32);
8788
let green = color.get("green").and_then(|x| x.as_f64()).map(|x| x as f32);
@@ -120,20 +121,13 @@ impl LayoutMessageHandler {
120121
.filter_map(|stop| {
121122
stop.as_object().and_then(|stop| {
122123
let position = stop.get("position").and_then(|x| x.as_f64());
123-
let color = stop.get("color").and_then(|x| x.as_object());
124-
125-
if let (Some(position), Some(color_object)) = (position, color) {
126-
if let Some(color) = decode_color(color_object) {
127-
return Some((position, color));
128-
}
129-
}
130-
131-
None
124+
let color = stop.get("color").and_then(|x| x.as_object()).and_then(decode_color);
125+
if let (Some(position), Some(color)) = (position, color) { Some((position, color)) } else { None }
132126
})
133127
})
134128
.collect::<Vec<_>>();
135129

136-
color_button.value = FillChoice::Gradient(GradientStops(gradient_stops));
130+
color_button.value = FillChoice::Gradient(GradientStops::new(gradient_stops));
137131
return (color_button.on_update.callback)(color_button);
138132
}
139133

editor/src/messages/layout/utility_types/widgets/button_widgets.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ pub struct ImageButton {
147147
#[derive(Clone, Derivative, serde::Serialize, serde::Deserialize, WidgetBuilder, specta::Type)]
148148
#[derivative(Debug, PartialEq, Default)]
149149
pub struct ColorInput {
150+
/// WARNING: The colors are gamma, not linear!
150151
#[widget_builder(constructor)]
151152
pub value: FillChoice,
152153

editor/src/messages/portfolio/document/graph_operation/graph_operation_message_handler.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, t
410410

411411
let [start, end] = [bounds_transform.inverse().transform_point2(layer[0]), bounds_transform.inverse().transform_point2(layer[1])];
412412
let stops = linear.stops().iter().map(|stop| (stop.offset().get() as f64, usvg_color(stop.color(), stop.opacity().get()))).collect();
413-
let stops = GradientStops(stops);
413+
let stops = GradientStops::new(stops);
414414

415415
Fill::Gradient(Gradient {
416416
start,
@@ -437,7 +437,7 @@ fn apply_usvg_fill(fill: &usvg::Fill, modify_inputs: &mut ModifyInputsContext, t
437437

438438
let [start, end] = [bounds_transform.inverse().transform_point2(layer[0]), bounds_transform.inverse().transform_point2(layer[1])];
439439
let stops = radial.stops().iter().map(|stop| (stop.offset().get() as f64, usvg_color(stop.color(), stop.opacity().get()))).collect();
440-
let stops = GradientStops(stops);
440+
let stops = GradientStops::new(stops);
441441

442442
Fill::Gradient(Gradient {
443443
start,

editor/src/messages/portfolio/document/node_graph/node_properties.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,7 +1087,10 @@ pub fn color_widget(document_node: &DocumentNode, node_id: NodeId, index: usize,
10871087
return LayoutGroup::Row { widgets };
10881088
};
10891089

1090+
// Add a separator
10901091
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
1092+
1093+
// Add the color input
10911094
match &**tagged_value {
10921095
TaggedValue::Color(color) => widgets.push(
10931096
color_button

editor/src/messages/portfolio/document/overlays/grid_overlays.rs

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use graphene_std::vector::style::FillChoice;
99

1010
fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, spacing: DVec2) {
1111
let origin = document.snapping_state.grid.origin;
12-
let grid_color = document.snapping_state.grid.grid_color;
12+
let grid_color = "#".to_string() + &document.snapping_state.grid.grid_color.to_rgba_hex_srgb();
1313
let Some(spacing) = GridSnapping::compute_rectangle_spacing(spacing, &document.document_ptz) else {
1414
return;
1515
};
@@ -36,11 +36,7 @@ fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context:
3636
} else {
3737
DVec2::new(secondary_pos, primary_end)
3838
};
39-
overlay_context.line(
40-
document_to_viewport.transform_point2(start),
41-
document_to_viewport.transform_point2(end),
42-
Some(&("#".to_string() + &grid_color.rgba_hex())),
43-
);
39+
overlay_context.line(document_to_viewport.transform_point2(start), document_to_viewport.transform_point2(end), Some(&grid_color));
4440
}
4541
}
4642
}
@@ -52,7 +48,7 @@ fn grid_overlay_rectangular(document: &DocumentMessageHandler, overlay_context:
5248
// TODO: Implement this with a dashed line (`set_line_dash`), with integer spacing which is continuously adjusted to correct the accumulated error.
5349
fn grid_overlay_rectangular_dot(document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, spacing: DVec2) {
5450
let origin = document.snapping_state.grid.origin;
55-
let grid_color = document.snapping_state.grid.grid_color;
51+
let grid_color = "#".to_string() + &document.snapping_state.grid.grid_color.to_rgba_hex_srgb();
5652
let Some(spacing) = GridSnapping::compute_rectangle_spacing(spacing, &document.document_ptz) else {
5753
return;
5854
};
@@ -80,16 +76,13 @@ fn grid_overlay_rectangular_dot(document: &DocumentMessageHandler, overlay_conte
8076
let x_per_dot = (end.x - start.x) / total_dots;
8177
for dot_index in 0..=total_dots as usize {
8278
let exact_x = x_per_dot * dot_index as f64;
83-
overlay_context.pixel(
84-
document_to_viewport.transform_point2(DVec2::new(start.x + exact_x, start.y)).round(),
85-
Some(&("#".to_string() + &grid_color.rgba_hex())),
86-
)
79+
overlay_context.pixel(document_to_viewport.transform_point2(DVec2::new(start.x + exact_x, start.y)).round(), Some(&grid_color))
8780
}
8881
}
8982
}
9083

9184
fn grid_overlay_isometric(document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, y_axis_spacing: f64, angle_a: f64, angle_b: f64) {
92-
let grid_color = document.snapping_state.grid.grid_color;
85+
let grid_color = "#".to_string() + &document.snapping_state.grid.grid_color.to_rgba_hex_srgb();
9386
let cmp = |a: &f64, b: &f64| a.partial_cmp(b).unwrap();
9487
let origin = document.snapping_state.grid.origin;
9588
let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz);
@@ -112,11 +105,7 @@ fn grid_overlay_isometric(document: &DocumentMessageHandler, overlay_context: &m
112105
let x_pos = (((min_x - origin.x) / spacing).ceil() + line_index as f64) * spacing + origin.x;
113106
let start = DVec2::new(x_pos, min_y);
114107
let end = DVec2::new(x_pos, max_y);
115-
overlay_context.line(
116-
document_to_viewport.transform_point2(start),
117-
document_to_viewport.transform_point2(end),
118-
Some(&("#".to_string() + &grid_color.rgba_hex())),
119-
);
108+
overlay_context.line(document_to_viewport.transform_point2(start), document_to_viewport.transform_point2(end), Some(&grid_color));
120109
}
121110

122111
for (tan, multiply) in [(tan_a, -1.), (tan_b, 1.)] {
@@ -130,17 +119,13 @@ fn grid_overlay_isometric(document: &DocumentMessageHandler, overlay_context: &m
130119
let y_pos = (((inverse_project(&min_y) - origin.y) / spacing).ceil() + line_index as f64) * spacing + origin.y;
131120
let start = DVec2::new(min_x, project(&DVec2::new(min_x, y_pos)));
132121
let end = DVec2::new(max_x, project(&DVec2::new(max_x, y_pos)));
133-
overlay_context.line(
134-
document_to_viewport.transform_point2(start),
135-
document_to_viewport.transform_point2(end),
136-
Some(&("#".to_string() + &grid_color.rgba_hex())),
137-
);
122+
overlay_context.line(document_to_viewport.transform_point2(start), document_to_viewport.transform_point2(end), Some(&grid_color));
138123
}
139124
}
140125
}
141126

142127
fn grid_overlay_isometric_dot(document: &DocumentMessageHandler, overlay_context: &mut OverlayContext, y_axis_spacing: f64, angle_a: f64, angle_b: f64) {
143-
let grid_color = document.snapping_state.grid.grid_color;
128+
let grid_color = "#".to_string() + &document.snapping_state.grid.grid_color.to_rgba_hex_srgb();
144129
let cmp = |a: &f64, b: &f64| a.partial_cmp(b).unwrap();
145130
let origin = document.snapping_state.grid.origin;
146131
let document_to_viewport = document.navigation_handler.calculate_offset_transform(overlay_context.size / 2., &document.document_ptz);
@@ -180,7 +165,7 @@ fn grid_overlay_isometric_dot(document: &DocumentMessageHandler, overlay_context
180165
overlay_context.dashed_line(
181166
document_to_viewport.transform_point2(start),
182167
document_to_viewport.transform_point2(end),
183-
Some(&("#".to_string() + &grid_color.rgba_hex())),
168+
Some(&grid_color),
184169
Some(1.),
185170
Some((spacing_x / cos_a) * document_to_viewport.matrix2.x_axis.length() - 1.),
186171
None,
@@ -228,10 +213,8 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
228213
};
229214
let update_color = |grid, update: fn(&mut GridSnapping) -> Option<&mut Color>| {
230215
update_val::<ColorInput, _>(grid, move |grid, color| {
231-
if let FillChoice::Solid(color) = color.value {
232-
if let Some(update_color) = update(grid) {
233-
*update_color = color;
234-
}
216+
if let (Some(color), Some(update_color)) = (color.value.as_solid(), update(grid)) {
217+
*update_color = color.to_linear_srgb();
235218
}
236219
})
237220
};
@@ -278,7 +261,7 @@ pub fn overlay_options(grid: &GridSnapping) -> Vec<LayoutGroup> {
278261
Separator::new(SeparatorType::Related).widget_holder(),
279262
]);
280263
color_widgets.push(
281-
ColorInput::new(FillChoice::Solid(grid.grid_color))
264+
ColorInput::new(FillChoice::Solid(grid.grid_color.to_gamma_srgb()))
282265
.tooltip("Grid display color")
283266
.allow_none(false)
284267
.on_update(update_color(grid, |grid| Some(&mut grid.grid_color)))

editor/src/messages/portfolio/document/overlays/utility_types.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ impl OverlayContext {
320320
let mut fill_color = graphene_std::Color::from_rgb_str(crate::consts::COLOR_OVERLAY_WHITE.strip_prefix('#').unwrap())
321321
.unwrap()
322322
.with_alpha(0.05)
323-
.rgba_hex();
323+
.to_rgba_hex_srgb();
324324
fill_color.insert(0, '#');
325325
let fill_color = Some(fill_color.as_str());
326326
self.line(start + DVec2::X * radius * sign, start + DVec2::X * (radius * scale), None);
@@ -357,7 +357,10 @@ impl OverlayContext {
357357

358358
// Hover ring
359359
if show_hover_ring {
360-
let mut fill_color = graphene_std::Color::from_rgb_str(COLOR_OVERLAY_BLUE.strip_prefix('#').unwrap()).unwrap().with_alpha(0.5).rgba_hex();
360+
let mut fill_color = graphene_std::Color::from_rgb_str(COLOR_OVERLAY_BLUE.strip_prefix('#').unwrap())
361+
.unwrap()
362+
.with_alpha(0.5)
363+
.to_rgba_hex_srgb();
361364
fill_color.insert(0, '#');
362365

363366
self.render_context.set_line_width(HOVER_RING_STROKE_WIDTH);

editor/src/messages/portfolio/document/utility_types/misc.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,10 +217,7 @@ impl Default for GridSnapping {
217217
Self {
218218
origin: DVec2::ZERO,
219219
grid_type: Default::default(),
220-
grid_color: COLOR_OVERLAY_GRAY
221-
.strip_prefix('#')
222-
.and_then(Color::from_rgb_str)
223-
.expect("Should create Color from prefixed hex string"),
220+
grid_color: Color::from_rgb_str(COLOR_OVERLAY_GRAY.strip_prefix('#').unwrap()).unwrap(),
224221
dot_display: false,
225222
}
226223
}

editor/src/messages/tool/common_functionality/color_selector.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,14 @@ impl ToolColorOptions {
6060

6161
pub fn apply_fill(&self, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>) {
6262
if let Some(color) = self.active_color() {
63-
let fill = graphene_core::vector::style::Fill::solid(color);
63+
let fill = graphene_core::vector::style::Fill::solid(color.to_gamma_srgb());
6464
responses.add(GraphOperationMessage::FillSet { layer, fill });
6565
}
6666
}
6767

6868
pub fn apply_stroke(&self, weight: f64, layer: LayerNodeIdentifier, responses: &mut VecDeque<Message>) {
6969
if let Some(color) = self.active_color() {
70-
let stroke = graphene_core::vector::style::Stroke::new(Some(color), weight);
70+
let stroke = graphene_core::vector::style::Stroke::new(Some(color.to_gamma_srgb()), weight);
7171
responses.add(GraphOperationMessage::StrokeSet { layer, stroke });
7272
}
7373
}
@@ -111,9 +111,11 @@ impl ToolColorOptions {
111111
widgets.push(radio);
112112
widgets.push(Separator::new(SeparatorType::Related).widget_holder());
113113

114-
let color_button = ColorInput::new(FillChoice::from_optional_color(self.active_color()))
115-
.allow_none(color_allow_none)
116-
.on_update(color_callback);
114+
let fill_choice = match self.active_color() {
115+
Some(color) => FillChoice::Solid(color.to_gamma_srgb()),
116+
None => FillChoice::None,
117+
};
118+
let color_button = ColorInput::new(fill_choice).allow_none(color_allow_none).on_update(color_callback);
117119
widgets.push(color_button.widget_holder());
118120

119121
widgets

editor/src/messages/tool/common_functionality/graph_modification_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ pub fn get_fill_color(layer: LayerNodeIdentifier, network_interface: &NodeNetwor
275275
let TaggedValue::Fill(graphene_std::vector::style::Fill::Solid(color)) = inputs.get(fill_index)?.as_value()? else {
276276
return None;
277277
};
278-
Some(*color)
278+
Some(color.to_linear_srgb())
279279
}
280280

281281
/// Get the current blend mode of a layer from the closest Blend Mode node

editor/src/messages/tool/tool_messages/brush_tool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl LayoutHolder for BrushTool {
155155
false,
156156
|_| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(None)).into(),
157157
|color_type: ToolColorType| WidgetCallback::new(move |_| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::ColorType(color_type.clone())).into()),
158-
|color: &ColorInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(color.value.as_solid())).into(),
158+
|color: &ColorInput| BrushToolMessage::UpdateOptions(BrushToolMessageOptionsUpdate::Color(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(),
159159
));
160160

161161
widgets.push(Separator::new(SeparatorType::Related).widget_holder());

editor/src/messages/tool/tool_messages/ellipse_tool.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ impl LayoutHolder for EllipseTool {
9191
true,
9292
|_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(None)).into(),
9393
|color_type: ToolColorType| WidgetCallback::new(move |_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColorType(color_type.clone())).into()),
94-
|color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(color.value.as_solid())).into(),
94+
|color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(),
9595
);
9696

9797
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
@@ -101,7 +101,7 @@ impl LayoutHolder for EllipseTool {
101101
true,
102102
|_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColor(None)).into(),
103103
|color_type: ToolColorType| WidgetCallback::new(move |_| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColorType(color_type.clone())).into()),
104-
|color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColor(color.value.as_solid())).into(),
104+
|color: &ColorInput| EllipseToolMessage::UpdateOptions(EllipseOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(),
105105
));
106106
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
107107
widgets.push(create_weight_widget(self.options.line_weight));

editor/src/messages/tool/tool_messages/eyedropper_tool.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ fn disable_cursor_preview(responses: &mut VecDeque<Message>) {
159159
fn update_cursor_preview(responses: &mut VecDeque<Message>, input: &InputPreprocessorMessageHandler, global_tool_data: &DocumentToolData, set_color_choice: Option<String>) {
160160
responses.add(FrontendMessage::UpdateEyedropperSamplingState {
161161
mouse_position: Some(input.mouse.position.into()),
162-
primary_color: "#".to_string() + global_tool_data.primary_color.rgb_hex().as_str(),
163-
secondary_color: "#".to_string() + global_tool_data.secondary_color.rgb_hex().as_str(),
162+
primary_color: "#".to_string() + global_tool_data.primary_color.to_rgb_hex_srgb().as_str(),
163+
secondary_color: "#".to_string() + global_tool_data.secondary_color.to_rgb_hex_srgb().as_str(),
164164
set_color_choice,
165165
});
166166
}

editor/src/messages/tool/tool_messages/fill_tool.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ impl Fsm for FillToolFsmState {
9191
return self;
9292
}
9393
let fill = match color_event {
94-
FillToolMessage::FillPrimaryColor => Fill::Solid(global_tool_data.primary_color),
95-
FillToolMessage::FillSecondaryColor => Fill::Solid(global_tool_data.secondary_color),
94+
FillToolMessage::FillPrimaryColor => Fill::Solid(global_tool_data.primary_color.to_gamma_srgb()),
95+
FillToolMessage::FillSecondaryColor => Fill::Solid(global_tool_data.secondary_color.to_gamma_srgb()),
9696
_ => return self,
9797
};
9898

@@ -167,7 +167,7 @@ mod test_fill {
167167
editor.click_tool(ToolType::Fill, MouseKeys::LEFT, DVec2::new(2., 2.), ModifierKeys::empty()).await;
168168
let fills = get_fills(&mut editor).await;
169169
assert_eq!(fills.len(), 1);
170-
assert_eq!(fills[0], Fill::Solid(Color::GREEN));
170+
assert_eq!(fills[0].as_solid().unwrap().to_rgba8_srgb(), Color::GREEN.to_rgba8_srgb());
171171
}
172172

173173
#[tokio::test]
@@ -180,6 +180,6 @@ mod test_fill {
180180
editor.click_tool(ToolType::Fill, MouseKeys::LEFT, DVec2::new(2., 2.), ModifierKeys::SHIFT).await;
181181
let fills = get_fills(&mut editor).await;
182182
assert_eq!(fills.len(), 1);
183-
assert_eq!(fills[0], Fill::Solid(color));
183+
assert_eq!(fills[0].as_solid().unwrap().to_rgba8_srgb(), color.to_rgba8_srgb());
184184
}
185185
}

editor/src/messages/tool/tool_messages/freehand_tool.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl LayoutHolder for FreehandTool {
9797
true,
9898
|_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(None)).into(),
9999
|color_type: ToolColorType| WidgetCallback::new(move |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColorType(color_type.clone())).into()),
100-
|color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(color.value.as_solid())).into(),
100+
|color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::FillColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(),
101101
);
102102

103103
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
@@ -107,7 +107,7 @@ impl LayoutHolder for FreehandTool {
107107
true,
108108
|_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(None)).into(),
109109
|color_type: ToolColorType| WidgetCallback::new(move |_| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColorType(color_type.clone())).into()),
110-
|color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(color.value.as_solid())).into(),
110+
|color: &ColorInput| FreehandToolMessage::UpdateOptions(FreehandOptionsUpdate::StrokeColor(color.value.as_solid().map(|color| color.to_linear_srgb()))).into(),
111111
));
112112
widgets.push(Separator::new(SeparatorType::Unrelated).widget_holder());
113113
widgets.push(create_weight_widget(self.options.line_weight));

0 commit comments

Comments
 (0)