The Birdfont Source Code


All Repositories / birdfont.git / blob – RSS feed

NameTable.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/NameTable.vala.
Remove prefered family and prefered style from name table
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 NameTable : OtfTable { 18 19 public static const uint16 COPYRIGHT_NOTICE = 0; 20 public static const uint16 FONT_NAME = 1; 21 public static const uint16 SUBFAMILY_NAME = 2; 22 public static const uint16 UNIQUE_IDENTIFIER = 3; 23 public static const uint16 FULL_FONT_NAME = 4; // name + subfamily 24 public static const uint16 VERSION = 5; 25 public static const uint16 POSTSCRIPT_NAME = 6; 26 public static const uint16 TRADE_MARK = 7; 27 public static const uint16 MANUFACTURER = 8; 28 public static const uint16 DESIGNER = 9; 29 public static const uint16 DESCRIPTION = 10; 30 public static const uint16 VENDOR_URL = 11; 31 public static const uint16 DESIGNER_URL = 12; 32 public static const uint16 LICENSE = 13; 33 public static const uint16 LICENSE_URL = 14; 34 public static const uint16 PREFERED_FAMILY = 16; 35 public static const uint16 PREFERED_SUB_FAMILY = 17; 36 37 38 Gee.ArrayList<uint16> identifiers; 39 Gee.ArrayList<string> text; 40 41 public NameTable () { 42 id = "name"; 43 text = new Gee.ArrayList<string> (); 44 identifiers = new Gee.ArrayList<uint16> (); 45 } 46 47 public string get_name (uint16 identifier) { 48 int i = 0; 49 50 foreach (uint16 n in identifiers) { 51 if (n == identifier) { 52 return text.get (i); 53 } 54 i++; 55 } 56 57 return ""; 58 } 59 60 public override void parse (FontData dis) throws Error { 61 uint16 format; 62 63 dis.seek (offset); 64 65 format = dis.read_ushort (); 66 67 switch (format) { 68 case 0: 69 parse_format0 (dis); 70 break; 71 72 case 1: 73 warning ("name table format 1 is not implemented yet"); 74 break; 75 76 default: 77 warning (@"unknown format $format in name table"); 78 break; 79 } 80 } 81 82 public void parse_format0 (FontData dis) throws Error { 83 uint16 count; 84 uint16 storage_offset; 85 86 Gee.ArrayList<uint16> strlen = new Gee.ArrayList<uint16> (); 87 Gee.ArrayList<uint16> off = new Gee.ArrayList<uint16> (); 88 Gee.ArrayList<uint16> name_id = new Gee.ArrayList<uint16> (); 89 Gee.ArrayList<uint16> encoding_id = new Gee.ArrayList<uint16> (); 90 Gee.ArrayList<uint16> platform = new Gee.ArrayList<uint16> (); 91 Gee.ArrayList<uint16> lang = new Gee.ArrayList<uint16> (); 92 93 count = dis.read_ushort (); 94 storage_offset = dis.read_ushort (); 95 96 for (int i = 0; i < count; i++) { 97 platform.add (dis.read_ushort ()); 98 encoding_id.add (dis.read_ushort ()); 99 lang.add (dis.read_ushort ()); 100 name_id.add (dis.read_ushort ()); 101 strlen.add (dis.read_ushort ()); 102 off.add (dis.read_ushort ()); 103 104 identifiers.add (name_id.get (name_id.size - 1)); 105 } 106 107 int plat; 108 StringBuilder str; 109 for (int i = 0; i < count; i++) { 110 plat = platform.get (i); 111 dis.seek (offset + storage_offset + off.get (i)); 112 str = new StringBuilder (); 113 114 switch (plat) { 115 case 1: 116 for (int j = 0; j < strlen.get (i); j++) { 117 char c = dis.read_char (); 118 str.append_c (c); 119 } 120 break; 121 122 case 3: 123 for (int j = 0; j < strlen.get (i); j += 2) { 124 unichar c; 125 char c0 = dis.read_char (); 126 char c1 = dis.read_char (); 127 128 c = c0 << 8; 129 c += c1; 130 131 str.append_unichar (c); 132 } 133 break; 134 135 default: 136 break; 137 } 138 139 text.add (str.str); 140 } 141 } 142 143 /** Create a valid PostScript name. */ 144 public string validate_ps_name (string s) { 145 return name_validation (s, false); 146 } 147 148 public string validate_name (string s) { 149 return name_validation (s, true); 150 } 151 152 public string validate_full_name (string s) { 153 string n = name_validation (s, true); 154 string regular_suffix = " Regular"; 155 156 if (n.has_suffix (regular_suffix)) { 157 n = n.substring (0, n.length - regular_suffix.length); 158 } 159 160 return n; 161 } 162 163 public static string name_validation (string s, bool allow_space, 164 int max_length = 27) { 165 166 string n; 167 int ccount; 168 unichar c; 169 StringBuilder name = new StringBuilder (); 170 171 n = s.strip (); 172 ccount = n.char_count (); 173 // truncate strings longer than 28 characters 174 for (int i = 0; i < ccount && i < max_length; i++) { 175 c = n.get_char (n.index_of_nth_char (i)); 176 177 if (allow_space && c == ' ') { 178 name.append_unichar (' '); 179 } else if (is_valid_ps_name_char (c)) { 180 name.append_unichar (c); 181 } else { 182 name.append_unichar ('_'); 183 } 184 } 185 186 return name.str; 187 } 188 189 static bool is_valid_ps_name_char (unichar c) { 190 switch (c) { 191 case '[': 192 return false; 193 case ']': 194 return false; 195 case '(': 196 return false; 197 case ')': 198 return false; 199 case '{': 200 return false; 201 case '}': 202 return false; 203 case '<': 204 return false; 205 case '>': 206 return false; 207 case '/': 208 return false; 209 case '%': 210 return false; 211 212 default: 213 break; 214 } 215 216 if (33 <= c <= 126) { 217 return true; 218 } 219 220 return false; 221 } 222 223 public void process () throws GLib.Error { 224 FontData fd = new FontData (); 225 Font font = OpenFontFormatWriter.get_current_font (); 226 uint16 len = 0; 227 string t; 228 uint16 p; 229 uint16 l; 230 uint16 num_records; 231 232 Gee.ArrayList<uint16> type = new Gee.ArrayList<uint16> (); 233 Gee.ArrayList<string> text = new Gee.ArrayList<string> (); 234 235 text.add (font.copyright); 236 type.add (COPYRIGHT_NOTICE); 237 238 text.add (validate_name (font.name)); 239 type.add (FONT_NAME); 240 241 text.add (validate_name (font.subfamily)); 242 type.add (SUBFAMILY_NAME); 243 244 text.add (validate_name (font.unique_identifier)); 245 type.add (UNIQUE_IDENTIFIER); 246 247 text.add (validate_full_name (font.full_name)); 248 type.add (FULL_FONT_NAME); 249 250 text.add (font.version); 251 type.add (VERSION); 252 253 text.add (validate_ps_name (font.postscript_name)); 254 type.add (POSTSCRIPT_NAME); 255 256 text.add (font.trademark); 257 type.add (TRADE_MARK); 258 259 text.add (font.manufacturer); 260 type.add (MANUFACTURER); 261 262 text.add (font.designer); 263 type.add (DESIGNER); 264 265 text.add (font.description); 266 type.add (DESCRIPTION); 267 268 text.add (font.vendor_url); 269 type.add (VENDOR_URL); 270 271 text.add (font.designer_url); 272 type.add (DESIGNER_URL); 273 274 text.add (font.license); 275 type.add (LICENSE); 276 277 text.add (font.license_url); 278 type.add (LICENSE_URL); 279 280 num_records = (uint16) text.size; 281 282 fd.add_ushort (0); // format 1 283 fd.add_ushort (2 * num_records); // nplatforms * nrecords 284 fd.add_ushort (6 + 12 * 2 * num_records); // string storage offset 285 286 for (int i = 0; i < num_records; i++) { 287 t = (!) text.get (i); 288 p = (!) type.get (i); 289 l = (uint16) FontData.macroman_strlen (t); 290 291 fd.add_ushort (1); // platform 292 fd.add_ushort (0); // encoding id 293 fd.add_ushort (0); // language 294 fd.add_ushort (p); // name id 295 fd.add_ushort (l); // strlen 296 fd.add_ushort (len); // offset from beginning of string storage 297 len += l; 298 } 299 300 for (int i = 0; i < num_records; i++) { 301 t = (!) text.get (i); 302 p = (!) type.get (i); 303 l = (uint16) FontData.utf16_strlen (t); 304 305 fd.add_ushort (3); // platform 306 fd.add_ushort (1); // encoding id 307 fd.add_ushort (0x0409); // language 308 fd.add_ushort (p); // name id 309 fd.add_ushort (l); // strlen 310 fd.add_ushort (len); // offset from beginning of string storage 311 len += l; 312 } 313 314 // platform 1 315 foreach (string s in text) { 316 fd.add_macroman_str (s); 317 } 318 319 // platform 3 320 foreach (string s in text) { 321 fd.add_str_utf16 (s); 322 } 323 324 fd.pad (); 325 326 this.font_data = fd; 327 } 328 } 329 330 } 331