[librsvg: 2/3] marker: factor out an Angle struct
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg: 2/3] marker: factor out an Angle struct
- Date: Mon, 10 Dec 2018 17:28:19 +0000 (UTC)
commit 6163b75c5d15cc7bce715490654d7884e0d7d429
Author: Paolo Borelli <pborelli gnome org>
Date: Sat Dec 8 21:14:22 2018 +0100
marker: factor out an Angle struct
This should be a zero-cost abstraction that helps us check we
pass the correct params. It also cleans up the code a bit.
rsvg_internals/src/marker.rs | 134 +++++++++++++++++++++++--------------------
1 file changed, 72 insertions(+), 62 deletions(-)
---
diff --git a/rsvg_internals/src/marker.rs b/rsvg_internals/src/marker.rs
index ac87aab1..149eda85 100644
--- a/rsvg_internals/src/marker.rs
+++ b/rsvg_internals/src/marker.rs
@@ -125,7 +125,7 @@ impl NodeMarker {
draw_ctx: &mut DrawingCtx,
xpos: f64,
ypos: f64,
- computed_angle: f64,
+ computed_angle: Angle,
line_width: f64,
clipping: bool,
) -> Result<(), RenderingError> {
@@ -151,10 +151,10 @@ impl NodeMarker {
let rotation = match self.orient.get() {
MarkerOrient::Auto => computed_angle,
- MarkerOrient::Degrees(d) => d * PI / 180.0,
+ MarkerOrient::Degrees(d) => Angle::from_degrees(d),
};
- affine.rotate(rotation);
+ affine.rotate(rotation.radians());
if self.units.get() == MarkerUnits::StrokeWidth {
affine.scale(line_width, line_width);
@@ -588,35 +588,50 @@ fn find_outgoing_directionality_forwards(
(false, 0.0, 0.0)
}
-// Normalizes an angle to [0.0, 2*PI)
-fn normalize_angle(angle: f64) -> f64 {
- let res = angle % (PI * 2.0);
- if res < 0.0 {
- res + PI * 2.0
- } else {
- res
+#[derive(Debug, Copy, Clone, PartialEq)]
+struct Angle(f64);
+
+impl Angle {
+ pub fn new(rad: f64) -> Angle {
+ Angle(Angle::normalize(rad))
}
-}
-fn angle_from_vector(vx: f64, vy: f64) -> f64 {
- let angle = vy.atan2(vx);
+ pub fn from_degrees(deg: f64) -> Angle {
+ Angle(Angle::normalize(deg * PI / 180.0))
+ }
- if angle.is_nan() {
- 0.0
- } else {
- normalize_angle(angle)
+ pub fn from_vector(vx: f64, vy: f64) -> Angle {
+ let rad = vy.atan2(vx);
+
+ if rad.is_nan() {
+ Angle(0.0)
+ } else {
+ Angle(Angle::normalize(rad))
+ }
}
-}
-fn bisect_angles(incoming: f64, outgoing: f64) -> f64 {
- let half_delta: f64;
+ pub fn radians(&self) -> f64 {
+ self.0
+ }
- half_delta = (outgoing - incoming) * 0.5;
+ pub fn bisect(&self, other: Angle) -> Angle {
+ let half_delta = (other.0 - self.0) * 0.5;
- if FRAC_PI_2 < half_delta.abs() {
- normalize_angle(incoming + half_delta - PI)
- } else {
- normalize_angle(incoming + half_delta)
+ if FRAC_PI_2 < half_delta.abs() {
+ Angle(Angle::normalize(self.0 + half_delta - PI))
+ } else {
+ Angle(Angle::normalize(self.0 + half_delta))
+ }
+ }
+
+ // Normalizes an angle to [0.0, 2*PI)
+ fn normalize(rad: f64) -> f64 {
+ let res = rad % (PI * 2.0);
+ if res < 0.0 {
+ res + PI * 2.0
+ } else {
+ res
+ }
}
}
@@ -633,7 +648,7 @@ fn emit_marker_by_name(
name: &Fragment,
xpos: f64,
ypos: f64,
- computed_angle: f64,
+ computed_angle: Angle,
line_width: f64,
clipping: bool,
) -> Result<(), RenderingError> {
@@ -667,11 +682,11 @@ fn emit_marker<E>(
segment: &Segment,
endpoint: MarkerEndpoint,
marker_type: MarkerType,
- orient: f64,
+ orient: Angle,
emit_fn: &mut E,
) -> Result<(), RenderingError>
where
- E: FnMut(MarkerType, f64, f64, f64) -> Result<(), RenderingError>,
+ E: FnMut(MarkerType, f64, f64, Angle) -> Result<(), RenderingError>,
{
let (x, y) = match *segment {
Segment::Degenerate { x, y } => (x, y),
@@ -711,7 +726,7 @@ pub fn render_markers_for_path_builder(
emit_markers_for_path_builder(
builder,
- &mut |marker_type: MarkerType, x: f64, y: f64, computed_angle: f64| {
+ &mut |marker_type: MarkerType, x: f64, y: f64, computed_angle: Angle| {
if let &IRI::Resource(ref marker) = match marker_type {
MarkerType::Start => &values.marker_start.0,
MarkerType::Middle => &values.marker_mid.0,
@@ -730,7 +745,7 @@ fn emit_markers_for_path_builder<E>(
emit_fn: &mut E,
) -> Result<(), RenderingError>
where
- E: FnMut(MarkerType, f64, f64, f64) -> Result<(), RenderingError>,
+ E: FnMut(MarkerType, f64, f64, Angle) -> Result<(), RenderingError>,
{
enum SubpathState {
NoSubpath,
@@ -755,7 +770,7 @@ where
&segments[i - 1],
MarkerEndpoint::End,
MarkerType::End,
- angle_from_vector(incoming_vx, incoming_vy),
+ Angle::from_vector(incoming_vx, incoming_vy),
emit_fn,
)?;
}
@@ -765,7 +780,7 @@ where
segment,
MarkerEndpoint::Start,
MarkerType::Middle,
- 0.0,
+ Angle::new(0.0),
emit_fn,
)?;
@@ -782,7 +797,7 @@ where
segment,
MarkerEndpoint::Start,
MarkerType::Start,
- angle_from_vector(outgoing_vx, outgoing_vy),
+ Angle::from_vector(outgoing_vx, outgoing_vy),
emit_fn,
)?;
@@ -797,22 +812,19 @@ where
let (has_outgoing, outgoing_vx, outgoing_vy) =
find_outgoing_directionality_forwards(&segments, i);
- let incoming: f64;
- let outgoing: f64;
+ let incoming = Angle::from_vector(incoming_vx, incoming_vy);
+ let outgoing = Angle::from_vector(outgoing_vx, outgoing_vy);
- incoming = angle_from_vector(incoming_vx, incoming_vy);
- outgoing = angle_from_vector(outgoing_vx, outgoing_vy);
-
- let angle: f64;
+ let angle: Angle;
if has_incoming && has_outgoing {
- angle = bisect_angles(incoming, outgoing);
+ angle = incoming.bisect(outgoing);
} else if has_incoming {
angle = incoming;
} else if has_outgoing {
angle = outgoing;
} else {
- angle = 0.0;
+ angle = Angle::new(0.0);
}
emit_marker(
@@ -839,12 +851,11 @@ where
if let PathCommand::ClosePath = builder.get_path_commands()[segments.len()] {
let (_, outgoing_vx, outgoing_vy) =
find_outgoing_directionality_forwards(&segments, 0);
- bisect_angles(
- angle_from_vector(incoming_vx, incoming_vy),
- angle_from_vector(outgoing_vx, outgoing_vy),
- )
+ let incoming = Angle::from_vector(incoming_vx, incoming_vy);
+ let outgoing = Angle::from_vector(outgoing_vx, outgoing_vy);
+ incoming.bisect(outgoing)
} else {
- angle_from_vector(incoming_vx, incoming_vy)
+ Angle::from_vector(incoming_vx, incoming_vy)
}
};
@@ -941,11 +952,10 @@ mod directionality_tests {
outgoing_vx: f64,
outgoing_vy: f64,
) {
- let bisected = super::bisect_angles(
- super::angle_from_vector(incoming_vx, incoming_vy),
- super::angle_from_vector(outgoing_vx, outgoing_vy),
- );
- assert!(expected.approx_eq(&bisected, 2.0 * PI * f64::EPSILON, 1));
+ let i = Angle::from_vector(incoming_vx, incoming_vy);
+ let o = Angle::from_vector(outgoing_vx, outgoing_vy);
+ let bisected = i.bisect(o);
+ assert!(expected.approx_eq(&bisected.radians(), 2.0 * PI * f64::EPSILON, 1));
}
#[test]
@@ -1278,7 +1288,7 @@ mod marker_tests {
&mut |marker_type: MarkerType,
x: f64,
y: f64,
- computed_angle: f64|
+ computed_angle: Angle|
-> Result<(), RenderingError> {
v.push((marker_type, x, y, computed_angle));
Ok(())
@@ -1289,10 +1299,10 @@ mod marker_tests {
assert_eq!(
v,
vec![
- (MarkerType::Start, 0.0, 0.0, 0.0),
- (MarkerType::Middle, 1.0, 0.0, angle_from_vector(1.0, 1.0)),
- (MarkerType::Middle, 1.0, 1.0, angle_from_vector(-1.0, 1.0)),
- (MarkerType::End, 0.0, 1.0, angle_from_vector(-1.0, 0.0)),
+ (MarkerType::Start, 0.0, 0.0, Angle::new(0.0)),
+ (MarkerType::Middle, 1.0, 0.0, Angle::from_vector(1.0, 1.0)),
+ (MarkerType::Middle, 1.0, 1.0, Angle::from_vector(-1.0, 1.0)),
+ (MarkerType::End, 0.0, 1.0, Angle::from_vector(-1.0, 0.0)),
]
);
}
@@ -1313,7 +1323,7 @@ mod marker_tests {
&mut |marker_type: MarkerType,
x: f64,
y: f64,
- computed_angle: f64|
+ computed_angle: Angle|
-> Result<(), RenderingError> {
v.push((marker_type, x, y, computed_angle));
Ok(())
@@ -1324,11 +1334,11 @@ mod marker_tests {
assert_eq!(
v,
vec![
- (MarkerType::Start, 0.0, 0.0, 0.0),
- (MarkerType::Middle, 1.0, 0.0, angle_from_vector(1.0, 1.0)),
- (MarkerType::Middle, 1.0, 1.0, angle_from_vector(-1.0, 1.0)),
- (MarkerType::Middle, 0.0, 1.0, angle_from_vector(-1.0, -1.0)),
- (MarkerType::End, 0.0, 0.0, angle_from_vector(1.0, -1.0)),
+ (MarkerType::Start, 0.0, 0.0, Angle::new(0.0)),
+ (MarkerType::Middle, 1.0, 0.0, Angle::from_vector(1.0, 1.0)),
+ (MarkerType::Middle, 1.0, 1.0, Angle::from_vector(-1.0, 1.0)),
+ (MarkerType::Middle, 0.0, 1.0, Angle::from_vector(-1.0, -1.0)),
+ (MarkerType::End, 0.0, 0.0, Angle::from_vector(1.0, -1.0)),
]
);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]