1 51 package org.apache.fop.fonts.apps; 52 53 import java.io.*; 54 import org.w3c.dom.*; 55 import org.apache.fop.fonts.*; 56 import java.util.HashMap; 57 import java.util.ArrayList; 58 import java.util.Iterator; 59 60 65 public class TTFReader { 66 67 private boolean invokedStandalone = false; 68 69 public TTFReader() {} 70 71 72 79 private static String[] parseArguments(HashMap options, String[] args) { 80 ArrayList arguments = new ArrayList(); 81 for (int i = 0; i < args.length; i++) { 82 if (args[i].startsWith("-")) { 83 if ((i + 1) < args.length &&!args[i + 1].startsWith("-")) { 84 options.put(args[i], args[i + 1]); 85 i++; 86 } else { 87 options.put(args[i], ""); 88 } 89 } else { 90 arguments.add(args[i]); 91 } 92 } 93 94 String[] argStrings = new String[arguments.size()]; 95 arguments.toArray(argStrings); 96 return argStrings; 97 } 98 99 100 private static final void displayUsage() { 101 System.out.println(" java org.apache.fop.fonts.apps.TTFReader [options] fontfile.ttf xmlfile.xml\n"); 102 System.out.println(" where options can be:\n"); 103 System.out.println("-enc ansi"); 104 System.out.println(" With this option you create a WinAnsi encoded font.\n"); 105 System.out.println(" The default is to create a CID keyed font."); 106 System.out.println(" If you're not going to use characters outside the"); 107 System.out.println(" pdfencoding range (almost the same as iso-8889-1)"); 108 System.out.println(" you can add this option."); 109 System.out.println("-ttcname <fontname>"); 110 System.out.println(" If you're reading data from a TrueType Collection"); 111 System.out.println(" (.ttc file) you must specify which font from the"); 112 System.out.println(" collection you will read metrics from. If you read"); 113 System.out.println(" from a .ttc file without this option, the fontnames"); 114 System.out.println(" will be listed for you."); 115 System.out.println(" -fn <fontname>\n"); 116 System.out.println(" default is to use the fontname in the .ttf file, but\n" 117 + " you can override that name to make sure that the\n"); 118 System.out.println(" embedded font is used (if you're embedding fonts)\n"); 119 System.out.println(" instead of installed fonts when viewing documents with Acrobat Reader.\n"); 120 } 121 122 123 142 public static void main(String[] args) { 143 String embFile = null; 144 String embResource = null; 145 String className = null; 146 String fontName = null; 147 String ttcName = null; 148 boolean isCid = true; 149 150 HashMap options = new HashMap(); 151 String[] arguments = parseArguments(options, args); 152 153 TTFReader app = new TTFReader(); 154 app.invokedStandalone = true; 155 156 System.out.println("TTF Reader v1.1.1"); 157 System.out.println(); 158 159 if (options.get("-enc") != null) { 160 String enc = (String)options.get("-enc"); 161 if ("ansi".equals(enc)) 162 isCid = false; 163 } 164 165 if (options.get("-ttcname") != null) 166 ttcName = (String)options.get("-ttcname"); 167 168 if (options.get("-ef") != null) 169 embFile = (String)options.get("-ef"); 170 171 if (options.get("-er") != null) 172 embResource = (String)options.get("-er"); 173 174 if (options.get("-fn") != null) 175 fontName = (String)options.get("-fn"); 176 177 if (options.get("-cn") != null) 178 className = (String)options.get("-cn"); 179 180 if (arguments.length != 2 || options.get("-h") != null 181 || options.get("-help") != null || options.get("--help") != null) 182 displayUsage(); 183 else { 184 TTFFile ttf = app.loadTTF(arguments[0], ttcName); 185 if (ttf != null) { 186 org.w3c.dom.Document doc = app.constructFontXML(ttf, 187 fontName, className, embResource, embFile, isCid, 188 ttcName); 189 190 if (isCid) 191 System.out.println("Creating CID encoded metrics"); 192 else 193 System.out.println("Creating WinAnsi encoded metrics"); 194 195 if (doc != null) { 196 app.writeFontXML(doc, arguments[1]); 197 } 198 199 if (ttf.isEmbeddable()) 200 System.out.println("This font contains no embedding license restrictions"); 201 else 202 System.out.println("** Note: This font contains license retrictions for\n" 203 + " embedding. This font shouldn't be embedded."); 204 205 } 206 } 207 } 208 209 215 public TTFFile loadTTF(String fileName, String fontName) { 216 TTFFile ttfFile = new TTFFile(); 217 try { 218 System.out.println("Reading " + fileName + "..."); 219 System.out.println(); 220 221 FontFileReader reader = new FontFileReader(fileName); 222 ttfFile.readFont(reader, fontName); 223 } catch (Exception e) { 224 e.printStackTrace(); 225 return null; 226 } 227 return ttfFile; 228 } 229 230 231 237 public void writeFontXML(org.w3c.dom.Document doc, String target) { 238 System.out.println("Writing xml font file " + target + "..."); 239 System.out.println(); 240 241 try { 242 javax.xml.transform.TransformerFactory.newInstance() 243 .newTransformer().transform( 244 new javax.xml.transform.dom.DOMSource(doc), 245 new javax.xml.transform.stream.StreamResult(new File(target))); 246 247 255 } catch (Exception e) { 256 e.printStackTrace(); 257 } 258 } 259 260 266 public org.w3c.dom.Document constructFontXML(TTFFile ttf, 267 String fontName, String className, String resource, String file, 268 boolean isCid, String ttcName) { 269 System.out.println("Creating xml font file..."); 270 System.out.println(); 271 272 Document doc; 274 try { 275 doc = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); 276 } 277 catch (javax.xml.parsers.ParserConfigurationException e) { 278 System.out.println("Can't create DOM implementation "+e.getMessage()); 279 return null; 280 } 281 Element root = doc.createElement("font-metrics"); 282 doc.appendChild(root); 283 if (isCid) 284 root.setAttribute("type", "TYPE0"); 285 else 286 root.setAttribute("type", "TRUETYPE"); 287 288 Element el = doc.createElement("font-name"); 289 root.appendChild(el); 290 291 295 String s = stripWhiteSpace(ttf.getPostscriptName()); 296 297 if (fontName != null) 298 el.appendChild(doc.createTextNode(stripWhiteSpace(fontName))); 299 else 300 el.appendChild(doc.createTextNode(s)); 301 302 el = doc.createElement("embed"); 303 root.appendChild(el); 304 if (file != null && ttf.isEmbeddable()) 305 el.setAttribute("file", file); 306 if (resource != null && ttf.isEmbeddable()) 307 el.setAttribute("class", resource); 308 309 el = doc.createElement("cap-height"); 310 root.appendChild(el); 311 el.appendChild(doc.createTextNode(String.valueOf(ttf.getCapHeight()))); 312 313 el = doc.createElement("x-height"); 314 root.appendChild(el); 315 el.appendChild(doc.createTextNode(String.valueOf(ttf.getXHeight()))); 316 317 el = doc.createElement("ascender"); 318 root.appendChild(el); 319 el.appendChild(doc.createTextNode(String.valueOf(ttf.getLowerCaseAscent()))); 320 321 el = doc.createElement("descender"); 322 root.appendChild(el); 323 el.appendChild(doc.createTextNode(String.valueOf(ttf.getLowerCaseDescent()))); 324 325 Element bbox = doc.createElement("bbox"); 326 root.appendChild(bbox); 327 int[] bb = ttf.getFontBBox(); 328 String[] names = { 329 "left", "bottom", "right", "top" 330 }; 331 for (int i = 0; i < 4; i++) { 332 el = doc.createElement(names[i]); 333 bbox.appendChild(el); 334 el.appendChild(doc.createTextNode(String.valueOf(bb[i]))); 335 } 336 337 el = doc.createElement("flags"); 338 root.appendChild(el); 339 el.appendChild(doc.createTextNode(String.valueOf(ttf.getFlags()))); 340 341 el = doc.createElement("stemv"); 342 root.appendChild(el); 343 el.appendChild(doc.createTextNode(ttf.getStemV())); 344 345 el = doc.createElement("italicangle"); 346 root.appendChild(el); 347 el.appendChild(doc.createTextNode(ttf.getItalicAngle())); 348 349 if (ttcName != null) { 350 el = doc.createElement("ttc-name"); 351 root.appendChild(el); 352 el.appendChild(doc.createTextNode(ttcName)); 353 } 354 355 el = doc.createElement("subtype"); 356 root.appendChild(el); 357 358 if (isCid) { 360 el.appendChild(doc.createTextNode("TYPE0")); 361 362 Element mel = doc.createElement("multibyte-extras"); 363 root.appendChild(mel); 364 365 el = doc.createElement("cid-type"); 366 mel.appendChild(el); 367 el.appendChild(doc.createTextNode("CIDFontType2")); 368 369 el = doc.createElement("default-width"); 370 mel.appendChild(el); 371 el.appendChild(doc.createTextNode("0")); 372 373 el = doc.createElement("bfranges"); 374 mel.appendChild(el); 375 ArrayList cmaps = ttf.getCMaps(); 376 for (int i = 0;i < cmaps.size(); i++) { 377 TTFCmapEntry ce = (TTFCmapEntry)cmaps.get(i); 378 Element el2 = doc.createElement("bf"); 379 el.appendChild(el2); 380 el2.setAttribute("us", String.valueOf(ce.unicodeStart)); 381 el2.setAttribute("ue", String.valueOf(ce.unicodeEnd)); 382 el2.setAttribute("gi", String.valueOf(ce.glyphStartIndex)); 383 } 384 385 el = doc.createElement("cid-widths"); 386 el.setAttribute("start-index", "0"); 387 mel.appendChild(el); 388 389 int[] wx = ttf.getWidths(); 390 for (int i = 0; i < wx.length; i++) { 391 Element wxel = doc.createElement("wx"); 392 wxel.setAttribute("w", String.valueOf(wx[i])); 393 el.appendChild(wxel); 394 } 395 } else { 396 el.appendChild(doc.createTextNode("TRUETYPE")); 398 399 Element sel = doc.createElement("singlebyte-extras"); 400 root.appendChild(sel); 401 402 el = doc.createElement("encoding"); 403 sel.appendChild(el); 404 el.appendChild(doc.createTextNode(ttf.getCharSetName())); 405 406 el = doc.createElement("first-char"); 407 sel.appendChild(el); 408 el.appendChild(doc.createTextNode(String.valueOf(ttf.getFirstChar()))); 409 410 el = doc.createElement("last-char"); 411 sel.appendChild(el); 412 el.appendChild(doc.createTextNode(String.valueOf(ttf.getLastChar()))); 413 414 Element widths = doc.createElement("widths"); 415 sel.appendChild(widths); 416 417 for (short i = ttf.getFirstChar(); i <= ttf.getLastChar(); i++) { 418 el = doc.createElement("char"); 419 widths.appendChild(el); 420 el.setAttribute("idx", String.valueOf(i)); 421 el.setAttribute("wdt", String.valueOf(ttf.getCharWidth(i))); 422 } 423 } 424 425 Iterator enum; 427 if (isCid) 428 enum = ttf.getKerning().keySet().iterator(); 429 else 430 enum = ttf.getAnsiKerning().keySet().iterator(); 431 432 while (enum.hasNext()) { 433 Integer kpx1 = (Integer)enum.next(); 434 435 el = doc.createElement("kerning"); 436 el.setAttribute("kpx1", kpx1.toString()); 437 root.appendChild(el); 438 Element el2 = null; 439 440 HashMap h2; 441 if (isCid) 442 h2 = (HashMap)ttf.getKerning().get(kpx1); 443 else 444 h2 = (HashMap)ttf.getAnsiKerning().get(kpx1); 445 446 for (Iterator enum2 = h2.keySet().iterator(); enum2.hasNext(); ) { 447 Integer kpx2 = (Integer)enum2.next(); 448 if (isCid || kpx2.intValue() < 256) { 449 el2 = doc.createElement("pair"); 450 el2.setAttribute("kpx2", kpx2.toString()); 451 Integer val = (Integer)h2.get(kpx2); 452 el2.setAttribute("kern", val.toString()); 453 el.appendChild(el2); 454 } 455 } 456 } 457 458 return doc; 459 } 460 461 462 private String stripWhiteSpace(String s) { 463 char[] ch = new char[s.length()]; 464 s.getChars(0, s.length(), ch, 0); 465 StringBuffer stb = new StringBuffer(); 466 for (int i = 0; i < ch.length; i++) 467 if (ch[i] != ' ' && ch[i] != '\r' && ch[i] != '\n' 468 && ch[i] != '\t') 469 stb.append(ch[i]); 470 471 return stb.toString(); 472 } 473 474 private String escapeString(String str) { 475 StringBuffer esc = new StringBuffer(); 476 477 for (int i = 0; i < str.length(); i++) { 478 if (str.charAt(i) == '\\') 479 esc.append("\\\\"); 480 else 481 esc.append(str.charAt(i)); 482 } 483 484 return esc.toString(); 485 } 486 487 } 488 489 | Popular Tags |