diff options
Diffstat (limited to 'src/org/apache/fop/fonts')
-rw-r--r-- | src/org/apache/fop/fonts/FontFileReader.java | 227 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/Glyphs.java | 1692 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/PFMFile.java | 59 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFCmapEntry.java | 60 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFDirTabEntry.java | 85 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFFile.java | 528 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFMtxEntry.java | 77 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFSegEntry.java | 61 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/apps/PFMReader.java | 232 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/apps/TTFReader.java | 504 |
10 files changed, 3470 insertions, 55 deletions
diff --git a/src/org/apache/fop/fonts/FontFileReader.java b/src/org/apache/fop/fonts/FontFileReader.java new file mode 100644 index 000000000..f6bc3cff9 --- /dev/null +++ b/src/org/apache/fop/fonts/FontFileReader.java @@ -0,0 +1,227 @@ +/* -- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fonts; +import java.io.FileInputStream; +import java.io.InputStream; +import java.io.File; +import java.io.IOException; + +/** Reads a file into an array and + provides file like functions for array access. +*/ +public class FontFileReader { + private int fsize; // file size + private int current; // current position in file + private byte[] file; + /** + * Initialisez class and reads stream. Init does not close stream + * @param stream InputStream to read from + * @param start initial size av array to read to + * @param inc if initial size isn't enough, create + new array with size + inc + */ + private void init(InputStream stream, int start, int inc) + throws java.io.IOException { + fsize=0; + current=0; + + file=new byte[start]; + + int l=stream.read(file, 0, start); + fsize+=l; + + if (l==start) { + // More to read - needs to extend + byte[] tmpbuf; + + while (l>0) { + tmpbuf=new byte[file.length + inc]; + System.arraycopy(file, 0, tmpbuf, 0, file.length); + l=stream.read(tmpbuf, file.length, inc); + fsize+=l; + file=tmpbuf; + + if (l<inc) // whole file read. No need to loop again + l=0; + } + } + } + + /** + * Constructor + * @param fileName filename to read + */ + public FontFileReader(String fileName) + throws java.io.IOException { + + // Get estimates for file size and increment + File f=new File(fileName); + FileInputStream ins = new FileInputStream(fileName); + init(ins, (int)(f.length()+1), (int)(f.length()/10)); + ins.close(); + } + + + /** Set current file position to offset */ + public void seek_set(long offset) throws IOException { + if (offset > fsize || offset < 0) + throw new java.io.EOFException("Reached EOF, file size="+fsize+ + " offset="+offset); + current=(int)offset; + } + + /** Set current file position to offset */ + public void seek_add(long add) throws IOException { + seek_set(current+add); + } + + public void skip(long add) throws IOException { + seek_add(add); + } + + /** return current file position */ + public int getCurrentPos() { + return current; + } + + public int getFileSize() { + return fsize; + } + + + /** Read 1 byte, throws EOFException on end of file */ + public byte read() throws IOException { + if (current>fsize) + throw new java.io.EOFException("Reached EOF, file size="+fsize); + + byte ret=file[current++]; + return ret; + } + + + + /** Read 1 signed byte from InputStream */ + public final byte readTTFByte() throws IOException { + return read(); + } + + /** Read 1 unsigned byte from InputStream */ + public final int readTTFUByte() throws IOException { + byte buf=read(); + + if (buf < 0) + return (int)(256+buf); + else + return (int)buf; + } + + /** Read 2 bytes signed from InputStream */ + public final short readTTFShort() throws IOException { + int ret=(readTTFUByte() << 8) + + readTTFUByte(); + short sret=(short)ret; + + return sret; + } + + /** Read 2 bytes unsigned from InputStream */ + public final int readTTFUShort() throws IOException { + int ret=(readTTFUByte() << 8) + + readTTFUByte(); + + return (int)ret; + } + + /** Read 4 bytes from InputStream */ + public final int readTTFLong() throws IOException { + long ret=readTTFUByte();// << 8; + ret=(ret << 8) + readTTFUByte(); + ret=(ret << 8) + readTTFUByte(); + ret=(ret << 8) + readTTFUByte(); + + return (int)ret; + } + + /** Read 4 bytes from InputStream */ + public final long readTTFULong() throws IOException { + long ret=readTTFUByte(); + ret=(ret << 8) + readTTFUByte(); + ret=(ret << 8) + readTTFUByte(); + ret=(ret << 8) + readTTFUByte(); + + return ret; + } + + /** Read a 0 terminatet ISO-8859-1 string */ + public final String readTTFString() throws IOException { + int i=current; + while (file[i++]!=0) { + if (i > fsize) + throw new java.io.EOFException("Reached EOF, file size="+fsize); + } + + byte[] tmp=new byte[i-current]; + System.arraycopy(file, current, tmp, 0, i-current); + return new String(tmp, "ISO-8859-1"); + } + + + /** Read an ISO-8859-1 string of len bytes*/ + public final String readTTFString(int len) throws IOException { + if ((len+current) > fsize) + throw new java.io.EOFException("Reached EOF, file size="+fsize); + + byte[] tmp=new byte[len]; + System.arraycopy(file, current, tmp, 0, len); + current+=len; + return new String(tmp, "ISO-8859-1"); + } +} diff --git a/src/org/apache/fop/fonts/Glyphs.java b/src/org/apache/fop/fonts/Glyphs.java new file mode 100644 index 000000000..cba61bcdb --- /dev/null +++ b/src/org/apache/fop/fonts/Glyphs.java @@ -0,0 +1,1692 @@ +/* -- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fonts; + +public class Glyphs { + static String notdef = ".notdef"; + + static String mac_glyph_names[] = { +/* 0x00 */ + notdef, + ".null", + "CR", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quotesingle", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", +/* 0x10 */ + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", +/* 0x20 */ + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", +/* 0x30 */ + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", +/* 0x40 */ + "bracketright", + "asciicircum", + "underscore", + "grave", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", +/* 0x50 */ + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", +/* 0x60 */ + "braceright", + "asciitilde", + "Adieresis", + "Aring", + "Ccedilla", + "Eacute", + "Ntilde", + "Odieresis", + "Udieresis", + "aacute", + "agrave", + "acircumflex", + "adieresis", + "atilde", + "aring", + "ccedilla", +/* 0x70 */ + "eacute", + "egrave", + "ecircumflex", + "edieresis", + "iacute", + "igrave", + "icircumflex", + "idieresis", + "ntilde", + "oacute", + "ograve", + "ocircumflex", + "odieresis", + "otilde", + "uacute", + "ugrave", +/* 0x80 */ + "ucircumflex", + "udieresis", + "dagger", + "degree", + "cent", + "sterling", + "section", + "bullet", + "paragraph", + "germandbls", + "registered", + "copyright", + "trademark", + "acute", + "dieresis", + "notequal", +/* 0x90 */ + "AE", + "Oslash", + "infinity", + "plusminus", + "lessequal", + "greaterequal", + "yen", + "mu", + "partialdiff", + "Sigma", + "Pi", + "pi", + "integral", + "ordfeminine", + "ordmasculine", + "Omega", +/* 0xa0 */ + "ae", + "oslash", + "questiondown", + "exclamdown", + "logicalnot", + "radical", + "florin", + "approxequal", + "Delta", + "guillemotleft", + "guillemotright", + "ellipsis", + "nbspace", + "Agrave", + "Atilde", + "Otilde", +/* 0xb0 */ + "OE", + "oe", + "endash", + "emdash", + "quotedblleft", + "quotedblright", + "quoteleft", + "quoteright", + "divide", + "lozenge", + "ydieresis", + "Ydieresis", + "fraction", + "currency", + "guilsinglleft", + "guilsinglright", +/* 0xc0 */ + "fi", + "fl", + "daggerdbl", + "periodcentered", + "quotesinglbase", + "quotedblbase", + "perthousand", + "Acircumflex", + "Ecircumflex", + "Aacute", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", +/* 0xd0 */ + "Oacute", + "Ocircumflex", + "applelogo", + "Ograve", + "Uacute", + "Ucircumflex", + "Ugrave", + "dotlessi", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "ring", + "cedilla", + "hungarumlaut", +/* 0xe0 */ + "ogonek", + "caron", + "Lslash", + "lslash", + "Scaron", + "scaron", + "Zcaron", + "zcaron", + "brokenbar", + "Eth", + "eth", + "Yacute", + "yacute", + "Thorn", + "thorn", + "minus", +/* 0xf0 */ + "multiply", + "onesuperior", + "twosuperior", + "threesuperior", + "onehalf", + "onequarter", + "threequarters", + "franc", + "Gbreve", + "gbreve", + "Idot", + "Scedilla", + "scedilla", + "Cacute", + "cacute", + "Ccaron", +/* 0x100 */ + "ccaron", + "dmacron" + }; + + static String[] tex8r = { + // 0x00 + ".notdef", + "dotaccent", + "fi", + "fl", + "fraction", + "hungarumlaut", + "Lslash", + "lslash", + "ogonek", + "ring", + ".notdef", + "breve", + "minus", + ".notdef", + "Zcaron", + "zcaron", + // 0x10 + "caron", + "dotlessi", + "dotlessj", + "ff", + "ffi", + "ffl", + ".notdef", + ".notdef", + ".notdef", + ".notdef", + ".notdef", + ".notdef", + ".notdef", + ".notdef", + "grave", + "quotesingle", + // 0x20 + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + // 0x30 + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + // 0x40 + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + // 0x50 + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + // 0x60 + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + // 0x70 + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + ".notdef", + // 0x80 + "Euro", + ".notdef", + "quotesinglbase", + "florin", + "quotedblbase", + "ellipsis", + "dagger", + "daggerdbl", + "circumflex", + "perthousand", + "Scaron", + "guilsinglleft", + "OE", + ".notdef", + ".notdef", + ".notdef", + // 0x90 + ".notdef", + ".notdef", + ".notdef", + "quotedblleft", + "quotedblright", + "bullet", + "endash", + "emdash", + "tilde", + "trademark", + "scaron", + "guilsinglright", + "oe", + ".notdef", + ".notdef", + "Ydieresis", + // 0xA0 + ".notdef", + "exclamdown", + "cent", + "sterling", + "currency", + "yen", + "brokenbar", + "section", + "dieresis", + "copyright", + "ordfeminine", + "guillemotleft", + "logicalnot", + "hyphen", + "registered", + "macron", + // 0xB0 + "degree", + "plusminus", + "twosuperior", + "threesuperior", + "acute", + "mu", + "paragraph", + "periodcentered", + "cedilla", + "onesuperior", + "ordmasculine", + "guillemotright", + "onequarter", + "onehalf", + "threequarters", + "questiondown", + // 0xC0 + "Agrave", + "Aacute", + "Acircumflex", + "Atilde", + "Adieresis", + "Aring", + "AE", + "Ccedilla", + "Egrave", + "Eacute", + "Ecircumflex", + "Edieresis", + "Igrave", + "Iacute", + "Icircumflex", + "Idieresis", + // 0xD0 + "Eth", + "Ntilde", + "Ograve", + "Oacute", + "Ocircumflex", + "Otilde", + "Odieresis", + "multiply", + "Oslash", + "Ugrave", + "Uacute", + "Ucircumflex", + "Udieresis", + "Yacute", + "Thorn", + "germandbls", + // 0xE0 + "agrave", + "aacute", + "acircumflex", + "atilde", + "adieresis", + "aring", + "ae", + "ccedilla", + "egrave", + "eacute", + "ecircumflex", + "edieresis", + "igrave", + "iacute", + "icircumflex", + "idieresis", + // 0xF0 + "eth", + "ntilde", + "ograve", + "oacute", + "ocircumflex", + "otilde", + "odieresis", + "divide", + "oslash", + "ugrave", + "uacute", + "ucircumflex", + "udieresis", + "yacute", + "thorn", + "ydieresis"}; + + static String[] unicode_glyphs={ + "\u0041", "A", + "\u00C6", "AE", + "\u01FC", "AEacute", + "\uF7E6", "AEsmall", + "\u00C1", "Aacute", + "\uF7E1", "Aacutesmall", + "\u0102", "Abreve", + "\u00C2", "Acircumflex", + "\uF7E2", "Acircumflexsmall", + "\uF6C9", "Acute", + "\uF7B4", "Acutesmall", + "\u00C4", "Adieresis", + "\uF7E4", "Adieresissmall", + "\u00C0", "Agrave", + "\uF7E0", "Agravesmall", + "\u0391", "Alpha", + "\u0386", "Alphatonos", + "\u0100", "Amacron", + "\u0104", "Aogonek", + "\u00C5", "Aring", + "\u01FA", "Aringacute", + "\uF7E5", "Aringsmall", + "\uF761", "Asmall", + "\u00C3", "Atilde", + "\uF7E3", "Atildesmall", + "\u0042", "B", + "\u0392", "Beta", + "\uF6F4", "Brevesmall", + "\uF762", "Bsmall", + "\u0043", "C", + "\u0106", "Cacute", + "\uF6CA", "Caron", + "\uF6F5", "Caronsmall", + "\u010C", "Ccaron", + "\u00C7", "Ccedilla", + "\uF7E7", "Ccedillasmall", + "\u0108", "Ccircumflex", + "\u010A", "Cdotaccent", + "\uF7B8", "Cedillasmall", + "\u03A7", "Chi", + "\uF6F6", "Circumflexsmall", + "\uF763", "Csmall", + "\u0044", "D", + "\u010E", "Dcaron", + "\u0110", "Dcroat", + "\u2206", "Delta", + "\u0394", "Delta", + "\uF6CB", "Dieresis", + "\uF6CC", "DieresisAcute", + "\uF6CD", "DieresisGrave", + "\uF7A8", "Dieresissmall", + "\uF6F7", "Dotaccentsmall", + "\uF764", "Dsmall", + "\u0045", "E", + "\u00C9", "Eacute", + "\uF7E9", "Eacutesmall", + "\u0114", "Ebreve", + "\u011A", "Ecaron", + "\u00CA", "Ecircumflex", + "\uF7EA", "Ecircumflexsmall", + "\u00CB", "Edieresis", + "\uF7EB", "Edieresissmall", + "\u0116", "Edotaccent", + "\u00C8", "Egrave", + "\uF7E8", "Egravesmall", + "\u0112", "Emacron", + "\u014A", "Eng", + "\u0118", "Eogonek", + "\u0395", "Epsilon", + "\u0388", "Epsilontonos", + "\uF765", "Esmall", + "\u0397", "Eta", + "\u0389", "Etatonos", + "\u00D0", "Eth", + "\uF7F0", "Ethsmall", + "\u20AC", "Euro", + "\u0046", "F", + "\uF766", "Fsmall", + "\u0047", "G", + "\u0393", "Gamma", + "\u011E", "Gbreve", + "\u01E6", "Gcaron", + "\u011C", "Gcircumflex", + "\u0122", "Gcommaaccent", + "\u0120", "Gdotaccent", + "\uF6CE", "Grave", + "\uF760", "Gravesmall", + "\uF767", "Gsmall", + "\u0048", "H", + "\u25CF", "H18533", + "\u25AA", "H18543", + "\u25AB", "H18551", + "\u25A1", "H22073", + "\u0126", "Hbar", + "\u0124", "Hcircumflex", + "\uF768", "Hsmall", + "\uF6CF", "Hungarumlaut", + "\uF6F8", "Hungarumlautsmall", + "\u0049", "I", + "\u0132", "IJ", + "\u00CD", "Iacute", + "\uF7ED", "Iacutesmall", + "\u012C", "Ibreve", + "\u00CE", "Icircumflex", + "\uF7EE", "Icircumflexsmall", + "\u00CF", "Idieresis", + "\uF7EF", "Idieresissmall", + "\u0130", "Idotaccent", + "\u2111", "Ifraktur", + "\u00CC", "Igrave", + "\uF7EC", "Igravesmall", + "\u012A", "Imacron", + "\u012E", "Iogonek", + "\u0399", "Iota", + "\u03AA", "Iotadieresis", + "\u038A", "Iotatonos", + "\uF769", "Ismall", + "\u0128", "Itilde", + "\u004A", "J", + "\u0134", "Jcircumflex", + "\uF76A", "Jsmall", + "\u004B", "K", + "\u039A", "Kappa", + "\u0136", "Kcommaaccent", + "\uF76B", "Ksmall", + "\u004C", "L", + "\uF6BF", "LL", + "\u0139", "Lacute", + "\u039B", "Lambda", + "\u013D", "Lcaron", + "\u013B", "Lcommaaccent", + "\u013F", "Ldot", + "\u0141", "Lslash", + "\uF6F9", "Lslashsmall", + "\uF76C", "Lsmall", + "\u004D", "M", + "\uF6D0", "Macron", + "\uF7AF", "Macronsmall", + "\uF76D", "Msmall", + "\u039C", "Mu", + "\u004E", "N", + "\u0143", "Nacute", + "\u0147", "Ncaron", + "\u0145", "Ncommaaccent", + "\uF76E", "Nsmall", + "\u00D1", "Ntilde", + "\uF7F1", "Ntildesmall", + "\u039D", "Nu", + "\u004F", "O", + "\u0152", "OE", + "\uF6FA", "OEsmall", + "\u00D3", "Oacute", + "\uF7F3", "Oacutesmall", + "\u014E", "Obreve", + "\u00D4", "Ocircumflex", + "\uF7F4", "Ocircumflexsmall", + "\u00D6", "Odieresis", + "\uF7F6", "Odieresissmall", + "\uF6FB", "Ogoneksmall", + "\u00D2", "Ograve", + "\uF7F2", "Ogravesmall", + "\u01A0", "Ohorn", + "\u0150", "Ohungarumlaut", + "\u014C", "Omacron", + "\u2126", "Omega", + "\u03A9", "Omega", + "\u038F", "Omegatonos", + "\u039F", "Omicron", + "\u038C", "Omicrontonos", + "\u00D8", "Oslash", + "\u01FE", "Oslashacute", + "\uF7F8", "Oslashsmall", + "\uF76F", "Osmall", + "\u00D5", "Otilde", + "\uF7F5", "Otildesmall", + "\u0050", "P", + "\u03A6", "Phi", + "\u03A0", "Pi", + "\u03A8", "Psi", + "\uF770", "Psmall", + "\u0051", "Q", + "\uF771", "Qsmall", + "\u0052", "R", + "\u0154", "Racute", + "\u0158", "Rcaron", + "\u0156", "Rcommaaccent", + "\u211C", "Rfraktur", + "\u03A1", "Rho", + "\uF6FC", "Ringsmall", + "\uF772", "Rsmall", + "\u0053", "S", + "\u250C", "SF010000", + "\u2514", "SF020000", + "\u2510", "SF030000", + "\u2518", "SF040000", + "\u253C", "SF050000", + "\u252C", "SF060000", + "\u2534", "SF070000", + "\u251C", "SF080000", + "\u2524", "SF090000", + "\u2500", "SF100000", + "\u2502", "SF110000", + "\u2561", "SF190000", + "\u2562", "SF200000", + "\u2556", "SF210000", + "\u2555", "SF220000", + "\u2563", "SF230000", + "\u2551", "SF240000", + "\u2557", "SF250000", + "\u255D", "SF260000", + "\u255C", "SF270000", + "\u255B", "SF280000", + "\u255E", "SF360000", + "\u255F", "SF370000", + "\u255A", "SF380000", + "\u2554", "SF390000", + "\u2569", "SF400000", + "\u2566", "SF410000", + "\u2560", "SF420000", + "\u2550", "SF430000", + "\u256C", "SF440000", + "\u2567", "SF450000", + "\u2568", "SF460000", + "\u2564", "SF470000", + "\u2565", "SF480000", + "\u2559", "SF490000", + "\u2558", "SF500000", + "\u2552", "SF510000", + "\u2553", "SF520000", + "\u256B", "SF530000", + "\u256A", "SF540000", + "\u015A", "Sacute", + "\u0160", "Scaron", + "\uF6FD", "Scaronsmall", + "\u015E", "Scedilla", + "\uF6C1", "Scedilla", + "\u015C", "Scircumflex", + "\u0218", "Scommaaccent", + "\u03A3", "Sigma", + "\uF773", "Ssmall", + "\u0054", "T", + "\u03A4", "Tau", + "\u0166", "Tbar", + "\u0164", "Tcaron", + "\u0162", "Tcommaaccent", + "\u021A", "Tcommaaccent", + "\u0398", "Theta", + "\u00DE", "Thorn", + "\uF7FE", "Thornsmall", + "\uF6FE", "Tildesmall", + "\uF774", "Tsmall", + "\u0055", "U", + "\u00DA", "Uacute", + "\uF7FA", "Uacutesmall", + "\u016C", "Ubreve", + "\u00DB", "Ucircumflex", + "\uF7FB", "Ucircumflexsmall", + "\u00DC", "Udieresis", + "\uF7FC", "Udieresissmall", + "\u00D9", "Ugrave", + "\uF7F9", "Ugravesmall", + "\u01AF", "Uhorn", + "\u0170", "Uhungarumlaut", + "\u016A", "Umacron", + "\u0172", "Uogonek", + "\u03A5", "Upsilon", + "\u03D2", "Upsilon1", + "\u03AB", "Upsilondieresis", + "\u038E", "Upsilontonos", + "\u016E", "Uring", + "\uF775", "Usmall", + "\u0168", "Utilde", + "\u0056", "V", + "\uF776", "Vsmall", + "\u0057", "W", + "\u1E82", "Wacute", + "\u0174", "Wcircumflex", + "\u1E84", "Wdieresis", + "\u1E80", "Wgrave", + "\uF777", "Wsmall", + "\u0058", "X", + "\u039E", "Xi", + "\uF778", "Xsmall", + "\u0059", "Y", + "\u00DD", "Yacute", + "\uF7FD", "Yacutesmall", + "\u0176", "Ycircumflex", + "\u0178", "Ydieresis", + "\uF7FF", "Ydieresissmall", + "\u1EF2", "Ygrave", + "\uF779", "Ysmall", + "\u005A", "Z", + "\u0179", "Zacute", + "\u017D", "Zcaron", + "\uF6FF", "Zcaronsmall", + "\u017B", "Zdotaccent", + "\u0396", "Zeta", + "\uF77A", "Zsmall", + "\u0061", "a", + "\u00E1", "aacute", + "\u0103", "abreve", + "\u00E2", "acircumflex", + "\u00B4", "acute", + "\u0301", "acutecomb", + "\u00E4", "adieresis", + "\u00E6", "ae", + "\u01FD", "aeacute", + "\u2015", "afii00208", + "\u0410", "afii10017", + "\u0411", "afii10018", + "\u0412", "afii10019", + "\u0413", "afii10020", + "\u0414", "afii10021", + "\u0415", "afii10022", + "\u0401", "afii10023", + "\u0416", "afii10024", + "\u0417", "afii10025", + "\u0418", "afii10026", + "\u0419", "afii10027", + "\u041A", "afii10028", + "\u041B", "afii10029", + "\u041C", "afii10030", + "\u041D", "afii10031", + "\u041E", "afii10032", + "\u041F", "afii10033", + "\u0420", "afii10034", + "\u0421", "afii10035", + "\u0422", "afii10036", + "\u0423", "afii10037", + "\u0424", "afii10038", + "\u0425", "afii10039", + "\u0426", "afii10040", + "\u0427", "afii10041", + "\u0428", "afii10042", + "\u0429", "afii10043", + "\u042A", "afii10044", + "\u042B", "afii10045", + "\u042C", "afii10046", + "\u042D", "afii10047", + "\u042E", "afii10048", + "\u042F", "afii10049", + "\u0490", "afii10050", + "\u0402", "afii10051", + "\u0403", "afii10052", + "\u0404", "afii10053", + "\u0405", "afii10054", + "\u0406", "afii10055", + "\u0407", "afii10056", + "\u0408", "afii10057", + "\u0409", "afii10058", + "\u040A", "afii10059", + "\u040B", "afii10060", + "\u040C", "afii10061", + "\u040E", "afii10062", + "\uF6C4", "afii10063", + "\uF6C5", "afii10064", + "\u0430", "afii10065", + "\u0431", "afii10066", + "\u0432", "afii10067", + "\u0433", "afii10068", + "\u0434", "afii10069", + "\u0435", "afii10070", + "\u0451", "afii10071", + "\u0436", "afii10072", + "\u0437", "afii10073", + "\u0438", "afii10074", + "\u0439", "afii10075", + "\u043A", "afii10076", + "\u043B", "afii10077", + "\u043C", "afii10078", + "\u043D", "afii10079", + "\u043E", "afii10080", + "\u043F", "afii10081", + "\u0440", "afii10082", + "\u0441", "afii10083", + "\u0442", "afii10084", + "\u0443", "afii10085", + "\u0444", "afii10086", + "\u0445", "afii10087", + "\u0446", "afii10088", + "\u0447", "afii10089", + "\u0448", "afii10090", + "\u0449", "afii10091", + "\u044A", "afii10092", + "\u044B", "afii10093", + "\u044C", "afii10094", + "\u044D", "afii10095", + "\u044E", "afii10096", + "\u044F", "afii10097", + "\u0491", "afii10098", + "\u0452", "afii10099", + "\u0453", "afii10100", + "\u0454", "afii10101", + "\u0455", "afii10102", + "\u0456", "afii10103", + "\u0457", "afii10104", + "\u0458", "afii10105", + "\u0459", "afii10106", + "\u045A", "afii10107", + "\u045B", "afii10108", + "\u045C", "afii10109", + "\u045E", "afii10110", + "\u040F", "afii10145", + "\u0462", "afii10146", + "\u0472", "afii10147", + "\u0474", "afii10148", + "\uF6C6", "afii10192", + "\u045F", "afii10193", + "\u0463", "afii10194", + "\u0473", "afii10195", + "\u0475", "afii10196", + "\uF6C7", "afii10831", + "\uF6C8", "afii10832", + "\u04D9", "afii10846", + "\u200E", "afii299", + "\u200F", "afii300", + "\u200D", "afii301", + "\u066A", "afii57381", + "\u060C", "afii57388", + "\u0660", "afii57392", + "\u0661", "afii57393", + "\u0662", "afii57394", + "\u0663", "afii57395", + "\u0664", "afii57396", + "\u0665", "afii57397", + "\u0666", "afii57398", + "\u0667", "afii57399", + "\u0668", "afii57400", + "\u0669", "afii57401", + "\u061B", "afii57403", + "\u061F", "afii57407", + "\u0621", "afii57409", + "\u0622", "afii57410", + "\u0623", "afii57411", + "\u0624", "afii57412", + "\u0625", "afii57413", + "\u0626", "afii57414", + "\u0627", "afii57415", + "\u0628", "afii57416", + "\u0629", "afii57417", + "\u062A", "afii57418", + "\u062B", "afii57419", + "\u062C", "afii57420", + "\u062D", "afii57421", + "\u062E", "afii57422", + "\u062F", "afii57423", + "\u0630", "afii57424", + "\u0631", "afii57425", + "\u0632", "afii57426", + "\u0633", "afii57427", + "\u0634", "afii57428", + "\u0635", "afii57429", + "\u0636", "afii57430", + "\u0637", "afii57431", + "\u0638", "afii57432", + "\u0639", "afii57433", + "\u063A", "afii57434", + "\u0640", "afii57440", + "\u0641", "afii57441", + "\u0642", "afii57442", + "\u0643", "afii57443", + "\u0644", "afii57444", + "\u0645", "afii57445", + "\u0646", "afii57446", + "\u0648", "afii57448", + "\u0649", "afii57449", + "\u064A", "afii57450", + "\u064B", "afii57451", + "\u064C", "afii57452", + "\u064D", "afii57453", + "\u064E", "afii57454", + "\u064F", "afii57455", + "\u0650", "afii57456", + "\u0651", "afii57457", + "\u0652", "afii57458", + "\u0647", "afii57470", + "\u06A4", "afii57505", + "\u067E", "afii57506", + "\u0686", "afii57507", + "\u0698", "afii57508", + "\u06AF", "afii57509", + "\u0679", "afii57511", + "\u0688", "afii57512", + "\u0691", "afii57513", + "\u06BA", "afii57514", + "\u06D2", "afii57519", + "\u06D5", "afii57534", + "\u20AA", "afii57636", + "\u05BE", "afii57645", + "\u05C3", "afii57658", + "\u05D0", "afii57664", + "\u05D1", "afii57665", + "\u05D2", "afii57666", + "\u05D3", "afii57667", + "\u05D4", "afii57668", + "\u05D5", "afii57669", + "\u05D6", "afii57670", + "\u05D7", "afii57671", + "\u05D8", "afii57672", + "\u05D9", "afii57673", + "\u05DA", "afii57674", + "\u05DB", "afii57675", + "\u05DC", "afii57676", + "\u05DD", "afii57677", + "\u05DE", "afii57678", + "\u05DF", "afii57679", + "\u05E0", "afii57680", + "\u05E1", "afii57681", + "\u05E2", "afii57682", + "\u05E3", "afii57683", + "\u05E4", "afii57684", + "\u05E5", "afii57685", + "\u05E6", "afii57686", + "\u05E7", "afii57687", + "\u05E8", "afii57688", + "\u05E9", "afii57689", + "\u05EA", "afii57690", + "\uFB2A", "afii57694", + "\uFB2B", "afii57695", + "\uFB4B", "afii57700", + "\uFB1F", "afii57705", + "\u05F0", "afii57716", + "\u05F1", "afii57717", + "\u05F2", "afii57718", + "\uFB35", "afii57723", + "\u05B4", "afii57793", + "\u05B5", "afii57794", + "\u05B6", "afii57795", + "\u05BB", "afii57796", + "\u05B8", "afii57797", + "\u05B7", "afii57798", + "\u05B0", "afii57799", + "\u05B2", "afii57800", + "\u05B1", "afii57801", + "\u05B3", "afii57802", + "\u05C2", "afii57803", + "\u05C1", "afii57804", + "\u05B9", "afii57806", + "\u05BC", "afii57807", + "\u05BD", "afii57839", + "\u05BF", "afii57841", + "\u05C0", "afii57842", + "\u02BC", "afii57929", + "\u2105", "afii61248", + "\u2113", "afii61289", + "\u2116", "afii61352", + "\u202C", "afii61573", + "\u202D", "afii61574", + "\u202E", "afii61575", + "\u200C", "afii61664", + "\u066D", "afii63167", + "\u02BD", "afii64937", + "\u00E0", "agrave", + "\u2135", "aleph", + "\u03B1", "alpha", + "\u03AC", "alphatonos", + "\u0101", "amacron", + "\u0026", "ampersand", + "\uF726", "ampersandsmall", + "\u2220", "angle", + "\u2329", "angleleft", + "\u232A", "angleright", + "\u0387", "anoteleia", + "\u0105", "aogonek", + "\u2248", "approxequal", + "\u00E5", "aring", + "\u01FB", "aringacute", + "\u2194", "arrowboth", + "\u21D4", "arrowdblboth", + "\u21D3", "arrowdbldown", + "\u21D0", "arrowdblleft", + "\u21D2", "arrowdblright", + "\u21D1", "arrowdblup", + "\u2193", "arrowdown", + "\uF8E7", "arrowhorizex", + "\u2190", "arrowleft", + "\u2192", "arrowright", + "\u2191", "arrowup", + "\u2195", "arrowupdn", + "\u21A8", "arrowupdnbse", + "\uF8E6", "arrowvertex", + "\u005E", "asciicircum", + "\u007E", "asciitilde", + "\u002A", "asterisk", + "\u2217", "asteriskmath", + "\uF6E9", "asuperior", + "\u0040", "at", + "\u00E3", "atilde", + "\u0062", "b", + //"\u005C", "backslash", + "\\", "backslash", + "\u007C", "bar", + "\u03B2", "beta", + "\u2588", "block", + "\uF8F4", "braceex", + "\u007B", "braceleft", + "\uF8F3", "braceleftbt", + "\uF8F2", "braceleftmid", + "\uF8F1", "bracelefttp", + "\u007D", "braceright", + "\uF8FE", "bracerightbt", + "\uF8FD", "bracerightmid", + "\uF8FC", "bracerighttp", + "\u005B", "bracketleft", + "\uF8F0", "bracketleftbt", + "\uF8EF", "bracketleftex", + "\uF8EE", "bracketlefttp", + "\u005D", "bracketright", + "\uF8FB", "bracketrightbt", + "\uF8FA", "bracketrightex", + "\uF8F9", "bracketrighttp", + "\u02D8", "breve", + "\u00A6", "brokenbar", + "\uF6EA", "bsuperior", + "\u2022", "bullet", + "\u0063", "c", + "\u0107", "cacute", + "\u02C7", "caron", + "\u21B5", "carriagereturn", + "\u010D", "ccaron", + "\u00E7", "ccedilla", + "\u0109", "ccircumflex", + "\u010B", "cdotaccent", + "\u00B8", "cedilla", + "\u00A2", "cent", + "\uF6DF", "centinferior", + "\uF7A2", "centoldstyle", + "\uF6E0", "centsuperior", + "\u03C7", "chi", + "\u25CB", "circle", + "\u2297", "circlemultiply", + "\u2295", "circleplus", + "\u02C6", "circumflex", + "\u2663", "club", + "\u003A", "colon", + "\u20A1", "colonmonetary", + "\u002C", "comma", + "\uF6C3", "commaaccent", + "\uF6E1", "commainferior", + "\uF6E2", "commasuperior", + "\u2245", "congruent", + "\u00A9", "copyright", + "\uF8E9", "copyrightsans", + "\uF6D9", "copyrightserif", + "\u00A4", "currency", + "\uF6D1", "cyrBreve", + "\uF6D2", "cyrFlex", + "\uF6D4", "cyrbreve", + "\uF6D5", "cyrflex", + "\u0064", "d", + "\u2020", "dagger", + "\u2021", "daggerdbl", + "\uF6D3", "dblGrave", + "\uF6D6", "dblgrave", + "\u010F", "dcaron", + "\u0111", "dcroat", + "\u00B0", "degree", + "\u03B4", "delta", + "\u2666", "diamond", + "\u00A8", "dieresis", + "\uF6D7", "dieresisacute", + "\uF6D8", "dieresisgrave", + "\u0385", "dieresistonos", + "\u00F7", "divide", + "\u2593", "dkshade", + "\u2584", "dnblock", + "\u0024", "dollar", + "\uF6E3", "dollarinferior", + "\uF724", "dollaroldstyle", + "\uF6E4", "dollarsuperior", + "\u20AB", "dong", + "\u02D9", "dotaccent", + "\u0323", "dotbelowcomb", + "\u0131", "dotlessi", + "\uF6BE", "dotlessj", + "\u22C5", "dotmath", + "\uF6EB", "dsuperior", + "\u0065", "e", + "\u00E9", "eacute", + "\u0115", "ebreve", + "\u011B", "ecaron", + "\u00EA", "ecircumflex", + "\u00EB", "edieresis", + "\u0117", "edotaccent", + "\u00E8", "egrave", + "\u0038", "eight", + "\u2088", "eightinferior", + "\uF738", "eightoldstyle", + "\u2078", "eightsuperior", + "\u2208", "element", + "\u2026", "ellipsis", + "\u0113", "emacron", + "\u2014", "emdash", + "\u2205", "emptyset", + "\u2013", "endash", + "\u014B", "eng", + "\u0119", "eogonek", + "\u03B5", "epsilon", + "\u03AD", "epsilontonos", + "\u003D", "equal", + "\u2261", "equivalence", + "\u212E", "estimated", + "\uF6EC", "esuperior", + "\u03B7", "eta", + "\u03AE", "etatonos", + "\u00F0", "eth", + "\u0021", "exclam", + "\u203C", "exclamdbl", + "\u00A1", "exclamdown", + "\uF7A1", "exclamdownsmall", + "\uF721", "exclamsmall", + "\u2203", "existential", + "\u0066", "f", + "\u2640", "female", + "\uFB00", "ff", + "\uFB03", "ffi", + "\uFB04", "ffl", + "\uFB01", "fi", + "\u2012", "figuredash", + "\u25A0", "filledbox", + "\u25AC", "filledrect", + "\u0035", "five", + "\u215D", "fiveeighths", + "\u2085", "fiveinferior", + "\uF735", "fiveoldstyle", + "\u2075", "fivesuperior", + "\uFB02", "fl", + "\u0192", "florin", + "\u0034", "four", + "\u2084", "fourinferior", + "\uF734", "fouroldstyle", + "\u2074", "foursuperior", + "\u2044", "fraction", + "\u2215", "fraction", + "\u20A3", "franc", + "\u0067", "g", + "\u03B3", "gamma", + "\u011F", "gbreve", + "\u01E7", "gcaron", + "\u011D", "gcircumflex", + "\u0123", "gcommaaccent", + "\u0121", "gdotaccent", + "\u00DF", "germandbls", + "\u2207", "gradient", + "\u0060", "grave", + "\u0300", "gravecomb", + "\u003E", "greater", + "\u2265", "greaterequal", + "\u00AB", "guillemotleft", + "\u00BB", "guillemotright", + "\u2039", "guilsinglleft", + "\u203A", "guilsinglright", + "\u0068", "h", + "\u0127", "hbar", + "\u0125", "hcircumflex", + "\u2665", "heart", + "\u0309", "hookabovecomb", + "\u2302", "house", + "\u02DD", "hungarumlaut", + "\u002D", "hyphen", + "\u00AD", "hyphen", + "\uF6E5", "hypheninferior", + "\uF6E6", "hyphensuperior", + "\u0069", "i", + "\u00ED", "iacute", + "\u012D", "ibreve", + "\u00EE", "icircumflex", + "\u00EF", "idieresis", + "\u00EC", "igrave", + "\u0133", "ij", + "\u012B", "imacron", + "\u221E", "infinity", + "\u222B", "integral", + "\u2321", "integralbt", + "\uF8F5", "integralex", + "\u2320", "integraltp", + "\u2229", "intersection", + "\u25D8", "invbullet", + "\u25D9", "invcircle", + "\u263B", "invsmileface", + "\u012F", "iogonek", + "\u03B9", "iota", + "\u03CA", "iotadieresis", + "\u0390", "iotadieresistonos", + "\u03AF", "iotatonos", + "\uF6ED", "isuperior", + "\u0129", "itilde", + "\u006A", "j", + "\u0135", "jcircumflex", + "\u006B", "k", + "\u03BA", "kappa", + "\u0137", "kcommaaccent", + "\u0138", "kgreenlandic", + "\u006C", "l", + "\u013A", "lacute", + "\u03BB", "lambda", + "\u013E", "lcaron", + "\u013C", "lcommaaccent", + "\u0140", "ldot", + "\u003C", "less", + "\u2264", "lessequal", + "\u258C", "lfblock", + "\u20A4", "lira", + "\uF6C0", "ll", + "\u2227", "logicaland", + "\u00AC", "logicalnot", + "\u2228", "logicalor", + "\u017F", "longs", + "\u25CA", "lozenge", + "\u0142", "lslash", + "\uF6EE", "lsuperior", + "\u2591", "ltshade", + "\u006D", "m", + "\u00AF", "macron", + "\u02C9", "macron", + "\u2642", "male", + "\u2212", "minus", + "\u2032", "minute", + "\uF6EF", "msuperior", + "\u00B5", "mu", + "\u03BC", "mu", + "\u00D7", "multiply", + "\u266A", "musicalnote", + "\u266B", "musicalnotedbl", + "\u006E", "n", + "\u0144", "nacute", + "\u0149", "napostrophe", + "\u0148", "ncaron", + "\u0146", "ncommaaccent", + "\u0039", "nine", + "\u2089", "nineinferior", + "\uF739", "nineoldstyle", + "\u2079", "ninesuperior", + "\u2209", "notelement", + "\u2260", "notequal", + "\u2284", "notsubset", + "\u207F", "nsuperior", + "\u00F1", "ntilde", + "\u03BD", "nu", + "\u0023", "numbersign", + "\u006F", "o", + "\u00F3", "oacute", + "\u014F", "obreve", + "\u00F4", "ocircumflex", + "\u00F6", "odieresis", + "\u0153", "oe", + "\u02DB", "ogonek", + "\u00F2", "ograve", + "\u01A1", "ohorn", + "\u0151", "ohungarumlaut", + "\u014D", "omacron", + "\u03C9", "omega", + "\u03D6", "omega1", + "\u03CE", "omegatonos", + "\u03BF", "omicron", + "\u03CC", "omicrontonos", + "\u0031", "one", + "\u2024", "onedotenleader", + "\u215B", "oneeighth", + "\uF6DC", "onefitted", + "\u00BD", "onehalf", + "\u2081", "oneinferior", + "\uF731", "oneoldstyle", + "\u00BC", "onequarter", + "\u00B9", "onesuperior", + "\u2153", "onethird", + "\u25E6", "openbullet", + "\u00AA", "ordfeminine", + "\u00BA", "ordmasculine", + "\u221F", "orthogonal", + "\u00F8", "oslash", + "\u01FF", "oslashacute", + "\uF6F0", "osuperior", + "\u00F5", "otilde", + "\u0070", "p", + "\u00B6", "paragraph", + "\u0028", "parenleft", + "\uF8ED", "parenleftbt", + "\uF8EC", "parenleftex", + "\u208D", "parenleftinferior", + "\u207D", "parenleftsuperior", + "\uF8EB", "parenlefttp", + "\u0029", "parenright", + "\uF8F8", "parenrightbt", + "\uF8F7", "parenrightex", + "\u208E", "parenrightinferior", + "\u207E", "parenrightsuperior", + "\uF8F6", "parenrighttp", + "\u2202", "partialdiff", + "\u0025", "percent", + "\u002E", "period", + "\u00B7", "periodcentered", + "\u2219", "periodcentered", + "\uF6E7", "periodinferior", + "\uF6E8", "periodsuperior", + "\u22A5", "perpendicular", + "\u2030", "perthousand", + "\u20A7", "peseta", + "\u03C6", "phi", + "\u03D5", "phi1", + "\u03C0", "pi", + "\u002B", "plus", + "\u00B1", "plusminus", + "\u211E", "prescription", + "\u220F", "product", + "\u2282", "propersubset", + "\u2283", "propersuperset", + "\u221D", "proportional", + "\u03C8", "psi", + "\u0071", "q", + "\u003F", "question", + "\u00BF", "questiondown", + "\uF7BF", "questiondownsmall", + "\uF73F", "questionsmall", + "\"", "quotedbl", +// "\u0022", "quotedbl", + "\u201E", "quotedblbase", + "\u201C", "quotedblleft", + "\u201D", "quotedblright", + "\u2018", "quoteleft", + "\u201B", "quotereversed", + "\u2019", "quoteright", + "\u201A", "quotesinglbase", + "\u0027", "quotesingle", + "\u0072", "r", + "\u0155", "racute", + "\u221A", "radical", + "\uF8E5", "radicalex", + "\u0159", "rcaron", + "\u0157", "rcommaaccent", + "\u2286", "reflexsubset", + "\u2287", "reflexsuperset", + "\u00AE", "registered", + "\uF8E8", "registersans", + "\uF6DA", "registerserif", + "\u2310", "revlogicalnot", + "\u03C1", "rho", + "\u02DA", "ring", + "\uF6F1", "rsuperior", + "\u2590", "rtblock", + "\uF6DD", "rupiah", + "\u0073", "s", + "\u015B", "sacute", + "\u0161", "scaron", + "\u015F", "scedilla", + "\uF6C2", "scedilla", + "\u015D", "scircumflex", + "\u0219", "scommaaccent", + "\u2033", "second", + "\u00A7", "section", + "\u003B", "semicolon", + "\u0037", "seven", + "\u215E", "seveneighths", + "\u2087", "seveninferior", + "\uF737", "sevenoldstyle", + "\u2077", "sevensuperior", + "\u2592", "shade", + "\u03C3", "sigma", + "\u03C2", "sigma1", + "\u223C", "similar", + "\u0036", "six", + "\u2086", "sixinferior", + "\uF736", "sixoldstyle", + "\u2076", "sixsuperior", + "\u002F", "slash", + "\u263A", "smileface", + "\u0020", "space", + "\u00A0", "space", + "\u2660", "spade", + "\uF6F2", "ssuperior", + "\u00A3", "sterling", + "\u220B", "suchthat", + "\u2211", "summation", + "\u263C", "sun", + "\u0074", "t", + "\u03C4", "tau", + "\u0167", "tbar", + "\u0165", "tcaron", + "\u0163", "tcommaaccent", + "\u021B", "tcommaaccent", + "\u2234", "therefore", + "\u03B8", "theta", + "\u03D1", "theta1", + "\u00FE", "thorn", + "\u0033", "three", + "\u215C", "threeeighths", + "\u2083", "threeinferior", + "\uF733", "threeoldstyle", + "\u00BE", "threequarters", + "\uF6DE", "threequartersemdash", + "\u00B3", "threesuperior", + "\u02DC", "tilde", + "\u0303", "tildecomb", + "\u0384", "tonos", + "\u2122", "trademark", + "\uF8EA", "trademarksans", + "\uF6DB", "trademarkserif", + "\u25BC", "triagdn", + "\u25C4", "triaglf", + "\u25BA", "triagrt", + "\u25B2", "triagup", + "\uF6F3", "tsuperior", + "\u0032", "two", + "\u2025", "twodotenleader", + "\u2082", "twoinferior", + "\uF732", "twooldstyle", + "\u00B2", "twosuperior", + "\u2154", "twothirds", + "\u0075", "u", + "\u00FA", "uacute", + "\u016D", "ubreve", + "\u00FB", "ucircumflex", + "\u00FC", "udieresis", + "\u00F9", "ugrave", + "\u01B0", "uhorn", + "\u0171", "uhungarumlaut", + "\u016B", "umacron", + "\u005F", "underscore", + "\u2017", "underscoredbl", + "\u222A", "union", + "\u2200", "universal", + "\u0173", "uogonek", + "\u2580", "upblock", + "\u03C5", "upsilon", + "\u03CB", "upsilondieresis", + "\u03B0", "upsilondieresistonos", + "\u03CD", "upsilontonos", + "\u016F", "uring", + "\u0169", "utilde", + "\u0076", "v", + "\u0077", "w", + "\u1E83", "wacute", + "\u0175", "wcircumflex", + "\u1E85", "wdieresis", + "\u2118", "weierstrass", + "\u1E81", "wgrave", + "\u0078", "x", + "\u03BE", "xi", + "\u0079", "y", + "\u00FD", "yacute", + "\u0177", "ycircumflex", + "\u00FF", "ydieresis", + "\u00A5", "yen", + "\u1EF3", "ygrave", + "\u007A", "z", + "\u017A", "zacute", + "\u017E", "zcaron", + "\u017C", "zdotaccent", + "\u0030", "zero", + "\u2080", "zeroinferior", + "\uF730", "zerooldstyle", + "\u2070", "zerosuperior", + "\u03B6", "zeta"}; + + /** Return the glyphname from a string, + eg, glyphToString("\\") returns "backslash" + */ + public static String glyphToString(String name) { + String ret=""; + int i=unicode_glyphs.length; + for (int j=0; j<i; j+=2) { + if (unicode_glyphs[j+1].equals(name)) { + ret=unicode_glyphs[j]; + j=i; + } + } + return ret; + } + /** Return the string representation of a glyphname, + eg stringToGlyph("backslash") returns "\\" + */ + public static String stringToGlyph(String name) { + String ret=""; + int i=unicode_glyphs.length; + for (int j=0; j<i; j+=2) { + if (unicode_glyphs[j].equals(name)) { + ret=unicode_glyphs[j+1]; + j=i; + } + } + return ret; + } +} + diff --git a/src/org/apache/fop/fonts/PFMFile.java b/src/org/apache/fop/fonts/PFMFile.java index 8ab72dee1..5ebb011cc 100644 --- a/src/org/apache/fop/fonts/PFMFile.java +++ b/src/org/apache/fop/fonts/PFMFile.java @@ -51,6 +51,7 @@ package org.apache.fop.fonts; import java.io.*; +import java.util.Hashtable; /** * This class represents a PFM file (or parts of it) as a Java object. @@ -84,7 +85,9 @@ public class PFMFile { //Extent table private int[] extentTable; + private Hashtable kerningTab; public PFMFile() { + kerningTab=new Hashtable(); } /** @@ -146,8 +149,17 @@ public class PFMFile { int size = inStream.readShort(); long extMetricsOffset = inStream.readInt(); long extentTableOffset = inStream.readInt(); - inStream.skip(12); + inStream.skip(4); + long kernPairOffset = inStream.readInt(); + long kernTrackOffset = inStream.readInt(); long driverInfoOffset = inStream.readInt(); + + if (kernPairOffset > 0) { + inStream.reset(); + inStream.skip(kernPairOffset); + loadKernPairs(inStream); + } + inStream.reset(); inStream.skip(driverInfoOffset); postscriptName = inStream.readString(); @@ -166,6 +178,40 @@ public class PFMFile { } /** + * Parses the kernPairs part of the pfm file + * + * @param inStream The stream from which to read the PFM file. + */ + private void loadKernPairs(PFMInputStream inStream) throws IOException { + int i = inStream.readShort(); + + + System.out.println(i + " kerning pairs"); + while (i > 0) { + int g1 = (int)inStream.readByte(); + i--; + //System.out.print ("Char no: ("+g1+", "); + + int g2 = (int)inStream.readByte(); + //System.out.print (g2+") kern"); + + int adj = inStream.readShort(); + if (adj > 0x8000) + adj=-(0x10000-adj); + //System.out.println (": " + adj); + + String glyph1=Glyphs.tex8r[g1]; + String glyph2=Glyphs.tex8r[g2]; + + Hashtable adjTab=(Hashtable)kerningTab.get(glyph1); + if (adjTab==null) + adjTab=new Hashtable(); + adjTab.put(glyph2, new Integer(adj)); + kerningTab.put(glyph1, adjTab); + } + } + + /** * Parses the extended metrics part of the PFM file. * * @param inStream The stream from which to read the PFM file. @@ -204,6 +250,15 @@ public class PFMFile { return windowsName; } + /** + * Return the kerning table. The kerning table is a hastable with + * strings with glyphnames as keys, containing hashtables as value. + * The value hashtable contain a glyph name string key and an Integer value + */ + public Hashtable getKerning() { + return kerningTab; + } + /** * Returns the Postscript name of the font. * @@ -378,4 +433,4 @@ public class PFMFile { public int getCharWidth(short which) { return extentTable[which-dfFirstChar]; } -}
\ No newline at end of file +} diff --git a/src/org/apache/fop/fonts/TTFCmapEntry.java b/src/org/apache/fop/fonts/TTFCmapEntry.java new file mode 100644 index 000000000..af1eb5c00 --- /dev/null +++ b/src/org/apache/fop/fonts/TTFCmapEntry.java @@ -0,0 +1,60 @@ +/* -- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fonts; + +class TTFCmapEntry { + int platform_id; + int encoding_id; + long offset; + + TTFCmapEntry() { + } +} diff --git a/src/org/apache/fop/fonts/TTFDirTabEntry.java b/src/org/apache/fop/fonts/TTFDirTabEntry.java new file mode 100644 index 000000000..42fed9f3a --- /dev/null +++ b/src/org/apache/fop/fonts/TTFDirTabEntry.java @@ -0,0 +1,85 @@ +/* -- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fonts; +import java.io.*; + +class TTFDirTabEntry { + byte[] tag; + int checksum; + long offset; + long length; + + TTFDirTabEntry() { + tag = new byte[4]; + } + + /** Read Dir Tab, return tag name */ + public String read(FontFileReader in) throws IOException { + tag[0]=in.readTTFByte(); + tag[1]=in.readTTFByte(); + tag[2]=in.readTTFByte(); + tag[3]=in.readTTFByte(); + + in.skip(4); // Skip checksum + + offset=in.readTTFULong(); + length=in.readTTFULong(); + + System.out.println ("Read dir tab [" + tag[0]+ + " "+tag[1] + + " "+tag[2] + + " "+tag[3] + + "] offset: " + offset + + " length: " + length + + " name: " + new String(tag)); + return new String(tag, "ISO-8859-1"); + } +} diff --git a/src/org/apache/fop/fonts/TTFFile.java b/src/org/apache/fop/fonts/TTFFile.java new file mode 100644 index 000000000..06987e77a --- /dev/null +++ b/src/org/apache/fop/fonts/TTFFile.java @@ -0,0 +1,528 @@ +/* -- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fonts; +import java.io.*; +import java.util.Hashtable; + +public class TTFFile { + static final byte NTABS = 24; + static final int NMACGLYPHS = 258; + static final int MAX_CHAR_CODE = 255; + static final int ENC_BUF_SIZE = 1024; + + boolean is_embeddable=true; + boolean hasSerifs=true; + Hashtable dirTabs; + Hashtable kerningTab; + + /** Position inputstream to position indicated + in the dirtab offset + offset */ + void seek_tab(FontFileReader in, String name, long offset) + throws IOException { + TTFDirTabEntry dt=(TTFDirTabEntry)dirTabs.get(name); + if (dt==null) { + System.out.println("Dirtab " + name + " not found."); + return; + } + + in.seek_set(dt.offset+offset); + } + + int get_ttf_funit(int n) { + int ret; + if (n < 0) { + long rest1=n % upem; + long storrest=1000*rest1; + long ledd2=rest1/storrest; + ret = -((-1000*n)/upem - (int)ledd2); + } else { + ret = (n/upem)*1000 + ((n % upem)*1000)/upem; + } + + return ret; + } + + int upem; + int ntabs; + int nhmtx; + int post_format; + int loca_format; + int nglyphs; + int nmglyphs; + int names_count; + + + + TTFDirTabEntry dir_tab; + TTFMtxEntry mtx_tab[]; + int[] mtx_encoded=null; + boolean reencoded=false; + String enc_names; + + String fontName=""; + String fullName=""; + String notice=""; + String familyName=""; + String subFamilyName=""; + + long italicAngle = 0; + long isFixedPitch = 0; + int fontBBox1 = 0; + int fontBBox2 = 0; + int fontBBox3 = 0; + int fontBBox4 = 0; + int capHeight = 0; + int underlinePosition = 0; + int underlineThickness = 0; + int xHeight = 0; + int ascender = 0; + int descender = 0; + + public void readFont(FontFileReader in) throws IOException { + int i, j, k, l, platform_id, encoding_id, language_id; + long n; + TTFDirTabEntry[] pd; + TTFMtxEntry[] pm; + String[] ps_glyphs_buf; + + in.skip(4); // TTF_FIXED_SIZE + ntabs=in.readTTFUShort(); + in.skip(6); // 3xTTF_USHORT_SIZE; + + // Read Dir tabs + dirTabs=new Hashtable(); + pd=new TTFDirTabEntry[ntabs]; + //System.out.println("Reading " + ntabs + " dir tables"); + for (i=0; i < ntabs; i++) { + pd[i]=new TTFDirTabEntry(); + dirTabs.put(pd[i].read(in), + pd[i]); + } + + seek_tab(in, "head", 2*4 + 2*4 + 2); + upem=in.readTTFUShort(); + + in.skip(16); + + fontBBox1=in.readTTFShort(); + fontBBox2=in.readTTFShort(); + fontBBox3=in.readTTFShort(); + fontBBox4=in.readTTFShort(); + + in.skip(2+2+2); + + loca_format=in.readTTFShort(); + + seek_tab(in, "maxp", 4); + nglyphs=in.readTTFUShort(); + //System.out.println("nglyphs= " + nglyphs); + mtx_tab=new TTFMtxEntry[nglyphs]; + + for (i=0; i < nglyphs; i++) + mtx_tab[i]=new TTFMtxEntry(); + + seek_tab(in, "hhea", 4); + ascender=in.readTTFShort(); // Use sTypoAscender in "OS/2" table? + descender=in.readTTFShort(); // Use sTypoDescender in "OS/2" table? + + in.skip(2+2+3*2+8*2); + nhmtx=in.readTTFUShort(); + //System.out.println("nhmtx: " + nhmtx); + seek_tab(in, "hmtx", 0); + for (i=0; i < nhmtx; i++) { + mtx_tab[i].wx=in.readTTFUShort(); + in.skip(2); + } + // NB: Her skal det settes mer wx. + + seek_tab(in, "post", 0); + post_format=in.readTTFLong(); + italicAngle=in.readTTFULong(); + //System.out.println("Italic angle: " + italicAngle); + underlinePosition=in.readTTFShort(); + underlineThickness=in.readTTFShort(); + isFixedPitch=in.readTTFULong(); + + in.skip(4*4); + + switch (post_format) { + case 0x00010000: + //System.out.println("Postscript format 1"); + for (i=0; i<Glyphs.mac_glyph_names.length; i++) { + mtx_tab[i].name=Glyphs.mac_glyph_names[i]; + } + break; + case 0x00020000: + //System.out.println("Postscript format 2"); + l = in.readTTFUShort(); + for (i=0; i < l ; i++) { + mtx_tab[i].index=in.readTTFUShort(); + } + + TTFDirTabEntry dirTab= + (TTFDirTabEntry)dirTabs.get("post"); + if (dirTab==null) + System.out.println("Can't find table 'post'"); + + n=dirTab.length - (in.getCurrentPos() - dirTab.offset); + ps_glyphs_buf=new String[(int)n]; + int nn=(ps_glyphs_buf.length < nglyphs) ? + ps_glyphs_buf.length : nglyphs; + //System.out.println("Reading " + n + " glyphnames"); + for (i=0; i < nn; i++) { + ps_glyphs_buf[i]=in.readTTFString(in.readTTFUByte()); + } + + for (i=0; i < l; i++) { + if (mtx_tab[i].index < NMACGLYPHS) { + mtx_tab[i].name = Glyphs.mac_glyph_names[mtx_tab[i].index]; + } else { + k = mtx_tab[i].index - NMACGLYPHS ; + mtx_tab[i].name=ps_glyphs_buf[k]; + } + } + + break; + case 0x00030000: + //System.out.println("Postscript format 3 - index"); + break; + default: + //System.out.println("Unknown format : " + post_format); + } + + // Check if font is embeddable + if (dirTabs.get("OS/2") != null) { + seek_tab(in, "OS/2", 2*4); + int fsType=in.readTTFUShort(); + if ((fsType & 2) == 0) + is_embeddable=false; + else + is_embeddable=true; + } else + is_embeddable=true; + + + + seek_tab(in, "loca", 0); + for (i=0; i < nglyphs ; i++) { + mtx_tab[i].offset = (loca_format == 1 ? in.readTTFULong() : + (in.readTTFUShort() << 1)); + } + + TTFDirTabEntry dirTab = + (TTFDirTabEntry)dirTabs.get("glyf"); + for (i=0; i < (nglyphs-1); i++) { + if (mtx_tab[i].offset != mtx_tab[i+1].offset) { + in.seek_set(dirTab.offset + mtx_tab[i].offset); + in.skip(2); + mtx_tab[i].bbox[0]=in.readTTFShort(); + mtx_tab[i].bbox[1]=in.readTTFShort(); + mtx_tab[i].bbox[2]=in.readTTFShort(); + mtx_tab[i].bbox[3]=in.readTTFShort(); + } else { + mtx_tab[i].bbox[0]=mtx_tab[0].bbox[0]; + mtx_tab[i].bbox[1]=mtx_tab[0].bbox[1]; + mtx_tab[i].bbox[2]=mtx_tab[0].bbox[2]; + mtx_tab[i].bbox[3]=mtx_tab[0].bbox[3]; + } + } + + //System.out.println("nglyf="+nglyphs+" mtx="+mtx_tab.length); + + + n=((TTFDirTabEntry)dirTabs.get("glyf")).offset; + for (i=0; i < nglyphs; i++) { + if ((i+1) >= mtx_tab.length || + mtx_tab[i].offset != mtx_tab[i+1].offset) { + in.seek_set(n+mtx_tab[i].offset); + in.skip(2); + mtx_tab[i].bbox[0]=in.readTTFShort(); + mtx_tab[i].bbox[1]=in.readTTFShort(); + mtx_tab[i].bbox[2]=in.readTTFShort(); + mtx_tab[i].bbox[3]=in.readTTFShort(); + } else { + mtx_tab[i].bbox[0]=mtx_tab[0].bbox[0]; + mtx_tab[i].bbox[1]=mtx_tab[0].bbox[0]; + mtx_tab[i].bbox[2]=mtx_tab[0].bbox[0]; + mtx_tab[i].bbox[3]=mtx_tab[0].bbox[0]; + } + //System.out.println(mtx_tab[i].toString(this)); + } + + seek_tab(in, "name", 2); + i = in.getCurrentPos(); + n = in.readTTFUShort(); + j = in.readTTFUShort() + i - 2; + i += 2*2; + + while (n-- > 0) { + in.seek_set(i); + platform_id=in.readTTFUShort(); + encoding_id=in.readTTFUShort(); + language_id=in.readTTFUShort(); + //System.out.println("Platform id: " + language_id); + //System.out.println("Encoding id: " + language_id); + //System.out.println("Language id: " + language_id); + k=in.readTTFUShort(); + l=in.readTTFUShort(); + + if ((platform_id==1 && encoding_id==0) && + (k==1 || k==2 || k==0 || k==4 || k==6)) { + in.seek_set(j+in.readTTFUShort()); + String txt = in.readTTFString(l); + switch (k) { + case 0: notice=txt; break; + case 1: familyName=txt; break; + case 2: subFamilyName=txt;break; + case 4: fullName=txt; break; + case 6: fontName=txt; break; + } + if (!notice.equals("") && !fullName.equals("") && + !fontName.equals("") && !familyName.equals("") && + !subFamilyName.equals("")) + break; + } + i+=6*2; + } + + dirTab= + (TTFDirTabEntry)dirTabs.get("PCLT"); + if (dirTab!=null) { + in.seek_set(dirTab.offset + 4 + 4 + 2); + xHeight=in.readTTFUShort(); + in.skip(2*2); + capHeight=in.readTTFUShort(); + in.skip(2+16+8+6+1+1); + + int serifStyle=in.readTTFUByte(); + serifStyle=serifStyle >> 6; + serifStyle=serifStyle & 3; + if (serifStyle == 1) + hasSerifs=false; + else + hasSerifs=true; + + } else { + // Approximate capHeight from height of "H" + for (i=0; i < mtx_tab.length; i++) { + if ("H".equals(mtx_tab[i].name)) + capHeight=mtx_tab[i].bbox[3]- + mtx_tab[i].bbox[1]; + } + } + + // Read kerning + kerningTab=new Hashtable(); + dirTab= + (TTFDirTabEntry)dirTabs.get("kern"); + if (dirTab!=null) { + seek_tab(in, "kern", 2); + for (n=in.readTTFUShort(); n>0 ; n--) { + in.skip(2*2); + k=in.readTTFUShort(); + if (!((k & 1)!=0) || (k & 2)!=0 || (k & 4)!=0) + return; + if ((k >> 8) !=0) + continue; + + k=in.readTTFUShort(); + in.skip(3 * 2); + while (k-- > 0) { + i=in.readTTFUShort(); + j=in.readTTFUShort(); + int kpx=in.readTTFShort(); + if (kpx != 0) { + Hashtable adjTab=(Hashtable)kerningTab.get(mtx_tab[i].name); + if (adjTab==null) + adjTab=new java.util.Hashtable(); + adjTab.put(mtx_tab[j].name, new Integer((int)get_ttf_funit(kpx))); + kerningTab.put(mtx_tab[i].name, adjTab); + } + } + } + //System.out.println(kerningTab.toString()); + } + } + + + public void printStuff() { + System.out.println("Font name: " + fontName); + System.out.println("Full name: " + fullName); + System.out.println("Family name: " + familyName); + System.out.println("Subfamily name: " + subFamilyName); + System.out.println("Notice: " + notice); + System.out.println("xHeight: " + (int)get_ttf_funit(xHeight)); + System.out.println("capheight: " + (int)get_ttf_funit(capHeight)); + + int italic=(int)(italicAngle>>16); + System.out.println("Italic: " + italic); + System.out.print("ItalicAngle: " + (short)(italicAngle/0x10000)); + if ((italicAngle % 0x10000) > 0 ) + System.out.print("."+(short)((italicAngle % 0x10000)*1000)/0x10000); + System.out.println(); + System.out.println("Ascender: " + get_ttf_funit(ascender)); + System.out.println("Descender: " + get_ttf_funit(descender)); + System.out.println("FontBBox: [" + (int)get_ttf_funit(fontBBox1) + + " " + (int)get_ttf_funit(fontBBox2) + + " " + (int)get_ttf_funit(fontBBox3) + + " " + (int)get_ttf_funit(fontBBox4)+"]"); + } + + public static void main(String[] args) { + try { + TTFFile ttfFile=new TTFFile(); + FontFileReader reader= + new FontFileReader(args[0]); + + ttfFile.readFont(reader); + ttfFile.printStuff(); + + } catch (IOException ioe) { + System.out.println(ioe.toString()); + } + } + + public String getWindowsName() { + return new String(familyName+","+subFamilyName); + } + public String getPostscriptName() { + return fontName; + } + public String getCharSetName() { + return "WinAnsi"; + } + public int getCapHeight() { + return (int)get_ttf_funit(capHeight); + } + public int getXHeight() { + return (int)get_ttf_funit(xHeight); + } + public int getFlags() { + int flags=32; // Use Adobe Standard charset + if (italicAngle != 0) + flags = flags | 64; + if (isFixedPitch != 0) + flags = flags | 2; + if (hasSerifs) + flags = flags | 1; + return flags; + } + public String getStemV() { + return "0"; + } + public String getItalicAngle() { + String ia=Short.toString((short)(italicAngle/0x10000)); + if ((italicAngle % 0x10000) > 0 ) + ia=ia+("."+Short.toString((short)((short)((italicAngle % 0x10000)*1000)/0x10000))); + + return ia; + } + public int[] getFontBBox() { + int[] fbb=new int[4]; + fbb[0]=(int)get_ttf_funit(fontBBox1); + fbb[1]=(int)get_ttf_funit(fontBBox2); + fbb[2]=(int)get_ttf_funit(fontBBox3); + fbb[3]=(int)get_ttf_funit(fontBBox4); + + return fbb; + } + public int getLowerCaseAscent() { + return (int)get_ttf_funit(ascender); + } + public int getLowerCaseDescent() { + return (int)get_ttf_funit(descender); + } + public short getLastChar() { + fixWidth(); + return (short)(nmglyphs-1); + } + public short getFirstChar() { + return 0; + } + + public int getCharWidth(int idx) { + fixWidth(); + + return (int)get_ttf_funit(mtx_encoded[idx]); + } + + public Hashtable getKerning() { + return kerningTab; + } + + public boolean isEmbeddable() { + return is_embeddable; + } + private void fixWidth() { + if (reencoded) + return; + reencoded=true; + //System.out.println("Reencoding widths"); + nmglyphs=0; + mtx_encoded=new int[Glyphs.tex8r.length]; + + Hashtable existingGlyphs=new java.util.Hashtable(); + + for (int i=0; i < mtx_tab.length; i++) + existingGlyphs.put(mtx_tab[i].name, new Integer(mtx_tab[i].wx)); + + + for (int i=0; i < Glyphs.tex8r.length; i++) { + nmglyphs++; + Integer wx=(Integer)existingGlyphs.get(Glyphs.tex8r[i]); + if (wx==null) + mtx_encoded[i]=0; + else + mtx_encoded[i]=wx.intValue(); + } + } +} + diff --git a/src/org/apache/fop/fonts/TTFMtxEntry.java b/src/org/apache/fop/fonts/TTFMtxEntry.java new file mode 100644 index 000000000..c44c2c965 --- /dev/null +++ b/src/org/apache/fop/fonts/TTFMtxEntry.java @@ -0,0 +1,77 @@ +/* -- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fonts; + +import java.io.*; + +class TTFMtxEntry { + int wx; + String name; + int index; + int[] bbox; + long offset; + byte found; + + TTFMtxEntry() { + name=""; + found=0; + bbox=new int[4]; + } + + public String toString(TTFFile t) { + return new String("Glyph "+name+ " index: " + index + + " bbox [ "+t.get_ttf_funit(bbox[0])+ + " " + t.get_ttf_funit(bbox[1]) + + " " + t.get_ttf_funit(bbox[2]) + + " " + t.get_ttf_funit(bbox[3]) + "]" + + "wx: "+t.get_ttf_funit(wx)); + } +} diff --git a/src/org/apache/fop/fonts/TTFSegEntry.java b/src/org/apache/fop/fonts/TTFSegEntry.java new file mode 100644 index 000000000..9c7cbad8c --- /dev/null +++ b/src/org/apache/fop/fonts/TTFSegEntry.java @@ -0,0 +1,61 @@ +/* -- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fonts; + +class TTFSegEntry { + int endCode; + int startCode; + int idDelta; + int idRangeOffset; + + TTFSegEntry() { + } +} diff --git a/src/org/apache/fop/fonts/apps/PFMReader.java b/src/org/apache/fop/fonts/apps/PFMReader.java index fc563d4d4..c7c1410f2 100644 --- a/src/org/apache/fop/fonts/apps/PFMReader.java +++ b/src/org/apache/fop/fonts/apps/PFMReader.java @@ -56,6 +56,9 @@ import org.apache.xerces.dom.*; import org.apache.xml.serialize.*; import org.apache.xalan.xslt.*; import org.apache.fop.fonts.*; +import java.util.Hashtable; +import java.util.Vector; +import java.util.Enumeration; /** * A tool which reads PFM files from Adobe Type 1 fonts and creates @@ -73,37 +76,120 @@ public class PFMReader { public PFMReader() { } + + /** + * Parse commandline arguments. put options in the Hashtable 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) + */ + private static String[] parseArguments(Hashtable options, String[] args) { + Vector arguments=new Vector(); + for (int i=0; i < args.length; i++) { + if (args[i].startsWith("-")) { + i++; + if (i < args.length) + options.put(args[i-1], args[i]); + else + options.put(args[i-1], ""); + } else { + arguments.addElement(args[i]); + } + } + + String[] argStrings=new String[arguments.size()]; + arguments.copyInto(argStrings); + return argStrings; + } + + private final static void displayUsage() { + System.out.println(" java org.apache.fop.fonts.apps.PFMReader [options] metricfile.pfm xmlfile.xml\n"); + System.out.println(" where options can be:\n"); + System.out.println(" -fn <fontname>\n"); + System.out.println(" default is to use the fontname in the .pfm file, but you can override\n"); + System.out.println(" that name to make sure that the embedded font is used instead of installed\n"); + System.out.println(" fonts when viewing documents with Acrobat Reader.\n"); + System.out.println(" -cn <classname>\n"); + System.out.println(" default is to use the fontname\n"); + System.out.println(" -ef <path to the Type1 .pfb fontfile>\n"); + System.out.println(" will add the possibility to embed the font. When running fop, fop will look\n"); + System.out.println(" for this file to embed it\n"); + System.out.println(" -er <path to Type1 fontfile relative to org/apache/fop/render/pdf/fonts>\n"); + System.out.println(" you can also include the fontfile in the fop.jar file when building fop.\n"); + System.out.println(" You can use both -ef and -er. The file specified in -ef will be searched first,\n"); + System.out.println(" then the -er file.\n"); + } + + /** * The main method for the PFM reader tool. * - * @param args Command-line arguments: [pfm-file] {[xml-file]} - * If [xml-file] is not provided, then just a little preview of - * the PFM ist displayed. + * @param args Command-line arguments: [options] metricfile.pfm xmlfile.xml + * where options can be: + * -fn <fontname> + * default is to use the fontname in the .pfm 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 Type1 .pfb fontfile> + * will add the possibility to embed the font. When running fop, fop will look + * for this file to embed it + * -er <path to Type1 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) { - PFMReader app = new PFMReader(); - app.invokedStandalone = true; - - System.out.println("PFM Reader v1.0"); - System.out.println(); - - if (args.length > 0) { - PFMFile pfm = app.loadPFM(args[0]); - if (pfm != null) { - app.preview(pfm); - - if (args.length > 1) { - org.w3c.dom.Document doc = app.constructFontXML(pfm); - doc = app.postProcessXML(doc); - if (doc != null) { - app.writeFontXML(doc, args[1]); - } - } - } - } else { - System.out.println("Arguments: <source> [<target>]"); - System.out.println("Example: COM_____.pfm COM_____.xml"); - } + String embFile=null; + String embResource=null; + String className=null; + String fontName=null; + + Hashtable options=new Hashtable(); + String[] arguments=parseArguments(options, args); + + PFMReader app = new PFMReader(); + app.invokedStandalone = true; + + System.out.println("PFM Reader v1.1"); + System.out.println(); + + 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 { + PFMFile pfm = app.loadPFM(arguments[0]); + if (pfm != null) { + app.preview(pfm); + + org.w3c.dom.Document doc = app.constructFontXML(pfm, + fontName, + className, + embResource, + embFile); + + doc = app.postProcessXML(doc); + if (doc != null) { + app.writeFontXML(doc, arguments[1]); + } + } + } } /** @@ -191,7 +277,9 @@ public class PFMReader { * @param pfm The PFM file to generate the font metrics from. * @return The DOM document representing the font metrics file. */ - public org.w3c.dom.Document constructFontXML(PFMFile pfm) { + public org.w3c.dom.Document constructFontXML(PFMFile pfm, String fontName, + String className, String resource, + String file) { System.out.println("Creating xml font file..."); System.out.println(); @@ -214,8 +302,25 @@ public class PFMReader { el = doc.createElement("class-name"); root.appendChild(el); - el.appendChild(doc.createTextNode(s)); + if (className != null) + el.appendChild(doc.createTextNode(className)); + else + el.appendChild(doc.createTextNode(s)); + el = doc.createElement("embedFile"); + root.appendChild(el); + if (file==null) + el.appendChild(doc.createTextNode("null")); + else + el.appendChild(doc.createTextNode("\""+escapeString(file)+"\"")); + + el = doc.createElement("embedResource"); + root.appendChild(el); + if (resource==null) + el.appendChild(doc.createTextNode("null")); + else + el.appendChild(doc.createTextNode("\""+escapeString(resource)+"\"")); + el = doc.createElement("subtype"); root.appendChild(el); el.appendChild(doc.createTextNode("Type1")); @@ -290,6 +395,25 @@ public class PFMReader { el.setAttribute("width", new Integer(pfm.getCharWidth(i)).toString()); } + + // Get kerning + for (Enumeration enum=pfm.getKerning().keys(); enum.hasMoreElements();) { + String kpx1=(String)enum.nextElement(); + el=doc.createElement("kerning"); + el.setAttribute("kpx1", kpx1); + root.appendChild(el); + Element el2=null; + + Hashtable h2=(Hashtable)pfm.getKerning().get(kpx1); + for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) { + String kpx2=(String)enum2.nextElement(); + el2=doc.createElement("pair"); + el2.setAttribute("kpx2", kpx2); + Integer val=(Integer)h2.get(kpx2); + el2.setAttribute("kern", val.toString()); + el.appendChild(el2); + } + } return doc; } @@ -301,53 +425,41 @@ public class PFMReader { * @return A DOM document representing the processed font metrics file. */ public org.w3c.dom.Document postProcessXML(org.w3c.dom.Document doc) { - try { - + try { + OutputFormat format = new OutputFormat(doc); //Serialize DOM + XMLSerializer serial = new XMLSerializer(System.out, format); + serial.asDOMSerializer(); // As a DOM Serializer + serial.serialize(doc.getDocumentElement()); + System.out.println("Postprocessing..."); System.out.println(); - // Create the 3 objects the XSLTProcessor needs to perform the transformation. - org.apache.xalan.xslt.XSLTInputSource xmlSource = - new org.apache.xalan.xslt.XSLTInputSource(doc); + InputStream xsl = this.getClass().getResourceAsStream(XSL_POSTPROCESS); if (xsl == null) { throw new Exception("Resource " + XSL_POSTPROCESS + " not found"); } - org.apache.xalan.xslt.XSLTInputSource xslSheet = - new org.apache.xalan.xslt.XSLTInputSource(xsl); - + Document targetDoc = new DocumentImpl(); - org.apache.xalan.xslt.XSLTResultTarget xmlResult = - new org.apache.xalan.xslt.XSLTResultTarget(targetDoc); - - // Use XSLTProcessorFactory to instantiate an XSLTProcessor. - org.apache.xalan.xslt.XSLTProcessor processor = - org.apache.xalan.xslt.XSLTProcessorFactory.getProcessor( - new org.apache.xalan.xpath.xdom.XercesLiaison()); - - // Perform the transformation. - processor.process(xmlSource, xslSheet, xmlResult); - + org.apache.fop.tools.xslt.XSLTransform.transform(doc, xsl, targetDoc); + System.out.println("Sorting..."); System.out.println(); // Sort the whole thing - xmlSource.setNode(targetDoc); + xsl = this.getClass().getResourceAsStream(XSL_SORT); if (xsl == null) { throw new Exception("Resource " + XSL_SORT + " not found"); } - xslSheet = new org.apache.xalan.xslt.XSLTInputSource(xsl); + org.w3c.dom.Document targetDocSorted = new DocumentImpl(); - xmlResult = - new org.apache.xalan.xslt.XSLTResultTarget(targetDocSorted); - // Perform the transformation (sort). - processor.process(xmlSource, xslSheet, xmlResult); + org.apache.fop.tools.xslt.XSLTransform.transform(targetDoc, xsl, targetDocSorted); return targetDocSorted; @@ -356,4 +468,18 @@ public class PFMReader { return null; } } + + + private String escapeString(String str) { + StringBuffer esc=new StringBuffer(); + + for (int i=0; i < str.length(); i++) { + if (str.charAt(i)=='\\') + esc.append("\\\\"); + else + esc.append(str.charAt(i)); + } + + return esc.toString(); + } } diff --git a/src/org/apache/fop/fonts/apps/TTFReader.java b/src/org/apache/fop/fonts/apps/TTFReader.java new file mode 100644 index 000000000..f7dbe0bfd --- /dev/null +++ b/src/org/apache/fop/fonts/apps/TTFReader.java @@ -0,0 +1,504 @@ +/* -- $Id$ -- + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999 The Apache Software Foundation. All rights reserved. + + Redistribution and use in source and binary forms, with or without modifica- + tion, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: "This product includes software + developed by the Apache Software Foundation (http://www.apache.org/)." + Alternately, this acknowledgment may appear in the software itself, if + and wherever such third-party acknowledgments normally appear. + + 4. The names "Fop" and "Apache Software Foundation" must not be used to + endorse or promote products derived from this software without prior + written permission. For written permission, please contact + apache@apache.org. + + 5. Products derived from this software may not be called "Apache", nor may + "Apache" appear in their name, without prior written permission of the + Apache Software Foundation. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- + DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + This software consists of voluntary contributions made by many individuals + on behalf of the Apache Software Foundation and was originally created by + James Tauber <jtauber@jtauber.com>. For more information on the Apache + Software Foundation, please see <http://www.apache.org/>. + + */ +package org.apache.fop.fonts.apps; + +import java.io.*; +import org.w3c.dom.*; +import org.apache.xerces.dom.*; +import org.apache.xml.serialize.*; +import org.apache.xalan.xslt.*; +import org.apache.fop.fonts.*; +import java.util.Hashtable; +import java.util.Vector; +import java.util.Enumeration; +/** + * A tool which reads TTF files and generates + * XML font metrics file for use in FOP. + * + */ +public class TTFReader { + + static private final String XSL_POSTPROCESS = "TTFPostProcess.xsl"; + static private final String XSL_SORT = "TTFPostProcessSort.xsl"; + + private boolean invokedStandalone = false; + + public TTFReader() { + } + + + /** + * Parse commandline arguments. put options in the Hashtable 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) + */ + private static String[] parseArguments(Hashtable options, String[] args) { + Vector arguments=new Vector(); + for (int i=0; i < args.length; i++) { + if (args[i].startsWith("-")) { + i++; + if (i < args.length) + options.put(args[i-1], args[i]); + else + options.put(args[i-1], ""); + } else { + arguments.addElement(args[i]); + } + } + + String[] argStrings=new String[arguments.size()]; + arguments.copyInto(argStrings); + return argStrings; + } + + + private final static void displayUsage() { + System.out.println(" java org.apache.fop.fonts.apps.TTFReader [options] fontfile.ttf xmlfile.xml\n"); + System.out.println(" where options can be:\n"); + System.out.println(" -fn <fontname>\n"); + System.out.println(" default is to use the fontname in the .ttf file, but you can override\n"); + System.out.println(" that name to make sure that the embedded font is used instead of installed\n"); + System.out.println(" fonts when viewing documents with Acrobat Reader.\n"); + System.out.println(" -cn <classname>\n"); + System.out.println(" default is to use the fontname\n"); + System.out.println(" -ef <path to the truetype fontfile>\n"); + System.out.println(" will add the possibility to embed the font. When running fop, fop will look\n"); + System.out.println(" for this file to embed it\n"); + System.out.println(" -er <path to truetype fontfile relative to org/apache/fop/render/pdf/fonts>\n"); + System.out.println(" you can also include the fontfile in the fop.jar file when building fop.\n"); + System.out.println(" You can use both -ef and -er. The file specified in -ef will be searched first,\n"); + System.out.println(" then the -er file.\n"); + } + + + /** + * The main method for the PFM reader 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; + + Hashtable options=new Hashtable(); + String[] arguments=parseArguments(options, args); + + TTFReader app = new TTFReader(); + app.invokedStandalone = true; + + System.out.println("TTF Reader v1.0"); + System.out.println(); + + 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]); + if (ttf != null) { + app.preview(ttf); + + org.w3c.dom.Document doc = app.constructFontXML(ttf, + fontName, + className, + embResource, + embFile); + + doc = app.postProcessXML(doc); + if (doc != null) { + app.writeFontXML(doc, arguments[1]); + } + } + } + } + + /** + * Read a TTF file and returns it as an object. + * + * @param filename The filename of the PFM file. + * @return The PFM as an object. + */ + public TTFFile loadTTF(String filename) { + TTFFile ttfFile=new TTFFile(); + try { + System.out.println("Reading " + filename + "..."); + System.out.println(); + + FontFileReader reader = new FontFileReader(filename); + ttfFile.readFont(reader); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + return ttfFile; + } + + /** + * Displays a preview of the TTF file on the console. + * + * @param ttf The TTF file to preview. + */ + public void preview(TTFFile ttf) { + PrintStream out = System.out; + + out.print("Font: "); + out.println(ttf.getWindowsName()); + out.print("Name: "); + out.println(ttf.getPostscriptName()); + out.print("CharSet: "); + out.println(ttf.getCharSetName()); + out.print("CapHeight: "); + out.println(ttf.getCapHeight()); + out.print("XHeight: "); + out.println(ttf.getXHeight()); + out.print("LowerCaseAscent: "); + out.println(ttf.getLowerCaseAscent()); + out.print("LowerCaseDescent: "); + out.println(ttf.getLowerCaseDescent()); + out.print("Having widths for "); + out.print(ttf.getLastChar()-ttf.getFirstChar()); + out.print(" characters ("); + out.print(ttf.getFirstChar()); + out.print("-"); + out.print(ttf.getLastChar()); + out.println(")."); + out.print("for example: Char "); + out.print(ttf.getFirstChar()); + out.print(" has a width of "); + out.println(ttf.getCharWidth(ttf.getFirstChar())); + out.println(); + if (ttf.isEmbeddable()) + out.println("This font might be embedded"); + else + out.println("This font might not be embedded"); + } + + /** + * 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) { + System.out.println("Writing xml font file " + target + "..."); + System.out.println(); + + try { + 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 e) { + e.printStackTrace(); + } + } + + /** + * Generates the font metrics file from the PFM file. + * + * @param pfm The PFM file to generate the font metrics from. + * @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) { + System.out.println("Creating xml font file..."); + System.out.println(); + + Document doc = new DocumentImpl(); + Element root = doc.createElement("font-metrics"); + doc.appendChild(root); + + 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 = ttf.getPostscriptName(); + + if (fontName != null) + el.appendChild(doc.createTextNode(fontName)); + else + el.appendChild(doc.createTextNode(s.replace('-', ','))); + + int pos = s.indexOf("-"); + if (pos >= 0) { + char sb[] = new char[s.length() - 1]; + s.getChars(0, pos, sb, 0); + s.getChars(pos + 1, s.length(), sb, pos); + s = new String(sb); + } + + el = doc.createElement("class-name"); + root.appendChild(el); + if (className != null) + el.appendChild(doc.createTextNode(className)); + else + el.appendChild(doc.createTextNode(s)); + + el = doc.createElement("embedFile"); + root.appendChild(el); + //if (file==null || !ttf.isEmbeddable()) + if (file==null) + el.appendChild(doc.createTextNode("null")); + else + el.appendChild(doc.createTextNode("\""+escapeString(file)+"\"")); + + el = doc.createElement("embedResource"); + root.appendChild(el); + //if (resource==null || !ttf.isEmbeddable()) + if (resource==null) + el.appendChild(doc.createTextNode("null")); + else + el.appendChild(doc.createTextNode("\""+escapeString(resource)+"\"")); + + el = doc.createElement("subtype"); + root.appendChild(el); + el.appendChild(doc.createTextNode("TRUETYPE")); + + el = doc.createElement("encoding"); + root.appendChild(el); + el.appendChild(doc.createTextNode(ttf.getCharSetName()+"Encoding")); + + el = doc.createElement("cap-height"); + root.appendChild(el); + Integer value = new Integer(ttf.getCapHeight()); + el.appendChild(doc.createTextNode(value.toString())); + + el = doc.createElement("x-height"); + root.appendChild(el); + value = new Integer(ttf.getXHeight()); + el.appendChild(doc.createTextNode(value.toString())); + + el = doc.createElement("ascender"); + root.appendChild(el); + value = new Integer(ttf.getLowerCaseAscent()); + el.appendChild(doc.createTextNode(value.toString())); + + el = doc.createElement("descender"); + root.appendChild(el); + value = new Integer(ttf.getLowerCaseDescent()); + el.appendChild(doc.createTextNode(value.toString())); + + 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); + value = new Integer(bb[i]); + el.appendChild(doc.createTextNode(value.toString())); + } + + el = doc.createElement("flags"); + root.appendChild(el); + value = new Integer(ttf.getFlags()); + el.appendChild(doc.createTextNode(value.toString())); + + el = doc.createElement("stemv"); + root.appendChild(el); + value = new Integer(ttf.getStemV()); + el.appendChild(doc.createTextNode(value.toString())); + + el = doc.createElement("italicangle"); + root.appendChild(el); + value = new Integer(ttf.getItalicAngle()); + el.appendChild(doc.createTextNode(value.toString())); + + el = doc.createElement("first-char"); + root.appendChild(el); + value = new Integer(ttf.getFirstChar()); + el.appendChild(doc.createTextNode(value.toString())); + + el = doc.createElement("last-char"); + root.appendChild(el); + value = new Integer(ttf.getLastChar()); + el.appendChild(doc.createTextNode(value.toString())); + + Element widths = doc.createElement("widths"); + root.appendChild(widths); + + for (short i = ttf.getFirstChar(); i < ttf.getLastChar(); i++) { + el = doc.createElement("char"); + widths.appendChild(el); + //el.setAttribute("ansichar", "0x00" + Integer.toHexString(i).toUpperCase()); + el.setAttribute("name", "0x00" + + Integer.toHexString(i).toUpperCase()); + el.setAttribute("width", + new Integer(ttf.getCharWidth(i)).toString()); + } + + // Get kerning + for (Enumeration enum=ttf.getKerning().keys(); enum.hasMoreElements();) { + String kpx1=(String)enum.nextElement(); + el=doc.createElement("kerning"); + el.setAttribute("kpx1", kpx1); + root.appendChild(el); + Element el2=null; + + Hashtable h2=(Hashtable)ttf.getKerning().get(kpx1); + for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) { + String kpx2=(String)enum2.nextElement(); + el2=doc.createElement("pair"); + el2.setAttribute("kpx2", kpx2); + Integer val=(Integer)h2.get(kpx2); + el2.setAttribute("kern", val.toString()); + el.appendChild(el2); + } + } + return doc; + } + + /** + * Modifies the generated font metrics file. First, it processes the + * character mmappings, then it sorts them. + * + * @param doc The DOM document representing the font metrics file. + * @return A DOM document representing the processed font metrics file. + */ + public org.w3c.dom.Document postProcessXML(org.w3c.dom.Document doc) { + if (true) + return doc; + try { + OutputFormat format = new OutputFormat(doc); //Serialize DOM + XMLSerializer serial = new XMLSerializer(System.out, format); + serial.asDOMSerializer(); // As a DOM Serializer + serial.serialize(doc.getDocumentElement()); + + System.out.println("Postprocessing..."); + System.out.println(); + + + + InputStream xsl = this.getClass().getResourceAsStream(XSL_POSTPROCESS); + if (xsl == null) { + throw new Exception("Resource " + XSL_POSTPROCESS + " not found"); + } + + Document targetDoc = new DocumentImpl(); + org.apache.fop.tools.xslt.XSLTransform.transform(doc, xsl, targetDoc); + + + System.out.println("Sorting..."); + System.out.println(); + + // Sort the whole thing + + + xsl = this.getClass().getResourceAsStream(XSL_SORT); + if (xsl == null) { + throw new Exception("Resource " + XSL_SORT + " not found"); + } + + + org.w3c.dom.Document targetDocSorted = new DocumentImpl(); + + org.apache.fop.tools.xslt.XSLTransform.transform(targetDoc, xsl, targetDocSorted); + + return targetDocSorted; + + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + + private String escapeString(String str) { + StringBuffer esc=new StringBuffer(); + + for (int i=0; i < str.length(); i++) { + if (str.charAt(i)=='\\') + esc.append("\\\\"); + else + esc.append(str.charAt(i)); + } + + return esc.toString(); + } +} + |