[librsvg/rustification] path_parser.c: Implement arc comamnds 'A' and 'a'
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/rustification] path_parser.c: Implement arc comamnds 'A' and 'a'
- Date: Tue, 8 Nov 2016 22:06:43 +0000 (UTC)
commit 6d5788b63c4001d071fcf29b79c8f75fb7c194cc
Author: Federico Mena Quintero <federico gnome org>
Date: Tue Nov 8 15:09:49 2016 -0600
path_parser.c: Implement arc comamnds 'A' and 'a'
We don't have a test for this yet; see the comment about handles_arc().
rust/src/path_parser.rs | 108 +++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 108 insertions(+), 0 deletions(-)
---
diff --git a/rust/src/path_parser.rs b/rust/src/path_parser.rs
index 53d69d7..7c154fd 100644
--- a/rust/src/path_parser.rs
+++ b/rust/src/path_parser.rs
@@ -274,6 +274,16 @@ impl<'external> PathParser<'external> {
}
}
+ fn flag (&mut self) -> Option <bool> {
+ if self.match_char ('0') {
+ return Some (false);
+ } else if self.match_char ('1') {
+ return Some (true);
+ } else {
+ return None;
+ }
+ }
+
fn coordinate_pair (&mut self) -> Option<(f64, f64)> {
if let Some (num1) = self.number () {
assert! (self.optional_comma_whitespace ());
@@ -362,6 +372,19 @@ impl<'external> PathParser<'external> {
println! ("emitting curveto ({} {}) ({} {}) ({} {})", x2, y2, x3, y3, x4, y4);
}
+ fn emit_arc (&mut self, rx: f64, ry: f64, x_axis_rotation: f64, large_arc: bool, sweep: bool, x: f64, y:
f64) {
+ let (start_x, start_y) = (self.current_x, self.current_y);
+
+ self.set_current_point (x, y);
+
+ self.builder.arc (start_x, start_y,
+ rx, ry,
+ x_axis_rotation,
+ large_arc,
+ sweep,
+ self.current_x, self.current_y);
+ }
+
fn emit_close_path (&mut self) {
let (x, y) = (self.subpath_start_x, self.subpath_start_y);
self.set_current_point (x, y);
@@ -873,7 +896,86 @@ impl<'external> PathParser<'external> {
false
}
+ fn elliptical_arc_argument_sequence (&mut self, absolute: bool) -> bool {
+ if let Some (rx) = self.nonnegative_number () {
+ assert! (self.optional_comma_whitespace ());
+
+ if let Some (ry) = self.nonnegative_number () {
+ assert! (self.optional_comma_whitespace ());
+
+ if let Some (x_axis_rotation) = self.number () {
+ if self.match_char (',') || self.optional_whitespace () {
+ if let Some (large_arc_flag) = self.flag () {
+ assert! (self.optional_comma_whitespace ());
+
+ if let Some (sweep_flag) = self.flag () {
+ assert! (self.optional_comma_whitespace ());
+
+ if let Some ((mut x, mut y)) = self.coordinate_pair () {
+ if !absolute {
+ x += self.current_x;
+ y += self.current_y;
+ }
+
+ self.emit_arc (rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, x,
y);
+
+ self.whitespace ();
+
+ if self.lookahead_is (',') {
+ assert! (self.match_char (','));
+ assert! (self.optional_whitespace ());
+
+ if !self.elliptical_arc_argument_sequence (absolute) {
+ self.error ("Expected x-radius after comma");
+ return false;
+ }
+ }
+
+ self.elliptical_arc_argument_sequence (absolute);
+ return true;
+ } else {
+ return self.error ("Expected destination coordinate pair for elliptical
arc");
+ }
+ } else {
+ return self.error ("Expected sweep-flag for elliptical arc");
+ }
+ } else {
+ return self.error ("Expected large-arc-flag for elliptical arc");
+ }
+ } else {
+ unreachable! ();
+ }
+ } else {
+ return self.error ("Expected x-axis-rotation for elliptical arc");
+ }
+ } else {
+ return self.error ("Expected nonnegative y-radius for elliptical arc");
+ }
+ } else {
+ false
+ }
+ }
+
fn elliptical_arc (&mut self) -> bool {
+ if self.lookahead_is ('A') || self.lookahead_is ('a') {
+ let absolute: bool;
+
+ if self.match_char ('A') {
+ absolute = true;
+ } else {
+ assert! (self.match_char ('a'));
+ absolute = false;
+ }
+
+ self.optional_whitespace ();
+
+ if self.elliptical_arc_argument_sequence (absolute) {
+ return true;
+ } else {
+ return self.error ("Expected nonnegative x-radius for elliptical arc");
+ }
+ }
+
false
}
}
@@ -1437,4 +1539,10 @@ mod tests {
closepath ()
]);
}
+
+ /* FIXME: we don't have a handles_arc() because
+ * we don't know what segments will be computed by PathBuilder::arc().
+ * Maybe we need to represent arcs as native path builder segments,
+ * and only explode them to Cairo curves at rendering time.
+ */
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]