The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

EditPointHandle.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/EditPointHandle.vala.
Ignore case in key bindings
1 /* 2 Copyright (C) 2012 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 Math; 16 17 namespace BirdFont { 18 19 public class EditPointHandle : GLib.Object { 20 21 public double length; 22 public unowned EditPoint parent; 23 public PointType type; 24 EditPoint? visual_handle = null; 25 static EditPoint none = new EditPoint (); 26 public bool active; 27 public bool selected; 28 29 public double angle; 30 31 public double x { 32 get { 33 double r = px (); 34 35 if (unlikely (r <= -100000)) { 36 print_position (); 37 move_to (0, 0); 38 } 39 40 return r; 41 } 42 43 set { 44 move_to_coordinate_internal (value, py ()); 45 46 if (parent.tie_handles) { 47 parent.process_tied_handle (); 48 } 49 50 if (parent.reflective_point) { 51 parent.process_symmetrical_handles (); 52 } 53 } 54 } 55 56 public double y { 57 get { 58 double r = py (); 59 60 if (unlikely (r <= -100000)) { 61 print_position (); 62 move_to (0, 0); 63 } 64 65 return r; 66 } 67 68 set { 69 move_to_coordinate_internal (px (), value); 70 71 if (parent.tie_handles) { 72 parent.process_tied_handle (); 73 } 74 75 if (parent.reflective_point) { 76 parent.process_symmetrical_handles (); 77 } 78 } 79 } 80 81 static int n_handles = 0; 82 83 public EditPointHandle.empty() { 84 this.parent = none; 85 this.angle = 0; 86 this.length = 10; 87 this.type = PointType.NONE; 88 this.active = false; 89 this.selected = false; 90 91 n_handles++; 92 } 93 94 public EditPointHandle (EditPoint parent, double angle, double length) { 95 this.parent = parent; 96 this.angle = angle; 97 this.length = length; 98 this.type = PointType.LINE_CUBIC; 99 this.active = false; 100 this.selected = false; 101 102 n_handles++; 103 } 104 105 ~EditPointHandle () { 106 n_handles--; 107 } 108 109 public EditPointHandle copy () { 110 EditPointHandle n = new EditPointHandle.empty (); 111 n.angle = angle; 112 n.length = length; 113 n.parent = parent; 114 n.type = type; 115 n.active = active; 116 n.selected = selected; 117 return n; 118 } 119 120 public EditPoint get_parent () { 121 return parent; 122 } 123 124 public void convert_to_line () { 125 switch (type) { 126 case PointType.QUADRATIC: 127 type = PointType.LINE_QUADRATIC; 128 break; 129 case PointType.DOUBLE_CURVE: 130 type = PointType.LINE_DOUBLE_CURVE; 131 break; 132 case PointType.CUBIC: 133 type = PointType.LINE_CUBIC; 134 break; 135 default: 136 break; 137 } 138 } 139 140 public bool is_curve () { 141 switch (type) { 142 case PointType.LINE_QUADRATIC: 143 return false; 144 case PointType.LINE_DOUBLE_CURVE: 145 return false; 146 case PointType.LINE_CUBIC: 147 return false; 148 } 149 150 return true; 151 } 152 153 public void convert_to_curve () { 154 switch (type) { 155 case PointType.LINE_QUADRATIC: 156 type = PointType.QUADRATIC; 157 break; 158 case PointType.LINE_DOUBLE_CURVE: 159 type = PointType.DOUBLE_CURVE; 160 break; 161 case PointType.LINE_CUBIC: 162 type = PointType.CUBIC; 163 break; 164 case PointType.QUADRATIC: 165 break; 166 case PointType.DOUBLE_CURVE: 167 break; 168 case PointType.CUBIC: 169 break; 170 default: 171 warning (@"Type $type"); 172 break; 173 } 174 } 175 176 public void set_point_type (PointType point_type) { 177 type = point_type; 178 } 179 180 double px () { 181 assert ((EditPoint?) parent != null); 182 return cos (angle) * length + parent.x; 183 } 184 185 double py () { 186 assert ((EditPoint?) parent != null); 187 return sin (angle) * length + parent.y; 188 } 189 190 internal void print_position () { 191 warning (@"\nEdit point handle at position $(px ()),$(py ()) is not valid.\n" 192 + @"Type: $(parent.type), " 193 + @"Angle: $angle, Length: $length."); 194 } 195 196 public EditPoint get_point () { 197 EditPoint p; 198 199 if (visual_handle == null) { 200 visual_handle = new EditPoint (0, 0); 201 } 202 203 p = (!) visual_handle; 204 p.x = x; 205 p.y = y; 206 207 return p; 208 } 209 210 public bool is_left_handle () { 211 return parent.get_left_handle () == this; 212 } 213 214 public void move_to_coordinate_delta (double dx, double dy) { 215 move_to_coordinate_internal (px () + dx, py () + dy); 216 } 217 218 public void move_to_coordinate (double x, double y) { 219 move_to_coordinate_internal (x, y); 220 221 if (parent.tie_handles) { 222 tie_handle (); 223 } 224 225 if (parent.reflective_point) { 226 tie_handle (); 227 process_symmetrical_handle (); 228 } 229 230 process_connected_handle (); 231 } 232 233 public void move_to_coordinate_internal (double x, double y) { 234 double a, b, c; 235 236 a = parent.x - x; 237 b = parent.y - y; 238 c = a * a + b * b; 239 240 if (unlikely(c == 0)) { 241 angle = 0; // FIXME: this should be a different point type without line handles 242 length = 0; 243 return; 244 } 245 246 length = sqrt (fabs (c)); 247 248 if (c < 0) length = -length; 249 250 if (y < parent.y) { 251 angle = acos (a / length) + PI; 252 } else { 253 angle = -acos (a / length) + PI; 254 } 255 } 256 257 public void process_connected_handle () { 258 EditPointHandle h; 259 260 if (unlikely (type == PointType.NONE)) { 261 warning ("Invalid type."); 262 } 263 264 if (type == PointType.QUADRATIC) { 265 if (!is_left_handle ()) { 266 if (parent.next != null) { 267 h = parent.get_next ().get_left_handle (); 268 h.parent.set_tie_handle (false); 269 h.type = PointType.QUADRATIC; 270 h.move_to_coordinate_internal (px (), py ()); 271 } 272 } else { 273 if (parent.prev != null) { 274 h = parent.get_prev ().get_right_handle (); 275 h.parent.set_tie_handle (false); 276 h.type = PointType.QUADRATIC; 277 h.move_to_coordinate_internal (px (), py ()); 278 } 279 } 280 } 281 } 282 283 public void process_symmetrical_handle () { 284 if (is_left_handle ()) { 285 parent.get_right_handle ().length = length; 286 parent.get_right_handle ().process_connected_handle (); 287 } else { 288 parent.get_left_handle ().length = length; 289 parent.get_left_handle ().process_connected_handle (); 290 } 291 292 process_connected_handle (); 293 } 294 295 public void tie_handle () { 296 if (is_left_handle ()) { 297 parent.get_right_handle ().angle = angle - PI; 298 parent.get_right_handle ().process_connected_handle (); 299 } else { 300 parent.get_left_handle ().angle = angle - PI; 301 parent.get_left_handle ().process_connected_handle (); 302 } 303 304 process_connected_handle (); 305 } 306 307 public void move_delta_coordinate (double dx, double dy) { 308 double px = px () + dx; 309 double py = py () + dy; 310 move_to_coordinate (px, py); 311 } 312 313 public void move_to (double x, double y) { 314 EditPoint.to_coordinate (ref x, ref y); 315 move_to_coordinate (x, y); 316 } 317 318 public bool is_line () { 319 return PenTool.is_line (type); 320 } 321 } 322 323 } 324