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