Clone in a terminal:
Commit 76c9ad8
Johan Mattsson - 2016-01-09T14:21:26+00:00
76c9ad8905cf9d3013d67ecb82b884adf105aa7fjohan.mattsson.m@gmail.com

Linear gradients and matrix tranform on gradients

Changed files (12)

Diff

diff --git a/libbirdfont/Layer.vala b/libbirdfont/Layer.valaindex c78de2d..91385f8 100644--- a/libbirdfont/Layer.vala+++ b/libbirdfont/Layer.vala@@ -25,12 +25,12 @@ public class Layer : GLib.Object { 	public Gradient? gradient = null; 	public bool single_path = false; 	-	public Gee.ArrayList<SvgTransform> transforms;+	public SvgTransforms transforms; 	 	public Layer () { 		objects = new ObjectGroup (); 		subgroups = new Gee.ArrayList<Layer> ();-		transforms = new Gee.ArrayList<SvgTransform> ();+		transforms = new SvgTransforms (); 	}  	public int index_of (Layer sublayer) {diff --git a/libbirdfont/Svg/Color.vala b/libbirdfont/Svg/Color.valaindex 6acdd99..1e8c47f 100644--- a/libbirdfont/Svg/Color.vala+++ b/libbirdfont/Svg/Color.vala@@ -266,7 +266,8 @@ public class Color { 	} 	 	public string to_string () {-		return @"r: $r, g: $g, b: $b, a: $a";+		string alpha = Font.to_hex_code ((unichar) Math.rint (a  * 254));+		return @"$(to_rgb_hex ())" + alpha; 	} 	 	public Color copy () {diff --git a/libbirdfont/Svg/Defs.vala b/libbirdfont/Svg/Defs.valanew file mode 100644index 0000000..4cfd66c--- /dev/null+++ b/libbirdfont/Svg/Defs.vala@@ -0,0 +1,85 @@+/*+	Copyright (C) 2016 Johan Mattsson++	This library is free software; you can redistribute it and/or modify +	it under the terms of the GNU Lesser General Public License as +	published by the Free Software Foundation; either version 3 of the +	License, or (at your option) any later version.++	This library is distributed in the hope that it will be useful, but +	WITHOUT ANY WARRANTY; without even the implied warranty of +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +	Lesser General Public License for more details.+*/++using B;+using Math;++namespace BirdFont {++public class Defs {+	public Gee.ArrayList<Gradient> gradients = new Gee.ArrayList<Gradient> ();++	public void add (Gradient g) {+		gradients.add (g);+	}+	+	public Gradient? get_gradient_for_url (string? url) {+		if (url == null) {+			return null;+		}+		+		string tag_id = (!) url;++		if (unlikely (!is_url (tag_id))) {+			warning ("Not an URL: " + tag_id);+			return null;+		}++		int p1 = tag_id.index_of ("(");+		if (unlikely (p1 == -1)) {+			warning ("Not an URL: " + tag_id);+			return null;+		}++		int p2 = tag_id.index_of (")");+		if (unlikely (p2 == -1 || p2 < p1)) {+			warning ("Not an URL: " +  tag_id);+			return null;+		}+	+		p1 += "(".length;+		int length = p2 - p1;+		tag_id = tag_id.substring (p1, length);+		+		return get_gradient_for_id (tag_id);+	} ++	public Gradient? get_gradient_for_id (string id) {+		string tag_id;+		+		if (id.has_prefix ("#")) {+			tag_id = id.substring ("#".length);+		} else {+			tag_id = id;+		}+		+		foreach (Gradient gradient in gradients) {+			if (gradient.id == tag_id) {+				return gradient;+			}+		}+		+		return null;		+	}++	public static bool is_url (string? attribute) {+		if (attribute == null) {+			return false;+		}+		+		return ((!) attribute).has_prefix ("url");+	}+}++}diff --git a/libbirdfont/Svg/Gradient.vala b/libbirdfont/Svg/Gradient.valaindex c91e5b9..959f53b 100644--- a/libbirdfont/Svg/Gradient.vala+++ b/libbirdfont/Svg/Gradient.vala@@ -25,7 +25,9 @@ public class Gradient : GLib.Object {  	public Gee.ArrayList<Stop> stops; 	-	public int id = -1;+	public string id = "";+	public string? href = null;+	public SvgTransforms transforms;  	public Gradient () { 		x1 = 0;@@ -33,6 +35,7 @@ public class Gradient : GLib.Object { 		x2 = 0; 		y2 = 0; 		stops = new Gee.ArrayList<Stop> ();+		transforms = new SvgTransforms (); 	} 	 	public Gradient copy () {@@ -48,6 +51,29 @@ public class Gradient : GLib.Object { 		 		return g; 	}+	+	public void copy_stops (Gradient g) {+		foreach (Stop stop in g.stops) {+			stops.add (stop.copy ());+		}+	}+	+	public string to_string () {+		StringBuilder description = new StringBuilder ();+		description.append ("Gradient: ");+		description.append (@"x1=$x1, y1=$y1, x2=$x2, y2=$y2");+		+		foreach (Stop stop in stops) {+			description.append (" ");+			description.append (stop.to_string ());+		}+		+		return description.str;+	}+	+	public Matrix get_matrix () {+		return transforms.get_matrix ();+	} }  }diff --git a/libbirdfont/Svg/Object.vala b/libbirdfont/Svg/Object.valaindex a6f178c..a6ce662 100644--- a/libbirdfont/Svg/Object.vala+++ b/libbirdfont/Svg/Object.vala@@ -22,7 +22,7 @@ public abstract class Object : GLib.Object { 	 	public bool visible = true; 	public SvgStyle style = new SvgStyle ();-	public Gee.ArrayList<SvgTransform> transforms = new Gee.ArrayList<SvgTransform> ();+	public SvgTransforms transforms = new SvgTransforms (); 	 	public virtual Color? color { get; set; } // FIXME: keep this in svg style 	public virtual Color? stroke_color { get; set; }@@ -94,9 +94,7 @@ public abstract class Object : GLib.Object { 	 		if (style.fill_gradient != null) { 			apply_gradient (cr, (!) style.fill_gradient);-		}-		-		if (style.fill != null) {+		} else if (style.fill != null) { 			fill = (!) style.fill; 			cr.set_source_rgba (fill.r, fill.g, fill.b, fill.a); 		}@@ -111,9 +109,7 @@ public abstract class Object : GLib.Object {  		if (style.stroke_gradient != null) { 			apply_gradient (cr, (!) style.stroke_gradient);-		}-		-		if (style.stroke != null) {+		} else if (style.stroke != null) { 			stroke = (!) style.stroke; 			cr.set_source_rgba (stroke.r, stroke.g, stroke.b, stroke.a); 		}@@ -141,45 +137,17 @@ public abstract class Object : GLib.Object { 				pattern.add_color_stop_rgba (s.offset, c.r, c.g, c.b, c.a); 			} 			+			pattern.set_matrix (g.get_matrix ());+			 			cr.set_source (pattern); 		} 	} 	 	public void apply_transform (Context cr) {-		foreach (SvgTransform transform in transforms) {-			if (transform.type == TransformType.SCALE) {-				if (transform.arguments.size == 1) {-					double s = transform.arguments.get_double (0);-					cr.scale (s, s);-				} else if (transform.arguments.size == 2) {-					double s0 = transform.arguments.get_double (0);-					double s1 = transform.arguments.get_double (1);-					cr.scale (s0, s1);-				}-			} else if (transform.type == TransformType.TRANSLATE) {-				if (transform.arguments.size == 1) {-					double s = transform.arguments.get_double (0);-					cr.translate (s, 0);-				} else if (transform.arguments.size == 2) {-					double s0 = transform.arguments.get_double (0);-					double s1 = transform.arguments.get_double (1);-					cr.translate (s0, s1);-				}-			} else if (transform.type == TransformType.MATRIX) {-				if (transform.arguments.size == 1) {-					double s0 = transform.arguments.get_double (0);-					double s1 = transform.arguments.get_double (1);-					double s2 = transform.arguments.get_double (2);-					double s3 = transform.arguments.get_double (3);					-					double s4 = transform.arguments.get_double (4);-					double s5 = transform.arguments.get_double (5);-					-					Matrix matrix = Matrix (s0, s1, s2, s3, s4, s5);-					cr.set_matrix (matrix);-				}-			}-		}+		Matrix matrix = transforms.get_matrix ();+		cr.set_matrix (matrix); 	}+					 }  }diff --git a/libbirdfont/Svg/Stop.vala b/libbirdfont/Svg/Stop.valaindex ad4aa4c..bec777f 100644--- a/libbirdfont/Svg/Stop.vala+++ b/libbirdfont/Svg/Stop.vala@@ -30,6 +30,10 @@ public class Stop : GLib.Object { 		s.offset = offset; 		return s; 	}+	+	public string to_string () {+		return @"Stop: $(offset), " + color.to_string ();+	} }  }diff --git a/libbirdfont/Svg/SvgDrawing.vala b/libbirdfont/Svg/SvgDrawing.valaindex 72f9994..2253a1d 100644--- a/libbirdfont/Svg/SvgDrawing.vala+++ b/libbirdfont/Svg/SvgDrawing.vala@@ -19,7 +19,7 @@ namespace BirdFont {  public class SvgDrawing { 	public Layer root_layer = new Layer ();-	public Gee.ArrayList<Gradient> gradients = new Gee.ArrayList<Gradient> ();+	public Defs defs = new Defs (); }  }diff --git a/libbirdfont/Svg/SvgFile.vala b/libbirdfont/Svg/SvgFile.valaindex 378bd0a..73eeae7 100644--- a/libbirdfont/Svg/SvgFile.vala+++ b/libbirdfont/Svg/SvgFile.vala@@ -18,6 +18,8 @@ namespace BirdFont {  public class SvgFile : GLib.Object { +	SvgDrawing drawing;+ 	public SvgFile () {		 	} 	@@ -42,7 +44,7 @@ public class SvgFile : GLib.Object { 	} 	 	private SvgDrawing parse_svg_file (Tag tag) {-		SvgDrawing drawing = new SvgDrawing ();+		drawing = new SvgDrawing (); 		 		foreach (Tag t in tag) { 			string name = t.get_name ();@@ -108,15 +110,37 @@ public class SvgFile : GLib.Object { 				parse_linear_gradient (drawing, t); 			} 		}+		+		foreach (Gradient gradient in drawing.defs.gradients) {+			if (gradient.href != null) {+				Gradient? referenced;+				referenced = drawing.defs.get_gradient_for_id ((!) gradient.href);+				+				if (referenced != null) {+					gradient.copy_stops ((!) referenced);+				}+				+				gradient.href = null;+			}+		} 	}  	void parse_linear_gradient (SvgDrawing drawing, Tag tag) { 		Gradient gradient = new Gradient (); 		+		drawing.defs.add (gradient);+		 		foreach (Attribute attr in tag.get_attributes ()) { 			string name = attr.get_name (); 			-			if (name == "href") {	+			// FIXME: gradientUnits+			+			if (name == "gradientTransform") {+				gradient.transforms = parse_transform (attr.get_content ());+			}++			if (name == "href") {+				gradient.href = attr.get_content (); 			}  			if (name == "x1") {@@ -134,6 +158,10 @@ public class SvgFile : GLib.Object { 			if (name == "y2") { 				gradient.y2 = parse_number (attr.get_content ()); 			}++			if (name == "id") {+				gradient.id = attr.get_content ();+			} 		} 		 		foreach (Tag t in tag) {@@ -141,15 +169,17 @@ public class SvgFile : GLib.Object { 			string name = t.get_name (); 			 			if (name == "stop") {-				parse_stop (gradient, tag);+				parse_stop (gradient, t); 			} 		} 	}  	void parse_stop (Gradient gradient, Tag tag) {-		SvgStyle style = SvgStyle.parse (tag.get_attributes ());+		SvgStyle style = SvgStyle.parse (drawing.defs, tag.get_attributes ()); 		Stop stop = new Stop (); 		+		gradient.stops.add (stop);+		 		foreach (Attribute attr in tag.get_attributes ()) { 			string name = attr.get_name (); 			@@ -252,7 +282,7 @@ public class SvgFile : GLib.Object { 		} 		 		rectangle.transforms = get_transform (tag.get_attributes ());-		rectangle.style = SvgStyle.parse (tag.get_attributes ());+		rectangle.style = SvgStyle.parse (drawing.defs,tag.get_attributes ()); 		rectangle.visible = is_visible (tag);	 		 		layer.add_object (rectangle);@@ -268,12 +298,12 @@ public class SvgFile : GLib.Object { 	} 	 	// FIXME: reverse order?-	public Gee.ArrayList<SvgTransform> parse_transform (string transforms) {+	public SvgTransforms parse_transform (string transforms) { 		string[] functions; 		string transform = transforms;-		Gee.ArrayList<SvgTransform> transform_functions;+		SvgTransforms transform_functions; 		-		transform_functions = new Gee.ArrayList<SvgTransform> ();+		transform_functions = new SvgTransforms (); 		 		transform = transform.replace ("\t", " "); 		transform = transform.replace ("\n", " ");@@ -438,14 +468,14 @@ public class SvgFile : GLib.Object { 		return !hidden; 	} -	private Gee.ArrayList<SvgTransform> get_transform (Attributes attributes) {+	private SvgTransforms get_transform (Attributes attributes) { 		foreach (Attribute attr in attributes) { 			if (attr.get_name () == "transform") { 				return parse_transform (attr.get_content ()); 			} 		} 		-		return new Gee.ArrayList<SvgTransform> ();+		return new SvgTransforms (); 	} 	 	private void parse_path (Layer layer, Tag tag) {@@ -458,7 +488,7 @@ public class SvgFile : GLib.Object { 		} 		 		path.transforms = get_transform (tag.get_attributes ());-		path.style = SvgStyle.parse (tag.get_attributes ());+		path.style = SvgStyle.parse (drawing.defs, tag.get_attributes ()); 		path.visible = is_visible (tag);	 		 		layer.add_object (path);diff --git a/libbirdfont/Svg/SvgParser.vala b/libbirdfont/Svg/SvgParser.valaindex 22ddc16..c3a107e 100644--- a/libbirdfont/Svg/SvgParser.vala+++ b/libbirdfont/Svg/SvgParser.vala@@ -508,7 +508,7 @@ public class SvgParser { 			} 		} 		-		style = SvgStyle.parse (tag.get_attributes ());+		style = SvgStyle.parse (null, tag.get_attributes ()); 		 		if (hidden) { 			return;@@ -576,7 +576,7 @@ public class SvgParser { 			} 		} 		-		style = SvgStyle.parse (tag.get_attributes ());+		style = SvgStyle.parse (null, tag.get_attributes ()); 		 		if (hidden) { 			return;@@ -642,7 +642,7 @@ public class SvgParser { 			} 		} 		-		style = SvgStyle.parse (tag.get_attributes ());+		style = SvgStyle.parse (null, tag.get_attributes ()); 		 		if (hidden) { 			return;@@ -720,7 +720,7 @@ public class SvgParser { 			} 		} 		-		style = SvgStyle.parse (tag.get_attributes ());+		style = SvgStyle.parse (null, tag.get_attributes ()); 		 		if (hidden) { 			return;@@ -815,7 +815,7 @@ public class SvgParser { 			} 		} -		style = SvgStyle.parse (tag.get_attributes ());+		style = SvgStyle.parse (null, tag.get_attributes ()); 		 		if (hidden) { 			return path_list;@@ -855,7 +855,7 @@ public class SvgParser { 			} 		} 		-		style = SvgStyle.parse (tag.get_attributes ());+		style = SvgStyle.parse (null, tag.get_attributes ()); 		 		if (hidden) { 			return;diff --git a/libbirdfont/Svg/SvgStyle.vala b/libbirdfont/Svg/SvgStyle.valaindex 3bdc673..a59bd11 100644--- a/libbirdfont/Svg/SvgStyle.vala+++ b/libbirdfont/Svg/SvgStyle.vala@@ -68,7 +68,7 @@ public class SvgStyle { 		return double.parse (style.get ("stroke-width")); 	} 	-	public static SvgStyle parse (Attributes attributes) {+	public static SvgStyle parse (Defs? d, Attributes attributes) { 		SvgStyle s = new SvgStyle (); 		double fill_opacity = 1; 		double stroke_opacity = 1;@@ -99,8 +99,17 @@ public class SvgStyle { 			} 		} 	+		s.stroke_width = SvgFile.parse_number (s.style.get ("stroke-width")); 		s.stroke = Color.parse (s.style.get ("stroke"));+		s.fill = Color.parse (s.style.get ("fill")); +		if (d != null) {+			Defs defs = (!) d;++			s.stroke_gradient = defs.get_gradient_for_url (s.style.get ("stroke"));+			s.fill_gradient = defs.get_gradient_for_url (s.style.get ("fill"));+		}+		 		if (s.fill != null) { 			Color color = (!) s.fill; 			color.a = fill_opacity;@@ -111,9 +120,6 @@ public class SvgStyle { 			color.a = stroke_opacity; 		} 		-		s.stroke_width = SvgFile.parse_number (s.style.get ("stroke-width"));-		s.fill = Color.parse (s.style.get ("fill"));-		 		return s; 	} 	diff --git a/libbirdfont/Svg/SvgTransform.vala b/libbirdfont/Svg/SvgTransform.valaindex 632b527..4721a7d 100644--- a/libbirdfont/Svg/SvgTransform.vala+++ b/libbirdfont/Svg/SvgTransform.vala@@ -13,6 +13,7 @@ */  using B;+using Cairo;  namespace BirdFont { @@ -29,6 +30,46 @@ public class SvgTransform : GLib.Object { 	 	public SvgTransform () { 	}+	+	public Matrix get_matrix () {+		Matrix matrix;+		+		matrix = Matrix.identity ();+		+		if (type == TransformType.SCALE) {+			if (arguments.size == 1) {+				double s = arguments.get_double (0);+				matrix.scale (s, s);+				return matrix;+			} else if (arguments.size == 2) {+				double s0 = arguments.get_double (0);+				double s1 = arguments.get_double (1);+				matrix.scale (s0, s1);+			}+		} else if (type == TransformType.TRANSLATE) {+			if (arguments.size == 1) {+				double s = arguments.get_double (0);+				matrix.translate (s, 0);+			} else if (arguments.size == 2) {+				double s0 = arguments.get_double (0);+				double s1 = arguments.get_double (1);+				matrix.translate (s0, s1);+			}+		} else if (type == TransformType.MATRIX) {+			if (arguments.size == 6) {+				double s0 = arguments.get_double (0);+				double s1 = arguments.get_double (1);+				double s2 = arguments.get_double (2);+				double s3 = arguments.get_double (3);					+				double s4 = arguments.get_double (4);+				double s5 = arguments.get_double (5);+				+				matrix = Matrix (s0, s1, s2, s3, s4, s5);+			}+		}+		+		return matrix;+	} }  }diff --git a/libbirdfont/Svg/SvgTransforms.vala b/libbirdfont/Svg/SvgTransforms.valanew file mode 100644index 0000000..e36e55b--- /dev/null+++ b/libbirdfont/Svg/SvgTransforms.vala@@ -0,0 +1,47 @@+/*+	Copyright (C) 2016 Johan Mattsson++	This library is free software; you can redistribute it and/or modify +	it under the terms of the GNU Lesser General Public License as +	published by the Free Software Foundation; either version 3 of the +	License, or (at your option) any later version.++	This library is distributed in the hope that it will be useful, but +	WITHOUT ANY WARRANTY; without even the implied warranty of +	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +	Lesser General Public License for more details.+*/++using Cairo;++namespace BirdFont {++public class SvgTransforms : GLib.Object {+	public Gee.ArrayList<SvgTransform> transforms;+	+	public SvgTransforms () {+		transforms = new Gee.ArrayList<SvgTransform> ();+	}++	public void add (SvgTransform transform) {+		transforms.add (transform);+	}+	+	public Matrix get_matrix () {+		Matrix matrix = Matrix.identity ();+		+		if (transforms.size == 0) {+			return Matrix.identity ();+		}+		+		matrix = transforms.get (0).get_matrix ();+		+		for (int i = 1; i < transforms.size; i++) {+			matrix.multiply (matrix, transforms.get (i).get_matrix ());+		}+		+		return matrix;+	}+}++}

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112