[librsvg/rustification] gradient.rs: Start an implementation of gradient parameters in Rust



commit 2842469ebb90f045d3c92d479795fa0b57cae89e
Author: Federico Mena Quintero <federico gnome org>
Date:   Wed Nov 23 19:04:35 2016 -0600

    gradient.rs: Start an implementation of gradient parameters in Rust
    
    Gradients can inherit their attributes from "fallback" gradients
    mentioned by IRI.  The C code does a little magic to resolve the
    fallbacks: it does a shallow-copy of an RsvgLinearGradient or
    RsvgRadialGradient structure, and then walks the chain of fallbacks,
    filling in the shallow-copied structure as appropriate.  This is done
    even for the children of the gradient node, i.e. its color stops: the
    pointer to the node->children is shallow-copied (!)
    
    For the Rust version, we'll have specific structures to hold a
    gradient's semantics.  They'll have Option<> fields that can be resolved
    from fallbacks.  We will have a "digested" array of color stops, not a
    high-level array of child nodes that may or may not actually contain
    stop elements.

 rust/src/gradient.rs |  108 ++++++++++++++++++++++++++++++++++++++++++++++++++
 rust/src/lib.rs      |    1 +
 2 files changed, 109 insertions(+), 0 deletions(-)
---
diff --git a/rust/src/gradient.rs b/rust/src/gradient.rs
new file mode 100644
index 0000000..4d25c49
--- /dev/null
+++ b/rust/src/gradient.rs
@@ -0,0 +1,108 @@
+extern crate cairo;
+
+use length::*;
+
+struct ColorStop {
+    offset: f64,
+    rgba:   u32
+}
+
+/* Any of the attributes in gradient elements may be omitted.  In turn, the missing
+ * ones can be inherited from the gradient referenced by its "fallback" IRI.  We
+ * represent these possibly-missing attributes as Option<foo>.
+ */
+struct GradientCommon {
+    obj_bbox: Option<bool>,
+    affine:   Option<cairo::Matrix>,
+    spread:   Option<cairo::Extend>,
+    fallback: Option<&str>,
+    stops:    Option<Vec<ColorStop>>
+}
+
+struct LinearGradient {
+    common: GradientCommon,
+    x1:     Option<RsvgLength>,
+    y1:     Option<RsvgLength>,
+    x2:     Option<RsvgLength>,
+    y2:     Option<RsvgLength>
+}
+
+struct RadialGradient {
+    common: GradientCommon,
+    cx:     Option<RsvgLength>,
+    cy:     Option<RsvgLength>,
+    r:      Option<RsvgLength>,
+    fx:     Option<RsvgLength>,
+    fy:     Option<RsvgLength>,
+}
+
+impl GradientCommon {
+    fn get_defaults () -> GradientCommon {
+        GradientCommon {
+            obj_bbox: Some (true),                         // these are per the spec
+            affine:   Some (cairo::Matrix::identity ()),
+            spread:   Some (cairo::Extend::Pad),
+            fallback: None,
+            stops:    Some (Vec<ColorStop>::new ())        // empty array of color stops
+        }
+    }
+
+    fn is_resolved (&self) -> bool {
+        self.obj_bbox.is_some() && 
+            self.affine.is_some () &&
+            self.spread.is_some () &&
+            self.stops.is_some ()
+    }
+}
+
+fn make_length (value: f64, dir: LengthDir) -> RsvgLength {
+    assert! (value >= 0.0 && value <= 1.0);
+
+    RsvgLength {
+        length: value,
+        unit:   LengthUnit::Default,
+        dir:    dir
+    }
+}
+
+impl LinearGradient {
+    fn get_defaults () -> LinearGradient {
+        LinearGradient {
+            common: GradientCommon::get_defaults (),
+            x1:     Some (make_length (0.0, LengthDir::Horizontal)),  // these are per the spec
+            y1:     Some (make_length (0.0, LengthDir::Vertical)),
+            x2:     Some (make_length (1.0, LengthDir::Horizontal)),
+            y2:     Some (make_length (0.0, LengthDir::Vertical))
+        }
+    }
+
+    fn is_resolved (&self) -> bool {
+        self.common.is_resolved () &&
+            self.x1.is_some () &&
+            self.y1.is_some () &&
+            self.x2.is_some () &&
+            self.y2.is_some ()
+    }
+}
+
+impl RadialGradient {
+    fn get_defaults () -> RadialGradient {
+        RadialGradient {
+            common: GradientCommon::get_defaults (),
+            cx:     Some (make_length (0.5, LengthDir::Horizontal)),
+            cy:     Some (make_length (0.5, LengthDir::Vertical)),
+            r:      Some (make_length (0.5, LengthDir::Both)),
+            fx:     Some (make_length (0.5, LengthDir::Horizontal)) // per the spec, equal to cx
+            fy:     Some (make_length (0.5, LengthDir::Vertical))   // per the spec, equal to cy
+        }
+    }
+
+    fn is_resolved (&self) -> bool {
+        self.common.is_resolved () &&
+            self.cx.is_some () && 
+            self.cy.is_some () && 
+            self.r.is_some () && 
+            self.fx.is_some () && 
+            self.fy.is_some ()
+    }
+}
diff --git a/rust/src/lib.rs b/rust/src/lib.rs
index 1283bdc..2068691 100644
--- a/rust/src/lib.rs
+++ b/rust/src/lib.rs
@@ -28,6 +28,7 @@ pub use length::{
 
 mod drawing_ctx;
 mod handle;
+mod gradient;
 mod length;
 mod marker;
 mod node;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]