Clone in a terminal:
Commit e380d78
Johan Mattsson - 2016-06-26T12:14:50+00:00
e380d7852ccb730f98e8de37d2f2e62405167fc7johan.mattsson.m@gmail.com

Rotate SVG paths

Changed files (22)

Diff

diff --git a/libbirdfont/DrawingTools.vala b/libbirdfont/DrawingTools.valaindex 3e7c653..63caf9a 100644--- a/libbirdfont/DrawingTools.vala+++ b/libbirdfont/DrawingTools.vala@@ -390,7 +390,7 @@ public class DrawingTools : ToolCollection  { 			 			if (glyph.active_paths.size > 0) { 				last_path = glyph.active_paths.get (glyph.active_paths.size - 1);-				resize_tool.rotate_selected_paths (angle - last_path.rotation, x, y);		+				resize_tool.rotate_selected_paths (angle - last_path.transforms.rotation, x, y);		 			} 			 			GlyphCanvas.redraw ();@@ -805,12 +805,12 @@ public class DrawingTools : ToolCollection  { 		 			if (StrokeTool.add_stroke) { 				foreach (SvgBird.Object p in g.active_paths) {-					p.stroke = StrokeTool.stroke_width;-					p.line_cap = StrokeTool.line_cap;+					p.style.stroke_width = StrokeTool.stroke_width;+					p.style.line_cap = StrokeTool.line_cap; 				} 			} else { 				foreach (SvgBird.Object p in g.active_paths) {-					p.stroke = 0;+					p.style.stroke_width = 0; 				}	 			} 			@@ -845,7 +845,7 @@ public class DrawingTools : ToolCollection  { 					 			if (tool && StrokeTool.add_stroke) { 				foreach (SvgBird.Object p in g.active_paths) {-					p.stroke = StrokeTool.stroke_width;+					p.style.stroke_width = StrokeTool.stroke_width; 					 					if (p is PathObject) { 						Path path = ((PathObject) p).get_path ();@@ -887,7 +887,7 @@ public class DrawingTools : ToolCollection  { 			g.store_undo_state (); 			 			foreach (SvgBird.Object p in g.active_paths) {-				p.line_cap = SvgBird.LineCap.BUTT;+				p.style.line_cap = SvgBird.LineCap.BUTT; 				 				if (p is PathObject) { 					((PathObject) p).get_path ().reset_stroke ();@@ -914,7 +914,7 @@ public class DrawingTools : ToolCollection  { 			g.store_undo_state (); 			 			foreach (SvgBird.Object p in g.active_paths) {-				p.line_cap = SvgBird.LineCap.ROUND;+				p.style.line_cap = SvgBird.LineCap.ROUND; 				 				if (p is PathObject) { 					((PathObject) p).get_path ().reset_stroke ();@@ -942,7 +942,7 @@ public class DrawingTools : ToolCollection  { 			g.store_undo_state (); 			 			foreach (SvgBird.Object p in g.active_paths) {-				p.line_cap = SvgBird.LineCap.SQUARE;+				p.style.line_cap = SvgBird.LineCap.SQUARE;  				if (p is PathObject) { 					((PathObject) p).get_path ().reset_stroke ();@@ -1277,7 +1277,7 @@ public class DrawingTools : ToolCollection  { 		Glyph g = MainWindow.get_current_glyph (); 		 		foreach (SvgBird.Object p in g.active_paths) {-			if (p.stroke > 0) {+			if (p.style.stroke_width > 0) { 				stroke = true; 			} 		}diff --git a/libbirdfont/EmbeddedSvg.vala b/libbirdfont/EmbeddedSvg.valaindex a10dbaf..82b2f65 100644--- a/libbirdfont/EmbeddedSvg.vala+++ b/libbirdfont/EmbeddedSvg.vala@@ -49,12 +49,12 @@ public class EmbeddedSvg : SvgBird.Object { 	public void draw_embedded_svg (Context cr) { 		cr.save (); 		cr.translate (Glyph.xc () + x, Glyph.yc () - y);+		apply_transform (cr); 		drawing.draw (cr); 		cr.restore (); 	} 	 	public override void draw_outline (Context cr) {-		cr.translate (x, -y); 		drawing.draw_outline (cr); 	} 	@@ -64,18 +64,10 @@ public class EmbeddedSvg : SvgBird.Object { 		move_bounding_box (dx, -dy); 	} 	-	public override void rotate (double theta, double xc, double yc) {-		drawing.rotate (theta, xc, yc);-	}-	 	public override bool is_empty () { 		return drawing.is_empty (); 	} 	-	public override void resize (double ratio_x, double ratio_y) {-		drawing.resize (ratio_x, ratio_y);-	}- 	public override SvgBird.Object copy () { 		EmbeddedSvg svg = new EmbeddedSvg ((SvgDrawing) drawing.copy ()); 		SvgBird.Object.copy_attributes (this, svg);diff --git a/libbirdfont/Glyph.vala b/libbirdfont/Glyph.valaindex 00a0ec3..51d5f49 100644--- a/libbirdfont/Glyph.vala+++ b/libbirdfont/Glyph.vala@@ -1527,7 +1527,7 @@ public class Glyph : FontDisplay { 		if (!draw_control_points) { 			foreach (SvgBird.Object object in get_visible_objects ()) { 				if (object is PathObject-					&& object.stroke > 0) {+					&& object.style.stroke_width > 0) { 						 					has_path = true; 					PathObject object_path = (PathObject) object;				@@ -1547,7 +1547,7 @@ public class Glyph : FontDisplay { 		if (!draw_control_points) { 			foreach (SvgBird.Object object in get_visible_objects ()) { 				if (object is PathObject-					&& object.stroke == 0) {+					&& object.style.stroke_width == 0) { 						 					has_path = true; 					PathObject object_path = (PathObject) object;				diff --git a/libbirdfont/MoveTool.vala b/libbirdfont/MoveTool.valaindex 60d1f98..5af27c7 100644--- a/libbirdfont/MoveTool.vala+++ b/libbirdfont/MoveTool.vala@@ -29,10 +29,12 @@ public class MoveTool : Tool { 	static double selection_y = 0;	 	static bool group_selection= false; 	-	public static static double selection_box_width = 0;-	public static static double selection_box_height = 0;-	public static static double selection_box_center_x = 0;-	public static static double selection_box_center_y = 0;+	public static double selection_box_width = 0;+	public static double selection_box_height = 0;+	public static double selection_box_center_x = 0;+	public static double selection_box_center_y = 0;+	public static double selection_box_left = 0;+	public static double selection_box_top = 0; 	 	public signal void selection_changed (); 	public signal void objects_moved ();@@ -249,15 +251,16 @@ public class MoveTool : Tool { 	public static void update_selection_boundaries () { 		get_selection_box_boundaries (out selection_box_center_x, 			out selection_box_center_y, out selection_box_width,-			out selection_box_height);	+			out selection_box_height, out selection_box_left, +			out selection_box_top);	 	}  	public void move_to_baseline () { 		Glyph glyph = MainWindow.get_current_glyph (); 		Font font = BirdFont.get_current_font ();-		double x, y, w, h;+		double x, y, w, h, l, t; 		-		get_selection_box_boundaries (out x, out y, out w, out h);+		get_selection_box_boundaries (out x, out y, out w, out h, out l, out t); 		 		foreach (SvgBird.Object path in glyph.active_paths) { 			path.move (glyph.left_limit - x + w / 2, font.base_line - y + h / 2);@@ -268,7 +271,9 @@ public class MoveTool : Tool { 		GlyphCanvas.redraw (); 	} 	-	public static void get_selection_box_boundaries (out double x, out double y, out double w, out double h) {+	public static void get_selection_box_boundaries (out double x, out double y, out double w, out double h,+		out double left, out double top) {+			 		double px, py, px2, py2; 		Glyph glyph = MainWindow.get_current_glyph (); 		@@ -276,6 +281,8 @@ public class MoveTool : Tool { 		py = 10000; 		px2 = -10000; 		py2 = -10000;+		top = 10000;+		left = 10000; 		 		foreach (SvgBird.Object o in glyph.active_paths) { 			if (o is PathObject) {@@ -283,6 +290,14 @@ public class MoveTool : Tool { 				p.update_region_boundaries (); 			} 			+			if (top > o.top) {+				top = o.top;+			}++			if (left > o.left) {+				left = o.left;+			}+			 			if (px > o.xmin) { 				px = o.xmin; 			} @@ -410,11 +425,7 @@ public class MoveTool : Tool { 	 	public static void update_boundaries_for_selection () { 		Glyph glyph = MainWindow.get_current_glyph ();-		foreach (SvgBird.Object o in glyph.active_paths) {-			if (o is PathObject) {-				((PathObject)o).get_path ().update_region_boundaries ();-			}-		}+		glyph.layers.update_boundaries_for_object (); 	} 	 	public static void flip_vertical () {@@ -426,7 +437,7 @@ public class MoveTool : Tool { 	}  	public static void flip (bool vertical) {-		double xc, yc, xc2, yc2, w, h;		+		double xc, yc, xc2, yc2, w, h, l, t; 		double dx, dy; 		Glyph glyph = MainWindow.get_current_glyph ();   		@@ -450,7 +461,7 @@ public class MoveTool : Tool { 			} 		} -		get_selection_box_boundaries (out xc2, out yc2, out w, out h); +		get_selection_box_boundaries (out xc2, out yc2, out w, out h, out l, out t);   		dx = -(xc2 - xc); 		dy = -(yc2 - yc);diff --git a/libbirdfont/OverView.vala b/libbirdfont/OverView.valaindex 8a04164..4cdc96f 100644--- a/libbirdfont/OverView.vala+++ b/libbirdfont/OverView.vala@@ -1455,7 +1455,6 @@ public class OverView : FontDisplay { 		selected_item = get_selected_item (); 		if (selected_item.glyphs != null) { 			open_glyph_signal ((!) selected_item.glyphs);-			GlyphCollection? gc2 = selected_item.glyphs; 			GlyphCollection gc = (!) selected_item.glyphs; 			gc.get_current ().close_path (); 		} else {diff --git a/libbirdfont/PathObject.vala b/libbirdfont/PathObject.valaindex 70d8b0f..d324e8a 100644--- a/libbirdfont/PathObject.vala+++ b/libbirdfont/PathObject.vala@@ -57,7 +57,7 @@ public class PathObject : SvgBird.Object { 		} 	} 	-	public override double stroke {+	public double stroke { 		get { 			return path.stroke; 		}@@ -98,11 +98,16 @@ public class PathObject : SvgBird.Object { 	} 	 	public void draw_path (Context cr) {+		cr.save ();+		apply_transform (cr);+		 		if (path.stroke > 0) { 			draw_path_list (path.get_completed_stroke (), cr); 		} else { 			path.draw_path (cr); 		}+		+		cr.restore (); 	}  	public static void draw_path_list (PathList pl, Context cr) {@@ -128,19 +133,10 @@ public class PathObject : SvgBird.Object { 		return base.update_boundaries (cr); 	} -	public override void rotate (double theta, double xc, double yc) {-		path.rotate (theta, xc, yc);-	}-	 	public override bool is_empty () { 		return path.points.size == 0; 	} 	-	public override void resize (double ratio_x, double ratio_y) {-		path.resize (ratio_x, ratio_y);-		path.reset_stroke ();-	}-	 	public override SvgBird.Object copy () { 		return new PathObject.create_copy (this); 	}diff --git a/libbirdfont/PenTool.vala b/libbirdfont/PenTool.valaindex 3ee01c4..908968b 100644--- a/libbirdfont/PenTool.vala+++ b/libbirdfont/PenTool.vala@@ -1055,11 +1055,14 @@ public class PenTool : Tool { 				// don't use set point to reflective to on open ends 				reflective = true; 				foreach (SvgBird.Object path in MainWindow.get_current_glyph ().active_paths) {-					if (path.is_open () && !path.is_empty () && path is PathObject) {+					if (!path.is_empty () && path is PathObject) { 						Path p = ((PathObject) path).get_path ();-						if (selected_handle.parent == p.get_first_point ()	-							|| selected_handle.parent == p.get_last_point ()) {-							reflective = false;+						+						if (p.is_open ()) {						+							if (selected_handle.parent == p.get_first_point ()	+								|| selected_handle.parent == p.get_last_point ()) {+								reflective = false;+							} 						} 					} 				}@@ -1835,8 +1838,6 @@ public class PenTool : Tool { 		Glyph g = MainWindow.get_current_glyph (); 		PathObject path; 		-		print ("Insert\n");-		 		if (!g.has_active_path_objects ()) { 			np = new Path (); 			g.add_path (np);diff --git a/libbirdfont/ResizeTool.vala b/libbirdfont/ResizeTool.valaindex 834a3fb..dec9127 100644--- a/libbirdfont/ResizeTool.vala+++ b/libbirdfont/ResizeTool.vala@@ -1,5 +1,5 @@ /*-	Copyright (C) 2013 2015 Johan Mattsson+	Copyright (C) 2013 2015 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 @@ -32,7 +32,9 @@ public class ResizeTool : Tool { 	static double selection_box_height = 0; 	static double selection_box_center_x = 0; 	static double selection_box_center_y = 0;-+	static double selection_box_left = 0;+	static double selection_box_top = 0;+	 	static bool rotate_path = false; 	static double last_rotate_y; 	static double rotation = 0;@@ -97,7 +99,7 @@ public class ResizeTool : Tool {  			if (glyph.active_paths.size > 0) { 				last_path = glyph.active_paths.get (glyph.active_paths.size - 1);-				last_rotate = last_path.rotation;+				last_rotate = last_path.transforms.rotation; 			} 					 			rotation = last_rotate;@@ -127,7 +129,9 @@ public class ResizeTool : Tool { 					PathObject path = (PathObject) p; 					path.get_path ().create_full_stroke (); 				}-			}+				+				p.transforms.collapse_transforms ();+			}			 		}); 		 		move_action.connect ((self, x, y)	 => {@@ -145,7 +149,6 @@ public class ResizeTool : Tool {  			if (rotate_path) { 				rotate (x, y);-				update_selection_box (); 			}  			if (move_paths @@ -235,26 +238,26 @@ public class ResizeTool : Tool {  	public void rotate_selected_paths (double angle, double cx, double cy) { 		Glyph glyph = MainWindow.get_current_glyph ();  -		double dx, dy, xc2, yc2, w, h; 		SvgBird.Object last_path;+		double x, y; 		-		foreach (SvgBird.Object p in glyph.active_paths) {-			p.rotate (angle, cx, cy);-		}--		MoveTool.get_selection_box_boundaries (out xc2, out yc2, out w, out h); --		dx = -(xc2 - cx);-		dy = -(yc2 - cy);+		glyph.layers.update_boundaries_for_object (); 		 		foreach (SvgBird.Object p in glyph.active_paths) {-			p.move (dx, dy);+			if (p is EmbeddedSvg) {+				EmbeddedSvg svg = (EmbeddedSvg) p;+				x = selection_box_left - svg.x + selection_box_width / 2;+				y = selection_box_top + svg.y + selection_box_height / 2;+				p.transforms.rotate (angle, x, y);+			} else {+				x = selection_box_left + selection_box_width / 2;+				y = selection_box_top + selection_box_height / 2;+				p.transforms.rotate (angle, x, y);+			} 		}-		+ 		last_rotate = rotation;-		-		MoveTool.update_selection_boundaries ();-		+ 		if (glyph.active_paths.size > 0) { 			last_path = glyph.active_paths.get (glyph.active_paths.size - 1); 			@@ -272,20 +275,15 @@ public class ResizeTool : Tool { 	 	/** Move rotate handle to pixel x,y. */ 	void rotate (double x, double y) {-		double cx, cy, xc, yc, a, b;		-		-		cx = Glyph.reverse_path_coordinate_x (selection_box_center_x);-		cy = Glyph.reverse_path_coordinate_y (selection_box_center_y);-		xc = selection_box_center_x;-		yc = selection_box_center_y;-		-		a = x - cx;-		b = y - cy;+		double a, b;		 		-		rotation = atan (b / a);+		a = Glyph.path_coordinate_x (x) - selection_box_center_x;+		b = selection_box_center_y - Glyph.path_coordinate_y (y); 		-		if (a < 0) {-			rotation += PI;+		rotation = atan2 (b, a);++		if (a == 0) {+			rotation = b > 0 ? PI / 2 : -PI / 2; 		} 		 		rotate_selected_paths (rotation - last_rotate, selection_box_center_x, selection_box_center_y);@@ -377,7 +375,7 @@ public class ResizeTool : Tool { 		 		// resize paths 		foreach (SvgBird.Object selected_path in glyph.active_paths) {-			selected_path.resize (ratio_x, ratio_y);+			selected_path.transforms.resize (ratio_x, ratio_y); 		} 		 		// move paths relative to the updated xmin and xmax@@ -388,7 +386,7 @@ public class ResizeTool : Tool { 		foreach (SvgBird.Object selected_path in glyph.active_paths) { 			selected_path.move (dx, dy);			 		}-		+ 		if (glyph.active_paths.size > 0) { 			update_selection_box (); 			objects_resized (selection_box_width, selection_box_height);@@ -409,7 +407,7 @@ public class ResizeTool : Tool { 		MoveTool.update_boundaries_for_selection (); 		MoveTool.get_selection_box_boundaries (out selection_box_center_x, 				out selection_box_center_y, out selection_box_width,-				out selection_box_height);+				out selection_box_height, out selection_box_left, out selection_box_top); 	}  	/** Move resize handle to pixel x,y. */@@ -441,44 +439,6 @@ public class ResizeTool : Tool { 			last_resize_y = py; 		} 	}-	-	public void full_height () {-		double xc, yc, w, h;-		Glyph glyph = MainWindow.get_current_glyph ();-		Font font = BirdFont.get_current_font ();-		-		MoveTool.update_boundaries_for_selection ();-		MoveTool.get_selection_box_boundaries (out xc, out yc, out w, out h);--		//compute scale-		double descender = font.base_line - (yc - h / 2);-		-		if (descender < 0) {-			descender = 0;-		}-		-		double font_height = font.top_position - font.base_line;-		double scale = font_height / (h - descender);-		-		resize_selected_paths (scale, scale);-		PenTool.reset_stroke ();--		MoveTool.update_boundaries_for_selection ();-		font.touch ();--		MoveTool.get_selection_box_boundaries (out selection_box_center_x,-											   out selection_box_center_y,-											   out selection_box_width,-											   out selection_box_height);-		-		DrawingTools.move_tool.move_to_baseline ();--		foreach (SvgBird.Object path in glyph.active_paths) {-			path.move (0, -descender * scale);-		}-		-		objects_resized (selection_box_width, selection_box_height);-	}  	void get_selection_min (out double x, out double y) { 		Glyph glyph = MainWindow.get_current_glyph ();diff --git a/libsvgbird/Circle.vala b/libsvgbird/Circle.valaindex e0728c7..5a3b178 100644--- a/libsvgbird/Circle.vala+++ b/libsvgbird/Circle.vala@@ -37,16 +37,10 @@ public class Circle : Object { 	public override void move (double dx, double dy) { 	} -	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 () { 		Circle c = new Circle (); 		diff --git a/libsvgbird/Ellipse.vala b/libsvgbird/Ellipse.valaindex 32ac418..07b0ad7 100644--- a/libsvgbird/Ellipse.vala+++ b/libsvgbird/Ellipse.vala@@ -43,16 +43,10 @@ public class Ellipse : Object { 	public override void move (double dx, double dy) { 	} -	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 () { 		Ellipse e = new Ellipse (); 		Object.copy_attributes (this, e);diff --git a/libsvgbird/EmptyObject.vala b/libsvgbird/EmptyObject.valaindex cd0545e..02b7ae8 100644--- a/libsvgbird/EmptyObject.vala+++ b/libsvgbird/EmptyObject.vala@@ -30,17 +30,11 @@ public class EmptyObject : Object {  	public override void move (double dx, double dy) { 	}-	-	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 EmptyObject (); 	}diff --git a/libsvgbird/Layer.vala b/libsvgbird/Layer.valaindex cbda126..25655f6 100644--- a/libsvgbird/Layer.vala+++ b/libsvgbird/Layer.vala@@ -224,17 +224,11 @@ public class Layer : Object { 		 	public override void move (double dx, double dy) { 	}--	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 string to_string () { 		return "Layer: " + name; 	}diff --git a/libsvgbird/Line.vala b/libsvgbird/Line.valaindex 5b0d0b2..0be7513 100644--- a/libsvgbird/Line.vala+++ b/libsvgbird/Line.vala@@ -46,17 +46,11 @@ public class Line : Object {  	public override void move (double dx, double dy) { 	}-	-	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 Line.create_copy (this); 	}diff --git a/libsvgbird/Object.vala b/libsvgbird/Object.valaindex ad40b01..b6525ce 100644--- a/libsvgbird/Object.vala+++ b/libsvgbird/Object.vala@@ -18,8 +18,6 @@ using Math; namespace SvgBird {  public abstract class Object : GLib.Object {-	bool open = false;-	 	public bool visible = true; 	public SvgStyle style = new SvgStyle (); 	public SvgTransforms transforms = new SvgTransforms ();@@ -27,10 +25,6 @@ public abstract class Object : GLib.Object { 	public string id = ""; 	public string css_class = ""; 	-	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 left { get; set; } 	public virtual double right { get; set; }@@ -90,12 +84,6 @@ public abstract class Object : GLib.Object { 		} 	} -	// FIXME: DELETE-	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 const double CANVAS_MAX = 100000; 	public const double CANVAS_MIN = -100000; 	@@ -103,24 +91,13 @@ public abstract class Object : GLib.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 bool is_over (double x, double y); 	public abstract void draw_outline (Context cr);  	public abstract Object copy ();-	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 abstract void move (double dx, double dy); 	 	public virtual void move_bounding_box (double dx, double dy) {@@ -131,35 +108,10 @@ public abstract class Object : GLib.Object { 	}  	public static void copy_attributes (Object from, Object to) {-		to.open = from.open;--		if (from.color != null) {-			to.color = ((!) from.color).copy ();-		} else {-			to.color = null;-		}-		-		if (from.stroke_color != null) {-			to.stroke_color = ((!) from.stroke_color).copy ();-		} else {-			to.stroke_color = null;-		}-		-		if (to.gradient != null) {-			to.gradient = ((!) from.gradient).copy ();-		} else {-			to.gradient = null;-		}-		-		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;+		to.left = from.left;+		to.right = from.right;+		to.top = from.top;+		to.bottom = from.bottom; 		 		to.style = from.style.copy (); 		to.transforms = from.transforms.copy ();@@ -244,10 +196,10 @@ public abstract class Object : GLib.Object { 		Matrix view_matrix = cr.get_matrix (); 		Matrix object_matrix = transforms.get_matrix (); 		-		object_matrix.multiply (object_matrix, view_matrix);+		object_matrix.multiply (object_matrix, view_matrix);		 		cr.set_matrix (object_matrix); 	}-+	 	/** @return true if the object has an area. */ 	public virtual bool update_boundaries (Context context) { 		double x0, y0, x1, y1;@@ -276,6 +228,7 @@ public abstract class Object : GLib.Object { 		return boundaries_width != 0; 	} +	// FIXME: store view matrix 	public virtual bool update_boundaries_for_object () { 		ImageSurface surface = new Cairo.ImageSurface (Cairo.Format.ARGB32, 1, 1); 		Context context = new Cairo.Context (surface);diff --git a/libsvgbird/Polygon.vala b/libsvgbird/Polygon.valaindex c2ee02d..244f001 100644--- a/libsvgbird/Polygon.vala+++ b/libsvgbird/Polygon.vala@@ -45,16 +45,10 @@ public class Polygon : Object { 	public override void move (double dx, double dy) { 	} 	-	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 () { 		Polygon p = new Polygon ();		 		p.points = points.copy ();diff --git a/libsvgbird/Polyline.vala b/libsvgbird/Polyline.valaindex 9434036..c52c54a 100644--- a/libsvgbird/Polyline.vala+++ b/libsvgbird/Polyline.vala@@ -42,17 +42,11 @@ public class Polyline : Object { 	 	public override void move (double dx, double dy) { 	}--	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 () { 		Polyline p = new Polyline ();		 		p.points = points.copy ();diff --git a/libsvgbird/Rectangle.vala b/libsvgbird/Rectangle.valaindex 362221d..d9cb79e 100644--- a/libsvgbird/Rectangle.vala+++ b/libsvgbird/Rectangle.vala@@ -65,16 +65,10 @@ public class Rectangle : Object { 		y += dy; 	} -	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 () { 		Rectangle r = new Rectangle (); 		diff --git a/libsvgbird/SvgDrawing.vala b/libsvgbird/SvgDrawing.valaindex 7f40284..49c5ff6 100644--- a/libsvgbird/SvgDrawing.vala+++ b/libsvgbird/SvgDrawing.vala@@ -83,17 +83,11 @@ public class SvgDrawing : Object { 	 	public override void move (double dx, double dy) { 	}-	-	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 string to_string () { 		return @"SvgDrawing width: $width, height: $height"; 	}diff --git a/libsvgbird/SvgPath.vala b/libsvgbird/SvgPath.valaindex 936d638..878e244 100644--- a/libsvgbird/SvgPath.vala+++ b/libsvgbird/SvgPath.vala@@ -94,17 +94,11 @@ public class SvgPath : Object {  	public override void move (double dx, double dy) { 	}-	-	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); 	}diff --git a/libsvgbird/SvgStyle.vala b/libsvgbird/SvgStyle.valaindex e917c85..d35f244 100644--- a/libsvgbird/SvgStyle.vala+++ b/libsvgbird/SvgStyle.vala@@ -24,6 +24,7 @@ public class SvgStyle : GLib.Object { 	public Color? fill = null; 	public Gradient? stroke_gradient = null; 	public Gradient? fill_gradient = null;+	public LineCap line_cap = LineCap.BUTT;  	public double stroke_width = 0; diff --git a/libsvgbird/SvgTransform.vala b/libsvgbird/SvgTransform.valaindex 56bcdae..7d8806b 100644--- a/libsvgbird/SvgTransform.vala+++ b/libsvgbird/SvgTransform.vala@@ -31,6 +31,17 @@ public class SvgTransform : GLib.Object { 	public SvgTransform () { 	} +	public SvgTransform.for_matrix (Matrix matrix) {+		type = TransformType.MATRIX;++		arguments.add (matrix.xx);+		arguments.add (matrix.yx);+		arguments.add (matrix.xy);+		arguments.add (matrix.yy);+		arguments.add (matrix.x0);+		arguments.add (matrix.y0);+	}+ 	public SvgTransform copy () { 		SvgTransform transform = new SvgTransform (); 		transform.type = type;diff --git a/libsvgbird/SvgTransforms.vala b/libsvgbird/SvgTransforms.valaindex cfbc322..8230bc4 100644--- a/libsvgbird/SvgTransforms.vala+++ b/libsvgbird/SvgTransforms.vala@@ -17,13 +17,53 @@ using Cairo; namespace SvgBird {  public class SvgTransforms : GLib.Object {+	public Matrix rotation_matrix; 	public Gee.ArrayList<SvgTransform> transforms; 	 	public double x = 0; 	public double y = 0;+	public double rotation = 0;+	public double scale_x = 1;+	public double scale_y = 1; 	 	public SvgTransforms () { 		transforms = new Gee.ArrayList<SvgTransform> ();+		rotation_matrix = Matrix.identity ();+	}++	public void collapse_transforms () {+		SvgTransform transform = new SvgTransform.for_matrix (rotation_matrix);+		add (transform);+		+		rotation_matrix = Matrix.identity ();+		rotation = 0;+		+		Matrix collapsed = get_matrix ();+		SvgTransform transform_transform = new SvgTransform.for_matrix (collapsed);+		transforms.clear ();+		add (transform_transform);+	}++	public void rotate (double theta, double x, double y) {+		rotation += theta;+		+		while (rotation > 2 * Math.PI) {+			rotation -= 2 * Math.PI;+		}++		while (rotation < -2 * Math.PI) {+			rotation += 2 * Math.PI;+		}++		rotation_matrix = Matrix.identity ();+		rotation_matrix.translate (x, y);+		rotation_matrix.rotate (rotation);+		rotation_matrix.translate (-x, -y);+	}++	public void resize (double x, double y) {+		scale_x += x;+		scale_y += y; 	}  	public SvgTransforms copy () {@@ -41,24 +81,21 @@ public class SvgTransforms : GLib.Object { 	} 	 	public Matrix get_matrix () {-		Matrix matrix = Matrix.identity ();-		-		matrix.translate (x, y);+		Matrix transformation_matrix = Matrix.identity (); 		 		for (int i = 0; i < transforms.size; i++) {-			matrix.multiply (matrix, transforms.get (i).get_matrix ());+			Matrix part = transforms.get (i).get_matrix ();+			transformation_matrix.multiply (transformation_matrix, part); 		}-		-		return matrix;++		transformation_matrix.multiply (transformation_matrix, rotation_matrix);++		return transformation_matrix; 	} 	 	public string to_string () { 		StringBuilder sb = new StringBuilder ();-		-		if (x != 0 || y != 0) {-			sb.append (@"$(TransformType.TRANSLATE): $x,$y ");-		}-		+ 		foreach (SvgTransform t in transforms) { 			sb.append (t.to_string ()); 			sb.append (" ");

Contact

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