The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

KernTable.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

Revisions

View the latest version of libbirdfont/OpenFontFormat/KernTable.vala.
Fix compile time warnings
1 /* 2 Copyright (C) 2012, 2013, 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 KernTable : OtfTable { 18 19 public const uint16 HORIZONTAL = 1; 20 public const uint16 MINIMUM = 1 << 1; 21 public const uint16 CROSS_STREAM = 1 << 2; 22 public const uint16 OVERRIDE = 1 << 3; 23 public const uint16 FORMAT = 1 << 8; 24 25 GlyfTable glyf_table; 26 27 KernList pairs; 28 29 // Only used for loading pairs 30 public Gee.ArrayList<Kern> kerning = new Gee.ArrayList<Kern> (); // TODO: replace with the KernList 31 public uint kerning_pairs = 0; 32 33 public KernTable (GlyfTable gt) { 34 glyf_table = gt; 35 id = "kern"; 36 pairs = new KernList (gt); 37 } 38 39 public override void parse (FontData dis) throws GLib.Error { 40 uint16 version; 41 uint16 sub_tables; 42 43 uint16 subtable_version; 44 uint16 subtable_length; 45 uint16 subtable_flags; 46 47 uint16 search_range; 48 uint16 entry_selector; 49 uint16 range_shift; 50 51 uint16 n_pairs; 52 53 dis.seek (offset); 54 55 version = dis.read_ushort (); 56 warn_if_fail (version == 0); 57 sub_tables = dis.read_ushort (); 58 59 for (uint16 i = 0; i < sub_tables; i++) { 60 subtable_version = dis.read_ushort (); 61 subtable_length = dis.read_ushort (); 62 subtable_flags = dis.read_ushort (); 63 64 n_pairs = dis.read_ushort (); 65 search_range = dis.read_ushort (); 66 entry_selector = dis.read_ushort (); 67 range_shift = dis.read_ushort (); 68 69 // TODO: check more flags 70 if ((subtable_flags & HORIZONTAL) > 0 && (subtable_flags & CROSS_STREAM) == 0 && (subtable_flags & MINIMUM) == 0) { 71 parse_pairs (dis, n_pairs); 72 } 73 } 74 } 75 76 public void parse_pairs (FontData dis, uint16 n_pairs) throws Error { 77 uint16 left; 78 uint16 right; 79 int16 k; 80 81 for (int i = 0; i < n_pairs; i++) { 82 left = dis.read_ushort (); 83 right = dis.read_ushort (); 84 k = dis.read_short (); 85 86 kerning.add (new Kern (left, right, k)); 87 } 88 } 89 90 public void process () throws GLib.Error { 91 FontData fd = new FontData (); 92 uint16 n_pairs = 0; 93 94 uint16 gid_left; 95 96 uint16 range_shift = 0; 97 uint16 entry_selector = 0; 98 uint16 search_range = 0; 99 100 int i; 101 102 uint last_gid_left; 103 uint last_gid_right; 104 105 if (pairs.get_length () == 0) { 106 pairs.fetch_all_pairs (); 107 } 108 109 fd.add_ushort (0); // version 110 fd.add_ushort (1); // n subtables 111 112 fd.add_ushort (0); // subtable version 113 114 if (pairs.get_length () > (uint16.MAX - 14) / 6.0) { 115 warning ("Too many kerning pairs!"); 116 n_pairs = (uint16) ((uint16.MAX - 14) / 6.0); 117 } else { 118 n_pairs = (uint16) pairs.get_length (); 119 } 120 121 this.kerning_pairs = n_pairs; 122 123 fd.add_ushort (6 * n_pairs + 14); // subtable length 124 fd.add_ushort (HORIZONTAL); // subtable flags 125 126 fd.add_ushort (n_pairs); 127 128 search_range = 6 * largest_pow2 (n_pairs); 129 entry_selector = largest_pow2_exponent (n_pairs); 130 range_shift = 6 * n_pairs - search_range; 131 132 fd.add_ushort (search_range); 133 fd.add_ushort (entry_selector); 134 fd.add_ushort (range_shift); 135 136 gid_left = 0; 137 i = 0; 138 last_gid_left = 0; 139 last_gid_right = 0; 140 141 pairs.all_kern ((kr) => { 142 Kern k = kr; 143 144 try { 145 if (k.left != last_gid_left) { 146 last_gid_right = 0; 147 } 148 149 if (unlikely (k.right < last_gid_right)) { 150 warning (@"Kerning table is not sorted $(k.right) < $last_gid_right"); 151 } 152 153 if (k.left < last_gid_left || k.right < last_gid_right) { 154 warning (@"Kerning table is not sorted. $(k.left) < $last_gid_left"); 155 } 156 157 last_gid_left = k.left; 158 last_gid_right = k.right; 159 160 fd.add_ushort (k.left); 161 fd.add_ushort (k.right); 162 fd.add_short (k.kerning); 163 } catch (GLib.Error e) { 164 warning (e.message); 165 } 166 }, n_pairs); 167 168 fd.pad (); 169 this.font_data = fd; 170 } 171 } 172 173 174 } 175 176