The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

GridTool.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
Circle boundaries heads/master
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 Cairo; 16 using Math; 17 18 namespace BirdFont { 19 20 public class GridTool : Tool { 21 22 static Gee.ArrayList<Line> horizontal; 23 static Gee.ArrayList<Line> vertical; 24 25 static bool grid_visible = false; 26 public static bool ttf_units = false; 27 28 public static double size_x; 29 public static double size_y; 30 31 public static Gee.ArrayList<SpinButton> sizes; 32 33 /** Lock grid and guides. */ 34 public static bool lock_grid = false; 35 36 public GridTool (string n) { 37 string units; 38 base (n, t_("Show grid")); 39 40 units = Preferences.get ("ttf_units"); 41 if (units == "true") { 42 ttf_units = true; 43 } 44 45 horizontal = new Gee.ArrayList <Line> (); 46 vertical = new Gee.ArrayList <Line> (); 47 48 sizes = new Gee.ArrayList <SpinButton> (); 49 50 size_x = 2; 51 size_y = 2; 52 53 update_lines (); 54 55 select_action.connect((self) => { 56 grid_visible = !grid_visible; 57 update_lines (); 58 GlyphCanvas.redraw (); 59 60 self.set_selected (grid_visible); 61 62 Toolbox tb = MainWindow.get_toolbox (); 63 Tool t = tb.get_tool ("help_lines"); 64 65 if (grid_visible && !t.is_selected ()) { 66 MainWindow.get_toolbox ().select_tool (t); 67 } 68 }); 69 70 press_action.connect((self, b, x, y) => { 71 }); 72 73 release_action.connect((self, b, x, y) => { 74 }); 75 76 move_action.connect ((self, x, y) => { 77 }); 78 79 draw_action.connect ((self, cairo_context, glyph) => { 80 }); 81 82 } 83 84 public static void set_grid_width (double w) { 85 double t = 0; 86 87 if (ttf_units) { 88 ttf_grid_coordinate (ref w, ref t); 89 } 90 91 size_x = w; 92 size_y = w; 93 94 update_lines (); 95 } 96 97 public static void ttf_grid_coordinate (ref double x, ref double y) { 98 x = GlyfData.tie_to_ttf_grid_x (MainWindow.get_current_glyph (), x); 99 y = GlyfData.tie_to_ttf_grid_y (BirdFont.get_current_font (), y); 100 } 101 102 public static void update_lines () { 103 Glyph g = MainWindow.get_current_glyph (); 104 double step = size_y; 105 Color color = Theme.get_color ("Grid"); 106 double i; 107 int max_lines = 600; 108 int n; 109 Line t, l, u; 110 111 112 Line baseline = g.get_line ("baseline"); 113 Line bottom_margin = g.get_line ("bottom margin"); 114 Line top_margin = g.get_line ("top margin"); 115 116 Line left = g.get_line ("left"); 117 Line right = g.get_line ("right"); 118 119 vertical.clear (); 120 horizontal.clear (); 121 122 n = 0; 123 for (i = left.get_pos () - 7 * step; i <= right.get_pos () + 7 * step; i += step) { 124 l = new Line ("grid", "", i, Line.VERTICAL); 125 l.set_moveable (false); 126 l.set_color (color.r, color.g, color.b, color.a); 127 vertical.add (l); 128 129 if (++n >= max_lines) { 130 break; 131 } 132 } 133 134 n = 0; 135 for (i = baseline.get_pos () - step; i >= bottom_margin.get_pos () - 7 * step; i -= step) { 136 t = new Line ("grid", "", i, Line.HORIZONTAL); 137 t.set_moveable (false); 138 t.set_color (color.r, color.g, color.b, color.a); 139 horizontal.insert (0, t); 140 141 if (++n >= max_lines) { 142 break; 143 } 144 145 } 146 147 for (i = baseline.get_pos (); i <= top_margin.get_pos () + 7 * step; i += step) { 148 u = new Line ("grid", "", i, Line.HORIZONTAL); 149 u.set_moveable (false); 150 u.set_color (color.r, color.g, color.b, color.a); 151 horizontal.add (u); 152 153 if (++n >= max_lines) { 154 break; 155 } 156 157 } 158 } 159 160 public static void tie_coordinate (ref double x, ref double y) { 161 tie_point (ref x, ref y, true); 162 } 163 164 public static void tie_point (ref double x, ref double y, bool coordinate) { 165 x = tie_point_x (x, coordinate); 166 y = tie_point_y (y, coordinate); 167 } 168 169 public static double tie_point_x (double x, bool coordinate) 170 requires (vertical.size >= 2) 171 { 172 double d, m; 173 Line xmin = vertical.get (0); 174 Line xpos; 175 Line startx = vertical.get (0); 176 Line stopx = vertical.get (vertical.size - 1); 177 178 // outside of the grid 179 if (!coordinate) { 180 if (!(startx.pos < Glyph.path_coordinate_x (x) < stopx.pos)) { 181 return x; 182 } 183 } else { 184 if (!(startx.pos < x < stopx.pos)) { 185 return x; 186 } 187 } 188 189 if (!coordinate) { 190 xpos = new Line ("", "", 0, Line.VERTICAL); 191 xpos.pos = Glyph.path_coordinate_x (x); 192 } else { 193 xpos = new Line ("", "", x, Line.VERTICAL); 194 } 195 196 m = double.MAX; 197 foreach (Line line in vertical) { 198 d = Math.fabs (line.get_pos () - xpos.get_pos ()); 199 200 if (d <= m) { 201 m = d; 202 xmin = line; 203 } 204 205 } 206 207 if (!coordinate) { 208 x = Glyph.reverse_path_coordinate_x (xmin.get_pos ()); 209 } else { 210 x = xmin.get_pos (); 211 } 212 213 return x; 214 } 215 216 public static double tie_point_y (double y, bool coordinate) 217 requires (horizontal.size >= 2) 218 { 219 double d, m; 220 Line ymin = horizontal.get (0); 221 Line ypos; 222 Line starty = horizontal.get (0); 223 Line stopy = horizontal.get (horizontal.size - 1); 224 225 // outside of the grid 226 if (!coordinate) { 227 if (!(starty.pos < Glyph.path_coordinate_y (y) < stopy.pos)) { 228 return y; 229 } 230 } else { 231 if (!(starty.pos < y < stopy.pos)) { 232 return y; 233 } 234 } 235 236 if (!coordinate) { 237 ypos = new Line ("", "", 0, Line.HORIZONTAL); 238 ypos.pos = Glyph.path_coordinate_y (y); 239 } else { 240 ypos = new Line ("", "", y, Line.HORIZONTAL); 241 } 242 243 m = double.MAX; 244 foreach (Line line in horizontal) { 245 d = Math.fabs (line.get_pos () - ypos.get_pos ()); 246 247 if (d <= m) { 248 m = d; 249 ymin = line; 250 } 251 252 } 253 254 if (!coordinate) { 255 y = Glyph.reverse_path_coordinate_y (ymin.get_pos ()); 256 } else { 257 y = ymin.get_pos (); 258 } 259 260 return y; 261 } 262 263 public static bool has_ttf_grid () { 264 return ttf_units; 265 } 266 267 public static bool is_visible () { 268 return grid_visible; 269 } 270 271 public static Gee.ArrayList<Line> get_horizontal_lines () { 272 return horizontal; 273 } 274 275 public static Gee.ArrayList<Line> get_vertical_lines () { 276 return vertical; 277 } 278 279 } 280 281 } 282 283