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