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.
Revert "Error handeling in merge code"
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 }); 121 122 TabContent.show_text_input (listener); 123 } 124 125 public void set_middle (int index) { 126 ContextualLigature lig; 127 TextListener listener; 128 129 return_if_fail (0 <= index < contextual_ligatures.size); 130 131 lig = contextual_ligatures.get (index); 132 listener = new TextListener (t_("Middle"), lig.input, t_("Set")); 133 134 listener.signal_text_input.connect ((text) => { 135 lig.input = text; 136 }); 137 138 listener.signal_submit.connect (() => { 139 TabContent.hide_text_input (); 140 MainWindow.get_ligature_display ().update_rows (); 141 sort_ligatures (); 142 }); 143 144 TabContent.show_text_input (listener); 145 } 146 147 public void set_end (int index) { 148 ContextualLigature lig; 149 TextListener listener; 150 151 return_if_fail (0 <= index < contextual_ligatures.size); 152 153 lig = contextual_ligatures.get (index); 154 listener = new TextListener (t_("End"), lig.lookahead, t_("Set")); 155 156 listener.signal_text_input.connect ((text) => { 157 lig.lookahead = text; 158 }); 159 160 listener.signal_submit.connect (() => { 161 TabContent.hide_text_input (); 162 MainWindow.get_ligature_display ().update_rows (); 163 sort_ligatures (); 164 }); 165 166 TabContent.show_text_input (listener); 167 } 168 169 public void set_ligature (int index) { 170 Ligature lig; 171 172 return_if_fail (0 <= index < ligatures.size); 173 174 lig = ligatures.get (index); 175 lig.set_ligature (); 176 } 177 178 public void set_contextual_ligature (int index) { 179 ContextualLigature lig; 180 TextListener listener; 181 182 return_if_fail (0 <= index < contextual_ligatures.size); 183 184 lig = contextual_ligatures.get (index); 185 listener = new TextListener (t_("Ligature"), lig.ligatures, t_("Set")); 186 187 listener.signal_text_input.connect ((text) => { 188 lig.ligatures = text; 189 }); 190 191 listener.signal_submit.connect (() => { 192 TabContent.hide_text_input (); 193 MainWindow.get_ligature_display ().update_rows (); 194 sort_ligatures (); 195 }); 196 197 TabContent.show_text_input (listener); 198 199 } 200 201 public void set_substitution (int index) { 202 Ligature lig; 203 204 return_if_fail (0 <= index < ligatures.size); 205 206 lig = ligatures.get (index); 207 lig.set_substitution (); 208 } 209 210 public void add_ligature (string subst, string liga) { 211 ligatures.insert (0, new Ligature (liga, subst)); 212 sort_ligatures (); 213 } 214 215 public void add_contextual_ligature (string ligature, string backtrack, string input, string lookahead) { 216 ContextualLigature l = new ContextualLigature (font, ligature, backtrack, input, lookahead); 217 contextual_ligatures.insert (0, l); 218 sort_ligatures (); 219 } 220 221 public void sort_ligatures () { 222 ligatures.sort ((a, b) => { 223 Ligature first, next; 224 int chars_first, chars_next; 225 226 first = (Ligature) a; 227 next = (Ligature) b; 228 229 chars_first = first.substitution.split (" ").length; 230 chars_next = next.substitution.split (" ").length; 231 232 return chars_next - chars_first; 233 }); 234 235 contextual_ligatures.sort ((a, b) => { 236 ContextualLigature first, next; 237 int chars_first, chars_next; 238 239 first = (ContextualLigature) a; 240 next = (ContextualLigature) b; 241 242 chars_first = first.backtrack.split (" ").length; 243 chars_first += first.input.split (" ").length; 244 chars_first += first.lookahead.split (" ").length; 245 246 chars_next = next.backtrack.split (" ").length; 247 chars_next += next.input.split (" ").length; 248 chars_next += next.lookahead.split (" ").length; 249 250 return chars_next - chars_first; 251 }); 252 } 253 } 254 255 } 256