Clone in a terminal:
Commit 3da8a54
Johan Mattsson - 2016-01-07T23:32:56+00:00
3da8a54f69e4a302017eb75de4f5879a9aa2ee61johan.mattsson.m@gmail.com

Use SVG transform, parse opacity and gradients

Changed files (17)

Diff

diff --git a/libbirdfont/Color.vala b/libbirdfont/Color.valadeleted file mode 100644index a6e872d..0000000--- a/libbirdfont/Color.vala+++ /dev/null@@ -1,281 +0,0 @@-/* Copyright (C) 1999 The Free Software Foundation- *- * Authors: Simon Budig <Simon.Budig@unix-ag.org> (original code)- *          Federico Mena-Quintero <federico@gimp.org> (cleanup for GTK+)- *          Jonathan Blandford <jrb@redhat.com> (cleanup for GTK+)- *- * 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 2 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.- *- * You should have received a copy of the GNU Lesser General Public- * License along with this library; if not, write to the- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,- * Boston, MA 02111-1307, USA.- */--namespace BirdFont {--public class Color {-	public double r;-	public double g;-	public double b;-	public double a;-	-	public Color (double r, double g, double b, double a) {-		this.r = r;-		this.g = g;-		this.b = b;-		this.a = a;-	}--	public Color.hsba (double h, double s, double v, double a) {-		double hue, saturation, value;-		double f, p, q, t;--		this.a = a;--		if (s == 0.0) {-			r = v;-			g = v;-			b = v;-		} else {-			hue = h * 6.0;-			saturation = s;-			value = v;--			if (hue == 6.0) {-				hue = 0.0;-			}--			f = hue - (int) hue;-			p = value * (1.0 - saturation);-			q = value * (1.0 - saturation * f);-			t = value * (1.0 - saturation * (1.0 - f));--			switch ((int) hue) {-			case 0:-				r = value;-				g = t;-				b = p;-				break;--			case 1:-				r = q;-				g = value;-				b = p;-				break;--			case 2:-				r = p;-				g = value;-				b = t;-				break;--			case 3:-				r = p;-				g = q;-				b = value;-				break;--			case 4:-				r = t;-				g = p;-				b = value;-				break;--			case 5:-				r = value;-				g = p;-				b = q;-				break;--			default:-				assert_not_reached ();-			}-		}-	}--	public static Color? parse (string? svg_color) {-		if (svg_color == null) {-			return null;-		}-		-		string color = ((!) svg_color).replace ("#", "");-		uint32 c;-		string[] arguments;-		Color parsed = black ();-		-		if (color.char_count () == 6) {-			color.scanf ("%x", out c);-			parsed.r = (uint8)((c & 0xFF0000) >> 16) / 254.0;-			parsed.g = (uint8)((c & 0x00FF00) >> 8)/ 254.0;-			parsed.b = (uint8)(c & 0x0000FF) / 254.0;-		} else if (color.char_count () == 3) {-			color.scanf ("%x", out c);-			parsed.r = (uint8)(((c & 0xF00) >> 4) | ((c & 0xF00) >> 8)) / 254.0;-			parsed.g = (uint8)((c & 0x0F0) | ((c & 0x0F0) >> 4)) / 254.0;-			parsed.b = (uint8)(((c & 0x00F) << 4) | (c & 0x00F)) / 254.0;-		} else if (color.index_of ("%") > -1) {-			color = color.replace ("rgb", "");-			color = color.replace (" ", "");-			color = color.replace ("\t", "");-			color = color.replace ("%", "");-			arguments = color.split (",");-			-			return_val_if_fail (arguments.length == 3, parsed);-			arguments[0].scanf ("%lf", out parsed.r);-			arguments[1].scanf ("%lf", out parsed.g);-			arguments[2].scanf ("%lf", out parsed.b);-		} else if (color.index_of ("rgb") > -1) {-			color = color.replace ("rgb", "");-			color = color.replace (" ", "");-			color = color.replace ("\t", "");-			arguments = color.split (",");-			-			return_val_if_fail (arguments.length == 3, parsed);-			-			int r, g, b;-			arguments[0].scanf ("%d", out r);-			parsed.r = r / 254.0;-			-			arguments[1].scanf ("%d", out g);-			parsed.g = g / 254.0;-			-			arguments[2].scanf ("%d", out b);-			parsed.b = b / 254.0;-		} else {-			warning ("Unknown color type: " + color);-		}-		-		-		return parsed;- 	}--	public void to_hsva (out double h, out double s, out double v, out double a) {-		double red, green, blue;-		double min, max;-		double delta;--		a = this.a;-		-		red = r;-		green = g;-		blue = b;--		h = 0.0;--		if (red > green) {-			if (red > blue)-				max = red;-			else-				max = blue;--			if (green < blue)-				min = green;-			else-				min = blue;-		} else {-			if (green > blue)-				max = green;-			else-				max = blue;--			if (red < blue)-				min = red;-			else-				min = blue;-		}--		v = max;--		if (max != 0.0)-			s = (max - min) / max;-		else-			s = 0.0;--		if (s == 0.0)-			h = 0.0;-		else {-			delta = max - min;--			if (red == max)-				h = (green - blue) / delta;-			else if (green == max)-				h = 2 + (blue - red) / delta;-			else if (blue == max)-				h = 4 + (red - green) / delta;--			h /= 6.0;--			if (h < 0.0)-				h += 1.0;-			else if (h > 1.0)-				h -= 1.0;-		}-	}--	public static Color black () {-		return new Color (0, 0, 0, 1);-	}--	public static Color red () {-		return new Color (1, 0, 0, 1);-	}--	public static Color green () {-		return new Color (0, 1, 0, 1);-	}--	public static Color blue () {-		return new Color (0, 0, 1, 1);-	}--	public static Color yellow () {-		return new Color (222.0 / 255, 203.0 / 255, 43 / 255.0, 1);-	}--	public static Color brown () {-		return new Color (160.0 / 255, 90.0 / 255, 44.0 / 255, 1);-	}-	-	public static Color pink () {-		return new Color (247.0 / 255, 27.0 / 255, 113 / 255.0, 1);-	}-	-	public static Color white () {-		return new Color (1, 1, 1, 1);-	}-	-	public static Color grey () {-		return new Color (0.5, 0.5, 0.5, 1);-	}-	-	public static Color magenta () {-		return new Color (103.0 / 255, 33.0 / 255, 120.0 / 255, 1);-	}-	-	public string to_string () {-		return @"r: $r, g: $g, b: $b, a: $a";-	}-	-	public Color copy () {-		return new Color (r, g, b, a);-	}--	public string to_rgb_hex () {-		string s = "#";-		s += Font.to_hex_code ((unichar) Math.rint (r  * 254));-		s += Font.to_hex_code ((unichar) Math.rint (g  * 254));-		s += Font.to_hex_code ((unichar) Math.rint (b  * 254));-		return s;-	}-}--}diff --git a/libbirdfont/Doubles.vala b/libbirdfont/Doubles.valaindex 9a8f9c9..9f158e3 100644--- a/libbirdfont/Doubles.vala+++ b/libbirdfont/Doubles.vala@@ -48,6 +48,20 @@ public class Doubles : GLib.Object { 		data[size] = d; 		size++; 	}+	+	public double get_double (int index) {+		if (unlikely (index < 0)) {+			warning ("index < 0");+			return 0;+		}++		if (unlikely (index >= size)) {+			warning ("index >= size");+			return 0;+		}+		+		return data[index];+	} }  }diff --git a/libbirdfont/Glyph.vala b/libbirdfont/Glyph.valaindex f967ac7..8f06a5d 100644--- a/libbirdfont/Glyph.vala+++ b/libbirdfont/Glyph.vala@@ -1793,6 +1793,7 @@ public class Glyph : FontDisplay { 			cr.save (); 			cr.new_path (); 			+			// FIXME: layer transforms 			foreach (Object o in get_visible_objects ()) { 				if (o is PathObject) { 					Path p = ((PathObject) o).get_path ();diff --git a/libbirdfont/Gradient.vala b/libbirdfont/Gradient.valadeleted file mode 100644index c91e5b9..0000000--- a/libbirdfont/Gradient.vala+++ /dev/null@@ -1,53 +0,0 @@-/*-	Copyright (C) 2015 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;-using Math;--namespace BirdFont {--public class Gradient : GLib.Object {-	public double x1;-	public double y1;-	public double x2;-	public double y2;--	public Gee.ArrayList<Stop> stops;-	-	public int id = -1;--	public Gradient () {-		x1 = 0;-		y1 = 0;-		x2 = 0;-		y2 = 0;-		stops = new Gee.ArrayList<Stop> ();-	}-	-	public Gradient copy () {-		Gradient g = new Gradient ();-		g.x1 = x1;-		g.y1 = y1;-		g.x2 = x2;-		g.y2 = y2;-		-		foreach (Stop s in stops) {-			g.stops.add (s.copy ());-		}-		-		return g;-	}-}--}diff --git a/libbirdfont/Object.vala b/libbirdfont/Object.valadeleted file mode 100644index 3047210..0000000--- a/libbirdfont/Object.vala+++ /dev/null@@ -1,110 +0,0 @@-/*-	Copyright (C) 2015 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;-using Math;--namespace BirdFont {--public abstract class Object : GLib.Object {-	bool open = false;-	-	public bool visible = true;-	public SvgStyle style = new SvgStyle ();-	public Gee.ArrayList<SvgTransform> transforms = new Gee.ArrayList<SvgTransform> ();-	-	public virtual Color? color { get; set; } // FIXME: keep this in svg style-	public virtual Color? stroke_color { get; set; }-	public virtual Gradient? gradient { get; set; }--	/** Path boundaries */-	public virtual double xmax { get; set; }-	public virtual double xmin { get; set; }-	public virtual double ymax { get; set; }-	public virtual double ymin { get; set; }-	-	public virtual double rotation { get; set; }-	public virtual double stroke { get; set; }-	public virtual LineCap line_cap { get; set; default = LineCap.BUTT; }-	public virtual bool fill { get; set; }-		-	public Object () {	-	}--	public Object.create_copy (Object o) {	-		open = o.open;-	}-		-	public void set_open (bool open) {-		this.open = open;-	}-	-	public bool is_open () {-		return open;-	}--	public abstract void update_region_boundaries ();-	public abstract bool is_over (double x, double y);-	public abstract void draw (Context cr, Color? c = null);-	public abstract Object copy ();-	public abstract void move (double dx, double dy);-	public abstract void rotate (double theta, double xc, double yc);-	public abstract bool is_empty ();-	public abstract void resize (double ratio_x, double ratio_y);--	public static void copy_attributes (Object from, Object to) {-		to.open = from.open;--		to.color = from.color;-		to.stroke_color = from.stroke_color;-		to.gradient = from.gradient;-		-		to.xmax = from.xmax;-		to.xmin = from.xmin;-		to.ymax = from.ymax;-		to.ymin = from.ymin;-		-		to.rotation = from.rotation;-		to.stroke = from.stroke;-		to.line_cap = from.line_cap;-		to.fill = from.fill;	-	}-	-	public virtual string to_string () {-		return "Object";-	}--	public void fill_and_stroke (Context cr) {-		Color fill, stroke;-		-		if (style.fill != null) {-			fill = (!) style.fill;-			cr.set_source_rgba (fill.r, fill.g, fill.b, fill.a);-			-			if (style.stroke != null) {-				cr.fill_preserve ();-			} else {-				cr.fill ();-			}-		}-		-		if (style.stroke != null) {-			stroke = (!) style.stroke;-			cr.set_source_rgba (stroke.r, stroke.g, stroke.b, stroke.a);-			cr.stroke ();-		}-	}-}--}diff --git a/libbirdfont/Stop.vala b/libbirdfont/Stop.valadeleted file mode 100644index ad4aa4c..0000000--- a/libbirdfont/Stop.vala+++ /dev/null@@ -1,35 +0,0 @@-/*-	Copyright (C) 2015 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;-using Math;--namespace BirdFont {--public class Stop : GLib.Object {-	public Color color = Color.black ();-	public double offset = 0;-	-	public Stop () {-	}-	-	public Stop copy () {-		Stop s = new Stop ();-		s.color = color.copy  ();-		s.offset = offset;-		return s;-	}-}--}diff --git a/libbirdfont/Svg/Color.vala b/libbirdfont/Svg/Color.valanew file mode 100644index 0000000..6acdd99--- /dev/null+++ b/libbirdfont/Svg/Color.vala@@ -0,0 +1,285 @@+/* Copyright (C) 1999 The Free Software Foundation+ *+ * Authors: Simon Budig <Simon.Budig@unix-ag.org> (original code)+ *          Federico Mena-Quintero <federico@gimp.org> (cleanup for GTK+)+ *          Jonathan Blandford <jrb@redhat.com> (cleanup for GTK+)+ *+ * 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 2 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.+ *+ * You should have received a copy of the GNU Lesser General Public+ * License along with this library; if not, write to the+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,+ * Boston, MA 02111-1307, USA.+ */++namespace BirdFont {++public class Color {+	public double r;+	public double g;+	public double b;+	public double a;+	+	public Color (double r, double g, double b, double a) {+		this.r = r;+		this.g = g;+		this.b = b;+		this.a = a;+	}++	public Color.hsba (double h, double s, double v, double a) {+		double hue, saturation, value;+		double f, p, q, t;++		this.a = a;++		if (s == 0.0) {+			r = v;+			g = v;+			b = v;+		} else {+			hue = h * 6.0;+			saturation = s;+			value = v;++			if (hue == 6.0) {+				hue = 0.0;+			}++			f = hue - (int) hue;+			p = value * (1.0 - saturation);+			q = value * (1.0 - saturation * f);+			t = value * (1.0 - saturation * (1.0 - f));++			switch ((int) hue) {+			case 0:+				r = value;+				g = t;+				b = p;+				break;++			case 1:+				r = q;+				g = value;+				b = p;+				break;++			case 2:+				r = p;+				g = value;+				b = t;+				break;++			case 3:+				r = p;+				g = q;+				b = value;+				break;++			case 4:+				r = t;+				g = p;+				b = value;+				break;++			case 5:+				r = value;+				g = p;+				b = q;+				break;++			default:+				assert_not_reached ();+			}+		}+	}++	public static Color? parse (string? svg_color) {+		if (svg_color == null) {+			return null;+		}+		+		string color = ((!) svg_color).replace ("#", "");+		uint32 c;+		string[] arguments;+		Color parsed = black ();++		if (color == "none") {+			return null;+		}+		+		if (color.char_count () == 6) {+			color.scanf ("%x", out c);+			parsed.r = (uint8)((c & 0xFF0000) >> 16) / 254.0;+			parsed.g = (uint8)((c & 0x00FF00) >> 8)/ 254.0;+			parsed.b = (uint8)(c & 0x0000FF) / 254.0;+		} else if (color.char_count () == 3) {+			color.scanf ("%x", out c);+			parsed.r = (uint8)(((c & 0xF00) >> 4) | ((c & 0xF00) >> 8)) / 254.0;+			parsed.g = (uint8)((c & 0x0F0) | ((c & 0x0F0) >> 4)) / 254.0;+			parsed.b = (uint8)(((c & 0x00F) << 4) | (c & 0x00F)) / 254.0;+		} else if (color.index_of ("%") > -1) {+			color = color.replace ("rgb", "");+			color = color.replace (" ", "");+			color = color.replace ("\t", "");+			color = color.replace ("%", "");+			arguments = color.split (",");+			+			return_val_if_fail (arguments.length == 3, parsed);+			arguments[0].scanf ("%lf", out parsed.r);+			arguments[1].scanf ("%lf", out parsed.g);+			arguments[2].scanf ("%lf", out parsed.b);+		} else if (color.index_of ("rgb") > -1) {+			color = color.replace ("rgb", "");+			color = color.replace (" ", "");+			color = color.replace ("\t", "");+			arguments = color.split (",");+			+			return_val_if_fail (arguments.length == 3, parsed);+			+			int r, g, b;+			arguments[0].scanf ("%d", out r);+			parsed.r = r / 254.0;+			+			arguments[1].scanf ("%d", out g);+			parsed.g = g / 254.0;+			+			arguments[2].scanf ("%d", out b);+			parsed.b = b / 254.0;+		} else {+			warning ("Unknown color type: " + color);+		}+		+		+		return parsed;+ 	}++	public void to_hsva (out double h, out double s, out double v, out double a) {+		double red, green, blue;+		double min, max;+		double delta;++		a = this.a;+		+		red = r;+		green = g;+		blue = b;++		h = 0.0;++		if (red > green) {+			if (red > blue)+				max = red;+			else+				max = blue;++			if (green < blue)+				min = green;+			else+				min = blue;+		} else {+			if (green > blue)+				max = green;+			else+				max = blue;++			if (red < blue)+				min = red;+			else+				min = blue;+		}++		v = max;++		if (max != 0.0)+			s = (max - min) / max;+		else+			s = 0.0;++		if (s == 0.0)+			h = 0.0;+		else {+			delta = max - min;++			if (red == max)+				h = (green - blue) / delta;+			else if (green == max)+				h = 2 + (blue - red) / delta;+			else if (blue == max)+				h = 4 + (red - green) / delta;++			h /= 6.0;++			if (h < 0.0)+				h += 1.0;+			else if (h > 1.0)+				h -= 1.0;+		}+	}++	public static Color black () {+		return new Color (0, 0, 0, 1);+	}++	public static Color red () {+		return new Color (1, 0, 0, 1);+	}++	public static Color green () {+		return new Color (0, 1, 0, 1);+	}++	public static Color blue () {+		return new Color (0, 0, 1, 1);+	}++	public static Color yellow () {+		return new Color (222.0 / 255, 203.0 / 255, 43 / 255.0, 1);+	}++	public static Color brown () {+		return new Color (160.0 / 255, 90.0 / 255, 44.0 / 255, 1);+	}+	+	public static Color pink () {+		return new Color (247.0 / 255, 27.0 / 255, 113 / 255.0, 1);+	}+	+	public static Color white () {+		return new Color (1, 1, 1, 1);+	}+	+	public static Color grey () {+		return new Color (0.5, 0.5, 0.5, 1);+	}+	+	public static Color magenta () {+		return new Color (103.0 / 255, 33.0 / 255, 120.0 / 255, 1);+	}+	+	public string to_string () {+		return @"r: $r, g: $g, b: $b, a: $a";+	}+	+	public Color copy () {+		return new Color (r, g, b, a);+	}++	public string to_rgb_hex () {+		string s = "#";+		s += Font.to_hex_code ((unichar) Math.rint (r  * 254));+		s += Font.to_hex_code ((unichar) Math.rint (g  * 254));+		s += Font.to_hex_code ((unichar) Math.rint (b  * 254));+		return s;+	}+}++}diff --git a/libbirdfont/Svg/Gradient.vala b/libbirdfont/Svg/Gradient.valanew file mode 100644index 0000000..c91e5b9--- /dev/null+++ b/libbirdfont/Svg/Gradient.vala@@ -0,0 +1,53 @@+/*+	Copyright (C) 2015 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;+using Math;++namespace BirdFont {++public class Gradient : GLib.Object {+	public double x1;+	public double y1;+	public double x2;+	public double y2;++	public Gee.ArrayList<Stop> stops;+	+	public int id = -1;++	public Gradient () {+		x1 = 0;+		y1 = 0;+		x2 = 0;+		y2 = 0;+		stops = new Gee.ArrayList<Stop> ();+	}+	+	public Gradient copy () {+		Gradient g = new Gradient ();+		g.x1 = x1;+		g.y1 = y1;+		g.x2 = x2;+		g.y2 = y2;+		+		foreach (Stop s in stops) {+			g.stops.add (s.copy ());+		}+		+		return g;+	}+}++}diff --git a/libbirdfont/Svg/Object.vala b/libbirdfont/Svg/Object.valanew file mode 100644index 0000000..a6f178c--- /dev/null+++ b/libbirdfont/Svg/Object.vala@@ -0,0 +1,185 @@+/*+	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;+using Math;++namespace BirdFont {++public abstract class Object : GLib.Object {+	bool open = false;+	+	public bool visible = true;+	public SvgStyle style = new SvgStyle ();+	public Gee.ArrayList<SvgTransform> transforms = new Gee.ArrayList<SvgTransform> ();+	+	public virtual Color? color { get; set; } // FIXME: keep this in svg style+	public virtual Color? stroke_color { get; set; }+	public virtual Gradient? gradient { get; set; }++	/** Path boundaries */+	public virtual double xmax { get; set; }+	public virtual double xmin { get; set; }+	public virtual double ymax { get; set; }+	public virtual double ymin { get; set; }+	+	public virtual double rotation { get; set; }+	public virtual double stroke { get; set; }+	public virtual LineCap line_cap { get; set; default = LineCap.BUTT; }+	public virtual bool fill { get; set; }+		+	public Object () {	+	}++	public Object.create_copy (Object o) {	+		open = o.open;+	}+		+	public void set_open (bool open) {+		this.open = open;+	}+	+	public bool is_open () {+		return open;+	}++	public abstract void update_region_boundaries ();+	public abstract bool is_over (double x, double y);+	public abstract void draw (Context cr, Color? c = null);+	public abstract Object copy ();+	public abstract void move (double dx, double dy);+	public abstract void rotate (double theta, double xc, double yc);+	public abstract bool is_empty ();+	public abstract void resize (double ratio_x, double ratio_y);++	public static void copy_attributes (Object from, Object to) {+		to.open = from.open;++		to.color = from.color;+		to.stroke_color = from.stroke_color;+		to.gradient = from.gradient;+		+		to.xmax = from.xmax;+		to.xmin = from.xmin;+		to.ymax = from.ymax;+		to.ymin = from.ymin;+		+		to.rotation = from.rotation;+		to.stroke = from.stroke;+		to.line_cap = from.line_cap;+		to.fill = from.fill;	+	}+	+	public virtual string to_string () {+		return "Object";+	}++	public void fill_and_stroke (Context cr) {+		Color fill, stroke;+		bool need_fill = style.fill_gradient != null || style.fill != null;+		bool need_stroke = style.stroke_gradient != null || style.stroke != null;+		+		cr.set_line_width (style.stroke_width);+	+		if (style.fill_gradient != null) {+			apply_gradient (cr, (!) style.fill_gradient);+		}+		+		if (style.fill != null) {+			fill = (!) style.fill;+			cr.set_source_rgba (fill.r, fill.g, fill.b, fill.a);+		}++		if (need_fill) {+			if (need_stroke) {+				cr.fill_preserve ();+			} else {+				cr.fill ();+			}	+		}++		if (style.stroke_gradient != null) {+			apply_gradient (cr, (!) style.stroke_gradient);+		}+		+		if (style.stroke != null) {+			stroke = (!) style.stroke;+			cr.set_source_rgba (stroke.r, stroke.g, stroke.b, stroke.a);+		}++		if (need_stroke) {+			cr.stroke ();+		}+	}+	+	public void apply_gradient (Context cr, Gradient? gradient) {+		Cairo.Pattern pattern;+		Gradient g;+		+		if (gradient != null) {+			g = (!) gradient;+			+			pattern = new Cairo.Pattern.linear (+				g.x1,+				g.y1,+				g.x2,+				g.y2);+			+			foreach (Stop s in g.stops) {+				Color c = s.color;+				pattern.add_color_stop_rgba (s.offset, c.r, c.g, c.b, c.a);+			}+			+			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);+				}+			}+		}+	}+}++}diff --git a/libbirdfont/Svg/Points.vala b/libbirdfont/Svg/Points.valaindex 7e93574..2f4dd25 100644--- a/libbirdfont/Svg/Points.vala+++ b/libbirdfont/Svg/Points.vala@@ -20,6 +20,7 @@ public class Points : GLib.Object { 	public Doubles point_data = new Doubles.for_capacity (100); 	public double x = 0; 	public double y = 0;+	public bool closed = false;  	public void add (double p) { 		point_data.add (p);diff --git a/libbirdfont/Svg/Rectangle.vala b/libbirdfont/Svg/Rectangle.valaindex d1c3925..da0db92 100644--- a/libbirdfont/Svg/Rectangle.vala+++ b/libbirdfont/Svg/Rectangle.vala@@ -36,6 +36,8 @@ public class Rectangle : Object { 	public override void draw (Context cr, Color? c = null) { 		cr.save (); 		+		apply_transform (cr);+		 		if (rx == 0 && ry == 0) { 			cr.rectangle (x, y, width, height); 		} else {diff --git a/libbirdfont/Svg/Stop.vala b/libbirdfont/Svg/Stop.valanew file mode 100644index 0000000..ad4aa4c--- /dev/null+++ b/libbirdfont/Svg/Stop.vala@@ -0,0 +1,35 @@+/*+	Copyright (C) 2015 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;+using Math;++namespace BirdFont {++public class Stop : GLib.Object {+	public Color color = Color.black ();+	public double offset = 0;+	+	public Stop () {+	}+	+	public Stop copy () {+		Stop s = new Stop ();+		s.color = color.copy  ();+		s.offset = offset;+		return s;+	}+}++}diff --git a/libbirdfont/Svg/SvgDrawing.vala b/libbirdfont/Svg/SvgDrawing.valanew file mode 100644index 0000000..72f9994--- /dev/null+++ b/libbirdfont/Svg/SvgDrawing.vala@@ -0,0 +1,25 @@+/*+	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 SvgDrawing {+	public Layer root_layer = new Layer ();+	public Gee.ArrayList<Gradient> gradients = new Gee.ArrayList<Gradient> ();+}++}diff --git a/libbirdfont/Svg/SvgFile.vala b/libbirdfont/Svg/SvgFile.valaindex ad93fb6..378bd0a 100644--- a/libbirdfont/Svg/SvgFile.vala+++ b/libbirdfont/Svg/SvgFile.vala@@ -21,7 +21,7 @@ public class SvgFile : GLib.Object { 	public SvgFile () {		 	} 	-	public Layer parse (string path) {+	public SvgDrawing parse (string path) { 		string xml_data; 		 		try {@@ -38,23 +38,27 @@ public class SvgFile : GLib.Object { 			warning (error.message); 		} 		-		return new Layer ();+		return new SvgDrawing (); 	} 	-	private Layer parse_svg_file (Tag tag) {-		Layer layer = new Layer ();-	+	private SvgDrawing parse_svg_file (Tag tag) {+		SvgDrawing drawing = new SvgDrawing ();+		 		foreach (Tag t in tag) { 			string name = t.get_name (); 			 			if (name == "g") {-				parse_layer (layer, t);+				parse_layer (drawing.root_layer, t);+			}++			if (name == "defs") {+				parse_defs (drawing, t); 			} 			-			parse_object (layer, t);+			parse_object (drawing.root_layer, t); 		} 		-		return layer;+		return drawing; 	}  	private void parse_layer (Layer layer, Tag tag) {@@ -77,12 +81,14 @@ public class SvgFile : GLib.Object { 		} 					 		foreach (Tag t in tag) {-			if (t.get_name () == "g") {+			string name = t.get_name ();+			+			if (name == "g") { 				Layer sublayer = new Layer (); 				parse_layer (layer, t); 				layer.subgroups.add (sublayer); 			}-+			 			parse_object (layer, t); 		} @@ -93,6 +99,89 @@ public class SvgFile : GLib.Object { 		} 	} +	void parse_defs (SvgDrawing drawing, Tag tag) {+		foreach (Tag t in tag) {+			// FIXME: radial+			string name = t.get_name ();+			+			if (name == "linearGradient") {+				parse_linear_gradient (drawing, t);+			}+		}+	}++	void parse_linear_gradient (SvgDrawing drawing, Tag tag) {+		Gradient gradient = new Gradient ();+		+		foreach (Attribute attr in tag.get_attributes ()) {+			string name = attr.get_name ();+			+			if (name == "href") {	+			}++			if (name == "x1") {+				gradient.x1 = parse_number (attr.get_content ());+			}++			if (name == "y1") {	+				gradient.y1 = parse_number (attr.get_content ());+			}+			+			if (name == "x2") {+				gradient.x2 = parse_number (attr.get_content ());+			}++			if (name == "y2") {+				gradient.y2 = parse_number (attr.get_content ());+			}+		}+		+		foreach (Tag t in tag) {+			// FIXME: radial+			string name = t.get_name ();+			+			if (name == "stop") {+				parse_stop (gradient, tag);+			}+		}+	}++	void parse_stop (Gradient gradient, Tag tag) {+		SvgStyle style = SvgStyle.parse (tag.get_attributes ());+		Stop stop = new Stop ();+		+		foreach (Attribute attr in tag.get_attributes ()) {+			string name = attr.get_name ();+			+			if (name == "offset") {+				string stop_offset = attr.get_content ();+				+				if (stop_offset.index_of ("%") > -1) {+					stop_offset = stop_offset.replace ("%", "");+					stop.offset = parse_number (stop_offset) / 100.0;+				} else {+					stop.offset = parse_number (stop_offset);+				}+			}+		}+		+		string? stop_color = style.style.get ("stop-color");+		string? stop_opacity = style.style.get ("stop-opacity");+		Color? color = Color.black ();+		+		if (stop_color != null) {+			color = Color.parse (stop_color);+			+			if (color != null) {+				stop.color = (!) color;+			}+		}++		if (stop_opacity != null && color != null) {+			((!) color).a = parse_number (stop_opacity);+		}+	}+	 	void parse_object (Layer layer, Tag tag) { 		string name = tag.get_name (); 		@@ -243,16 +332,22 @@ public class SvgFile : GLib.Object { 		return transform; 	} -    private string remove_unit (string d) {+    private static string remove_unit (string d) { 		string s = d.replace ("pt", ""); 		s = s.replace ("pc", ""); 		s = s.replace ("mm", ""); 		s = s.replace ("cm", ""); 		s = s.replace ("in", "");+		s = s.replace ("px", ""); 		return s; 	}     -	private double parse_number (string d) {+	public static double parse_number (string? number_with_unit) {+		if (number_with_unit == null) {+			return 0;+		}+		+		string d = (!) number_with_unit; 		string s = remove_unit (d); 		double n = SvgParser.parse_double (s); 		@@ -397,6 +492,7 @@ public class SvgFile : GLib.Object { 				points.add (bezier_points[i].x0); 				points.add (bezier_points[i].y0); 			} else if (bezier_points[i].type == 'z') {+				points.closed = true; 				path_data.add (points); 				points = new Points (); 			} else {@@ -405,6 +501,10 @@ public class SvgFile : GLib.Object { 			} 		} +		if (points.point_data.size > 0) {+			path_data.add (points);+		}+ 		return path_data; 	} }diff --git a/libbirdfont/Svg/SvgParser.vala b/libbirdfont/Svg/SvgParser.valaindex 10b47a8..22ddc16 100644--- a/libbirdfont/Svg/SvgParser.vala+++ b/libbirdfont/Svg/SvgParser.vala@@ -64,8 +64,8 @@ public class SvgParser { 		 	public static void import_color_svg (Glyph glyph, string path) { 		SvgFile svg_file = new SvgFile ();-		Layer layer = svg_file.parse (path);-		glyph.add_layer (layer);+		SvgDrawing drawing = svg_file.parse (path);+		glyph.add_layer (drawing.root_layer); 	} 	 	public static void import_folder (SvgType type) {diff --git a/libbirdfont/Svg/SvgPath.vala b/libbirdfont/Svg/SvgPath.valaindex b78a04c..f040193 100644--- a/libbirdfont/Svg/SvgPath.vala+++ b/libbirdfont/Svg/SvgPath.vala@@ -32,15 +32,19 @@ public class SvgPath : Object { 			 	public override void draw (Context cr, Color? c = null) { 		cr.save ();+		apply_transform (cr);		+		cr.new_path (); 		 		foreach (Points p in points) {-			cr.new_path ();-			cr.move_to (p.x, p.y);			+			cr.move_to (p.x, p.y); 			draw_points (cr, p);+			+			if (p.closed) {+				cr.close_path ();+			} 		}-+			 		fill_and_stroke	(cr);- 		cr.restore (); 	} diff --git a/libbirdfont/Svg/SvgStyle.vala b/libbirdfont/Svg/SvgStyle.valaindex 8a1be19..3bdc673 100644--- a/libbirdfont/Svg/SvgStyle.vala+++ b/libbirdfont/Svg/SvgStyle.vala@@ -19,10 +19,14 @@ namespace BirdFont {  public class SvgStyle { 	-	Gee.HashMap<string, string> style;+	public Gee.HashMap<string, string> style; 	 	public Color? stroke = null; 	public Color? fill = null;+	public Gradient? stroke_gradient = null;+	public Gradient? fill_gradient = null;++	public double stroke_width = 0; 	 	public SvgStyle () { 		style = new Gee.HashMap<string, string> ();@@ -64,9 +68,10 @@ public class SvgStyle { 		return double.parse (style.get ("stroke-width")); 	} 	-	 	public static SvgStyle parse (Attributes attributes) { 		SvgStyle s = new SvgStyle ();+		double fill_opacity = 1;+		double stroke_opacity = 1; 		 		foreach (Attribute a in attributes) { 			if (a.get_name () == "style") {@@ -84,9 +89,29 @@ public class SvgStyle { 			if (a.get_name () == "fill") { 				s.style.set ("fill", a.get_content ()); 			}++			if (a.get_name () == "fill-opacity") {+				fill_opacity = SvgFile.parse_number (a.get_content ());+			}++			if (a.get_name () == "stroke-opacity") {+				stroke_opacity = SvgFile.parse_number (a.get_content ());+			} 		} 	 		s.stroke = Color.parse (s.style.get ("stroke"));++		if (s.fill != null) {+			Color color = (!) s.fill;+			color.a = fill_opacity;+		}+		+		if (s.stroke != null) {+			Color color = (!) s.stroke;+			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;

Contact

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