The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

OtfFeatureTable.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/OtfFeatureTable.vala.
Merge ../birdfont-2.x
1 /* 2 Copyright (C) 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 17 namespace BirdFont { 18 19 /** A table for managing feature tags in Open Type tables. */ 20 public class OtfFeatureTable : Table { 21 Gee.ArrayList<Row> rows = new Gee.ArrayList<Row> (); 22 23 static const int NONE = 0; 24 static const int OTF_FEATURE = 1; 25 static const int SOURCE_GLYPH = 2; // the glyph to replace 26 static const int REPLACEMENT_GLYPH = 3; 27 static const int ALTERNATE_ENTRY = 4; 28 29 GlyphCollection? glyph_collection = null; 30 GlyphCollection? replacement_glyph = null; 31 string alternate_name = ""; 32 TextListener listener; 33 34 Gee.ArrayList<AlternateItem> undo_items; 35 // FIXME: implement redo 36 37 bool ignore_input = false; 38 39 public OtfFeatureTable (GlyphCollection? gc) { 40 glyph_collection = gc; 41 undo_items = new Gee.ArrayList<AlternateItem> (); 42 } 43 44 public override void selected_canvas () { 45 ignore_input = true; // make sure that tripple clicks in overview are ignored 46 47 TimeoutSource input_delay = new TimeoutSource (250); 48 input_delay.set_callback(() => { 49 ignore_input = false; 50 return false; 51 }); 52 input_delay.attach (null); 53 54 base.selected_canvas (); 55 } 56 57 public override Gee.ArrayList<Row> get_rows () { 58 return rows; 59 } 60 61 public override void selected_row (Row row, int column, bool delete_button) { 62 int row_index = row.get_index (); 63 GLib.Object o; 64 String s; 65 AlternateItem a; 66 67 if (ignore_input) { 68 return; 69 } 70 71 if (row_index == SOURCE_GLYPH) { 72 GlyphSelection gs = new GlyphSelection (); 73 74 gs.selected_glyph.connect ((gc) => { 75 glyph_collection = gc; 76 replacement_glyph = null; 77 Tool.yield (); 78 MainWindow.get_tab_bar ().select_tab_name (get_name ()); 79 }); 80 81 GlyphCanvas.set_display (gs); 82 } else if (row_index == REPLACEMENT_GLYPH) { 83 GlyphSelection gs = new GlyphSelection (); 84 85 gs.selected_glyph.connect ((gc) => { 86 replacement_glyph = gc; 87 Tool.yield (); 88 MainWindow.get_tab_bar ().select_tab_name (get_name ()); 89 }); 90 91 GlyphCanvas.set_display (gs); 92 } else if (row_index == OTF_FEATURE) { 93 return_if_fail (row.has_row_data ()); 94 o = (!) row.get_row_data (); 95 return_if_fail (o is String); 96 s = (String) o; 97 add_new_alternate (s.data); 98 } else if (row_index == ALTERNATE_ENTRY) { 99 if (delete_button) { 100 return_if_fail (row.has_row_data ()); 101 o = (!) row.get_row_data (); 102 return_if_fail (o is AlternateItem); 103 a = (AlternateItem) o; 104 105 a.delete_item_from_list (); 106 Font f = BirdFont.get_current_font (); 107 f.alternates.remove_empty_sets (); 108 109 undo_items.add (a); 110 111 update_rows (); 112 GlyphCanvas.redraw (); 113 } 114 } 115 } 116 117 public override void update_rows () { 118 Row row; 119 Font font; 120 121 font = BirdFont.get_current_font (); 122 rows.clear (); 123 124 row = new Row.headline (t_("Glyph Substitutions")); 125 rows.add (row); 126 127 string glyph = ""; 128 129 if (glyph_collection == null) { 130 glyph = t_("New glyph"); 131 } else { 132 glyph = ((!) glyph_collection).get_name (); 133 } 134 135 row = new Row.columns_1 (t_("Glyph") + ": " + glyph, SOURCE_GLYPH, false); 136 rows.add (row); 137 138 string replacement = t_("New glyph"); 139 140 if (replacement_glyph != null) { 141 GlyphCollection gc = (!) replacement_glyph; 142 replacement = gc.get_name (); 143 } 144 145 row = new Row.columns_1 (t_("Replacement") + ": " + replacement, REPLACEMENT_GLYPH, false); 146 rows.add (row); 147 148 // FIXME: reuse parts of this for fractions etc. 149 150 row = new Row.headline (t_("Tag")); 151 rows.add (row); 152 153 row = new Row.columns_1 (OtfLabel.get_string ("salt"), OTF_FEATURE, false); 154 row.set_row_data (new String ("salt")); 155 rows.add (row); 156 157 row = new Row.columns_1 (OtfLabel.get_string ("smcp"), OTF_FEATURE, false); 158 row.set_row_data (new String ("smcp")); 159 rows.add (row); 160 161 row = new Row.columns_1 (OtfLabel.get_string ("c2sc"), OTF_FEATURE, false); 162 row.set_row_data (new String ("c2sc")); 163 rows.add (row); 164 165 row = new Row.columns_1 (OtfLabel.get_string ("swsh"), OTF_FEATURE, false); 166 row.set_row_data (new String ("swsh")); 167 rows.add (row); 168 169 Gee.ArrayList<string> tags = font.alternates.get_all_tags (); 170 foreach (string tag in tags) { 171 row = new Row.headline (OtfLabel.get_string (tag)); 172 rows.add (row); 173 add_alternate_items (tag); 174 } 175 176 GlyphCanvas.redraw (); 177 } 178 179 void add_alternate_items (string tag) { 180 Font font = BirdFont.get_current_font (); 181 foreach (Alternate alt in font.alternates.get_alt (tag)) { 182 add_alternate_rows (alt); 183 } 184 } 185 186 void add_alternate_rows (Alternate alt) { 187 Row row; 188 189 foreach (string a in alt.alternates) { 190 row = new Row.columns_2 (alt.glyph_name, a, ALTERNATE_ENTRY, true); 191 row.set_row_data (new AlternateItem (alt, a)); 192 rows.add (row); 193 } 194 } 195 196 public override string get_label () { 197 return t_("Glyph Substitutions"); 198 } 199 200 public override string get_name () { 201 return "Glyph Substitutions"; 202 } 203 204 public override void draw (WidgetAllocation allocation, Context cr) { 205 base.draw (allocation, cr); 206 } 207 208 public void add_new_alternate (string tag) { 209 GlyphCollection gc; 210 211 if (glyph_collection == null) { 212 MainWindow.show_message (t_("Select a glyph to create an alternate for.")); 213 return; 214 } 215 216 gc = (!) glyph_collection; 217 218 listener = new TextListener (t_("Glyph name"), "", t_("Add")); 219 220 listener.signal_text_input.connect ((text) => { 221 alternate_name = text; 222 }); 223 224 listener.signal_submit.connect (() => { 225 GlyphCollection alt; 226 Font font; 227 OverView overview = MainWindow.get_overview (); 228 229 font = BirdFont.get_current_font (); 230 231 if (font.glyph_name.has_key (alternate_name)) { 232 MainWindow.show_message (t_("All glyphs must have unique names.")); 233 } else { 234 alt = new GlyphCollection.with_glyph ('\0', alternate_name); 235 alt.set_unassigned (true); 236 font.add_new_alternate (gc, alt, tag); 237 update_rows (); 238 GlyphCanvas.redraw (); 239 MainWindow.get_overview ().update_item_list (); 240 overview.open_glyph_signal (alt); 241 } 242 }); 243 244 if (replacement_glyph != null) { 245 GlyphCollection replacement = (!) replacement_glyph; 246 Font f = BirdFont.get_current_font (); 247 f.add_alternate (gc.get_name (), replacement.get_name (), tag); 248 update_rows (); 249 GlyphCanvas.redraw (); 250 } else { 251 TabContent.show_text_input (listener); 252 } 253 } 254 255 public override void undo () { 256 AlternateItem item; 257 Font font; 258 259 font = BirdFont.get_current_font (); 260 261 if (undo_items.size > 0) { 262 item = undo_items.get (undo_items.size - 1); 263 undo_items.remove_at (undo_items.size - 1); 264 265 font.add_alternate (item.alternate_list.glyph_name, 266 item.alternate, 267 item.alternate_list.tag); 268 269 update_rows (); 270 GlyphCanvas.redraw (); 271 } 272 } 273 } 274 275 } 276