.
1 /*
2 Copyright (C) 2013 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 public class KerningTools : ToolCollection {
21 public static Gee.ArrayList<Expander> expanders;
22 public static int next_class = 0;
23 public static Expander classes;
24
25 public static double font_size = 1;
26 public static ZoomBar zoom_bar;
27
28 public KerningTools () {
29 init ();
30 }
31
32 public static void init () {
33 Expander kerning_tools = new Expander (t_("Kerning Tools"));
34 classes = new Expander ();
35 expanders = new Gee.ArrayList<Expander> ();
36
37 Expander font_name = new Expander ();
38 font_name.add_tool (new FontName ());
39 font_name.draw_separator = false;
40
41 Expander zoom_expander = new Expander (t_("Font Size"));
42
43 zoom_bar = new ZoomBar ();
44 zoom_bar.new_zoom.connect ((z) => {
45 font_size = 3 * z;
46
47 if (font_size < 0.1) {
48 font_size = 0.1;
49 }
50
51 GlyphCanvas.redraw ();
52 });
53 zoom_expander.add_tool (zoom_bar);
54
55 Tool new_kerning_class = new Tool ("kerning_class", t_("Create new kerning class."));
56 new_kerning_class.select_action.connect ((self) => {
57 classes.add_tool (new KerningRange (@"Kerning class $(++next_class)"));
58 Toolbox.redraw_tool_box ();
59 });
60 kerning_tools.add_tool (new_kerning_class);
61
62 Tool text_kerning = new Tool ("kerning_text_input", t_("Use text input to enter kerning values."));
63 text_kerning.select_action.connect ((self) => {
64 KerningDisplay d = MainWindow.get_kerning_display ();
65 d.set_kerning_by_text ();
66 });
67 kerning_tools.add_tool (text_kerning);
68
69 Tool insert_last = new Tool ("insert_last_glyph", t_("Insert glyph from overview"));
70 insert_last.select_action.connect ((self) => {
71 KerningDisplay d = MainWindow.get_kerning_display ();
72 GlyphSelection gs = new GlyphSelection ();
73
74 gs.selected_glyph.connect ((gc) => {
75 d.inser_glyph (gc.get_current ());
76 MainWindow.get_tab_bar ().select_tab_name ("Kerning");
77 });
78
79 GlyphCanvas.set_display (gs);
80 });
81 kerning_tools.add_tool (insert_last);
82
83 Tool insert_unicode = new Tool ("insert_unichar", t_("Insert character by unicode value"));
84 insert_unicode.select_action.connect ((self) => {
85 KerningDisplay d = MainWindow.get_kerning_display ();
86 d.insert_unichar ();
87 });
88 kerning_tools.add_tool (insert_unicode);
89
90 kerning_tools.set_persistent (false);
91 kerning_tools.set_unique (false);
92
93 classes.set_persistent (true);
94 classes.set_unique (true);
95
96 expanders.add (font_name);
97 expanders.add (zoom_expander);
98 expanders.add (kerning_tools);
99 expanders.add (classes);
100 }
101
102 public static void add_unique_class (KerningRange kerning_class) {
103 KerningRange k;
104
105 if (is_null (classes)) { // FIXME: export without tools
106 init ();
107 }
108
109 foreach (Tool t in classes.tool) {
110 if (!(t is KerningRange)) {
111 warning ("Tool is not kerning range");
112 return;
113 }
114
115 k = (KerningRange) t;
116 if (k.glyph_range.get_all_ranges () == kerning_class.glyph_range.get_all_ranges ()) {
117 return;
118 }
119 }
120
121 classes.add_tool (kerning_class);
122 }
123
124 public static GlyphRange get_kerning_class (int index) {
125 if (likely (0 <= index < classes.tool.size)) {
126 return ((KerningRange) classes.tool.get (index)).glyph_range;
127 } else {
128 warning ("Index out of bounds.");
129 return new GlyphRange ();
130 }
131 }
132
133 public static void update_kerning_classes () {
134 KerningClasses k = BirdFont.get_current_font ().get_kerning_classes ();
135 KerningRange kr;
136 GlyphRange r;
137 int i;
138
139 remove_all_kerning_classes ();
140
141 for (i = 0; i < k.classes_first.size; i++) {
142 r = k.classes_first.get (i);
143 if (r.is_class ()) {
144 kr = new KerningRange ();
145 kr.set_ranges (r.get_all_ranges ());
146 add_unique_class (kr);
147 }
148
149 r = k.classes_last.get (i);
150 if (r.is_class ()) {
151 kr = new KerningRange ();
152 kr.set_ranges (r.get_all_ranges ());
153 add_unique_class (kr);
154 }
155 }
156 }
157
158 private static void remove_all_kerning_classes () {
159 if (is_null (classes)) { // FIXME: export without tools
160 init ();
161 }
162
163 classes.tool.clear ();
164
165 if (!is_null (MainWindow.get_toolbox ())) {
166 MainWindow.get_toolbox ().update_expanders ();
167 }
168 }
169
170 public static void remove_empty_classes () {
171 KerningRange kr;
172 int i;
173
174 if (classes.tool.size == 0) {
175 return;
176 }
177
178 i = 0;
179 foreach (Tool t in classes.tool) {
180 return_if_fail (t is KerningRange);
181
182 kr = (KerningRange) t;
183 if (kr.glyph_range.is_empty ()) {
184 classes.tool.remove_at (i);
185 remove_empty_classes ();
186 Toolbox.redraw_tool_box ();
187 return;
188 }
189
190 i++;
191 }
192 }
193
194 public override Gee.ArrayList<Expander> get_expanders () {
195 return expanders;
196 }
197
198 public static void update_spacing_classes () {
199 KerningRange kr;
200
201 if (classes.tool.size == 0) {
202 return;
203 }
204
205 foreach (Tool t in classes.tool) {
206 return_if_fail (t is KerningRange);
207
208 kr = (KerningRange) t;
209 kr.update_spacing_class ();
210 }
211 }
212 }
213
214 }
215