The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

HmtxTable.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/HmtxTable.vala.
Debug info for boundaries
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 HmtxTable : OtfTable { 18 19 uint32 nmetrics; 20 uint32 nmonospaced; 21 22 uint16* advance_width = null; 23 uint16* left_side_bearing = null; 24 uint16* left_side_bearing_monospaced = null; 25 26 public int16 max_advance = 0; 27 public int16 max_extent = 0; 28 public int16 min_lsb = int16.MAX; 29 public int16 min_rsb = int16.MAX; 30 31 HeadTable head_table; 32 GlyfTable glyf_table; 33 34 public HmtxTable (HeadTable h, GlyfTable gt) { 35 head_table = h; 36 glyf_table = gt; 37 id = "hmtx"; 38 } 39 40 ~HmtxTable () { 41 if (advance_width != null) { 42 delete advance_width; 43 } 44 45 if (left_side_bearing != null) { 46 delete left_side_bearing; 47 } 48 } 49 50 public double get_advance (uint32 i) { 51 if (i >= nmetrics) { 52 warning (@"i >= nmetrics $i >= $nmetrics"); 53 return 0; 54 } 55 56 return_val_if_fail (advance_width != null, 0.0); 57 58 return advance_width[i] * 1000 / head_table.get_units_per_em (); 59 } 60 61 /** Get left side bearing relative to xmin. */ 62 public double get_lsb (uint32 i) { 63 return_val_if_fail (i < nmetrics, 0.0); 64 return_val_if_fail (left_side_bearing != null, 0.0); 65 66 return left_side_bearing[i] * 1000 / head_table.get_units_per_em (); 67 } 68 69 public new void parse (FontData dis, HheaTable hhea_table, LocaTable loca_table) throws GLib.Error { 70 nmetrics = hhea_table.num_horizontal_metrics; 71 nmonospaced = loca_table.size - nmetrics; 72 73 dis.seek (offset); 74 75 if (nmetrics > loca_table.size) { 76 warning (@"(nmetrics > loca_table.size) ($nmetrics > $(loca_table.size))"); 77 return; 78 } 79 80 printd (@"nmetrics: $nmetrics\n"); 81 printd (@"loca_table.size: $(loca_table.size)\n"); 82 83 advance_width = new uint16[nmetrics]; 84 left_side_bearing = new uint16[nmetrics]; 85 left_side_bearing_monospaced = new uint16[nmonospaced]; 86 87 for (int i = 0; i < nmetrics; i++) { 88 advance_width[i] = dis.read_ushort (); 89 left_side_bearing[i] = dis.read_short (); 90 } 91 92 for (int i = 0; i < nmonospaced; i++) { 93 left_side_bearing_monospaced[i] = dis.read_short (); 94 } 95 } 96 97 public void process () { 98 FontData fd = new FontData (); 99 100 int16 advance; 101 int16 extent; 102 int16 rsb; 103 int16 lsb; 104 105 int16 left_guide; 106 int16 right_guide; 107 108 double xmin; 109 double xmax; 110 int i; 111 112 Glyph g; 113 114 if (advance_width != null) { 115 warning ("advance_width is set"); 116 delete advance_width; 117 } 118 advance_width = new uint16 [glyf_table.glyphs.size]; 119 120 // advance and lsb 121 nmetrics = 0; 122 i = 0; 123 foreach (GlyphCollection gc in glyf_table.glyphs) { 124 g = gc.get_current (); 125 126 return_if_fail (0 <= i < glyf_table.glyf_data.size); 127 128 GlyfData gd = glyf_table.glyf_data.get (i); 129 130 xmax = gd.bounding_box_xmax; 131 xmin = gd.bounding_box_xmin; 132 133 left_guide = (int16) Math.rint (g.left_limit * HeadTable.UNITS); 134 right_guide = (int16) Math.rint (g.right_limit * HeadTable.UNITS); 135 136 lsb = (int16) xmin; 137 advance = right_guide - left_guide; 138 139 extent = (int16) xmax; 140 rsb = (int16) Math.rint (advance - extent); 141 142 fd.add_u16 (advance); 143 fd.add_16 (lsb); 144 145 if (!g.is_empty_ttf ()) { 146 if (advance > max_advance) { 147 max_advance = advance; 148 } 149 150 if (extent > max_extent) { 151 max_extent = extent; 152 } 153 154 if (rsb < min_rsb) { 155 min_rsb = rsb; 156 } 157 158 if (lsb < min_lsb) { 159 min_lsb = lsb; 160 } 161 } 162 163 if (extent < 0) { 164 warning ("Negative extent."); 165 } 166 167 advance_width[nmetrics] = (uint16) extent; 168 nmetrics++; 169 i++; 170 } 171 172 // monospaced lsb ... 173 174 font_data = fd; 175 176 if (max_advance == 0) { 177 warning ("max_advance is zero"); 178 } 179 } 180 181 public int16 get_average_width () { 182 double total_width = 0; 183 uint non_zero_glyphs = 0; 184 for (int i = 0; i < nmetrics; i++) { 185 if (advance_width[i] != 0) { 186 total_width += advance_width[i]; 187 non_zero_glyphs++; 188 } 189 } 190 return (int16) Math.rint (total_width / non_zero_glyphs); 191 } 192 } 193 194 } 195