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