Clone in a terminal:
Commit 647f984
Johan Mattsson - 2019-07-22T19:31:40+00:00
647f9849000576c6787fd644280d5566311badcfjohan.mattsson.m@gmail.com

Fix resize tool

Changed files (5)

Diff

diff --git a/libbirdfont/Doubles.vala b/libbirdfont/Doubles.valanew file mode 100644index 0000000..ec5199e--- /dev/null+++ b/libbirdfont/Doubles.vala@@ -0,0 +1,174 @@+/*+	Copyright (C) 2015 2019 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 = 0;+	int capacity = 10;+	+	public Doubles () {+		data = new double[capacity];+	}++	public Doubles.for_capacity (int capacity) {+		data = new double[capacity];+		this.capacity = capacity;+	}+	+	~Doubles () {+		delete data;+		data = null;+	}++	public void clear () {+		size = 0;+	}+	+	public void set_double (int index, double p) {+		if (unlikely (index < 0)) {+			warning ("index < 0");+			return;+		}++		if (unlikely (index >= size)) {+			warning ("index >= size");+			return;+		}+		+		data[index] = p;+	}+	+	public void insert (int index, double p) {+		insert_element (index);+		data[index] = p;+	}++	public void insert_element (int index) {+		if (capacity < size + 1) {+			increase_capacity ();+		}+		+		if (unlikely (index < 0 || index > size)) {+			warning (@"Bad index $index.");+			return;+		}+		+		double* point_data = new double[capacity];+		+		if (index > 0) {+			Posix.memcpy (point_data, data, sizeof (double) * index);+		}+		+		if (index < size) {+			int dest_position = index + 1; +			Posix.memcpy (point_data + dest_position, data + index, sizeof (double) * (size - index));+		}+		+		size += 1;+		delete data;+		data = point_data;+	}+	+	public void remove_first (int n) {+		if (size < n) {+			return;+		}+		+		size -= n;+		+		for (int i = 0; i < size; i++) {+			data[i] = data[i + n];+		}+	}+	+	public void remove (int offset, int length) {+		if (unlikely (offset < 0 || offset + length > size)) {+			warning (@"Invalid offset: $offset, length: $length, size: $size");+			return;+		}+		+		for (int i = offset; i < size; i++) {+			data[i] = data[i + length];+		}+		+		size -= length;+	}+	+	void increase_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;		+	}++	public void add (double d) {+		if (size >= capacity) {+			increase_capacity ();+		}+		+		data[size] = d;+		size++;+	}+	+	public Doubles copy () {+		Doubles d = new Doubles ();+		delete d.data;+		d.data = new double[capacity];+		d.capacity = capacity;+		d.size = size;+		Posix.memcpy (d.data, data, sizeof (double) * size);+		return d;+	}+	+	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];+	}++	+	public string get_string (int i) {+		return round (get_double (i));+	}++	public static string round (double p) {+		string v = p.to_string ();+		char[] c = new char [501];+		+		v = p.format (c, "%3.5f");+		+		if (v.index_of ("e") != -1) {	+			return "0.0";+		}+		+		return v;+	}+}++}+diff --git a/libbirdfont/Path.vala b/libbirdfont/Path.valaindex 8ad6624..bfb2f4a 100644--- a/libbirdfont/Path.vala+++ b/libbirdfont/Path.vala@@ -1,5 +1,5 @@ /*-	Copyright (C) 2012 - 2016 Johan Mattsson+	Copyright (C) 2012 - 2016 2019 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 @@ -1147,7 +1147,45 @@ public class Path : GLib.Object { 			ymin = e.y; 		} 	}+	+	public void transform (Matrix matrix) {+		double x, y;+		EditPointHandle handle;+		+		foreach (EditPoint point in points) {+			x = point.x;+			y = point.y;+			+			matrix.transform_point (ref x, ref y);+			+			point.independent_x = x;+			point.independent_y = y;+			+			handle = point.get_right_handle ();+			+			x = handle.x;+			y = handle.y;+			+			matrix.transform_point (ref x, ref y);+			+			handle.independent_x = x;+			handle.independent_y = y;++			handle = point.get_left_handle ();+			+			x = handle.x;+			y = handle.y;+			+			matrix.transform_point (ref x, ref y);+			+			handle.independent_x = x;+			handle.independent_y = y;++		} 		+		update_region_boundaries ();+	}+ 	/** Test if @param path is a valid outline for this object. */	 	public bool test_is_outline (Path path) { 		assert (false);diff --git a/libbirdfont/ResizeTool.vala b/libbirdfont/ResizeTool.valaindex d1ef7b8..aad972e 100644--- a/libbirdfont/ResizeTool.vala+++ b/libbirdfont/ResizeTool.vala@@ -1,5 +1,5 @@ /*-	Copyright (C) 2013 2015 Johan Mattsson+	Copyright (C) 2013 2015 2019 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 @@ -351,15 +351,16 @@ public class ResizeTool : Tool {  	public void resize_selected_paths (double ratio_x, double ratio_y) { 		Glyph g = MainWindow.get_current_glyph ();-		resize_glyph (g, ratio_x, ratio_y, true);+		resize_glyph (g, ratio_x, ratio_y, true, true); 	}-	-	public void resize_glyph (Glyph glyph, double ratio_x,-			double ratio_y, bool selected = true) {-					-		double resize_pos_x = 0;-		double resize_pos_y = 0;-		double selection_minx, selection_miny, dx, dy;++	public void resize_glyph (Glyph glyph,+			double ratio_x,+			double ratio_y,+			bool selected = true,+			bool relative_to_object = false) {+				+		Font font = BirdFont.get_current_font (); 		 		if (!selected) { 			glyph.clear_active_paths ();@@ -369,25 +370,38 @@ public class ResizeTool : Tool { 			} 		} 		-		get_selection_min (out resize_pos_x, out resize_pos_y);-		-		// resize paths-		foreach (Path selected_path in glyph.active_paths) {-			selected_path.resize (ratio_x, ratio_y);-			selected_path.reset_stroke ();+		foreach (Path path in glyph.active_paths) {+			x = selection_box_center_x - selection_box_width / 2;+			y = font.base_line;+				+			if (relative_to_object) {+				y = selection_box_center_y - selection_box_height / 2;+			}+				+			SvgTransforms transform = new SvgTransforms ();+			transform.resize (ratio_x, ratio_y, x, y);+			Matrix matrix = transform.get_matrix ();+			path.transform (matrix);+			path.reset_stroke (); 		}-		+				 		if (glyph.active_paths.size > 0) {-			update_selection_box ();-			objects_resized (selection_box_width, selection_box_height);+			foreach (Path p in glyph.active_paths) {+				p.update_region_boundaries ();+			} 		}  		if (!selected) {-			glyph.left_limit *= ratio_x; +			glyph.add_help_lines ();+			glyph.left_limit *= ratio_x; 			glyph.right_limit *= ratio_x; 			glyph.clear_active_paths (); 			glyph.remove_lines (); 			glyph.add_help_lines ();++			glyph.view_zoom = 1;+			glyph.view_offset_x = 0;+			glyph.view_offset_y = 0; 		} 	} diff --git a/libbirdfont/SvgTransform.vala b/libbirdfont/SvgTransform.valanew file mode 100644index 0000000..96581ac--- /dev/null+++ b/libbirdfont/SvgTransform.vala@@ -0,0 +1,112 @@+/*+	Copyright (C) 2016 2019 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 Cairo;++namespace BirdFont {++public enum TransformType {+	NONE,+	TRANSLATE,+	MATRIX,+	SCALE,+	ROTATE+}++public class SvgTransform : GLib.Object {+	public TransformType type = TransformType.NONE;+	public Doubles arguments = new Doubles.for_capacity (10);+	+	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;+		transform.arguments = arguments.copy ();+		return transform;+	}++	public string to_string () {+		StringBuilder sb = new StringBuilder ();+		+		sb.append (@"$type");+		sb.append (" ");+		+		for (int i = 0; i < arguments.size; i++) {+			sb.append (@"$(arguments.get_double (i)) ");+		}++		return sb.str;+	}+		+	public Matrix get_matrix () {+		Matrix matrix;+		+		matrix = Matrix.identity ();+		+		if (type == TransformType.ROTATE) {+			if (arguments.size == 1) {+				double r = arguments.get_double (0);+				r *= Math.PI / 180;+				matrix.rotate (r);+			}+		} else if (type == TransformType.SCALE) {+			if (arguments.size == 1) {+				double s = arguments.get_double (0);+				matrix.scale (s, s);+			} 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/SvgTransforms.vala b/libbirdfont/SvgTransforms.valanew file mode 100644index 0000000..8e220ed--- /dev/null+++ b/libbirdfont/SvgTransforms.vala@@ -0,0 +1,174 @@+/*+	Copyright (C) 2016 2019 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 Matrix rotation_matrix;+	public Matrix size_matrix;+	public Gee.ArrayList<SvgTransform> transforms;+	+	public double rotation = 0;+	public double total_rotation = 0;+	public double translate_x = 0;+	public double translate_y = 0;+	+	public SvgTransforms () {+		transforms = new Gee.ArrayList<SvgTransform> ();+		rotation_matrix = Matrix.identity ();+		size_matrix = Matrix.identity ();+	}++	public void clear_rotation () {+		rotation = 0;+		total_rotation = 0;+		rotation_matrix = Matrix.identity ();	+	}++	public double get_rotation () {+		Matrix m = get_matrix ();+		double w = 1;+		double h = 1;+		m.transform_distance (ref w, ref h);+		return Math.atan2 (h, w);+	}++	public void collapse_transforms () {+		Matrix collapsed = get_matrix ();+		+		translate_x	= 0;+		translate_y	= 0;++		rotation_matrix = Matrix.identity ();+		rotation = 0;++		size_matrix = Matrix.identity ();+		+		clear ();+		+		SvgTransform collapsed_transform = new SvgTransform.for_matrix (collapsed);+		add (collapsed_transform);+	}++	public void clear () {+		transforms.clear ();+		+		rotation_matrix = Matrix.identity ();+		rotation = 0;+		+		size_matrix = Matrix.identity ();+		+		translate_x = 0;+		translate_y = 0;+	}++	public void translate (double x, double y) {+		translate_x += x;+		translate_y += y;+	}++	public void rotate (double theta, double x, double y) {+		rotation += theta;+		total_rotation += theta;+		+		while (rotation > 2 * Math.PI) {+			rotation -= 2 * Math.PI;+		}++		while (rotation < -2 * Math.PI) {+			rotation += 2 * Math.PI;+		}++		while (total_rotation > 2 * Math.PI) {+			total_rotation -= 2 * Math.PI;+		}++		while (total_rotation < -2 * Math.PI) {+			total_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 scale_x, double scale_y, double x, double y) {+		if (scale_x <= 0 || scale_y <= 0) {+			return;+		}+		+		double x2 = x;+		double y2 = y;+		+		size_matrix = Matrix.identity ();+		size_matrix.scale (scale_x, scale_y);+		size_matrix.transform_point (ref x2, ref y2);++		double dx = x - x2;+		double dy = y - y2;+		+		size_matrix.translate (dx / scale_x, dy / scale_y);+	}++	public SvgTransforms copy () {+		SvgTransforms copy_transforms = new SvgTransforms ();+		+		foreach (SvgTransform t in transforms) {+			copy_transforms.add (t.copy ());+		}+		+		return copy_transforms;+	}++	public void insert (int position, SvgTransform transform) {+		transforms.insert (position, transform);+	}++	public void add (SvgTransform transform) {+		transforms.add (transform);+	}+	+	public Matrix get_matrix () {+		Matrix transformation_matrix = Matrix.identity ();+		+		for (int i = 0; i < transforms.size; i++) {+			Matrix part = transforms.get (i).get_matrix ();+			transformation_matrix.multiply (part, transformation_matrix);+		}++		transformation_matrix.translate (translate_x, translate_y);++		transformation_matrix.multiply (transformation_matrix, rotation_matrix);+		transformation_matrix.multiply (transformation_matrix, size_matrix);++		return transformation_matrix;+	}+	+	public string to_string () {+		StringBuilder sb = new StringBuilder ();++		foreach (SvgTransform t in transforms) {+			sb.append (t.to_string ());+			sb.append (" ");+		}+		+		return sb.str;+	}+}++}+

Contact

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