Clone in a terminal:
Commit dfde4f4
Johan Mattsson - 2016-01-06T04:44:55+00:00
dfde4f4b657be0e20ac3300c0f30cf009fbcf203johan.mattsson.m@gmail.com

Parse SVG files

Changed files (14)

Diff

diff --git a/dodo.py b/dodo.pyindex 76db874..6c96486 100644--- a/dodo.py+++ b/dodo.py@@ -303,6 +303,7 @@ def make_libbirdfont(target_binary, deps):         libbirdfont/OpenFontFormat/*.vala \         libbirdfont/TextRendering/*.vala \         libbirdfont/Svg/*.vala \+        --pkg posix \         --pkg """ + config.GEE + """ \         --pkg gio-2.0 \         --pkg cairo \diff --git a/libbirdfont/BezierPoints.vala b/libbirdfont/BezierPoints.valadeleted file mode 100644index 609f075..0000000--- a/libbirdfont/BezierPoints.vala+++ /dev/null@@ -1,33 +0,0 @@-/*-	Copyright (C) 2014 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.-*/--namespace BirdFont {--/** Bezier point container for the SVG parser. */-public class BezierPoints {-	public unichar type = '\0';-	public unichar svg_type = '\0';-	public double x0  = 0;-	public double y0 = 0;-	public double x1 = 0;-	public double y1 = 0;-	public double x2 = 0;-	public double y2 = 0;-	-	public string to_string () {-		return @"$((!)type.to_string ()) $x0,$y0 $x1,$y1 $x2,$y2 SVG:$((!)svg_type.to_string ())";-	}-}--}diff --git a/libbirdfont/Doubles.vala b/libbirdfont/Doubles.valanew file mode 100644index 0000000..50264d5--- /dev/null+++ b/libbirdfont/Doubles.vala@@ -0,0 +1,54 @@+/*+	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;++namespace BirdFont {++public class Doubles : GLib.Object {+	public double* data;+	public int size = 10;+	int capacity = 10;+	+	public Doubles () {+		data = new double[capacity];+	}++	~Doubles () {+		delete data;+		data = null;+	}+	+	public Doubles.for_capacity (int capacity) {+		data = new double[capacity];+		this.capacity = capacity;+	}+		+	public void add(double d) {+		if (size >= capacity) {+			int new_capacity = 2 * capacity;+			double* new_data = new double[new_capacity];+			Posix.memcpy (new_data, data, sizeof (double) * size);+			delete data;+			data = new_data;+			capacity = new_capacity;+		}+		+		data[size] = d;+		size++;+	}+}++}+diff --git a/libbirdfont/FastPath.vala b/libbirdfont/FastPath.valaindex b87ea7a..dfd926e 100644--- a/libbirdfont/FastPath.vala+++ b/libbirdfont/FastPath.vala@@ -227,6 +227,11 @@ public class FastPath : Object { 	public override Object copy () { 		return new FastPath.create_copy (this); 	}++	public override string to_string () {+		return "FastPath";+	}+ }  }diff --git a/libbirdfont/Glyph.vala b/libbirdfont/Glyph.valaindex 75fe30a..52a9e90 100644--- a/libbirdfont/Glyph.vala+++ b/libbirdfont/Glyph.vala@@ -242,6 +242,11 @@ public class Glyph : FontDisplay { 		current_layer = layers.subgroups.size - 1; 	} +	public void add_layer (Layer layer) {+		layers.add_layer (layer);+		current_layer = layers.subgroups.size - 1;+	}+	 	public int get_layer_index (Layer layer) { 		return layers.index_of (layer); 	}@@ -1704,7 +1709,6 @@ public class Glyph : FontDisplay {  	/** Draw filled paths. */ 	public void draw_paths (Context cr, Color? c = null) {-		 		cr.save (); 		cr.new_path (); 		@@ -1788,10 +1792,20 @@ public class Glyph : FontDisplay {  			cr.save (); 			cr.new_path ();-			foreach (Path p in get_visible_paths ()) {-				if (p.stroke == 0) {-					color = p.color == null ? Color.black () : (!) p.color;-					p.draw_path (cr, color);+			+			get_current_layer ().print();+			+			foreach (Object o in get_visible_objects ()) {+				print("visible obj\n");+				if (o is FastPath) {+					Path p = ((FastPath) o).get_path ();++					if (p.stroke == 0) {+						color = p.color == null ? Color.black () : (!) p.color;+						p.draw_path (cr, color);+					}+				} else {+					o.draw (cr); 				} 			} 			cr.close_path ();diff --git a/libbirdfont/Layer.vala b/libbirdfont/Layer.valaindex f862209..bea608c 100644--- a/libbirdfont/Layer.vala+++ b/libbirdfont/Layer.vala@@ -25,9 +25,12 @@ public class Layer : GLib.Object { 	public Gradient? gradient = null; 	public bool single_path = false; 	+	public Gee.ArrayList<SvgTransform> transforms;+	 	public Layer () { 		objects = new ObjectGroup (); 		subgroups = new Gee.ArrayList<Layer> ();+		transforms = new Gee.ArrayList<SvgTransform> (); 	}  	public int index_of (Layer sublayer) {@@ -64,21 +67,21 @@ public class Layer : GLib.Object { 	}  	public ObjectGroup get_visible_objects () {-		ObjectGroup paths = new ObjectGroup ();+		ObjectGroup object_group = new ObjectGroup (); 		 		if (visible) { 			foreach (Object o in objects) {-				paths.add (o);+				object_group.add (o); 			} 		} 		 		foreach (Layer sublayer in subgroups) { 			if (sublayer.visible) {-				paths.append (sublayer.get_visible_objects ());+				object_group.append (sublayer.get_visible_objects ()); 			} 		} 		-		return paths;		+		return object_group;		 	}  	public PathList get_visible_paths () {@@ -211,15 +214,27 @@ public class Layer : GLib.Object { 	} 		 	public void print (int indent = 0) {+		stdout.printf (@"Layer: $(name)");++		if (!visible) {+			stdout.printf (" hidden");+		}+		+		stdout.printf (@"\n");+		 		foreach (Object o in objects) { 			for (int i = 0; i < indent; i++) { 				stdout.printf ("\t"); 			}-			stdout.printf (@"Path open: $(o.is_open ())");+			stdout.printf (@"Object $(o.to_string ())"); 			 			if (o.color != null) { 				stdout.printf (" %s", ((!) o.color).to_rgb_hex ()); 			}++			if (!o.visible) {+				stdout.printf (" hidden");+			} 			 			stdout.printf ("\n"); 		}diff --git a/libbirdfont/Object.vala b/libbirdfont/Object.valaindex 0a38bf9..8863e53 100644--- a/libbirdfont/Object.vala+++ b/libbirdfont/Object.vala@@ -20,6 +20,10 @@ 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 abstract Color? color { get; set; } 	public abstract Color? stroke_color { get; set; } 	public abstract Gradient? gradient { get; set; }@@ -58,6 +62,28 @@ public abstract class Object : GLib.Object { 	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";+	} }  }diff --git a/libbirdfont/Svg/BezierPoints.vala b/libbirdfont/Svg/BezierPoints.valanew file mode 100644index 0000000..609f075--- /dev/null+++ b/libbirdfont/Svg/BezierPoints.vala@@ -0,0 +1,33 @@+/*+	Copyright (C) 2014 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.+*/++namespace BirdFont {++/** Bezier point container for the SVG parser. */+public class BezierPoints {+	public unichar type = '\0';+	public unichar svg_type = '\0';+	public double x0  = 0;+	public double y0 = 0;+	public double x1 = 0;+	public double y1 = 0;+	public double x2 = 0;+	public double y2 = 0;+	+	public string to_string () {+		return @"$((!)type.to_string ()) $x0,$y0 $x1,$y1 $x2,$y2 SVG:$((!)svg_type.to_string ())";+	}+}++}diff --git a/libbirdfont/Svg/Points.vala b/libbirdfont/Svg/Points.valanew file mode 100644index 0000000..3253257--- /dev/null+++ b/libbirdfont/Svg/Points.vala@@ -0,0 +1,30 @@+/*+	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;++namespace BirdFont {++public class Points : GLib.Object {+	public Doubles point_data = new Doubles.for_capacity (100);+	public double x = 0;+	public double y = 0;++	public void add (double p) {+		point_data.add (p);+	}+}++}+diff --git a/libbirdfont/Svg/Svg.vala b/libbirdfont/Svg/Svg.valaindex 5b2682b..82eaf9a 100644--- a/libbirdfont/Svg/Svg.vala+++ b/libbirdfont/Svg/Svg.vala@@ -16,6 +16,8 @@ using Cairo;  namespace BirdFont { +// FIXME: substrings+ public class Svg {  	/** Export to svg glyph data. */diff --git a/libbirdfont/Svg/SvgFile.vala b/libbirdfont/Svg/SvgFile.valaindex 2418f3f..18e0655 100644--- a/libbirdfont/Svg/SvgFile.vala+++ b/libbirdfont/Svg/SvgFile.vala@@ -12,10 +12,330 @@ 	Lesser General Public License for more details. */ +using B;+ namespace BirdFont {  public class SvgFile : GLib.Object { +	public SvgFile () {		+	}+	+	public Layer parse (string path) {+		string xml_data;+		+		try {+			FileUtils.get_contents (path, out xml_data);+			XmlParser xmlparser = new XmlParser (xml_data);+			+			if (xmlparser.validate ()) {+				Tag root = xmlparser.get_root_tag ();+				return parse_svg_file (root);+			} else {+				warning ("Invalid xml file.");+			}+		} catch (GLib.Error error) {+			warning (error.message);+		}+		+		return new Layer ();+	}+	+	private Layer parse_svg_file (Tag tag) {+		Layer layer = new Layer ();+	+		foreach (Tag t in tag) {+			string name = t.get_name ();+			+			if (name == "g") {+				parse_layer (layer, t);+			}+			+			parse_object (layer, t);+		}+		+		return layer;+	}++	private void parse_layer (Layer layer, Tag tag) {+		bool hidden = false;++		foreach (Attribute attr in tag.get_attributes ()) {	+			if (attr.get_name () == "display" && attr.get_content () == "none") {+				hidden = true;+			}+			+			if (attr.get_name () == "visibility"+				&& (attr.get_content () == "hidden" +					|| attr.get_content () == "collapse")) {+				hidden = true;+			}+		}+		+		if (hidden) {+			layer.visible = !hidden;+		}+					+		foreach (Tag t in tag) {+			if (t.get_name () == "g") {+				Layer sublayer = new Layer ();+				parse_layer (layer, t);+				layer.subgroups.add (sublayer);+			}++			parse_object (layer, t);+		}++		foreach (Attribute attr in tag.get_attributes ()) {	+			if (attr.get_name () == "transform") {+				layer.transforms = parse_transform (attr.get_content ());+			}+		}+	}++	void parse_object (Layer layer, Tag tag) {+		string name = tag.get_name ();+		+		if (name == "path") {+			parse_path (layer, tag);+		}+					+		if (name == "polygon") {+			parse_polygon (layer, tag);+		}++		if (name == "polyline") {+			parse_polyline (layer, tag);+		}+		+		if (name == "rect") {+			parse_rect (layer, tag);+		}++		if (name == "circle") {+			parse_circle (layer, tag);+		}++		if (name == "ellipse") {+			parse_ellipse (layer, tag);+		}+		+		if (name == "line") {+			parse_line (layer, tag);+		}+	}++	private void parse_polygon (Layer layer, Tag tag) {+	}+	+	private void parse_polyline (Layer layer, Tag tag) {+	}+	+	private void parse_rect (Layer layer, Tag tag) {+	}+	+	private void parse_circle (Layer layer, Tag tag) {+	}+	+	private void parse_ellipse (Layer layer, Tag tag) {+	}+	+	private void parse_line (Layer layer, Tag tag) {+	}+	+	// FIXME: reverse order?+	public Gee.ArrayList<SvgTransform> parse_transform (string transforms) {+		string[] functions;+		string transform = transforms;+		Gee.ArrayList<SvgTransform> transform_functions;+		+		transform_functions = new Gee.ArrayList<SvgTransform> ();+		+		transform = transform.replace ("\t", " ");+		transform = transform.replace ("\n", " ");+		transform = transform.replace ("\r", " ");+		+		// use only a single space as separator+		while (transform.index_of ("  ") > -1) {+			transform = transform.replace ("  ", " ");+		}+		+		if (unlikely (transform.index_of (")") > -1)) {+			warning ("No parenthesis in transform function.");+			return transform_functions;+		}+		+		 // add separator+		transform = transform.replace (") ", "|");+		transform = transform.replace (")", "|"); +		functions = transform.split ("|");+		+		for (int i = 0; i < functions.length; i++) {+			if (functions[i].has_prefix ("translate")) {+				transform_functions.add (translate (functions[i]));+			}+			+			if (functions[i].has_prefix ("scale")) {+				transform_functions.add (scale (functions[i]));+			}++			if (functions[i].has_prefix ("matrix")) {+				transform_functions.add (matrix (functions[i]));+			}+			+			// TODO: rotate etc.+		}+		+		return transform_functions;+	}++	private SvgTransform matrix (string function) {+		string parameters = get_transform_parameters (function);+		string[] p = parameters.split (" ");+		SvgTransform transform = new SvgTransform ();+		transform.type = TransformType.MATRIX;+		+		if (unlikely (p.length != 6)) {+			warning ("Expecting six parameters for matrix transformation.");+			return transform;+		}+		+		for (int i = 0; i < 6; i++) {+			double argument = SvgParser.parse_double (p[i]);+			transform.arguments.add (argument);+		}+		+		return transform;+	}+		+	private SvgTransform scale (string function) {+		string parameters = get_transform_parameters (function);+		string[] p = parameters.split (" ");+		SvgTransform transform = new SvgTransform ();+		transform.type = TransformType.SCALE;++		if (p.length > 0) {+			transform.arguments.add (SvgParser.parse_double (p[0]));+		}+		+		if (p.length > 1) {+			transform.arguments.add (SvgParser.parse_double (p[1]));+		}+		+		return transform;+	}+	+	private SvgTransform translate (string function) {+		string parameters = get_transform_parameters (function);+		string[] p = parameters.split (" ");+		SvgTransform transform = new SvgTransform ();+		transform.type = TransformType.TRANSLATE;+		+		if (p.length > 0) {+			transform.arguments.add (SvgParser.parse_double (p[0]));+		}+		+		if (p.length > 1) {+			transform.arguments.add (SvgParser.parse_double (p[1]));+		}+		+		return transform;+	}++	private string get_transform_parameters (string function) {+		int i;+		string param = "";+		+		i = function.index_of ("(");+		return_val_if_fail (i != -1, param);+		param = function.substring (i);++		param = param.replace ("(", "");+		param = param.replace ("\n", " ");+		param = param.replace ("\t", " ");+		param = param.replace (",", " ");+		+		while (param.index_of ("  ") > -1) {+			param.replace ("  ", " ");+		}+			+		return param.strip();			+	}++	private bool is_visible (Tag tag) {+		bool hidden = false;++		foreach (Attribute attr in tag.get_attributes ()) {+			if (attr.get_name () == "display" && attr.get_content () == "none") {+				hidden = true;+			}+			+			if (attr.get_name () == "visibility"+				&& (attr.get_content () == "hidden" +					|| attr.get_content () == "collapse")) {+				hidden = true;+			}+		}+		+		return !hidden;+	}++	private void parse_path (Layer layer, Tag tag) {+		SvgPath path = new SvgPath ();++		foreach (Attribute attr in tag.get_attributes ()) {+			if (attr.get_name () == "d") {+				path.points = parse_points (attr.get_content ());+			}++			if (attr.get_name () == "transform") {+				path.transforms = parse_transform (attr.get_content ());+			}+		}+		+		path.style = SvgStyle.parse (tag.get_attributes ());+		path.visible = is_visible (tag);	+		+		layer.add_object (path);+	}++	public Gee.ArrayList<Points> parse_points (string data) {+		Gee.ArrayList<Points> path_data = new Gee.ArrayList<Points> ();+		Points points = new Points ();+		BezierPoints[] bezier_points;+		int points_size;+	+		SvgParser.get_bezier_points (data, out bezier_points, out points_size, true);++		for (int i = 0; i < points_size; i++) {+			if (bezier_points[i].type == 'M') {+				points.x = bezier_points[i].x0;+				points.y = bezier_points[i].y0;+			} else if (bezier_points[i].type == 'C') {+				points.add (bezier_points[i].x0);+				points.add (bezier_points[i].y0);+				points.add (bezier_points[i].x1);+				points.add (bezier_points[i].y1);+				points.add (bezier_points[i].x2);+				points.add (bezier_points[i].y2);+			} else if (bezier_points[i].type == 'L') {+				points.add (bezier_points[i].x0);+				points.add (bezier_points[i].y0);+				points.add (bezier_points[i].x0);+				points.add (bezier_points[i].y0);+				points.add (bezier_points[i].x0);+				points.add (bezier_points[i].y0);+			} else if (bezier_points[i].type == 'z') {+				path_data.add (points);+				points = new Points ();+			} else {+				string type = (!) bezier_points[i].type.to_string ();+				warning (@"SVG conversion not implemented for $type");+			}+		}++		return path_data;+	} }  }diff --git a/libbirdfont/Svg/SvgParser.vala b/libbirdfont/Svg/SvgParser.valaindex e3e0575..cde1dfb 100644--- a/libbirdfont/Svg/SvgParser.vala+++ b/libbirdfont/Svg/SvgParser.vala@@ -63,18 +63,9 @@ public class SvgParser { 	} 		 	public static void import_color_svg (Glyph glyph, string path) {-		try {-			string data;-			FileUtils.get_contents (path, out data);-			glyph.color_svg_data = data;--			if (glyph.color_svg_data != null) {-				glyph.svg_x = glyph.left_limit;-				glyph.svg_y = BirdFont.get_current_font ().top_position;-			}-		} catch (GLib.Error e) {-			warning (e.message);-		}+		SvgFile svg_file = new SvgFile ();+		Layer layer = svg_file.parse (path);+		glyph.add_layer (layer); 	} 	 	public static void import_folder (SvgType type) {@@ -1017,7 +1008,7 @@ public class SvgParser { 	/** Add space as separator to svg data.  	 * @param d svg data 	 */-	static string add_separators (string d) {+	public static string add_separators (string d) { 		string data = d; 		 		data = data.replace (",", " ");@@ -1063,44 +1054,34 @@ public class SvgParser { 			g.add_path (path); 		} 	}-	-	/** -	 * @param d svg data-	 * @param glyph use lines from this glyph but don't add the generated paths-	 * @param svg_glyph parse svg glyph with origo in lower left corner-	 * -	 * @return the new paths-	 */-	public PathList parse_svg_data (string d, Glyph glyph, bool svg_glyph = false, double units = 1) {++	public static void get_bezier_points (string point_data, out BezierPoints[] bezier_points, out int points, bool svg_glyph) { 		double px = 0; 		double py = 0; 		double px2 = 0; 		double py2 = 0; 		double cx = 0; 		double cy = 0;-		string data;-		Font font;-		PathList path_list = new PathList ();-		BezierPoints[] bezier_points; 		string[] c; 		double arc_rx, arc_ry; 		double arc_rotation; 		int large_arc; 		int arc_sweep; 		double arc_dest_x, arc_dest_y;--		font = BirdFont.get_current_font (); 		-		data = add_separators (d);+		int bi = 0;++		string data = add_separators (point_data); 		c = data.split (" ");-		bezier_points = new BezierPoints[8 * c.length + 1]; // the arc instruction can use up to eight points++		// the arc instruction can use up to eight points+		int bezier_points_length = 8 * c.length + 1;+		bezier_points = new BezierPoints[bezier_points_length];  		-		for (int i = 0; i < 2 * c.length + 1; i++) {+		for (int i = 0; i < bezier_points_length; i++) { 			bezier_points[i] = new BezierPoints (); 		}-		-		int bi = 0;-		+ 		// parse path 		int i = -1; 		while (++i < c.length && bi < bezier_points.length) {	@@ -1358,7 +1339,6 @@ public class SvgParser { 					bi++; 				} 			} else if (c[i] == "Q") {- 				while (i + 4 < c.length && is_point (c[i + 1])) { 					bezier_points[bi].type = 'Q'; 					bezier_points[bi].svg_type = 'Q';@@ -1431,7 +1411,7 @@ public class SvgParser { 										 					// the reflection 					cx = 2 * px - px2;-					cy = 2 * py - py2; // if (svg_glyph) ?+					cy = 2 * py - py2; 					 					bezier_points[bi].x0 = cx; 					bezier_points[bi].y0 = cy;@@ -1538,7 +1518,7 @@ public class SvgParser { 					px = cx; 					py = cy;	 					-					bi++;				+					bi++; 				} 			} else if (c[i] == "a") { 				while (i + 7 < c.length && is_point (c[i + 1])) {					@@ -1564,8 +1544,6 @@ public class SvgParser { 					 					px = cx; 					py = cy;-					-					 				} 			} else if (i + 7 < c.length && c[i] == "A") { 				while (is_point (c[i + 1])) {					@@ -1613,15 +1591,38 @@ public class SvgParser { 		 		if (bi == 0) { 			warning ("No points in path.");+		}++		points = bi;+	}+	+	/** +	 * @param d svg data+	 * @param glyph use lines from this glyph but don't add the generated paths+	 * @param svg_glyph parse svg glyph with origo in lower left corner+	 * +	 * @return the new paths+	 */+	public PathList parse_svg_data (string d, Glyph glyph, bool svg_glyph = false, double units = 1) {+		Font font;+		PathList path_list = new PathList ();+		BezierPoints[] bezier_points;+		int points;++		font = BirdFont.get_current_font ();+		get_bezier_points (d, out bezier_points, out points, svg_glyph);+	+		if (points == 0) {+			warning ("No points in path."); 			return path_list;	 		} 		-		move_and_resize (bezier_points, bi, svg_glyph, units, glyph);+		move_and_resize (bezier_points, points, svg_glyph, units, glyph); 		 		if (format == SvgFormat.ILLUSTRATOR) {-			path_list = create_paths_illustrator (bezier_points, bi);+			path_list = create_paths_illustrator (bezier_points, points); 		} else {-			path_list = create_paths_inkscape (bezier_points, bi);+			path_list = create_paths_inkscape (bezier_points, points); 		}  		// TODO: Find out if it is possible to tie handles.@@ -2044,13 +2045,13 @@ public class SvgParser { 		return int.parse ((!) s); 	} 	-	static double parse_double (string? s) {-		if (is_null (s)) {+	public static double parse_double (string? s) {+		if (unlikely (is_null (s))) { 			warning ("Got null instead of expected string."); 			return 0; 		} 		-		if (!is_point ((!) s)) {+		if (unlikely (!is_point ((!) s))) { 			warning (@"Expecting a double got: $((!) s)"); 			return 0; 		}@@ -2089,7 +2090,7 @@ public class SvgParser { 			}  			bezier_points[bi] = new BezierPoints ();-			bezier_points[bi].type == 'L';+			bezier_points[bi].type = 'L'; 			bezier_points[bi].x0 = parse_double (c[i]); 			bezier_points[bi].y0 = -parse_double (c[i + 1]); 			bi++;diff --git a/libbirdfont/Svg/SvgPath.vala b/libbirdfont/Svg/SvgPath.valanew file mode 100644index 0000000..eabe861--- /dev/null+++ b/libbirdfont/Svg/SvgPath.vala@@ -0,0 +1,127 @@+/*+	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;++namespace BirdFont {++public class SvgPath : Object {+	public override double stroke { get; set; }+	public override double rotation { get; set; }+	public override LineCap line_cap { get; set; }+	public override bool fill { get; set; }++	public override Color? color { get; set; }+	public override Color? stroke_color { get; set; }+	public override Gradient? gradient { get; set; }++	public override double xmin { get; set; }+	public override double xmax { get; set; }+	public override double ymin { get; set; }+	public override double ymax { get; set; }+	+	public Gee.ArrayList<Points> points = new Gee.ArrayList<Points> ();+	+	public SvgPath () {+	}++	public SvgPath.create_copy (SvgPath p) {+		Object.copy_attributes (p, this);+	}+	+	public override bool is_over (double x, double y) {+		return false;+	}+			+	public override void draw (Context cr, Color? c = null) {+		cr.save ();+		+		foreach (Points p in points) {+			cr.new_path ();+			cr.move_to (p.x, p.y);+			+			draw_points (cr, p);+		}+		+		cr.fill (); // FIXME: stroke etc.+		cr.restore ();+	}++	public void draw_points (Context cr, Points points) {+		Doubles p = points.point_data;++		print(@"draw $(p.size)\n");+		+		return_if_fail (p.size % 6 != 0);+		+		for (int i = 0; i < p.size; i += 6) {+			cr.curve_to (p.data[i], p.data[i + 1], +				p.data[i + 2], p.data[i + 3],+				p.data[i + 4], p.data[i + 5]);+				+			print(@"$(p.data[i])");+		}+		+		cr.set_source_rgba (0, 0.5, 0, 1);+		cr.fill ();+		+		cr.close_path ();+		cr.new_path ();+		cr.move_to (points.x, points.y);+		cr.set_source_rgba (0, 0, 0.5, 0.5);+		+		for (int i = 0; i < p.size; i += 2) {+			cr.line_to (p.data[i], p.data[i + 1]);+		}++		cr.fill ();++		cr.close_path ();+		cr.new_path ();+		cr.move_to (points.x, points.y);+		cr.set_source_rgba (0.5, 0, 0, 0.5);+		+		for (int i = 0; i < p.size; i += 6) {+			cr.line_to (p.data[i + 4], p.data[i + 5]);+		}++		cr.fill ();		+	}++	public override void move (double dx, double dy) {+	}+	+	public override void update_region_boundaries () {+	}++	public override void rotate (double theta, double xc, double yc) {+	}+	+	public override bool is_empty () {+		return false;+	}+	+	public override void resize (double ratio_x, double ratio_y) {+	}+	+	public override Object copy () {+		return new SvgPath.create_copy (this);+	}++	public override string to_string () {+		return "SvgPath";+	}+}++}diff --git a/libbirdfont/Svg/SvgTransform.vala b/libbirdfont/Svg/SvgTransform.valanew file mode 100644index 0000000..a4bb027--- /dev/null+++ b/libbirdfont/Svg/SvgTransform.vala@@ -0,0 +1,34 @@+/*+	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 B;++namespace BirdFont {++public enum TransformType {+	NONE,+	TRANSLATE,+	MATRIX,+	SCALE+}++public class SvgTransform : GLib.Object {+	public TransformType type = TransformType.NONE;+	public Doubles arguments = new Doubles.for_capacity (10);+	+	public SvgTransform () {+	}+}++}

Contact

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