All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sta.cts.TTFReader Maven / Gradle / Ivy


package com.sta.cts;

import org.apache.fop.fonts.CMapSegment;
import org.w3c.dom.Document;
import org.apache.fop.fonts.truetype.FontFileReader;

import java.io.FileInputStream;
import java.util.ArrayList;
import org.w3c.dom.Element;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.fop.fonts.truetype.TTFFile;
import java.io.FileOutputStream;
import java.util.List;

import com.sta.mlogger.MLogger;

/**
 * 

Name: TTFReader

*

Description: TTF-Reader.

*

Copyright: Copyright (c) 2012, 2013, 2016, 2017, 2019, 2021

*

Company: >StA-Soft<

* @author StA * @version 1.0 */ public class TTFReader { /** * Verwendung unklar. */ private boolean invokedStandalone = false; //=========================================================================== /** * Constructor. */ public TTFReader() { } /** * Parse commandline arguments. put options in the HashMap and return * arguments in the String array * the arguments: -fn Perpetua,Bold -cn PerpetuaBold per.ttf Perpetua.xml * returns a String[] with the per.ttf and Perpetua.xml. The hash * will have the (key, value) pairs: (-fn, Perpetua) and (-cn, PerpetuaBold) * @param options Options * @param args Arguments * @return parsed arguments */ private static String[] parseArguments(HashMap options, String[] args) { ArrayList arguments = new ArrayList(); for (int i = 0; i < args.length; i++) { if (args[i].startsWith("-")) { if ((i + 1) < args.length && !args[i + 1].startsWith("-")) { options.put(args[i], args[i + 1]); i++; } else { options.put(args[i], ""); } } else { arguments.add(args[i]); } } String[] argStrings = new String[arguments.size()]; arguments.toArray(argStrings); return argStrings; } /** * Hinweise zur Verwendung. */ private static void displayUsage() { MLogger.err(" java org.apache.fop.fonts.apps.TTFReader [options] fontfile.ttf xmlfile.xml"); MLogger.err(" where options can be:"); MLogger.err("-enc ansi"); MLogger.err(" With this option you create a WinAnsi encoded font."); MLogger.err(" The default is to create a CID keyed font."); MLogger.err(" If you're not going to use characters outside the"); MLogger.err(" pdfencoding range (almost the same as iso-8889-1)"); MLogger.err(" you can add this option."); MLogger.err("-ttcname "); MLogger.err(" If you're reading data from a TrueType Collection"); MLogger.err(" (.ttc file) you must specify which font from the"); MLogger.err(" collection you will read metrics from. If you read"); MLogger.err(" from a .ttc file without this option, the fontnames"); MLogger.err(" will be listed for you."); MLogger.err(" -fn "); MLogger.err(" default is to use the fontname in the .ttf file, but"); MLogger.err(" you can override that name to make sure that the"); MLogger.err(" embedded font is used (if you're embedding fonts)"); MLogger.err(" instead of installed fonts when viewing documents with Acrobat Reader."); } /** * The main method for the TTFReader tool. * * @param args Command-line arguments: [options] fontfile.ttf xmlfile.xml * where options can be: * -fn <fontname> * default is to use the fontname in the .ttf file, but you can override * that name to make sure that the embedded font is used instead of installed * fonts when viewing documents with Acrobat Reader. * -cn <classname> * default is to use the fontname * -ef <path to the truetype fontfile> * will add the possibility to embed the font. When running fop, fop will look * for this file to embed it * -er <path to truetype fontfile relative to org/apache/fop/render/pdf/fonts> * you can also include the fontfile in the fop.jar file when building fop. * You can use both -ef and -er. The file specified in -ef will be searched first, * then the -er file. */ public static void main(String[] args) { String embFile = null; String embResource = null; String className = null; String fontName = null; String ttcName = null; boolean isCid = true; HashMap options = new HashMap(); String[] arguments = parseArguments(options, args); TTFReader app = new TTFReader(); app.invokedStandalone = true; MLogger.inf("TTF Reader v1.1.1"); MLogger.inf(""); if (options.get("-enc") != null) { String enc = (String) options.get("-enc"); if ("ansi".equals(enc)) { isCid = false; } } if (options.get("-ttcname") != null) { ttcName = (String) options.get("-ttcname"); } if (options.get("-ef") != null) { embFile = (String) options.get("-ef"); } if (options.get("-er") != null) { embResource = (String) options.get("-er"); } if (options.get("-fn") != null) { fontName = (String) options.get("-fn"); } if (options.get("-cn") != null) { className = (String) options.get("-cn"); } if ((arguments.length != 2) || (options.get("-h") != null) || (options.get("-help") != null) || (options.get("--help") != null)) { displayUsage(); } else { TTFFile ttf = app.loadTTF(arguments[0], ttcName); if (ttf != null) { org.w3c.dom.Document doc = app.constructFontXML(ttf, fontName, className, embResource, embFile, isCid, ttcName); if (isCid) { MLogger.inf("Creating CID encoded metrics"); } else { MLogger.inf("Creating WinAnsi encoded metrics"); } if (doc != null) { app.writeFontXML(doc, arguments[1]); } if (ttf.isEmbeddable()) { MLogger.inf("This font contains no embedding license restrictions"); } else { MLogger.inf("** Note: This font contains license retrictions for embedding. This font shouldn't be embedded."); } } } } /** * Read a TTF file and returns it as an object. * @param filename The filename of the PFM file. * @param fontname font name * @return The TTF as an object. */ public TTFFile loadTTF(String filename, String fontname) { TTFFile ttfFile = new TTFFile(); try { MLogger.inf("Reading " + filename + "..."); MLogger.inf(""); FontFileReader reader = new FontFileReader(new FileInputStream(filename)); ttfFile.readFont(reader, fontname); } catch (Exception ex) { MLogger.err("", ex); return null; } return ttfFile; } /** * Writes the generated DOM Document to a file. * * @param doc The DOM Document to save. * @param target The target filename for the XML file. */ public void writeFontXML(org.w3c.dom.Document doc, String target) { MLogger.inf("Writing xml font file " + target + "..."); MLogger.inf(""); try { javax.xml.transform.TransformerFactory.newInstance() .newTransformer().transform( new javax.xml.transform.dom.DOMSource(doc), new javax.xml.transform.stream.StreamResult(new FileOutputStream(target))); // new javax.xml.transform.stream.StreamResult(new File(target))); /* OutputFormat format = new OutputFormat(doc); // Serialize DOM FileWriter out = new FileWriter(target); // Writer will be a String XMLSerializer serial = new XMLSerializer(out, format); serial.asDOMSerializer(); // As a DOM Serializer serial.serialize(doc.getDocumentElement()); out.close(); */ } catch (Exception ex) { MLogger.err("", ex); } } /** * Generates the font metrics file from the TTF/TTC file. * @param ttf The PFM file to generate the font metrics from. * @param fontname font name * @param classname class name * @param resource resource * @param file file * @param isCid is cid * @param ttcName TTC-Name * @return The DOM document representing the font metrics file. */ public org.w3c.dom.Document constructFontXML(TTFFile ttf, String fontname, String classname, String resource, String file, boolean isCid, String ttcName) { MLogger.inf("Creating xml font file..."); MLogger.inf(""); // Document doc = new DocumentImpl(); Document doc; try { doc = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); } catch (javax.xml.parsers.ParserConfigurationException ex) { MLogger.err("Can't create DOM implementation.", ex); return null; } Element root = doc.createElement("font-metrics"); doc.appendChild(root); if (isCid) { root.setAttribute("type", "TYPE0"); } else { root.setAttribute("type", "TRUETYPE"); } Element el = doc.createElement("font-name"); root.appendChild(el); // Note that the PostScript name usually is something like // "Perpetua-Bold", but the TrueType spec says that in the ttf file // it should be "Perpetua,Bold". String s = stripWhiteSpace(ttf.getPostScriptName()); if (fontname != null) { MLogger.inf("FontName = " + fontname); el.appendChild(doc.createTextNode(stripWhiteSpace(fontname))); } else { StringBuilder sb = new StringBuilder(); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if ((ch > 32) && (ch < 128)) { sb.append(ch); } } int len = sb.length(); if (sb.charAt(len - 1) == ',') { sb.delete(len - 1, len); } s = sb.toString(); MLogger.inf("PostscriptName = " + s); el.appendChild(doc.createTextNode(s)); } el = doc.createElement("embed"); root.appendChild(el); if (file != null && ttf.isEmbeddable()) { el.setAttribute("file", file); } if (resource != null && ttf.isEmbeddable()) { el.setAttribute("class", resource); } el = doc.createElement("cap-height"); root.appendChild(el); el.appendChild(doc.createTextNode(String.valueOf(ttf.getCapHeight()))); el = doc.createElement("x-height"); root.appendChild(el); el.appendChild(doc.createTextNode(String.valueOf(ttf.getXHeight()))); el = doc.createElement("ascender"); root.appendChild(el); el.appendChild(doc.createTextNode(String.valueOf(ttf.getLowerCaseAscent()))); el = doc.createElement("descender"); root.appendChild(el); el.appendChild(doc.createTextNode(String.valueOf(ttf.getLowerCaseDescent()))); Element bbox = doc.createElement("bbox"); root.appendChild(bbox); int[] bb = ttf.getFontBBox(); String[] names = { "left", "bottom", "right", "top" }; for (int i = 0; i < 4; i++) { el = doc.createElement(names[i]); bbox.appendChild(el); el.appendChild(doc.createTextNode(String.valueOf(bb[i]))); } el = doc.createElement("flags"); root.appendChild(el); el.appendChild(doc.createTextNode(String.valueOf(ttf.getFlags()))); el = doc.createElement("stemv"); root.appendChild(el); el.appendChild(doc.createTextNode(ttf.getStemV())); el = doc.createElement("italicangle"); root.appendChild(el); el.appendChild(doc.createTextNode(ttf.getItalicAngle())); if (ttcName != null) { el = doc.createElement("ttc-name"); root.appendChild(el); el.appendChild(doc.createTextNode(ttcName)); } el = doc.createElement("subtype"); root.appendChild(el); // Fill in extras for CID keyed fonts if (isCid) { el.appendChild(doc.createTextNode("TYPE0")); Element mel = doc.createElement("multibyte-extras"); root.appendChild(mel); el = doc.createElement("cid-type"); mel.appendChild(el); el.appendChild(doc.createTextNode("CIDFontType2")); el = doc.createElement("default-width"); mel.appendChild(el); el.appendChild(doc.createTextNode("0")); el = doc.createElement("bfranges"); mel.appendChild(el); // ArrayList cmaps = ttf.getCMaps(); List cmaps = ttf.getCMaps(); for (int i = 0; i < cmaps.size(); i++) { CMapSegment ce = cmaps.get(i); Element el2 = doc.createElement("bf"); el.appendChild(el2); el2.setAttribute("us", String.valueOf(ce.getUnicodeStart())); el2.setAttribute("ue", String.valueOf(ce.getUnicodeEnd())); el2.setAttribute("gi", String.valueOf(ce.getGlyphStartIndex())); } el = doc.createElement("cid-widths"); el.setAttribute("start-index", "0"); mel.appendChild(el); int[] wx = ttf.getWidths(); for (int i = 0; i < wx.length; i++) { Element wxel = doc.createElement("wx"); wxel.setAttribute("w", String.valueOf(wx[i])); el.appendChild(wxel); } } else { // Fill in extras for singlebyte fonts el.appendChild(doc.createTextNode("TRUETYPE")); Element sel = doc.createElement("singlebyte-extras"); root.appendChild(sel); el = doc.createElement("encoding"); sel.appendChild(el); el.appendChild(doc.createTextNode(ttf.getCharSetName())); el = doc.createElement("first-char"); sel.appendChild(el); el.appendChild(doc.createTextNode(String.valueOf(ttf.getFirstChar()))); el = doc.createElement("last-char"); sel.appendChild(el); el.appendChild(doc.createTextNode(String.valueOf(ttf.getLastChar()))); Element widths = doc.createElement("widths"); sel.appendChild(widths); for (short i = ttf.getFirstChar(); i <= ttf.getLastChar(); i++) { el = doc.createElement("char"); widths.appendChild(el); el.setAttribute("idx", String.valueOf(i)); el.setAttribute("wdt", String.valueOf(ttf.getCharWidth(i))); } } // Get kerning Iterator enumx; if (isCid) { enumx = ttf.getKerning().keySet().iterator(); } else { enumx = ttf.getAnsiKerning().keySet().iterator(); } while (enumx.hasNext()) { Integer kpx1 = (Integer) enumx.next(); el = doc.createElement("kerning"); el.setAttribute("kpx1", kpx1.toString()); root.appendChild(el); Element el2 = null; HashMap h2; if (isCid) { h2 = (HashMap) ttf.getKerning().get(kpx1); } else { h2 = (HashMap) ttf.getAnsiKerning().get(kpx1); } for (Iterator enum2 = h2.keySet().iterator(); enum2.hasNext();) { Integer kpx2 = (Integer) enum2.next(); if (isCid || kpx2.intValue() < 256) { el2 = doc.createElement("pair"); el2.setAttribute("kpx2", kpx2.toString()); Integer val = (Integer) h2.get(kpx2); el2.setAttribute("kern", val.toString()); el.appendChild(el2); } } } return doc; } /** * White-Spaces entfernen. * @param s Text * @return Text ohne White-Spaces */ private String stripWhiteSpace(String s) { char[] ch = new char[s.length()]; s.getChars(0, s.length(), ch, 0); StringBuilder sb = new StringBuilder(); for (int i = 0; i < ch.length; i++) { if (ch[i] != ' ' && ch[i] != '\r' && ch[i] != '\n' && ch[i] != '\t') { sb.append(ch[i]); } } return sb.toString(); } /** * Text mit Escape-Sequenzen versehen. * @param str Text * @return Text mit Escape-Sequenzen */ private String escapeString(String str) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '\\') { sb.append("\\\\"); } else { sb.append(str.charAt(i)); } } return sb.toString(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy