[librsvg/rustification] gradient.rs: Implement setting linear gradients on a Cairo context
- From: Federico Mena Quintero <federico src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [librsvg/rustification] gradient.rs: Implement setting linear gradients on a Cairo context
- Date: Thu, 1 Dec 2016 03:19:47 +0000 (UTC)
commit 675922d932f75aeb8036ce33215b19d45171fd45
Author: Federico Mena Quintero <federico gnome org>
Date: Wed Nov 30 18:10:12 2016 -0600
gradient.rs: Implement setting linear gradients on a Cairo context
rust/Cargo.toml | 7 ++-
rust/src/gradient.rs | 114 +++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 113 insertions(+), 8 deletions(-)
---
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 188362a..949e4b0 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -7,13 +7,16 @@ authors = ["Federico Mena Quintero <federico gnome org>"]
libc = "0.2"
[dependencies.cairo-sys-rs]
-git = "https://github.com/gtk-rs/cairo.git"
+#git = "https://github.com/gtk-rs/cairo.git"
+git = "https://github.com/federicomenaquintero/cairo.git"
[dependencies.cairo-rs]
-git = "https://github.com/gtk-rs/cairo.git"
+#git = "https://github.com/gtk-rs/cairo.git"
+git = "https://github.com/federicomenaquintero/cairo.git"
[dependencies.glib]
git = "https://github.com/gtk-rs/glib"
+version = "0.1.1"
[lib]
name = "rsvg_internals"
diff --git a/rust/src/gradient.rs b/rust/src/gradient.rs
index cab051a..61f0f48 100644
--- a/rust/src/gradient.rs
+++ b/rust/src/gradient.rs
@@ -4,9 +4,15 @@ extern crate cairo_sys;
extern crate glib;
use self::glib::translate::*;
+use self::cairo::Pattern;
use length::*;
+use drawing_ctx;
+use drawing_ctx::RsvgDrawingCtx;
+
+use bbox::*;
+
use self::cairo::MatrixTrait;
#[derive(Copy, Clone)]
@@ -74,7 +80,7 @@ impl GradientCommon {
}
fn is_resolved (&self) -> bool {
- self.obj_bbox.is_some() &&
+ self.obj_bbox.is_some() &&
self.affine.is_some () &&
self.spread.is_some () &&
self.stops.is_some ()
@@ -146,10 +152,10 @@ impl GradientVariant {
},
GradientVariant::Radial { cx, cy, r, fx, fy } => {
- cx.is_some () &&
- cy.is_some () &&
- r.is_some () &&
- fx.is_some () &&
+ cx.is_some () &&
+ cy.is_some () &&
+ r.is_some () &&
+ fx.is_some () &&
fy.is_some ()
}
}
@@ -228,6 +234,20 @@ impl Gradient {
self.common.add_color_stop (offset, rgba);
}
+ fn add_color_stops_to_pattern (&self,
+ pattern: &mut cairo::Gradient,
+ opacity: u8) {
+ let stops = self.common.stops.as_ref ().unwrap ();
+
+ for stop in stops {
+ let rgba = stop.rgba;
+ pattern.add_color_stop_rgba (stop.offset,
+ ((rgba >> 24) & 0xff) as f64 / 255.0,
+ ((rgba >> 16) & 0xff) as f64 / 255.0,
+ ((rgba >> 8) & 0xff) as f64 / 255.0,
+ (((rgba >> 0) & 0xff) * opacity as u32) as f64 / 255.0 / 255.0);
+ }
+ }
}
trait FallbackSource {
@@ -260,6 +280,88 @@ fn resolve_gradient (gradient: &Gradient, fallback_source: &FallbackSource) -> G
result
}
+fn set_common_on_pattern (gradient: &Gradient,
+ draw_ctx: &mut RsvgDrawingCtx,
+ pattern: &mut cairo::LinearGradient,
+ bbox: &RsvgBbox,
+ opacity: u8)
+{
+ let cr = drawing_ctx::get_cairo_context (draw_ctx);
+
+ let mut affine = gradient.common.affine.unwrap ();
+
+ let obj_bbox = gradient.common.obj_bbox.unwrap ();
+
+ if obj_bbox {
+ let bbox_matrix = cairo::Matrix::new (bbox.rect.width, 0.0,
+ 0.0, bbox.rect.height,
+ bbox.rect.x, bbox.rect.y);
+ affine = cairo::Matrix::multiply (&affine, &bbox_matrix);
+ }
+
+ affine.invert ();
+ pattern.set_matrix (affine);
+ pattern.set_extend (gradient.common.spread.unwrap ());
+
+ gradient.add_color_stops_to_pattern (pattern, opacity);
+
+ cr.set_source (pattern);
+}
+
+fn set_linear_gradient_on_pattern (gradient: &Gradient,
+ draw_ctx: &mut RsvgDrawingCtx,
+ bbox: &RsvgBbox,
+ opacity: u8)
+{
+ if let GradientVariant::Linear { x1, y1, x2, y2 } = gradient.variant {
+ let obj_bbox = gradient.common.obj_bbox.unwrap ();
+
+ if obj_bbox {
+ drawing_ctx::push_view_box (draw_ctx, 1.0, 1.0);
+ }
+
+ let mut pattern = cairo::LinearGradient::new (x1.as_ref ().unwrap ().normalize (draw_ctx),
+ y1.as_ref ().unwrap ().normalize (draw_ctx),
+ x2.as_ref ().unwrap ().normalize (draw_ctx),
+ y2.as_ref ().unwrap ().normalize (draw_ctx));
+
+ if obj_bbox {
+ drawing_ctx::pop_view_box (draw_ctx);
+ }
+
+ set_common_on_pattern (gradient, draw_ctx, &mut pattern, bbox, opacity);
+ } else {
+ unreachable! ();
+ }
+}
+
+fn set_radial_gradient_on_pattern (gradient: &Gradient,
+ draw_ctx: &mut RsvgDrawingCtx,
+ bbox: &RsvgBbox,
+ opacity: u8) {
+ unimplemented! ();
+}
+
+fn set_pattern_on_draw_context (gradient: &Gradient,
+ draw_ctx: &mut RsvgDrawingCtx,
+ bbox: &RsvgBbox,
+ opacity: u8) {
+ assert! (gradient.is_resolved ());
+
+ match gradient.variant {
+ GradientVariant::Linear { .. } => {
+ set_linear_gradient_on_pattern (gradient, draw_ctx, bbox, opacity);
+ }
+
+ GradientVariant::Radial { .. } => {
+ set_radial_gradient_on_pattern (gradient, draw_ctx, bbox, opacity);
+ }
+ }
+
+
+}
+
+
/* All the arguments are pointers because they are in fact optional in
* SVG. We turn the arguments into Option<foo>: NULL into None, and
* anything else into a Some().
@@ -276,7 +378,7 @@ pub unsafe extern fn gradient_linear_new (x1: *const RsvgLength,
let my_obj_bbox = { if obj_bbox.is_null () { None } else { Some (*obj_bbox) } };
let my_affine = { if affine.is_null () { None } else { Some (*affine) } };
let my_spread = { if spread.is_null () { None } else { Some (*spread) } };
- let my_fallback_name = from_glib_none (fallback_name);
+ let my_fallback_name = { if fallback_name.is_null () { None } else { Some (String::from_glib_none
(fallback_name)) } };
let my_x1 = { if x1.is_null () { None } else { Some (*x1) } };
let my_y1 = { if y1.is_null () { None } else { Some (*y1) } };
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]