.
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