The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

KerningTools.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/KerningTools.vala.
Use trusty in travis
1 /* 2 Copyright (C) 2013 2014 2015 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 static Tool previous_kerning_string; 29 public static Tool next_kerning_string; 30 31 public static Expander otf_features; 32 33 static OtfTags active_otf_features; 34 35 public KerningTools () { 36 selected (); 37 } 38 39 public override void selected () { 40 init (); 41 } 42 43 public static OtfTags get_otf_tags () { 44 if (is_null (active_otf_features)) { 45 return new OtfTags (); 46 } 47 48 return active_otf_features; 49 } 50 51 public static void init () { 52 Font font = BirdFont.get_current_font (); 53 54 active_otf_features = new OtfTags (); 55 56 Expander kerning_tools = new Expander (t_("Kerning Tools")); 57 classes = new Expander (); 58 expanders = new Gee.ArrayList<Expander> (); 59 60 Expander font_name = new Expander (); 61 font_name.add_tool (new FontName ()); 62 63 Expander zoom_expander = new Expander (t_("Font Size")); 64 65 zoom_bar = new ZoomBar (); 66 zoom_bar.new_zoom.connect ((z) => { 67 Font f; 68 69 font_size = 3 * z; 70 71 if (font_size < 0.1) { 72 font_size = 0.1; 73 } 74 75 f = BirdFont.get_current_font (); 76 f.settings.set_setting ("kerning_zoom", @"$z"); 77 78 GlyphCanvas.redraw (); 79 }); 80 zoom_expander.add_tool (zoom_bar); 81 82 Tool new_kerning_class = new Tool ("kerning_class", t_("Create new kerning class.")); 83 new_kerning_class.select_action.connect ((self) => { 84 Font f = BirdFont.get_current_font (); 85 string label = t_("Kerning class"); 86 KerningRange kr = new KerningRange (f, @"$label $(++next_class)"); 87 classes.add_tool (kr); 88 self.set_selected (false); 89 classes.redraw (); 90 }); 91 kerning_tools.add_tool (new_kerning_class); 92 93 Tool text_kerning = new Tool ("kerning_text_input", t_("Use text input to enter kerning values.")); 94 text_kerning.select_action.connect ((self) => { 95 KerningDisplay d = MainWindow.get_kerning_display (); 96 d.set_kerning_by_text (); 97 self.set_selected (false); 98 }); 99 kerning_tools.add_tool (text_kerning); 100 101 Tool insert_last = new Tool ("insert_glyph_from_overview", t_("Insert glyph from overview")); 102 insert_last.select_action.connect ((self) => { 103 KerningDisplay d = MainWindow.get_kerning_display (); 104 GlyphSelection gs = new GlyphSelection (); 105 106 gs.selected_glyph.connect ((gc) => { 107 d.inser_glyph (gc.get_current ()); 108 MainWindow.get_tab_bar ().select_tab_name ("Kerning"); 109 }); 110 111 GlyphCanvas.set_display (gs); 112 self.set_selected (false); 113 }); 114 kerning_tools.add_tool (insert_last); 115 116 Tool insert_unicode = new Tool ("insert_unichar", t_("Insert character by unicode value")); 117 insert_unicode.select_action.connect ((self) => { 118 KerningDisplay d = MainWindow.get_kerning_display (); 119 d.insert_unichar (); 120 self.set_selected (false); 121 }); 122 kerning_tools.add_tool (insert_unicode); 123 124 string empty_kerning_text = t_("Open a text file with kerning strings first."); 125 126 previous_kerning_string = new Tool ("previous_kerning_string", t_("Previous kerning string")); 127 previous_kerning_string.select_action.connect ((self) => { 128 FontDisplay fd = MainWindow.get_current_display (); 129 KerningDisplay d = (KerningDisplay) fd; 130 Font f = BirdFont.get_current_font (); 131 string w = f.kerning_strings.previous (); 132 133 if (f.kerning_strings.is_empty ()) { 134 MainWindow.show_message (empty_kerning_text); 135 } else if (w == "") { 136 MainWindow.show_message (t_("You have reached the beginning of the list.")); 137 } else { 138 d.new_line (); 139 d.add_text (w); 140 } 141 self.set_selected (false); 142 }); 143 kerning_tools.add_tool (previous_kerning_string); 144 145 next_kerning_string = new Tool ("next_kerning_string", t_("Next kerning string")); 146 next_kerning_string.select_action.connect ((self) => { 147 FontDisplay fd = MainWindow.get_current_display (); 148 KerningDisplay d = (KerningDisplay) fd; 149 Font f = BirdFont.get_current_font (); 150 string w = f.kerning_strings.next (); 151 152 if (f.kerning_strings.is_empty ()) { 153 MainWindow.show_message (empty_kerning_text); 154 } else if (w == "") { 155 MainWindow.show_message (t_("You have reached the end of the list.")); 156 } else { 157 d.new_line (); 158 d.add_text (w); 159 } 160 self.set_selected (false); 161 }); 162 kerning_tools.add_tool (next_kerning_string); 163 164 otf_features = new Expander (t_("Substitutions")); 165 166 foreach (string tag in font.alternates.get_all_tags ()) { 167 add_otf_label (tag); 168 } 169 170 kerning_tools.set_persistent (false); 171 kerning_tools.set_unique (false); 172 173 classes.set_persistent (true); 174 classes.set_unique (true); 175 176 expanders.add (font_name); 177 expanders.add (zoom_expander); 178 expanders.add (kerning_tools); 179 expanders.add (classes); 180 expanders.add (otf_features); 181 } 182 183 public static void add_otf_label (string tag) { 184 OtfLabel otf_label = new OtfLabel (tag); 185 FontSettings fs = BirdFont.get_current_font ().settings; 186 187 otf_features.add_tool (otf_label); 188 otf_label.otf_feature_activity.connect ((enable, tag) => { 189 OtfTags tags = active_otf_features.copy (); 190 KerningDisplay kd = MainWindow.get_kerning_display (); 191 kd.new_segment (); 192 193 // create a new feature set in order to keep the features 194 // for other parts of the text in kerning tab 195 active_otf_features = tags; 196 197 if (enable) { 198 tags.add (tag); 199 fs.set_setting (@"kerning_$(tag)", "true"); 200 } else { 201 tags.remove (tag); 202 fs.set_setting (@"kerning_$(tag)", "false"); 203 } 204 205 kd.get_last_segment ().set_otf_tags (tags); 206 207 GlyphCanvas.redraw (); 208 }); 209 210 bool enable = fs.get_setting (@"kerning_$(tag)") == "true"; 211 otf_label.set_selected_tag (enable); 212 } 213 214 public static void add_unique_class (KerningRange kerning_class) { 215 KerningRange k; 216 217 if (is_null (classes)) { // FIXME: export without tools 218 init (); 219 } 220 221 foreach (Tool t in classes.tool) { 222 if (!(t is KerningRange)) { 223 warning ("Tool is not kerning range"); 224 return; 225 } 226 227 k = (KerningRange) t; 228 if (k.glyph_range.get_all_ranges () == kerning_class.glyph_range.get_all_ranges ()) { 229 return; 230 } 231 } 232 233 classes.add_tool (kerning_class); 234 } 235 236 public static GlyphRange get_kerning_class (int index) { 237 if (likely (0 <= index < classes.tool.size)) { 238 return ((KerningRange) classes.tool.get (index)).glyph_range; 239 } else { 240 warning ("Index out of bounds."); 241 return new GlyphRange (); 242 } 243 } 244 245 public static void update_kerning_classes () { 246 Font font = BirdFont.get_current_font (); 247 KerningClasses k = font.get_kerning_classes (); 248 KerningRange kr; 249 GlyphRange r; 250 int i; 251 252 remove_all_kerning_classes (); 253 254 for (i = 0; i < k.classes_first.size; i++) { 255 r = k.classes_first.get (i); 256 if (r.is_class ()) { 257 kr = new KerningRange (font); 258 kr.set_ranges (r.get_all_ranges ()); 259 add_unique_class (kr); 260 } 261 262 r = k.classes_last.get (i); 263 if (r.is_class ()) { 264 kr = new KerningRange (font); 265 kr.set_ranges (r.get_all_ranges ()); 266 add_unique_class (kr); 267 } 268 } 269 } 270 271 private static void remove_all_kerning_classes () { 272 if (is_null (classes)) { // FIXME: export without tools 273 init (); 274 } 275 276 classes.tool.clear (); 277 278 if (!is_null (MainWindow.get_toolbox ())) { 279 MainWindow.get_toolbox ().update_expanders (); 280 } 281 } 282 283 public static void remove_empty_classes () { 284 KerningRange kr; 285 int i; 286 287 if (classes.tool.size == 0) { 288 return; 289 } 290 291 i = 0; 292 foreach (Tool t in classes.tool) { 293 return_if_fail (t is KerningRange); 294 295 kr = (KerningRange) t; 296 if (kr.glyph_range.is_empty ()) { 297 classes.tool.remove_at (i); 298 remove_empty_classes (); 299 Toolbox.redraw_tool_box (); 300 return; 301 } 302 303 i++; 304 } 305 } 306 307 public override Gee.ArrayList<Expander> get_expanders () { 308 return expanders; 309 } 310 311 public static void update_spacing_classes () { 312 KerningRange kr; 313 314 if (classes.tool.size == 0) { 315 return; 316 } 317 318 foreach (Tool t in classes.tool) { 319 return_if_fail (t is KerningRange); 320 321 kr = (KerningRange) t; 322 kr.update_spacing_class (); 323 } 324 } 325 326 public override Gee.ArrayList<string> get_displays () { 327 Gee.ArrayList<string> d = new Gee.ArrayList<string> (); 328 d.add ("Kerning"); 329 d.add ("Spacing"); 330 return d; 331 } 332 333 } 334 335 } 336