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

Revisions

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