The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

LigatureCollection.vala in libbirdfont/OpenFontFormat

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
Add *nix as OS tag heads/master
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 namespace BirdFont { 16 17 public class LigatureCollection : GLib.Object { 18 19 public Gee.ArrayList<LigatureSet> ligature_sets; 20 21 LigatureSet lig_set; 22 LigatureSet last_set; 23 24 public LigatureCollection.clig (GlyfTable glyf_table) { 25 ligature_sets = new Gee.ArrayList<LigatureSet> (); 26 lig_set = new LigatureSet (glyf_table); 27 last_set = new LigatureSet (glyf_table); 28 29 add_clig_ligatures (glyf_table); 30 } 31 32 public LigatureCollection.contextual (GlyfTable glyf_table, ContextualLigature ligature) { 33 ligature_sets = new Gee.ArrayList<LigatureSet> (); 34 lig_set = new LigatureSet (glyf_table); 35 last_set = new LigatureSet (glyf_table); 36 37 add_contextual_ligatures (glyf_table, ligature); 38 } 39 40 void add_clig_ligatures (GlyfTable glyf_table) { 41 Font font = BirdFont.get_current_font (); 42 Ligatures ligatures = font.get_ligatures (); 43 44 ligatures.get_ligatures ((parts, ligature) => { 45 add_ligatures (glyf_table, parts, ligature); 46 }); 47 } 48 49 void add_contextual_ligatures (GlyfTable glyf_table, ContextualLigature cl) { 50 foreach (string l in cl.ligatures.strip ().split (" ")) { 51 add_ligatures (glyf_table, cl.input, l); 52 } 53 } 54 55 // multiple ligatures in non-contextual substitution 56 public void add_ligatures (GlyfTable glyf_table, string characters, string ligatures) 57 requires (!is_null (lig_set) && !is_null (last_set)) { 58 59 Font font = BirdFont.get_current_font (); 60 string[] parts = characters.strip ().split (" "); 61 string l = ligatures; 62 bool has_set = false; 63 64 if (l.has_prefix ("U+") || l.has_prefix ("u+")) { 65 l = (!) Font.to_unichar (l).to_string (); 66 } 67 68 if (l == "space") { 69 l = " "; 70 } 71 72 if (!font.has_glyph (l)) { 73 warning (@"Ligature $l does not correspond to a glyph in this font."); 74 return; 75 } 76 77 foreach (string p in parts) { 78 if (p.has_prefix ("U+") || p.has_prefix ("u+")) { 79 p = (!) Font.to_unichar (p).to_string (); 80 } 81 82 if (p == "space") { 83 p = " "; 84 } 85 86 if (!font.has_glyph (p)) { 87 warning (@"Ligature substitution of $p is not possible, the character does have a glyph."); 88 return; 89 } 90 } 91 92 if (parts.length == 0) { 93 warning ("No parts."); 94 return; 95 } 96 97 foreach (LigatureSet s in ligature_sets) { 98 if (s.starts_with (parts[0])) { 99 has_set = true; 100 last_set = s; 101 } 102 } 103 104 if (has_set) { 105 last_set.add (new Ligature (l, characters)); 106 } else { 107 lig_set = new LigatureSet (glyf_table); 108 lig_set.add (new Ligature (l, characters)); 109 ligature_sets.add (lig_set); 110 } 111 112 // make sure coverage table is sorted otherwise will substitution not work 113 ligature_sets.sort ((a, b) => { 114 LigatureSet la = (LigatureSet) a; 115 LigatureSet lb = (LigatureSet) b; 116 string ca, cb; 117 118 if (la.get_coverage_char () == "space") { 119 ca = " "; 120 } else { 121 ca = la.get_coverage_char (); 122 } 123 124 if (lb.get_coverage_char () == "space") { 125 cb = " "; 126 } else { 127 cb = lb.get_coverage_char (); 128 } 129 130 return strcmp (ca, cb); 131 }); 132 } 133 134 public FontData get_font_data (GlyfTable glyf_table) throws GLib.Error { 135 FontData set_data; 136 uint16 ligature_pos; 137 uint16 table_start; 138 int coverage_offset; 139 FontData fd; 140 141 fd = new FontData (); 142 143 // ligature substitution subtable 144 table_start = (uint16) fd.length_with_padding (); 145 146 fd.add_ushort (1); // format identifier 147 148 coverage_offset = 6 + 2 * ligature_sets.size; 149 fd.add_ushort ((uint16) coverage_offset); // offset to coverage 150 fd.add_ushort ((uint16) ligature_sets.size); // number of ligature set tables 151 152 // array of offsets to ligature sets 153 uint16 size = 0; 154 foreach (LigatureSet l in ligature_sets) { 155 ligature_pos = 10 + (uint16) ligature_sets.size * 4 + size; 156 fd.add_ushort (ligature_pos); 157 size += (uint16) l.get_set_data ().length_with_padding (); 158 } 159 160 // coverage 161 fd.add_ushort (1); // format 162 fd.add_ushort ((uint16) ligature_sets.size); 163 164 // coverage gid: 165 foreach (LigatureSet l in ligature_sets) { 166 fd.add_ushort ((uint16) glyf_table.get_gid (l.get_coverage_char ())); 167 } 168 169 foreach (LigatureSet l in ligature_sets) { 170 set_data = l.get_set_data (); 171 fd.append (set_data); 172 } 173 174 return fd; 175 } 176 } 177 178 } 179