The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

PointConverter.vala in libbirdfont

This file is a part of the Birdfont project.

Contributing

Send patches or pull requests to johan.mattsson.m@gmail.com.
Clone this repository: git clone https://github.com/johanmattssonm/birdfont.git

Revisions

View the latest version of libbirdfont/PointConverter.vala.
Suppress zoom when canvas is moving
1 /* 2 Copyright (C) 2014 Johan Mattsson 3 4 This library is free software; you can redistribute it and/or modify 5 it under the terms of the GNU Lesser General Public License as 6 published by the Free Software Foundation; either version 3 of the 7 License, or (at your option) any later version. 8 9 This library is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 */ 14 15 using Cairo; 16 using Math; 17 18 namespace BirdFont { 19 20 /** A class for converting control points. */ 21 public class PointConverter { 22 23 Path original_path; 24 Path quadratic_path; 25 26 public PointConverter (Path path) { 27 original_path = path; 28 } 29 30 public Path get_quadratic_path () { 31 bool add_more_points = false; 32 33 quadratic_path = original_path.copy (); 34 35 estimated_cubic_path (); 36 37 if (add_more_points) { 38 warning ("Too many points in segment."); 39 } 40 41 if (quadratic_path.points.size < 2) { 42 return new Path (); 43 } 44 45 foreach (EditPoint e in quadratic_path.points) { 46 if (e.get_right_handle ().type == PointType.CUBIC) { 47 PenTool.convert_point_segment_type (e, e.get_next (), PointType.DOUBLE_CURVE); 48 } 49 } 50 51 if (quadratic_path.get_last_point ().get_right_handle ().type == PointType.CUBIC) { 52 PenTool.convert_point_segment_type (quadratic_path.get_last_point (), 53 quadratic_path.get_first_point (), 54 PointType.DOUBLE_CURVE); 55 } 56 57 quadratic_path.add_hidden_double_points (); 58 59 return quadratic_path; 60 } 61 62 public void estimated_cubic_path () { 63 EditPoint segment_start; 64 EditPoint segment_stop; 65 EditPoint quadratic_segment_start; 66 EditPoint quadratic_segment_stop; 67 EditPoint e; 68 double distance, step; 69 int points_in_segment = 0; 70 int size; 71 72 if (quadratic_path.points.size <= 1) { 73 } 74 75 foreach (EditPoint ep in quadratic_path.points) { 76 ep.set_tie_handle (false); 77 ep.set_reflective_handles (false); 78 } 79 80 size = quadratic_path.points.size; 81 segment_start = quadratic_path.get_first_point (); 82 for (int i = 0; i < size; i++) { 83 segment_stop = (i == size -1) 84 ? quadratic_path.get_first_point () 85 : segment_start.get_next (); 86 87 quadratic_segment_start = segment_start.copy (); 88 quadratic_segment_stop = segment_stop.copy (); 89 90 PenTool.convert_point_segment_type (quadratic_segment_start, quadratic_segment_stop, PointType.DOUBLE_CURVE); 91 92 distance = 0; 93 e = new EditPoint (); 94 if (segment_start.get_right_handle ().is_line () 95 && segment_stop.get_left_handle ().is_line ()) { 96 // skipping line 97 } else if (points_in_segment >= 10) { 98 warning ("Too many points."); 99 } else { 100 find_largest_distance (segment_start, segment_stop, 101 quadratic_segment_start, quadratic_segment_stop, 102 out distance, out e, out step); 103 } 104 105 if (distance > 0.2) { // range 0.1 - 0.4, 106 quadratic_path.insert_new_point_on_path (e); 107 points_in_segment++; 108 size += 2; // the new point + segment start 109 } else { 110 points_in_segment = 0; 111 segment_start = segment_stop; 112 } 113 } 114 } 115 116 // TODO: Optimize 117 public static void find_largest_distance (EditPoint a0, EditPoint a1, EditPoint b0, EditPoint b1, 118 out double distance, out EditPoint new_point, out double step) { 119 double max_d; 120 double min_d; 121 int steps = (int) (1.6 * Path.get_length_from (a0, a1)); 122 double x_out, y_out; 123 double step_out; 124 125 x_out = 0; 126 y_out = 0; 127 step_out = 0; 128 step = 0; 129 distance = 0; 130 131 new_point = new EditPoint (); 132 new_point.prev = a0; 133 new_point.next = a1; 134 new_point.get_right_handle ().type = PointType.CUBIC; 135 new_point.get_left_handle ().type = PointType.CUBIC; 136 137 steps = 20; // FIXME: adjust to length 138 139 if (a0.get_right_handle ().type == PointType.QUADRATIC 140 || a1.get_left_handle ().type == PointType.QUADRATIC 141 || a0.get_right_handle ().type == PointType.LINE_QUADRATIC 142 || a1.get_left_handle ().type == PointType.LINE_QUADRATIC) { 143 return; 144 } 145 146 max_d = Glyph.CANVAS_MIN; 147 min_d = Glyph.CANVAS_MAX; 148 Path.all_of (a0, a1, (xa, ya, ta) => { 149 150 min_d = double.MAX; 151 Path.all_of (b0, b1, (xb, yb, tb) => { 152 double d = Path.distance (xa, xb, ya, yb); 153 154 if (d < min_d) { 155 min_d = d; 156 } 157 158 return true; 159 }, steps); 160 161 if (min_d > max_d) { 162 max_d = min_d; 163 x_out = xa; 164 y_out = ya; 165 step_out = ta; 166 } 167 168 return true; 169 }, steps); 170 171 distance = max_d; 172 new_point.x = x_out; 173 new_point.y = y_out; 174 step = step_out; 175 } 176 } 177 178 } 179