Updated Files
libbirdfont/Doubles.vala |
libbirdfont/Path.vala |
libbirdfont/ResizeTool.vala |
libbirdfont/SvgTransform.vala |
libbirdfont/SvgTransforms.vala |
--- /dev/null
+++ b/libbirdfont/Doubles.vala
@@ -1,1 +1,175 @@
+ /*
+ 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;
+ }
+ }
+
+ }
+
--- 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 @@
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);
--- 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 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 @@
}
}
- 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;
}
}
--- /dev/null
+++ b/libbirdfont/SvgTransform.vala
@@ -1,1 +1,113 @@
+ /*
+ 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;
+ }
+ }
+
+ }
--- /dev/null
+++ b/libbirdfont/SvgTransforms.vala
@@ -1,1 +1,175 @@
+ /*
+ 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;
+ }
+ }
+
+ }
+