The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

Ligatures.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/Ligatures.vala.
Parse more style attributes in SVG files
1 /* 2 Copyright (C) 2014 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 Ligatures : GLib.Object { 21 22 public Gee.ArrayList<Ligature> ligatures = new Gee.ArrayList<Ligature> (); 23 public Gee.ArrayList<ContextualLigature> contextual_ligatures = new Gee.ArrayList<ContextualLigature> (); 24 25 public delegate void LigatureIterator (string substitution, string ligature); 26 public delegate void SingleLigatureIterator (GlyphSequence substitution, GlyphSequence ligature); 27 28 public delegate void ContextualLigatureIterator (ContextualLigature lig); 29 30 unowned Font font; 31 32 public Ligatures (Font font) { 33 this.font = font; 34 35 font.font_deleted.connect (() => { 36 this.font = Font.empty; 37 }); 38 } 39 40 public void get_ligatures (LigatureIterator iter) { 41 foreach (Ligature l in ligatures) { 42 iter (l.substitution, l.ligature); 43 } 44 } 45 46 public void get_contextual_ligatures (ContextualLigatureIterator iter) { 47 foreach (ContextualLigature l in contextual_ligatures) { 48 iter (l); 49 } 50 } 51 52 public void get_single_substitution_ligatures (SingleLigatureIterator iter) { 53 get_ligatures ((substitution, ligature) => { 54 GlyphCollection? gc; 55 GlyphSequence lig; 56 GlyphSequence gs; 57 string[] subst_names = substitution.split (" "); 58 59 lig = new GlyphSequence (); 60 foreach (string n in font.get_names (ligature)) { 61 gc = font.get_glyph_collection_by_name (n); 62 63 if (gc == null) { 64 return; 65 } 66 67 lig.add (((!) gc).get_current ()); 68 } 69 70 gs = new GlyphSequence (); 71 foreach (string s in subst_names) { 72 gc = font.get_glyph_collection_by_name (s); 73 74 if (gc == null) { 75 return; 76 } 77 78 gs.glyph.add (((!) gc).get_current ()); 79 } 80 81 iter (gs, lig); 82 }); 83 } 84 85 public int count () { 86 return ligatures.size; 87 } 88 89 public int count_contextual_ligatures () { 90 return contextual_ligatures.size; 91 } 92 93 public void remove_at (int i) { 94 return_if_fail (0 <= i < ligatures.size); 95 ligatures.remove_at (i); 96 } 97 98 public void remove_contextual_ligatures_at (int i) { 99 return_if_fail (0 <= i < contextual_ligatures.size); 100 contextual_ligatures.remove_at (i); 101 } 102 103 public void set_beginning (int index) { 104 ContextualLigature lig; 105 TextListener listener; 106 107 return_if_fail (0 <= index < contextual_ligatures.size); 108 109 lig = contextual_ligatures.get (index); 110 listener = new TextListener (t_("Beginning"), lig.backtrack, t_("Set")); 111 112 listener.signal_text_input.connect ((text) => { 113 lig.backtrack = text; 114 }); 115 116 listener.signal_submit.connect (() => { 117 TabContent.hide_text_input (); 118 MainWindow.get_ligature_display ().update_rows (); 119 sort_ligatures (); 120 GlyphCanvas.redraw (); 121 }); 122 123 TabContent.show_text_input (listener); 124 } 125 126 public void set_middle (int index) { 127 ContextualLigature lig; 128 TextListener listener; 129 130 return_if_fail (0 <= index < contextual_ligatures.size); 131 132 lig = contextual_ligatures.get (index); 133 listener = new TextListener (t_("Middle"), lig.input, t_("Set")); 134 135 listener.signal_text_input.connect ((text) => { 136 lig.input = text; 137 }); 138 139 listener.signal_submit.connect (() => { 140 TabContent.hide_text_input (); 141 MainWindow.get_ligature_display ().update_rows (); 142 sort_ligatures (); 143 GlyphCanvas.redraw (); 144 }); 145 146 TabContent.show_text_input (listener); 147 } 148 149 public void set_end (int index) { 150 ContextualLigature lig; 151 TextListener listener; 152 153 return_if_fail (0 <= index < contextual_ligatures.size); 154 155 lig = contextual_ligatures.get (index); 156 listener = new TextListener (t_("End"), lig.lookahead, t_("Set")); 157 158 listener.signal_text_input.connect ((text) => { 159 lig.lookahead = text; 160 }); 161 162 listener.signal_submit.connect (() => { 163 TabContent.hide_text_input (); 164 MainWindow.get_ligature_display ().update_rows (); 165 sort_ligatures (); 166 GlyphCanvas.redraw (); 167 }); 168 169 TabContent.show_text_input (listener); 170 } 171 172 public void set_ligature (int index) { 173 Ligature lig; 174 175 return_if_fail (0 <= index < ligatures.size); 176 177 lig = ligatures.get (index); 178 lig.set_ligature (); 179 } 180 181 public void set_contextual_ligature (int index) { 182 ContextualLigature lig; 183 TextListener listener; 184 185 return_if_fail (0 <= index < contextual_ligatures.size); 186 187 lig = contextual_ligatures.get (index); 188 listener = new TextListener (t_("Ligature"), lig.ligatures, t_("Set")); 189 190 listener.signal_text_input.connect ((text) => { 191 lig.ligatures = text; 192 }); 193 194 listener.signal_submit.connect (() => { 195 TabContent.hide_text_input (); 196 MainWindow.get_ligature_display ().update_rows (); 197 sort_ligatures (); 198 GlyphCanvas.redraw (); 199 }); 200 201 TabContent.show_text_input (listener); 202 203 } 204 205 public void set_substitution (int index) { 206 Ligature lig; 207 208 return_if_fail (0 <= index < ligatures.size); 209 210 lig = ligatures.get (index); 211 lig.set_substitution (); 212 } 213 214 public void add_ligature (string subst, string liga) { 215 ligatures.insert (0, new Ligature (liga, subst)); 216 sort_ligatures (); 217 } 218 219 public void add_contextual_ligature (string ligature, string backtrack, string input, string lookahead) { 220 ContextualLigature l = new ContextualLigature (font, ligature, backtrack, input, lookahead); 221 contextual_ligatures.insert (0, l); 222 sort_ligatures (); 223 } 224 225 public void sort_ligatures () { 226 ligatures.sort ((a, b) => { 227 Ligature first, next; 228 int chars_first, chars_next; 229 230 first = (Ligature) a; 231 next = (Ligature) b; 232 233 chars_first = first.substitution.split (" ").length; 234 chars_next = next.substitution.split (" ").length; 235 236 return chars_next - chars_first; 237 }); 238 239 contextual_ligatures.sort ((a, b) => { 240 ContextualLigature first, next; 241 int chars_first, chars_next; 242 243 first = (ContextualLigature) a; 244 next = (ContextualLigature) b; 245 246 chars_first = first.backtrack.split (" ").length; 247 chars_first += first.input.split (" ").length; 248 chars_first += first.lookahead.split (" ").length; 249 250 chars_next = next.backtrack.split (" ").length; 251 chars_next += next.input.split (" ").length; 252 chars_next += next.lookahead.split (" ").length; 253 254 return chars_next - chars_first; 255 }); 256 } 257 } 258 259 } 260