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 contextual ligatures to the GUI and fix directory privileges
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 Gee.ArrayList<Ligature> ligatures = new Gee.ArrayList<Ligature> (); 23 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, GlyphCollection ligature); 27 28 public delegate void ContextualLigatureIterator (ContextualLigature lig); 29 30 public Ligatures () { 31 } 32 33 public void get_ligatures (LigatureIterator iter) { 34 foreach (Ligature l in ligatures) { 35 iter (l.substitution, l.ligature); 36 } 37 } 38 39 public void get_contextual_ligatures (ContextualLigatureIterator iter) { 40 foreach (ContextualLigature l in contextual_ligatures) { 41 iter (l); 42 } 43 } 44 45 public void get_single_substitution_ligatures (SingleLigatureIterator iter) { 46 get_ligatures ((substitution, ligature) => { 47 Font font = BirdFont.get_current_font (); 48 GlyphCollection? gc; 49 GlyphCollection li; 50 GlyphSequence gs; 51 string[] subst_names = substitution.split (" "); 52 53 gc = font.get_glyph_collection_by_name (ligature); 54 55 if (gc == null) { 56 return; 57 } 58 59 li = (!) gc; 60 61 gs = new GlyphSequence (); 62 foreach (string s in subst_names) { 63 gc = font.get_glyph_collection_by_name (s); 64 65 if (gc == null) { 66 return; 67 } 68 69 gs.glyph.add (((!) gc).get_current ()); 70 } 71 72 iter (gs, li); 73 }); 74 } 75 76 public int count () { 77 return ligatures.size; 78 } 79 80 public int count_contextual_ligatures () { 81 return contextual_ligatures.size; 82 } 83 84 public void remove_at (int i) { 85 return_if_fail (0 <= i < ligatures.size); 86 ligatures.remove_at (i); 87 } 88 89 public void remove_contextual_ligatures_at (int i) { 90 return_if_fail (0 <= i < contextual_ligatures.size); 91 contextual_ligatures.remove_at (i); 92 } 93 94 /** Add ligaure for a chained substitution. */ 95 public void add_substitution_at (int index) { 96 return_if_fail (0 <= index < contextual_ligatures.size); 97 contextual_ligatures.get (index).add_ligature (); 98 } 99 100 public void set_beginning (int index) { 101 ContextualLigature lig; 102 TextListener listener; 103 104 return_if_fail (0 <= index < contextual_ligatures.size); 105 106 lig = contextual_ligatures.get (index); 107 listener = new TextListener (t_("Beginning"), lig.backtrack, t_("Set")); 108 109 listener.signal_text_input.connect ((text) => { 110 lig.backtrack = text; 111 }); 112 113 listener.signal_submit.connect (() => { 114 MainWindow.native_window.hide_text_input (); 115 MainWindow.get_ligature_display ().update_rows (); 116 }); 117 118 MainWindow.native_window.set_text_listener (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 MainWindow.native_window.hide_text_input (); 136 MainWindow.get_ligature_display ().update_rows (); 137 }); 138 139 MainWindow.native_window.set_text_listener (listener); 140 } 141 142 public void set_end (int index) { 143 ContextualLigature lig; 144 TextListener listener; 145 146 return_if_fail (0 <= index < contextual_ligatures.size); 147 148 lig = contextual_ligatures.get (index); 149 listener = new TextListener (t_("End"), lig.lookahead, t_("Set")); 150 151 listener.signal_text_input.connect ((text) => { 152 lig.lookahead = text; 153 }); 154 155 listener.signal_submit.connect (() => { 156 MainWindow.native_window.hide_text_input (); 157 MainWindow.get_ligature_display ().update_rows (); 158 }); 159 160 MainWindow.native_window.set_text_listener (listener); 161 } 162 163 public void set_ligature (int index) { 164 Ligature lig; 165 TextListener listener; 166 167 return_if_fail (0 <= index < ligatures.size); 168 169 lig = ligatures.get (index); 170 lig.set_ligature (); 171 } 172 173 public void set_substitution (int index) { 174 Ligature lig; 175 TextListener listener; 176 177 return_if_fail (0 <= index < ligatures.size); 178 179 lig = ligatures.get (index); 180 lig.set_substitution (); 181 } 182 183 public void add_ligature (string subst, string liga) { 184 ligatures.insert (0, new Ligature (liga, subst)); 185 sort_ligatures (); 186 } 187 188 public void add_contextual_ligature (string backtrack, string input, string lookahead) { 189 ContextualLigature l = new ContextualLigature (backtrack, input, lookahead); 190 contextual_ligatures.insert (0, l); 191 sort_ligatures (); 192 } 193 194 public void sort_ligatures () { 195 ligatures.sort ((a, b) => { 196 Ligature first, next; 197 int chars_first, chars_next; 198 199 first = (Ligature) a; 200 next = (Ligature) b; 201 202 chars_first = first.substitution.split (" ").length; 203 chars_next = next.substitution.split (" ").length; 204 205 return chars_next - chars_first; 206 }); 207 208 contextual_ligatures.sort ((a, b) => { 209 ContextualLigature first, next; 210 int chars_first, chars_next; 211 212 first = (ContextualLigature) a; 213 next = (ContextualLigature) b; 214 215 chars_first = first.backtrack.split (" ").length; 216 chars_first += first.input.split (" ").length; 217 chars_first += first.lookahead.split (" ").length; 218 219 chars_next = next.backtrack.split (" ").length; 220 chars_next += next.input.split (" ").length; 221 chars_next += next.lookahead.split (" ").length; 222 223 return chars_next - chars_first; 224 }); 225 226 foreach (ContextualLigature c in contextual_ligatures) { 227 c.sort (); 228 } 229 } 230 } 231 232 } 233