Skip to content

Commit 1e62af8

Browse files
committed
Remove trailing zeros in rendered SVG path output
1 parent 8dfdc2b commit 1e62af8

File tree

4 files changed

+44
-17
lines changed

4 files changed

+44
-17
lines changed

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

+4-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ impl LayoutHolder for PathTool {
155155
})
156156
.tooltip(colinear_handles_tooltip)
157157
.widget_holder();
158-
let colinear_handles_label = TextLabel::new("Colinear Handles").tooltip(colinear_handles_tooltip).widget_holder();
158+
let colinear_handles_label = TextLabel::new("Colinear Handles")
159+
.disabled(self.tool_data.selection_status.is_none())
160+
.tooltip(colinear_handles_tooltip)
161+
.widget_holder();
159162

160163
Layout::WidgetLayout(WidgetLayout::new(vec![LayoutGroup::Row {
161164
widgets: vec![

libraries/bezier-rs/src/bezier/core.rs

+23-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use super::*;
2+
use utils::format_point;
3+
24
use std::fmt::Write;
35

46
/// Functionality relating to core `Bezier` operations, such as constructors and `abs_diff_eq`.
@@ -122,32 +124,38 @@ impl Bezier {
122124
pub fn write_curve_argument(&self, svg: &mut String) -> std::fmt::Result {
123125
match self.handles {
124126
BezierHandles::Linear => svg.push_str(SVG_ARG_LINEAR),
125-
BezierHandles::Quadratic { handle } => write!(svg, "{SVG_ARG_QUADRATIC}{:.6},{:.6}", handle.x, handle.y)?,
126-
BezierHandles::Cubic { handle_start, handle_end } => write!(svg, "{SVG_ARG_CUBIC}{:.6},{:.6} {:.6},{:.6}", handle_start.x, handle_start.y, handle_end.x, handle_end.y)?,
127+
BezierHandles::Quadratic { handle } => {
128+
format_point(svg, SVG_ARG_QUADRATIC, handle.x, handle.y)?;
129+
}
130+
BezierHandles::Cubic { handle_start, handle_end } => {
131+
format_point(svg, SVG_ARG_CUBIC, handle_start.x, handle_start.y)?;
132+
format_point(svg, " ", handle_end.x, handle_end.y)?;
133+
}
127134
}
128-
write!(svg, " {:.6},{:.6}", self.end.x, self.end.y)
135+
format_point(svg, " ", self.end.x, self.end.y)
129136
}
130137

131138
/// Return the string argument used to create the lines connecting handles to endpoints in an SVG `path`
132139
pub(crate) fn svg_handle_line_argument(&self) -> Option<String> {
140+
let mut result = String::new();
141+
133142
match self.handles {
134-
BezierHandles::Linear => None,
143+
BezierHandles::Linear => {}
135144
BezierHandles::Quadratic { handle } => {
136-
let handle_line = format!("{SVG_ARG_LINEAR}{:.6} {:.6}", handle.x, handle.y);
137-
Some(format!(
138-
"{SVG_ARG_MOVE}{:.6} {:.6} {handle_line} {SVG_ARG_MOVE}{:.6} {:.6} {handle_line}",
139-
self.start.x, self.start.y, self.end.x, self.end.y
140-
))
145+
let _ = format_point(&mut result, SVG_ARG_MOVE, self.start.x, self.start.y);
146+
let _ = format_point(&mut result, SVG_ARG_LINEAR, handle.x, handle.y);
147+
let _ = format_point(&mut result, SVG_ARG_MOVE, self.end.x, self.end.y);
148+
let _ = format_point(&mut result, SVG_ARG_LINEAR, handle.x, handle.y);
141149
}
142150
BezierHandles::Cubic { handle_start, handle_end } => {
143-
let handle_start_line = format!("{SVG_ARG_LINEAR}{:.6} {:.6}", handle_start.x, handle_start.y);
144-
let handle_end_line = format!("{SVG_ARG_LINEAR}{} {}", handle_end.x, handle_end.y);
145-
Some(format!(
146-
"{SVG_ARG_MOVE}{:.6} {:.6} {handle_start_line} {SVG_ARG_MOVE}{:.6} {:.6} {handle_end_line}",
147-
self.start.x, self.start.y, self.end.x, self.end.y
148-
))
151+
let _ = format_point(&mut result, SVG_ARG_MOVE, self.start.x, self.start.y);
152+
let _ = format_point(&mut result, SVG_ARG_LINEAR, handle_start.x, handle_start.y);
153+
let _ = format_point(&mut result, SVG_ARG_MOVE, self.end.x, self.end.y);
154+
let _ = format_point(&mut result, SVG_ARG_LINEAR, handle_end.x, handle_end.y);
149155
}
150156
}
157+
158+
(!result.is_empty()).then_some(result)
151159
}
152160

153161
/// Appends to the `svg` mutable string with an SVG shape representation of the curve.

libraries/bezier-rs/src/subpath/core.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::*;
22
use crate::consts::*;
3+
use crate::utils::format_point;
34

45
use glam::DVec2;
56
use std::fmt::Write;
@@ -163,8 +164,10 @@ impl<PointId: crate::Identifier> Subpath<PointId> {
163164
if self.is_empty() {
164165
return Ok(());
165166
}
167+
166168
let start = transform.transform_point2(self[0].anchor);
167-
write!(svg, "{SVG_ARG_MOVE}{:.6},{:.6}", start.x, start.y)?;
169+
format_point(svg, SVG_ARG_MOVE, start.x, start.y)?;
170+
168171
for bezier in self.iter() {
169172
bezier.apply_transformation(|pos| transform.transform_point2(pos)).write_curve_argument(svg)?;
170173
svg.push(' ');

libraries/bezier-rs/src/utils.rs

+13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::consts::{MAX_ABSOLUTE_DIFFERENCE, STRICT_MAX_ABSOLUTE_DIFFERENCE};
22
use crate::{ManipulatorGroup, Subpath};
33

44
use glam::{BVec2, DMat2, DVec2};
5+
use std::fmt::Write;
56

67
#[derive(Copy, Clone, PartialEq)]
78
/// A structure which can be used to reference a particular point along a `Bezier`.
@@ -294,6 +295,18 @@ pub fn compute_circular_subpath_details<PointId: crate::Identifier>(left: DVec2,
294295
)
295296
}
296297

298+
pub fn format_point(svg: &mut String, prefix: &str, x: f64, y: f64) -> std::fmt::Result {
299+
write!(svg, "{prefix}{:.6}", x)?;
300+
let trimmed_length = svg.trim_end_matches('0').trim_end_matches('.').len();
301+
svg.truncate(trimmed_length);
302+
303+
write!(svg, ",{:.6}", y)?;
304+
let trimmed_length = svg.trim_end_matches('0').trim_end_matches('.').len();
305+
svg.truncate(trimmed_length);
306+
307+
Ok(())
308+
}
309+
297310
#[cfg(test)]
298311
mod tests {
299312
use super::*;

0 commit comments

Comments
 (0)