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