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.
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 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 n = n.replace ("-Regular", " Regular"); 157 n = n.replace ("-Bold", " Bold"); 158 n = n.replace ("-Italic", " Italic"); 159 160 if (n.has_suffix (regular_suffix)) { 161 n = n.substring (0, n.length - regular_suffix.length); 162 } 163 164 return n; 165 } 166 167 public static string name_validation (string s, bool allow_space, 168 int max_length = 27) { 169 170 string n; 171 int ccount; 172 unichar c; 173 StringBuilder name = new StringBuilder (); 174 175 n = s.strip (); 176 ccount = n.char_count (); 177 // truncate strings longer than 28 characters 178 for (int i = 0; i < ccount && i < max_length; i++) { 179 c = n.get_char (n.index_of_nth_char (i)); 180 181 if (allow_space && c == ' ') { 182 name.append_unichar (' '); 183 } else if (is_valid_ps_name_char (c)) { 184 name.append_unichar (c); 185 } else { 186 name.append_unichar ('_'); 187 } 188 } 189 190 return name.str; 191 } 192 193 static bool is_valid_ps_name_char (unichar c) { 194 switch (c) { 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 case '/': 212 return false; 213 case '%': 214 return false; 215 216 default: 217 break; 218 } 219 220 if (33 <= c <= 126) { 221 return true; 222 } 223 224 return false; 225 } 226 227 public void process () throws GLib.Error { 228 FontData fd = new FontData (); 229 Font font = OpenFontFormatWriter.get_current_font (); 230 uint16 len = 0; 231 string t; 232 uint16 p; 233 uint16 l; 234 uint16 num_records; 235 236 Gee.ArrayList<uint16> type = new Gee.ArrayList<uint16> (); 237 Gee.ArrayList<string> text = new Gee.ArrayList<string> (); 238 239 text.add (font.copyright); 240 type.add (COPYRIGHT_NOTICE); 241 242 text.add (validate_name (font.name)); 243 type.add (FONT_NAME); 244 245 text.add (validate_name (font.subfamily)); 246 type.add (SUBFAMILY_NAME); 247 248 text.add (validate_name (font.unique_identifier)); 249 type.add (UNIQUE_IDENTIFIER); 250 251 text.add (validate_full_name (font.full_name)); 252 type.add (FULL_FONT_NAME); 253 254 text.add (font.version); 255 type.add (VERSION); 256 257 text.add (validate_ps_name (font.postscript_name)); 258 type.add (POSTSCRIPT_NAME); 259 260 text.add (font.trademark); 261 type.add (TRADE_MARK); 262 263 text.add (font.manufacturer); 264 type.add (MANUFACTURER); 265 266 text.add (font.designer); 267 type.add (DESIGNER); 268 269 text.add (font.description); 270 type.add (DESCRIPTION); 271 272 text.add (font.vendor_url); 273 type.add (VENDOR_URL); 274 275 text.add (font.designer_url); 276 type.add (DESIGNER_URL); 277 278 text.add (font.license); 279 type.add (LICENSE); 280 281 text.add (font.license_url); 282 type.add (LICENSE_URL); 283 284 num_records = (uint16) text.size; 285 286 fd.add_ushort (0); // format 1 287 fd.add_ushort (2 * num_records); // nplatforms * nrecords 288 fd.add_ushort (6 + 12 * 2 * num_records); // string storage offset 289 290 for (int i = 0; i < num_records; i++) { 291 t = (!) text.get (i); 292 p = (!) type.get (i); 293 l = (uint16) FontData.macroman_strlen (t); 294 295 fd.add_ushort (1); // platform 296 fd.add_ushort (0); // encoding id 297 fd.add_ushort (0); // language 298 fd.add_ushort (p); // name id 299 fd.add_ushort (l); // strlen 300 fd.add_ushort (len); // offset from beginning of string storage 301 len += l; 302 } 303 304 for (int i = 0; i < num_records; i++) { 305 t = (!) text.get (i); 306 p = (!) type.get (i); 307 l = (uint16) FontData.utf16_strlen (t); 308 309 fd.add_ushort (3); // platform 310 fd.add_ushort (1); // encoding id 311 fd.add_ushort (0x0409); // language 312 fd.add_ushort (p); // name id 313 fd.add_ushort (l); // strlen 314 fd.add_ushort (len); // offset from beginning of string storage 315 len += l; 316 } 317 318 // platform 1 319 foreach (string s in text) { 320 fd.add_macroman_str (s); 321 } 322 323 // platform 3 324 foreach (string s in text) { 325 fd.add_str_utf16 (s); 326 } 327 328 fd.pad (); 329 330 this.font_data = fd; 331 } 332 } 333 334 } 335