001/* 002 * $Id: Pfm2afm.java 4784 2011-03-15 08:33:00Z blowagie $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044 045/******************************************************************** 046 * * 047 * Title: pfm2afm - Convert Windows .pfm files to .afm files * 048 * * 049 * Author: Ken Borgendale 10/9/91 Version 1.0 * 050 * * 051 * Function: * 052 * Convert a Windows .pfm (Printer Font Metrics) file to a * 053 * .afm (Adobe Font Metrics) file. The purpose of this is * 054 * to allow fonts put out for Windows to be used with OS/2. * 055 * * 056 * Syntax: * 057 * pfm2afm infile [outfile] -a * 058 * * 059 * Copyright: * 060 * pfm2afm - Copyright (C) IBM Corp., 1991 * 061 * * 062 * This code is released for public use as long as the * 063 * copyright remains intact. This code is provided asis * 064 * without any warrenties, express or implied. * 065 * * 066 * Notes: * 067 * 1. Much of the information in the original .afm file is * 068 * lost when the .pfm file is created, and thus cannot be * 069 * reconstructed by this utility. This is especially true * 070 * of data for characters not in the Windows character set. * 071 * * 072 * 2. This module is coded to be compiled by the MSC 6.0. * 073 * For other compilers, be careful of the packing of the * 074 * PFM structure. * 075 * * 076 ********************************************************************/ 077 078/******************************************************************** 079 * * 080 * Modifications by Rod Smith, 5/22/96 * 081 * * 082 * These changes look for the strings "italic", "bold", "black", * 083 * and "light" in the font's name and set the weight accordingly * 084 * and adds an ItalicAngle line with a value of "0" or "-12.00". * 085 * This allows OS/2 programs such as DeScribe to handle the bold * 086 * and italic attributes appropriately, which was not the case * 087 * when I used the original version on fonts from the KeyFonts * 088 * Pro 2002 font CD. * 089 * * 090 * I've also increased the size of the buffer used to load the * 091 * .PFM file; the old size was inadequate for most of the fonts * 092 * from the SoftKey collection. * 093 * * 094 * Compiled with Watcom C 10.6 * 095 * * 096 ********************************************************************/ 097 098/******************************************************************** 099 * * 100 * Further modifications, 4/21/98, by Rod Smith * 101 * * 102 * Minor changes to get the program to compile with gcc under * 103 * Linux (Red Hat 5.0, to be precise). I had to add an itoa * 104 * function from the net (the function was buggy, so I had to fix * 105 * it, too!). I also made the program more friendly towards * 106 * files with mixed-case filenames. * 107 * * 108 ********************************************************************/ 109 110/******************************************************************** 111 * * 112 * 1/31/2005, by Paulo Soares * 113 * * 114 * This code was integrated into iText. * 115 * Note that the itoa function mentioned in the comment by Rod * 116 * Smith is no longer in the code because Java has native support * 117 * in PrintWriter to convert integers to strings * 118 * * 119 ********************************************************************/ 120 121/******************************************************************** 122 * * 123 * 7/16/2005, by Bruno Lowagie * 124 * * 125 * I solved an Eclipse Warning. * 126 * * 127 ********************************************************************/ 128 129/******************************************************************** 130 * * 131 * 9/14/2006, by Xavier Le Vourch * 132 * * 133 * expand import clauses (import java.io.*) * 134 * the removal of an exception in readString was restored on 9/16 * 135 * * 136 ********************************************************************/ 137package com.itextpdf.text.pdf; 138 139import java.io.FileOutputStream; 140import java.io.IOException; 141import java.io.OutputStream; 142import java.io.OutputStreamWriter; 143import java.io.PrintWriter; 144import com.itextpdf.text.error_messages.MessageLocalization; 145 146/** 147 * Converts a PFM file into an AFM file. 148 */ 149public final class Pfm2afm { 150 private RandomAccessFileOrArray in; 151 private PrintWriter out; 152 153 /** Creates a new instance of Pfm2afm */ 154 private Pfm2afm(RandomAccessFileOrArray in, OutputStream out) throws IOException { 155 this.in = in; 156 this.out = new PrintWriter(new OutputStreamWriter(out, "ISO-8859-1")); 157 } 158 159 /** 160 * Converts a PFM file into an AFM file. 161 * @param in the PFM file 162 * @param out the AFM file 163 * @throws IOException on error 164 */ 165 public static void convert(RandomAccessFileOrArray in, OutputStream out) throws IOException { 166 Pfm2afm p = new Pfm2afm(in, out); 167 p.openpfm(); 168 p.putheader(); 169 p.putchartab(); 170 p.putkerntab(); 171 p.puttrailer(); 172 p.out.flush(); 173 } 174 175 /* 176 public static void main(String[] args) { 177 try { 178 RandomAccessFileOrArray in = new RandomAccessFileOrArray(args[0]); 179 OutputStream out = new FileOutputStream(args[1]); 180 convert(in, out); 181 in.close(); 182 out.close(); 183 } 184 catch (Exception e) { 185 e.printStackTrace(); 186 } 187 } 188 */ 189 190 private String readString(int n) throws IOException { 191 byte b[] = new byte[n]; 192 in.readFully(b); 193 int k; 194 for (k = 0; k < b.length; ++k) { 195 if (b[k] == 0) 196 break; 197 } 198 return new String(b, 0, k, "ISO-8859-1"); 199 } 200 201 private String readString() throws IOException { 202 StringBuffer buf = new StringBuffer(); 203 while (true) { 204 int c = in.read(); 205 if (c <= 0) 206 break; 207 buf.append((char)c); 208 } 209 return buf.toString(); 210 } 211 212 private void outval(int n) { 213 out.print(' '); 214 out.print(n); 215 } 216 217 /* 218 * Output a character entry 219 */ 220 private void outchar(int code, int width, String name) { 221 out.print("C "); 222 outval(code); 223 out.print(" ; WX "); 224 outval(width); 225 if (name != null) { 226 out.print(" ; N "); 227 out.print(name); 228 } 229 out.print(" ;\n"); 230 } 231 232 private void openpfm() throws IOException { 233 in.seek(0); 234 vers = in.readShortLE(); 235 h_len = in.readIntLE(); 236 copyright = readString(60); 237 type = in.readShortLE(); 238 points = in.readShortLE(); 239 verres = in.readShortLE(); 240 horres = in.readShortLE(); 241 ascent = in.readShortLE(); 242 intleading = in.readShortLE(); 243 extleading = in.readShortLE(); 244 italic = (byte)in.read(); 245 uline = (byte)in.read(); 246 overs = (byte)in.read(); 247 weight = in.readShortLE(); 248 charset = (byte)in.read(); 249 pixwidth = in.readShortLE(); 250 pixheight = in.readShortLE(); 251 kind = (byte)in.read(); 252 avgwidth = in.readShortLE(); 253 maxwidth = in.readShortLE(); 254 firstchar = in.read(); 255 lastchar = in.read(); 256 defchar = (byte)in.read(); 257 brkchar = (byte)in.read(); 258 widthby = in.readShortLE(); 259 device = in.readIntLE(); 260 face = in.readIntLE(); 261 bits = in.readIntLE(); 262 bitoff = in.readIntLE(); 263 extlen = in.readShortLE(); 264 psext = in.readIntLE(); 265 chartab = in.readIntLE(); 266 res1 = in.readIntLE(); 267 kernpairs = in.readIntLE(); 268 res2 = in.readIntLE(); 269 fontname = in.readIntLE(); 270 if (h_len != in.length() || extlen != 30 || fontname < 75 || fontname > 512) 271 throw new IOException(MessageLocalization.getComposedMessage("not.a.valid.pfm.file")); 272 in.seek(psext + 14); 273 capheight = in.readShortLE(); 274 xheight = in.readShortLE(); 275 ascender = in.readShortLE(); 276 descender = in.readShortLE(); 277 } 278 279 private void putheader() throws IOException { 280 out.print("StartFontMetrics 2.0\n"); 281 if (copyright.length() > 0) 282 out.print("Comment " + copyright + '\n'); 283 out.print("FontName "); 284 in.seek(fontname); 285 String fname = readString(); 286 out.print(fname); 287 out.print("\nEncodingScheme "); 288 if (charset != 0) 289 out.print("FontSpecific\n"); 290 else 291 out.print("AdobeStandardEncoding\n"); 292 /* 293 * The .pfm is missing full name, so construct from font name by 294 * changing the hyphen to a space. This actually works in a lot 295 * of cases. 296 */ 297 out.print("FullName " + fname.replace('-', ' ')); 298 if (face != 0) { 299 in.seek(face); 300 out.print("\nFamilyName " + readString()); 301 } 302 303 out.print("\nWeight "); 304 if (weight > 475 || fname.toLowerCase().indexOf("bold") >= 0) 305 out.print("Bold"); 306 else if ((weight < 325 && weight != 0) || fname.toLowerCase().indexOf("light") >= 0) 307 out.print("Light"); 308 else if (fname.toLowerCase().indexOf("black") >= 0) 309 out.print("Black"); 310 else 311 out.print("Medium"); 312 313 out.print("\nItalicAngle "); 314 if (italic != 0 || fname.toLowerCase().indexOf("italic") >= 0) 315 out.print("-12.00"); 316 /* this is a typical value; something else may work better for a 317 specific font */ 318 else 319 out.print("0"); 320 321 /* 322 * The mono flag in the pfm actually indicates whether there is a 323 * table of font widths, not if they are all the same. 324 */ 325 out.print("\nIsFixedPitch "); 326 if ((kind & 1) == 0 || /* Flag for mono */ 327 avgwidth == maxwidth ) { /* Avg width = max width */ 328 out.print("true"); 329 isMono = true; 330 } 331 else { 332 out.print("false"); 333 isMono = false; 334 } 335 336 /* 337 * The font bounding box is lost, but try to reconstruct it. 338 * Much of this is just guess work. The bounding box is required in 339 * the .afm, but is not used by the PM font installer. 340 */ 341 out.print("\nFontBBox"); 342 if (isMono) 343 outval(-20); /* Just guess at left bounds */ 344 else 345 outval(-100); 346 outval(-(descender+5)); /* Descender is given as positive value */ 347 outval(maxwidth+10); 348 outval(ascent+5); 349 350 /* 351 * Give other metrics that were kept 352 */ 353 out.print("\nCapHeight"); 354 outval(capheight); 355 out.print("\nXHeight"); 356 outval(xheight); 357 out.print("\nDescender"); 358 outval(-descender); 359 out.print("\nAscender"); 360 outval(ascender); 361 out.print('\n'); 362 } 363 364 private void putchartab() throws IOException { 365 int count = lastchar - firstchar + 1; 366 int ctabs[] = new int[count]; 367 in.seek(chartab); 368 for (int k = 0; k < count; ++k) 369 ctabs[k] = in.readUnsignedShortLE(); 370 int back[] = new int[256]; 371 if (charset == 0) { 372 for (int i = firstchar; i <= lastchar; ++i) { 373 if (Win2PSStd[i] != 0) 374 back[Win2PSStd[i]] = i; 375 } 376 } 377 /* Put out the header */ 378 out.print("StartCharMetrics"); 379 outval(count); 380 out.print('\n'); 381 382 /* Put out all encoded chars */ 383 if (charset != 0) { 384 /* 385 * If the charset is not the Windows standard, just put out 386 * unnamed entries. 387 */ 388 for (int i = firstchar; i <= lastchar; i++) { 389 if (ctabs[i - firstchar] != 0) { 390 outchar(i, ctabs[i - firstchar], null); 391 } 392 } 393 } 394 else { 395 for (int i = 0; i < 256; i++) { 396 int j = back[i]; 397 if (j != 0) { 398 outchar(i, ctabs[j - firstchar], WinChars[j]); 399 ctabs[j - firstchar] = 0; 400 } 401 } 402 /* Put out all non-encoded chars */ 403 for (int i = firstchar; i <= lastchar; i++) { 404 if (ctabs[i - firstchar] != 0) { 405 outchar(-1, ctabs[i - firstchar], WinChars[i]); 406 } 407 } 408 } 409 /* Put out the trailer */ 410 out.print("EndCharMetrics\n"); 411 412 } 413 414 private void putkerntab() throws IOException { 415 if (kernpairs == 0) 416 return; 417 in.seek(kernpairs); 418 int count = in.readUnsignedShortLE(); 419 int nzero = 0; 420 int kerns[] = new int[count * 3]; 421 for (int k = 0; k < kerns.length;) { 422 kerns[k++] = in.read(); 423 kerns[k++] = in.read(); 424 if ((kerns[k++] = in.readShortLE()) != 0) 425 ++nzero; 426 } 427 if (nzero == 0) 428 return; 429 out.print("StartKernData\nStartKernPairs"); 430 outval(nzero); 431 out.print('\n'); 432 for (int k = 0; k < kerns.length; k += 3) { 433 if (kerns[k + 2] != 0) { 434 out.print("KPX "); 435 out.print(WinChars[kerns[k]]); 436 out.print(' '); 437 out.print(WinChars[kerns[k + 1]]); 438 outval(kerns[k + 2]); 439 out.print('\n'); 440 } 441 } 442 /* Put out trailer */ 443 out.print("EndKernPairs\nEndKernData\n"); 444 } 445 446 447 private void puttrailer() { 448 out.print("EndFontMetrics\n"); 449 } 450 451 private short vers; 452 private int h_len; /* Total length of .pfm file */ 453 private String copyright; /* Copyright string [60]*/ 454 private short type; 455 private short points; 456 private short verres; 457 private short horres; 458 private short ascent; 459 private short intleading; 460 private short extleading; 461 private byte italic; 462 private byte uline; 463 private byte overs; 464 private short weight; 465 private byte charset; /* 0=windows, otherwise nomap */ 466 private short pixwidth; /* Width for mono fonts */ 467 private short pixheight; 468 private byte kind; /* Lower bit off in mono */ 469 private short avgwidth; /* Mono if avg=max width */ 470 private short maxwidth; /* Use to compute bounding box */ 471 private int firstchar; /* First char in table */ 472 private int lastchar; /* Last char in table */ 473 private byte defchar; 474 private byte brkchar; 475 private short widthby; 476 private int device; 477 private int face; /* Face name */ 478 private int bits; 479 private int bitoff; 480 private short extlen; 481 private int psext; /* PostScript extension */ 482 private int chartab; /* Character width tables */ 483 private int res1; 484 private int kernpairs; /* Kerning pairs */ 485 private int res2; 486 private int fontname; /* Font name */ 487 488/* 489 * Some metrics from the PostScript extension 490 */ 491 private short capheight; /* Cap height */ 492 private short xheight; /* X height */ 493 private short ascender; /* Ascender */ 494 private short descender; /* Descender (positive) */ 495 496 497 private boolean isMono; 498/** 499 * Translate table from 1004 to psstd. 1004 is an extension of the 500 * Windows translate table used in PM. 501 */ 502 private int Win2PSStd[] = { 503 0, 0, 0, 0, 197, 198, 199, 0, 202, 0, 205, 206, 207, 0, 0, 0, // 00 504 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 10 505 32, 33, 34, 35, 36, 37, 38, 169, 40, 41, 42, 43, 44, 45, 46, 47, // 20 506 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 30 507 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 40 508 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 50 509 193, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, // 60 510 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, // 70 511 128, 0, 184, 166, 185, 188, 178, 179, 195, 189, 0, 172, 234, 0, 0, 0, // 80 512 0, 96, 0, 170, 186, 183, 177, 208, 196, 0, 0, 173, 250, 0, 0, 0, // 90 513 0, 161, 162, 163, 168, 165, 0, 167, 200, 0, 227, 171, 0, 0, 0, 197, // A0 514 0, 0, 0, 0, 194, 0, 182, 180, 203, 0, 235, 187, 0, 0, 0, 191, // B0 515 0, 0, 0, 0, 0, 0, 225, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C0 516 0, 0, 0, 0, 0, 0, 0, 0, 233, 0, 0, 0, 0, 0, 0, 251, // D0 517 0, 0, 0, 0, 0, 0, 241, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E0 518 0, 0, 0, 0, 0, 0, 0, 0, 249, 0, 0, 0, 0, 0, 0, 0 // F0 519 }; 520 521/** 522 * Character class. This is a minor attempt to overcome the problem that 523 * in the pfm file, all unused characters are given the width of space. 524 * Note that this array isn't used in iText. 525 */ 526 private int WinClass[] = { 527 0, 0, 0, 0, 2, 2, 2, 0, 2, 0, 2, 2, 2, 0, 0, 0, /* 00 */ 528 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 10 */ 529 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 */ 530 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 */ 531 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 */ 532 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 */ 533 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 */ 534 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, /* 70 */ 535 0, 0, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, /* 80 */ 536 0, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 0, 2, /* 90 */ 537 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* a0 */ 538 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* b0 */ 539 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* c0 */ 540 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* d0 */ 541 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e0 */ 542 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 /* f0 */ 543 }; 544 545/** 546 * Windows character names. Give a name to the used locations 547 * for when the all flag is specified. 548 */ 549 private String WinChars[] = { 550 "W00", /* 00 */ 551 "W01", /* 01 */ 552 "W02", /* 02 */ 553 "W03", /* 03 */ 554 "macron", /* 04 */ 555 "breve", /* 05 */ 556 "dotaccent", /* 06 */ 557 "W07", /* 07 */ 558 "ring", /* 08 */ 559 "W09", /* 09 */ 560 "W0a", /* 0a */ 561 "W0b", /* 0b */ 562 "W0c", /* 0c */ 563 "W0d", /* 0d */ 564 "W0e", /* 0e */ 565 "W0f", /* 0f */ 566 "hungarumlaut", /* 10 */ 567 "ogonek", /* 11 */ 568 "caron", /* 12 */ 569 "W13", /* 13 */ 570 "W14", /* 14 */ 571 "W15", /* 15 */ 572 "W16", /* 16 */ 573 "W17", /* 17 */ 574 "W18", /* 18 */ 575 "W19", /* 19 */ 576 "W1a", /* 1a */ 577 "W1b", /* 1b */ 578 "W1c", /* 1c */ 579 "W1d", /* 1d */ 580 "W1e", /* 1e */ 581 "W1f", /* 1f */ 582 "space", /* 20 */ 583 "exclam", /* 21 */ 584 "quotedbl", /* 22 */ 585 "numbersign", /* 23 */ 586 "dollar", /* 24 */ 587 "percent", /* 25 */ 588 "ampersand", /* 26 */ 589 "quotesingle", /* 27 */ 590 "parenleft", /* 28 */ 591 "parenright", /* 29 */ 592 "asterisk", /* 2A */ 593 "plus", /* 2B */ 594 "comma", /* 2C */ 595 "hyphen", /* 2D */ 596 "period", /* 2E */ 597 "slash", /* 2F */ 598 "zero", /* 30 */ 599 "one", /* 31 */ 600 "two", /* 32 */ 601 "three", /* 33 */ 602 "four", /* 34 */ 603 "five", /* 35 */ 604 "six", /* 36 */ 605 "seven", /* 37 */ 606 "eight", /* 38 */ 607 "nine", /* 39 */ 608 "colon", /* 3A */ 609 "semicolon", /* 3B */ 610 "less", /* 3C */ 611 "equal", /* 3D */ 612 "greater", /* 3E */ 613 "question", /* 3F */ 614 "at", /* 40 */ 615 "A", /* 41 */ 616 "B", /* 42 */ 617 "C", /* 43 */ 618 "D", /* 44 */ 619 "E", /* 45 */ 620 "F", /* 46 */ 621 "G", /* 47 */ 622 "H", /* 48 */ 623 "I", /* 49 */ 624 "J", /* 4A */ 625 "K", /* 4B */ 626 "L", /* 4C */ 627 "M", /* 4D */ 628 "N", /* 4E */ 629 "O", /* 4F */ 630 "P", /* 50 */ 631 "Q", /* 51 */ 632 "R", /* 52 */ 633 "S", /* 53 */ 634 "T", /* 54 */ 635 "U", /* 55 */ 636 "V", /* 56 */ 637 "W", /* 57 */ 638 "X", /* 58 */ 639 "Y", /* 59 */ 640 "Z", /* 5A */ 641 "bracketleft", /* 5B */ 642 "backslash", /* 5C */ 643 "bracketright", /* 5D */ 644 "asciicircum", /* 5E */ 645 "underscore", /* 5F */ 646 "grave", /* 60 */ 647 "a", /* 61 */ 648 "b", /* 62 */ 649 "c", /* 63 */ 650 "d", /* 64 */ 651 "e", /* 65 */ 652 "f", /* 66 */ 653 "g", /* 67 */ 654 "h", /* 68 */ 655 "i", /* 69 */ 656 "j", /* 6A */ 657 "k", /* 6B */ 658 "l", /* 6C */ 659 "m", /* 6D */ 660 "n", /* 6E */ 661 "o", /* 6F */ 662 "p", /* 70 */ 663 "q", /* 71 */ 664 "r", /* 72 */ 665 "s", /* 73 */ 666 "t", /* 74 */ 667 "u", /* 75 */ 668 "v", /* 76 */ 669 "w", /* 77 */ 670 "x", /* 78 */ 671 "y", /* 79 */ 672 "z", /* 7A */ 673 "braceleft", /* 7B */ 674 "bar", /* 7C */ 675 "braceright", /* 7D */ 676 "asciitilde", /* 7E */ 677 "W7f", /* 7F */ 678 "euro", /* 80 */ 679 "W81", /* 81 */ 680 "quotesinglbase", /* 82 */ 681 "florin", /* 83 */ 682 "quotedblbase", /* 84 */ 683 "ellipsis", /* 85 */ 684 "dagger", /* 86 */ 685 "daggerdbl", /* 87 */ 686 "circumflex", /* 88 */ 687 "perthousand", /* 89 */ 688 "Scaron", /* 8A */ 689 "guilsinglleft", /* 8B */ 690 "OE", /* 8C */ 691 "W8d", /* 8D */ 692 "Zcaron", /* 8E */ 693 "W8f", /* 8F */ 694 "W90", /* 90 */ 695 "quoteleft", /* 91 */ 696 "quoteright", /* 92 */ 697 "quotedblleft", /* 93 */ 698 "quotedblright", /* 94 */ 699 "bullet", /* 95 */ 700 "endash", /* 96 */ 701 "emdash", /* 97 */ 702 "tilde", /* 98 */ 703 "trademark", /* 99 */ 704 "scaron", /* 9A */ 705 "guilsinglright", /* 9B */ 706 "oe", /* 9C */ 707 "W9d", /* 9D */ 708 "zcaron", /* 9E */ 709 "Ydieresis", /* 9F */ 710 "reqspace", /* A0 */ 711 "exclamdown", /* A1 */ 712 "cent", /* A2 */ 713 "sterling", /* A3 */ 714 "currency", /* A4 */ 715 "yen", /* A5 */ 716 "brokenbar", /* A6 */ 717 "section", /* A7 */ 718 "dieresis", /* A8 */ 719 "copyright", /* A9 */ 720 "ordfeminine", /* AA */ 721 "guillemotleft", /* AB */ 722 "logicalnot", /* AC */ 723 "syllable", /* AD */ 724 "registered", /* AE */ 725 "macron", /* AF */ 726 "degree", /* B0 */ 727 "plusminus", /* B1 */ 728 "twosuperior", /* B2 */ 729 "threesuperior", /* B3 */ 730 "acute", /* B4 */ 731 "mu", /* B5 */ 732 "paragraph", /* B6 */ 733 "periodcentered", /* B7 */ 734 "cedilla", /* B8 */ 735 "onesuperior", /* B9 */ 736 "ordmasculine", /* BA */ 737 "guillemotright", /* BB */ 738 "onequarter", /* BC */ 739 "onehalf", /* BD */ 740 "threequarters", /* BE */ 741 "questiondown", /* BF */ 742 "Agrave", /* C0 */ 743 "Aacute", /* C1 */ 744 "Acircumflex", /* C2 */ 745 "Atilde", /* C3 */ 746 "Adieresis", /* C4 */ 747 "Aring", /* C5 */ 748 "AE", /* C6 */ 749 "Ccedilla", /* C7 */ 750 "Egrave", /* C8 */ 751 "Eacute", /* C9 */ 752 "Ecircumflex", /* CA */ 753 "Edieresis", /* CB */ 754 "Igrave", /* CC */ 755 "Iacute", /* CD */ 756 "Icircumflex", /* CE */ 757 "Idieresis", /* CF */ 758 "Eth", /* D0 */ 759 "Ntilde", /* D1 */ 760 "Ograve", /* D2 */ 761 "Oacute", /* D3 */ 762 "Ocircumflex", /* D4 */ 763 "Otilde", /* D5 */ 764 "Odieresis", /* D6 */ 765 "multiply", /* D7 */ 766 "Oslash", /* D8 */ 767 "Ugrave", /* D9 */ 768 "Uacute", /* DA */ 769 "Ucircumflex", /* DB */ 770 "Udieresis", /* DC */ 771 "Yacute", /* DD */ 772 "Thorn", /* DE */ 773 "germandbls", /* DF */ 774 "agrave", /* E0 */ 775 "aacute", /* E1 */ 776 "acircumflex", /* E2 */ 777 "atilde", /* E3 */ 778 "adieresis", /* E4 */ 779 "aring", /* E5 */ 780 "ae", /* E6 */ 781 "ccedilla", /* E7 */ 782 "egrave", /* E8 */ 783 "eacute", /* E9 */ 784 "ecircumflex", /* EA */ 785 "edieresis", /* EB */ 786 "igrave", /* EC */ 787 "iacute", /* ED */ 788 "icircumflex", /* EE */ 789 "idieresis", /* EF */ 790 "eth", /* F0 */ 791 "ntilde", /* F1 */ 792 "ograve", /* F2 */ 793 "oacute", /* F3 */ 794 "ocircumflex", /* F4 */ 795 "otilde", /* F5 */ 796 "odieresis", /* F6 */ 797 "divide", /* F7 */ 798 "oslash", /* F8 */ 799 "ugrave", /* F9 */ 800 "uacute", /* FA */ 801 "ucircumflex", /* FB */ 802 "udieresis", /* FC */ 803 "yacute", /* FD */ 804 "thorn", /* FE */ 805 "ydieresis" /* FF */ 806 }; 807}