diff options
author | Kelly Campbell <kellyc@apache.org> | 2001-02-05 08:35:46 +0000 |
---|---|---|
committer | Kelly Campbell <kellyc@apache.org> | 2001-02-05 08:35:46 +0000 |
commit | 3adb1822bede8f9cb385161953d31d4de51e9684 (patch) | |
tree | 7821882b14db1dbe15b41c059fb5719758cae555 /src/org/apache | |
parent | a0de8b9e1ede578b39fb7dc55f8e17e718928993 (diff) | |
download | xmlgraphics-fop-3adb1822bede8f9cb385161953d31d4de51e9684.tar.gz xmlgraphics-fop-3adb1822bede8f9cb385161953d31d4de51e9684.zip |
Added TrueType and embedded font support from Tore Engvig and
Alain Fagot
PR:
Obtained from:
Submitted by: Tore Engvig <tengvig@infostream.no>, Alain FAGOT <Alain.FAGOT@framfab.nl>
Reviewed by:
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194018 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/org/apache')
33 files changed, 5110 insertions, 135 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(); + } +} + diff --git a/src/org/apache/fop/layout/FontDescriptor.java b/src/org/apache/fop/layout/FontDescriptor.java index defc71540..77f2939d7 100644 --- a/src/org/apache/fop/layout/FontDescriptor.java +++ b/src/org/apache/fop/layout/FontDescriptor.java @@ -54,16 +54,23 @@ package org.apache.fop.layout; public interface FontDescriptor { //Required - public int getAscender(); //Ascent in pdf spec - public int getCapHeight(); - public int getDescender(); //Descent in pdf spec - public int getFlags(); - public int[] getFontBBox(); - public String fontName(); //should be getFontName(). not? - public int getItalicAngle(); - public int getStemV(); + public int getAscender(); //Ascent in pdf spec + public int getCapHeight(); + public int getDescender(); //Descent in pdf spec + public int getFlags(); + public int[] getFontBBox(); + public String fontName(); //should be getFontName(). not? + public int getItalicAngle(); + public int getStemV(); - //Optional + public boolean hasKerningInfo(); + public java.util.Hashtable getKerningInfo(); + public boolean isEmbeddable(); + public byte getSubType(); + public org.apache.fop.pdf.PDFStream getFontFile(int objNum); + //Optional - but needed to calculate font-size-adjust... //public int getXHeight(); } + + diff --git a/src/org/apache/fop/layout/FontState.java b/src/org/apache/fop/layout/FontState.java index 4d28f93ac..f022ab54a 100644 --- a/src/org/apache/fop/layout/FontState.java +++ b/src/org/apache/fop/layout/FontState.java @@ -118,6 +118,17 @@ public class FontState { public int getXHeight() { return metric.getXHeight(fontSize) / 1000; } + public java.util.Hashtable getKerning() { + java.util.Hashtable ret=new java.util.Hashtable(); + try { + FontMetric fm=fontInfo.getMetricsFor(fontFamily, fontStyle, fontWeight); + if (fm instanceof org.apache.fop.layout.FontDescriptor) { + org.apache.fop.layout.FontDescriptor fdes=(org.apache.fop.layout.FontDescriptor)fm; + ret=fdes.getKerningInfo(); + } + } catch (Exception e) {} + return ret; + } public int width(int charnum) { // returns width of given character number in millipoints diff --git a/src/org/apache/fop/pdf/PDFCIDFont.java b/src/org/apache/fop/pdf/PDFCIDFont.java new file mode 100644 index 000000000..f13141da0 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFCIDFont.java @@ -0,0 +1,199 @@ +/*-- $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.pdf; + +// based on work by Takayuki Takeuchi +/** + * class representing a "character identifier" font (p 210 and onwards). + */ +public class PDFCIDFont extends PDFObject { + + public static final byte CID_TYPE0 = 0; + public static final byte CID_TYPE2 = 1; + protected static final String[] TYPE_NAMES = {"CIDFontType0", "CIDFontType2"}; + + protected String basefont; + + protected String cidtype; + protected Integer dw; + protected PDFWArray w; + protected int[] dw2; + protected PDFWArray w2; + protected PDFCIDSystemInfo systemInfo; + protected PDFCIDFontDescriptor descriptor; + /** + * /CIDToGIDMap (only for CIDFontType2, see p 212) + * can be either "Identity" (default) or a PDFStream + */ + protected PDFStream cidMap; + + // compatibility with Takayuki Takeuchi + /** + * create the /Font object + */ + public PDFCIDFont(int number, String basefont, String cidtype, + int dw, int[] w, String registry, String ordering, int supplement, + PDFCIDFontDescriptor descriptor) { + + super(number); + + this.basefont = basefont; + this.cidtype = cidtype; + this.dw = new Integer(dw); + this.w = new PDFWArray(); + this.w.addEntry(0, w); + this.dw2 = null; + this.w2 = null; + this.systemInfo = new PDFCIDSystemInfo(registry, ordering, supplement); + this.descriptor = descriptor; + this.cidMap = null; + } + + /** + * create the /Font object + */ + public PDFCIDFont(int number, String basefont, String cidtype, + int dw, PDFWArray w, PDFCIDSystemInfo systemInfo, + PDFCIDFontDescriptor descriptor) { + + super(number); + + this.basefont = basefont; + this.cidtype = cidtype; + this.dw = new Integer(dw); + this.w = w; + this.dw2 = null; + this.w2 = null; + this.systemInfo = systemInfo; + this.descriptor = descriptor; + this.cidMap = null; + } + + /** set the /DW attribute */ + public void setDW(int dw) { + this.dw = new Integer(dw); + } + + /** set the /W array */ + public void setW(PDFWArray w) { + this.w = w; + } + + /** set the (two elements) /DW2 array */ + public void setDW2(int[] dw2) { + this.dw2 = dw2; + } + + /** set the two elements of the /DW2 array */ + public void setDW2(int posY, int displacementY) { + this.dw2 = new int[] {posY, displacementY}; + } + + /** set the /W2 array */ + public void setW2(PDFWArray w2) { + this.w2 = w2; + } + + /** set the /CIDToGIDMap (to be used only for CIDFontType2) */ + public void setCIDMap(PDFStream map) { + this.cidMap = map; + } + + /** set the /CIDToGIDMap (to be used only for CIDFontType2) to "Identity" */ + public void setCIDMapIdentity() { + this.cidMap = null; // not an error here, simply use the default + } + + /** + * produce the PDF representation for the object + * + * @return the PDF + */ + public byte[] toPDF() { + return toPDFString().getBytes(); + } + + public String toPDFString() { + StringBuffer p = new StringBuffer(); + p.append(this.number); p.append(" "); + p.append(this.generation); + p.append(" obj\n<< /Type /Font"); + p.append("\n/BaseFont /"); p.append(this.basefont); + if (cidMap != null) { + p.append(" \n/CIDToGIDMap "); + p.append(cidMap.referencePDF()); + } + p.append(" \n/Subtype /"); p.append(this.cidtype); + p.append("\n"); p.append(systemInfo.toPDF()); + p.append("\n/FontDescriptor "); + p.append(this.descriptor.referencePDF()); + if (dw != null) { + p.append("\n/DW "); p.append(this.dw); + } + if (w != null) { + p.append("\n/W "); + p.append(w.toPDF()); + p.append(" \n>>\nendobj\n"); + } + if (dw2 != null) { + p.append("\n/DW2 ["); // always two values, see p 211 + p.append(this.dw2[0]); + p.append(this.dw2[1]); + p.append("] \n>>\nendobj\n"); + } + if (w2 != null) { + p.append("\n/W2 "); + p.append(w2.toPDF()); + p.append(" \n>>\nendobj\n"); + } + return p.toString(); + } +} diff --git a/src/org/apache/fop/pdf/PDFCIDFontDescriptor.java b/src/org/apache/fop/pdf/PDFCIDFontDescriptor.java new file mode 100644 index 000000000..9e8cddec5 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFCIDFontDescriptor.java @@ -0,0 +1,102 @@ +/*-- $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.pdf; + +// based on work by Takayuki Takeuchi +/** + * class representing a font descriptor for CID fonts. + * + * Font descriptors for CID fonts are specified on page 227 and onwards of the PDF 1.3 spec. + */ +public class PDFCIDFontDescriptor extends PDFFontDescriptor { + + protected String lang; + protected PDFStream cidSet; + + /** + * create the /FontDescriptor object + * + * @param number the object's number + * @param basefont the base font name + * @param fontBBox the bounding box for the described font + * @param flags various characteristics of the font + * @param capHeight height of the capital letters + * @param stemV the width of the dominant vertical stems of glyphs + * @param italicAngle the angle of the vertical dominant strokes + * @param lang the language + */ + public PDFCIDFontDescriptor(int number, + String basefont, + int[] fontBBox, + int capHeight, + int flags, + int italicAngle, int stemV, + String lang) { + + super(number, basefont, fontBBox[3], fontBBox[1], capHeight, flags, + new PDFRectangle(fontBBox), italicAngle, stemV); + + this.lang = lang; + } + + public void setCIDSet(PDFStream cidSet) { + this.cidSet = cidSet; + } + + protected void fillInPDF(StringBuffer p) { + if (lang != null) { + p.append("\n/Lang /"); p.append(lang); + } + if (cidSet != null) { + p.append("\n/CIDSet /"); this.cidSet.referencePDF(); + } + } +} diff --git a/src/org/apache/fop/pdf/PDFCIDSystemInfo.java b/src/org/apache/fop/pdf/PDFCIDSystemInfo.java new file mode 100644 index 000000000..c8b87bde4 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFCIDSystemInfo.java @@ -0,0 +1,92 @@ +/*-- $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.pdf; + +// based on work by Takayuki Takeuchi +/** + * class representing system information for "character identifier" fonts. + * + * this small object is used in the CID fonts and in the CMaps. + */ +public class PDFCIDSystemInfo extends PDFObject { + private static final StringBuffer p = new StringBuffer(); + protected String registry; + protected String ordering; + protected int supplement; + + public PDFCIDSystemInfo(String registry, String ordering, int supplement) { + this.registry = registry; + this.ordering = ordering; + this.supplement = supplement; + } + + /** + * produce the PDF representation for the object. + * + * unlike the other objects, the CIDSystemInfo is written directly inside + * the referencing object + * + * @return the PDF + */ + public byte[] toPDF() { + return toPDFString().getBytes(); + } + + public String toPDFString() { + p.setLength(0); + p.append("/CIDSystemInfo << /Registry ("); p.append(registry); + p.append(")/Ordering ("); p.append(ordering); + p.append(")/Supplement "); p.append(supplement); + p.append(" >>"); + return p.toString(); + } +} + diff --git a/src/org/apache/fop/pdf/PDFCMap.java b/src/org/apache/fop/pdf/PDFCMap.java new file mode 100644 index 000000000..1a086a9af --- /dev/null +++ b/src/org/apache/fop/pdf/PDFCMap.java @@ -0,0 +1,184 @@ +/*-- $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.pdf; + +/** + * class representing the CMap encodings. + * + * CMaps are defined on page 215 and onwards. + * The predefined CMap names are drawn from Table 7.20 + * on pages 215, 216 and 217 . + */ +public class PDFCMap extends PDFStream { + /** Chinese (simplified) */ + public static final String GB_EUC_H= "GB-EUC-H"; + public static final String GB_EUC_V= "GB_EUC_V"; + public static final String GBpc_EUC_H= "GBpc-EUC-H"; + public static final String GBpc_EUC_V= "GBpc-EUC-V"; + public static final String GBK_EUC_H= "GBK-EUC-H"; + public static final String GBK_EUC_V= "GBK-EUC-V"; + public static final String UniGB_UCS2_H= "UniGB-UCS2-H"; + public static final String UniGB_UCS2_V= "UniGB-UCS2-V"; + /** Chinese (traditional) */ + public static final String B5pc_H= "B5pc-H"; + public static final String B5pc_V= "B5pc-V"; + public static final String ETen_B5_H= "ETen-B5-H"; + public static final String ETen_B5_V= "ETen-B5-V"; + public static final String ETenms_B5_H= "ETenms-B5-H"; + public static final String ETenms_B5_V= "ETenms-B5-V"; + public static final String CNS_EUC_H= "CNS-EUC-H"; + public static final String CNS_EUC_V= "CNS-EUC-V"; + public static final String UniCNS_UCS2_H= "UniCNS-UCS2-H"; + public static final String UniCNS_UCS2_V= "UniCNS-UCS2-V"; + /** Japanese */ + public static final String _83pv_RKSJ_H= "83pv-RKSJ-H"; // no V version + public static final String _90ms_RKSJ_H= "90ms-RKSJ-H"; + public static final String _90ms_RKSJ_V= "90ms-RKSJ-V"; + public static final String _90msp_RKSJ_H= "90msp-RKSJ-H"; + public static final String _90msp_RKSJ_V= "90msp-RKSJ-V"; + public static final String _90pv_RKSJ_H= "90pv-RKSJ-H"; // no V version + public static final String Add_RKSJ_H= "Add-RKSJ-H"; + public static final String Add_RKSJ_V= "Add-RKSJ-V"; + public static final String EUC_H= "EUC-H"; + public static final String EUC_V= "EUC-V"; + public static final String Ext_RKSJ_H= "Ext-RKSJ-H"; + public static final String Ext_RKSJ_V= "Ext-RKSJ-V"; + public static final String H= "H"; + public static final String V= "V"; + public static final String UniJIS_UCS2_H= "UniJIS-UCS2-H"; + public static final String UniJIS_UCS2_V= "UniJIS-UCS2-V"; + public static final String UniJIS_UCS2_HW_H= "UniJIS-UCS2-HW-H"; + public static final String UniJIS_UCS2_HW_V= "UniJIS-UCS2-HW-V"; + /** Korean */ + public static final String KSC_EUC_H= "KSC-EUC-H"; + public static final String KSC_EUC_V= "KSC-EUC-V"; + public static final String KSCms_UHC_H= "KSCms-UHC-H"; + public static final String KSCms_UHC_V= "KSCms-UHC-V"; + public static final String KSCms_UHC_HW_H= "KSCms-UHC-HW-H"; + public static final String KSCms_UHC_HW_V= "KSCms-UHC-HW-V"; + public static final String KSCpc_EUC_H= "KSCpc-EUC-H"; // no V version + public static final String UniKSC_UCS2_H= "UniKSC-UCS2-H"; + public static final String UniKSC_UCS2_V= "UniKSC-UCS2-V"; + /** Generic */ + public static final String Identity_H= "Identity-H"; + public static final String Identity_V= "Identity-V"; + + /** /CMapName attribute, one of the predefined constants */ + protected String name; + + /** /CIDSystemInfo attribute */ + protected PDFCIDSystemInfo sysInfo; + + /** horizontal writing direction */ + public static final byte WMODE_HORIZONTAL = 0; + /** vertical writing direction */ + public static final byte WMODE_VERTICAL = 1; + /** font's writing direction */ + protected byte wMode = WMODE_HORIZONTAL; + + /** base CMap (String or PDFStream) */ + protected Object base; + + /** + * create the /CMap object + * + * @param name one the registered names (see Table 7.20 on p 215) + * @param sysInfo the attributes of the character collection of the CIDFont + */ + public PDFCMap(int number, String name, PDFCIDSystemInfo sysInfo) { + super(number); + this.name = name; + this.sysInfo = sysInfo; + this.base = null; + } + + /** + * set the writing direction + * + * @param mode is either <code>WMODE_HORIZONTAL</code> + * or <code>WMODE_VERTICAL</code> + */ + public void setWMode(byte mode) { + this.wMode = mode; + } + + /** + * set the base CMap + * + * @param base the name of the base CMap (see Table 7.20) + */ + public void setUseCMap(String base) { + this.base = base; + } + + /** + * set the base CMap + * + * @param base the stream to be used as base CMap + */ + public void setUseCMap(PDFStream base) { + this.base = base; + } + + public void fillInPDF(StringBuffer p) { + p.append(" /Type /CMap\n/CMapName /" + name); + p.append("\n"); p.append(sysInfo.toPDF()); + p.append("\n/WMode "); p.append(wMode); + if (base != null) { + p.append("\n/UseCMap "); + if (base instanceof String) { + p.append("/"+base); + } else { // base instanceof PDFStream + p.append(((PDFStream)base).referencePDF()); + } + } + } +} diff --git a/src/org/apache/fop/pdf/PDFCharProcs.java b/src/org/apache/fop/pdf/PDFCharProcs.java new file mode 100644 index 000000000..2ba96f277 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFCharProcs.java @@ -0,0 +1,88 @@ +/*-- $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.pdf; + +import java.util.Hashtable; + +/** + * class representing a /CharProcs dictionary for Type3 fonts. + * + * <p><b>CAUTION: this is not yet fully implemented!!!!!!!</b> + * I miss an exemple of <i>how</i> to output this dictionary. + * </p> + * + * Type3 fonts are specified on page 206 and onwards of the PDF 1.3 spec. + */ +public class PDFCharProcs extends PDFObject { + + /** the (character name, drawing stream) pairs for a Type3 font */ + protected Hashtable keys; + + public PDFCharProcs() { + keys = new Hashtable(); + } + + /** + * add a character definition in the dictionary + * + * @param name the character name + * @param stream the stream that draws the character + */ + public void addCharacter(String name, PDFStream stream) { + keys.put(name, stream); + } + + /** not done yet */ + public byte[] toPDF() { + //TODO: implement this org.apache.fop.pdf.PDFObject abstract method + return new byte[0]; + } +} diff --git a/src/org/apache/fop/pdf/PDFDocument.java b/src/org/apache/fop/pdf/PDFDocument.java index c69556046..7adcbb174 100644 --- a/src/org/apache/fop/pdf/PDFDocument.java +++ b/src/org/apache/fop/pdf/PDFDocument.java @@ -756,9 +756,13 @@ public class PDFDocument { this.objects.addElement(font); return font; } else { + byte subtype=PDFFont.TYPE1; + if (metrics instanceof org.apache.fop.render.pdf.Font) + subtype=((org.apache.fop.render.pdf.Font)metrics).getSubType(); + PDFFontNonBase14 font = (PDFFontNonBase14)PDFFont.createFont( ++this.objectcount, fontname, - PDFFont.TYPE1, basefont, encoding); + subtype, basefont, encoding); this.objects.addElement(font); PDFFontDescriptor pdfdesc = makeFontDescriptor(descriptor); font.setDescriptor(pdfdesc); @@ -776,12 +780,28 @@ public class PDFDocument { /* create a PDFFontDescriptor with the next object number and add to the list of objects */ - PDFFontDescriptor font = new PDFFontDescriptor(++this.objectcount, - desc.fontName(), desc.getAscender(), desc.getDescender(), - desc.getCapHeight(), desc.getFlags(), - new PDFRectangle(desc.getFontBBox()), desc.getStemV(), - desc.getItalicAngle()); - this.objects.addElement(font); + PDFFontDescriptor font = + new PDFFontDescriptor(++this.objectcount, + desc.fontName(), desc.getAscender(), desc.getDescender(), + desc.getCapHeight(), desc.getFlags(), + new PDFRectangle(desc.getFontBBox()), desc.getStemV(), + desc.getItalicAngle()); + + // Check if embedding of this font is enabled in the configurationfile + // and that the font is embeddable + java.util.Vector cfgv= + org.apache.fop.configuration.Configuration.getListValue("embed-fonts", 0); + if (cfgv!=null && cfgv.contains(desc.fontName()) && desc.isEmbeddable()) { + PDFStream stream=desc.getFontFile(this.objectcount+1); + if (stream!=null) { + this.objectcount++; + font.setFontFile(desc.getSubType(), stream); + this.objects.addElement(font); + this.objects.addElement(stream); + } + } else { + this.objects.addElement(font); + } return font; } diff --git a/src/org/apache/fop/pdf/PDFFont.java b/src/org/apache/fop/pdf/PDFFont.java index 9b11c5f02..fefc42547 100644 --- a/src/org/apache/fop/pdf/PDFFont.java +++ b/src/org/apache/fop/pdf/PDFFont.java @@ -146,9 +146,9 @@ public class PDFFont extends PDFObject { /* case TYPE3 : return new PDFFontType3(number, fontname, subtype, basefont, encoding); + */ case TRUETYPE : return new PDFFontTrueType(number, fontname, subtype, basefont, encoding); - */ } return null; // should not happend } @@ -184,13 +184,13 @@ public class PDFFont extends PDFObject { return font; case TYPE3 : return null; // should not happend - /* + case TRUETYPE : - font = new PDFFontTrueType(number, fontname, subtype, basefont, encoding); - font.setWidthMetrics(firstChar, lastChar, widths); - font.setDescriptor(descriptor); - return font; - */ + font = new PDFFontTrueType(number, fontname, subtype, basefont, encoding); + font.setWidthMetrics(firstChar, lastChar, widths); + font.setDescriptor(descriptor); + return font; + } return null; // should not happend } diff --git a/src/org/apache/fop/pdf/PDFFontDescriptor.java b/src/org/apache/fop/pdf/PDFFontDescriptor.java index 23c6a60f9..97fd60e72 100644 --- a/src/org/apache/fop/pdf/PDFFontDescriptor.java +++ b/src/org/apache/fop/pdf/PDFFontDescriptor.java @@ -91,9 +91,12 @@ public class PDFFontDescriptor extends PDFObject { * @param italicAngle the angle of the vertical dominant strokes * @param stemV the width of the dominant vertical stems of glyphs */ - public PDFFontDescriptor(int number, String basefont, int ascent, - int descent, int capHeight, int flags, PDFRectangle fontBBox, - int italicAngle, int stemV) { + public PDFFontDescriptor(int number, + String basefont, + int ascent, int descent, + int capHeight, int flags, + PDFRectangle fontBBox, + int italicAngle, int stemV) { /* generic creation of PDF object */ super(number); @@ -145,7 +148,7 @@ public class PDFFontDescriptor extends PDFObject { + " obj\n<< /Type /FontDescriptor" + "\n/FontName /" + this.basefont); - p.append("\n/FontBBox "); p.append(fontBBox.toPDF()); + p.append("\n/FontBBox "); p.append(fontBBox.toPDFString()); p.append("\n/Flags "); p.append(flags); p.append("\n/CapHeight "); p.append(capHeight); p.append("\n/Ascent "); p.append(ascent); diff --git a/src/org/apache/fop/pdf/PDFFontTrueType.java b/src/org/apache/fop/pdf/PDFFontTrueType.java new file mode 100644 index 000000000..be1f37131 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFFontTrueType.java @@ -0,0 +1,78 @@ +/*-- $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.pdf; + +/** + * class representing a TrueType font. + * + * In fact everything already done in the superclass. + * Must only define the not default constructor. + */ +public class PDFFontTrueType extends PDFFontNonBase14 { + + /** + * create the /Font object + * + * @param number the object's number + * @param fontname the internal name for the font + * @param subtype the font's subtype (PDFFont.TRUETYPE) + * @param basefont the base font name + * @param encoding the character encoding schema used by the font + * @param mapping the Unicode mapping mechanism + */ + public PDFFontTrueType(int number, String fontname, byte subtype, + String basefont, Object encoding/*, PDFToUnicode mapping*/) { + + /* generic creation of PDF object */ + super(number, fontname, subtype, basefont, encoding/*, mapping*/); + } + +} diff --git a/src/org/apache/fop/pdf/PDFFontType0.java b/src/org/apache/fop/pdf/PDFFontType0.java new file mode 100644 index 000000000..7cc0003ca --- /dev/null +++ b/src/org/apache/fop/pdf/PDFFontType0.java @@ -0,0 +1,123 @@ +/*-- $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.pdf; + +/** + * class representing a Type0 font. + * + * Type0 fonts are specified on page 208 and onwards of the PDF 1.3 spec. + */ +public class PDFFontType0 extends PDFFont { + + /** this should be an array of CIDFont but only the first one is used */ + protected PDFCIDFont descendantFonts; + + /** + * create the /Font object + * + * @param number the object's number + * @param fontname the internal name for the font + * @param subtype the font's subtype (PDFFont.TYPE0) + * @param basefont the base font name + * @param encoding the character encoding schema used by the font + * @param mapping the Unicode mapping mechanism + */ + public PDFFontType0(int number, String fontname, byte subtype, + String basefont, Object encoding/*, PDFToUnicode mapping*/) { + + /* generic creation of PDF object */ + super(number, fontname, subtype, basefont, encoding/*, mapping*/); + + /* set fields using paramaters */ + this.descendantFonts = null; + } + + /** + * create the /Font object + * + * @param number the object's number + * @param fontname the internal name for the font + * @param subtype the font's subtype (PDFFont.TYPE0) + * @param basefont the base font name + * @param encoding the character encoding schema used by the font + * @param mapping the Unicode mapping mechanism + * @param descendantFonts the CIDFont upon which this font is based + */ + public PDFFontType0(int number, String fontname, byte subtype, + String basefont, Object encoding/*, PDFToUnicode mapping*/, + PDFCIDFont descendantFonts) { + + /* generic creation of PDF object */ + super(number, fontname, subtype, basefont, encoding/*, mapping*/); + + /* set fields using paramaters */ + this.descendantFonts = descendantFonts; + } + + /** + * set the descendant font + * + * @param descendantFonts the CIDFont upon which this font is based + */ + public void setDescendantFonts(PDFCIDFont descendantFonts) { + this.descendantFonts = descendantFonts; + } + + /** + * fill in the specifics for the font's subtype + */ + protected void fillInPDF(StringBuffer p) { + if (descendantFonts != null) { + p.append("\n/DescendantFonts [ "+ this.descendantFonts.referencePDF() + " ] "); + } + + } +} diff --git a/src/org/apache/fop/pdf/PDFFontType3.java b/src/org/apache/fop/pdf/PDFFontType3.java new file mode 100644 index 000000000..0461228d2 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFFontType3.java @@ -0,0 +1,168 @@ +/*-- $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.pdf; + +/** + * class representing a Type3 font. + * + * <p><b>CAUTION: this is not yet fully implemented!!!!!!!</b> + * the /CharProcs is still missing its <code>toPDF()</code> method. + * </p> + * + * Type3 fonts are specified on page 206 and onwards of the PDF 1.3 spec. + */ +public class PDFFontType3 extends PDFFontNonBase14 { + + /** font's required /FontBBox bounding box */ + protected PDFRectangle fontBBox; + + /** font's required /FontMatrix array */ + protected PDFArray fontMatrix; + + /** font's required /CharProcs dictionary */ + protected PDFCharProcs charProcs; + + /** font's optional /Resources object */ + protected PDFResources resources; + + /** + * create the /Font object + * + * @param number the object's number + * @param fontname the internal name for the font + * @param subtype the font's subtype (PDFFont.TYPE3) + * @param basefont the base font name + * @param encoding the character encoding schema used by the font + * @param mapping the Unicode mapping mechanism + */ + public PDFFontType3(int number, String fontname, byte subtype, + String basefont, Object encoding/*, PDFToUnicode mapping*/) { + + /* generic creation of PDF object */ + super(number, fontname, subtype, basefont, encoding/*, mapping*/); + + this.fontBBox = null; + this.fontMatrix = null; + this.charProcs = null; + } + + /** + * create the /Font object + * + * @param number the object's number + * @param fontname the internal name for the font + * @param subtype the font's subtype (PDFFont.TYPE3) + * @param basefont the base font name + * @param encoding the character encoding schema used by the font + * @param mapping the Unicode mapping mechanism + * @param fontBBox the font's bounding box + * @param fontMatrix the font's transformation matrix + * @param charProcs the glyphs' definitions + */ + public PDFFontType3(int number, String fontname, byte subtype, + String basefont, Object encoding/*, PDFToUnicode mapping*/, + PDFRectangle fontBBox, PDFArray fontMatrix, PDFCharProcs charProcs) { + + /* generic creation of PDF object */ + super(number, fontname, subtype, basefont, encoding/*, mapping*/); + + this.fontBBox = fontBBox; + this.fontMatrix = fontMatrix; + this.charProcs = charProcs; + } + + /** + * set the font's bounding box + * + * @param bbox bounding box for the font + */ + public void setFontBBox(PDFRectangle bbox) { + this.fontBBox = bbox; + } + + /** + * set the font's transformation matrix + * + * @param matrix the transformation matrix for the font + */ + public void setFontMatrix(PDFArray matrix) { + this.fontMatrix = matrix; + } + + /** + * set the glyphs' definitions. + * The /CharProcs object needs to be registered in the document's resources. + * + * @param chars the glyphs' dictionary + */ + public void setCharProcs(PDFCharProcs chars) { + this.charProcs = chars; + } + + /** + * fill in the specifics for the font's subtype. + * + * the given buffer already contains the fields common to all font types. + * + * @param p the buffer to be completed with the type specific fields + */ + protected void fillInPDF(StringBuffer p) { + if (fontBBox != null) { + p.append("\n/FontBBox "); p.append(fontBBox.toPDF()); + } + if (fontMatrix != null) { + p.append("\n/FontMatrix "); p.append(fontMatrix.toPDF()); + } + if (charProcs != null) { + p.append("\n/CharProcs "); p.append(charProcs.referencePDF()); + } + } +} diff --git a/src/org/apache/fop/pdf/PDFRectangle.java b/src/org/apache/fop/pdf/PDFRectangle.java index d0efca90a..24809d241 100644 --- a/src/org/apache/fop/pdf/PDFRectangle.java +++ b/src/org/apache/fop/pdf/PDFRectangle.java @@ -97,7 +97,11 @@ public class PDFRectangle { * * @return the PDF */ - public byte[] toPDF() { - return (" [" + llx + " " + lly + " " + urx + " " + ury + "] ").getBytes(); - } + public byte[] toPDF() { + return toPDFString().getBytes(); + } + + public String toPDFString() { + return new String(" [" + llx + " " + lly + " " + urx + " " + ury + "] "); + } } diff --git a/src/org/apache/fop/pdf/PDFStream.java b/src/org/apache/fop/pdf/PDFStream.java index b374b062c..195b2e857 100644 --- a/src/org/apache/fop/pdf/PDFStream.java +++ b/src/org/apache/fop/pdf/PDFStream.java @@ -69,7 +69,7 @@ import org.apache.fop.messaging.MessageHandler; public class PDFStream extends PDFObject { /** the stream of PDF commands */ - private ByteArrayOutputStream _data; + protected ByteArrayOutputStream _data; /** the filters that should be applied */ private Vector _filters; diff --git a/src/org/apache/fop/pdf/PDFT1Stream.java b/src/org/apache/fop/pdf/PDFT1Stream.java new file mode 100644 index 000000000..644831370 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFT1Stream.java @@ -0,0 +1,154 @@ +/*-- $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.pdf; + +public class PDFT1Stream extends PDFStream { + private int origLength; + private int len1, len3; + private byte[] originalData=null; + + public PDFT1Stream(int num, int len) { + super(num); + origLength=len; + } + + private final static boolean byteCmp(byte[] src, int offset, byte[] cmp) { + boolean ret=true; + for (int i=0; ret==true && i < cmp.length; i++) { + //System.out.println("Compare: "); + //System.out.println(" "+src[offset+i]+" "+cmp[i]); + if (src[offset+i]!=cmp[i]) + ret=false; + } + return ret; + } + + /** + * calculates the Length1 and Length3 PDFStream attributes for type1 + * font embedding + */ + private void calcLengths(byte[] originalData) { + // Calculate length 1 and 3 + //System.out.println ("Checking font, size = "+originalData.length); + + // Length1 is the size of the initial ascii portion + // search for "currentfile eexec" + // Get the first binary number and search backwards for "eexec" + len1=30; + + byte[] eexec=(new String("currentfile eexec")).getBytes(); + //System.out.println("Length1="+len1); + while (!byteCmp(originalData, len1-eexec.length, eexec)) + len1++; + // Skip newline + len1++; + + // Length3 is length of the last portion of the file + len3=0; + byte[] cltom=(new String("cleartomark")).getBytes(); + len3 -= cltom.length; + while (!byteCmp(originalData, origLength+len3, cltom)) { + len3--; + //System.out.println("Len3="+len3); + } + len3 = -len3; + len3++; + // Eat 512 zeroes + int numZeroes=0; + byte[] ws1="\n".getBytes(); + byte[] ws2="\r".getBytes(); + byte[] ws3="0".getBytes(); + while ((originalData[origLength-len3]==ws1[0] || + originalData[origLength-len3]==ws2[0] || + originalData[origLength-len3]==ws3[0]) && numZeroes < 512) { + len3++; + if (originalData[origLength-len3]==ws3[0]) + numZeroes++; + } + //System.out.println("Length3="+len3); + } + + // overload the base object method so we don't have to copy + // byte arrays around so much + protected int output(java.io.OutputStream stream) throws java.io.IOException + { + int length = 0; + String filterEntry = applyFilters(); + String preData= + new String(this.number + " " + this.generation + + " obj\n<< /Length " + + (_data.size()+1) + " " + + filterEntry + " " + + "/Length1 " + len1 + + " /Length2 " + (origLength-len3 -len1) + + " /Length3 " + len3 + + " >>\n"); + + byte[] p = preData.getBytes(); + stream.write(p); + length += p.length; + + length += outputStreamData(stream); + p = "endobj\n".getBytes(); + stream.write(p); + length += p.length; + System.out.println("Embedded Type1 font"); + return length; + } + + public void setData(byte[] data, int size) + throws java.io.IOException { + calcLengths(data); + _data.reset(); + //System.out.println("Writing " + size + " bytes of font data"); + _data.write(data, 0, size); + } +} diff --git a/src/org/apache/fop/pdf/PDFTTFStream.java b/src/org/apache/fop/pdf/PDFTTFStream.java new file mode 100644 index 000000000..1b17e02f8 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFTTFStream.java @@ -0,0 +1,91 @@ +/*-- $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.pdf; + +public class PDFTTFStream extends PDFStream { + private int origLength; + + public PDFTTFStream(int num, int len) { + super(num); + origLength=len; + } + // overload the base object method so we don't have to copy + // byte arrays around so much + protected int output(java.io.OutputStream stream) throws java.io.IOException + { + int length = 0; + String filterEntry = applyFilters(); + String preData= + new String(this.number + " " + this.generation + + " obj\n<< /Length " + + (_data.size()+1) + " " + + filterEntry + " " + + "/Length1 " + origLength + + " >>\n"); + + byte[] p = preData.getBytes(); + stream.write(p); + length += p.length; + + length += outputStreamData(stream); + p = "endobj\n".getBytes(); + stream.write(p); + length += p.length; + return length; + } + + public void setData(byte[] data, int size) + throws java.io.IOException { + _data.reset(); + System.out.println("Writing " + size + " bytes of font data"); + _data.write(data, 0, size); + } +} diff --git a/src/org/apache/fop/pdf/PDFWArray.java b/src/org/apache/fop/pdf/PDFWArray.java new file mode 100644 index 000000000..6e025b6f1 --- /dev/null +++ b/src/org/apache/fop/pdf/PDFWArray.java @@ -0,0 +1,144 @@ +/*-- $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.pdf; + +import java.util.Vector; + +/** + * class representing a <b>W</b> array for CID fonts. + */ +public class PDFWArray { + + /** the metrics */ + private Vector entries; + + public PDFWArray() { + entries = new Vector(); + } + + /** + * add an entry for single starting CID. + * i.e. in the form "c [w ...]" + * + * @param start the starting CID value. + * @param metrics the metrics array. + */ + public void addEntry(int start, int[] metrics) { + entries.add(new Entry(start, metrics)); + } + + /** + * add an entry for a range of CIDs (/W element on p 213) + * + * @param first the first CID in the range + * @param last the last CID in the range + * @param width the width for all CIDs in the range + */ + public void addEntry(int first, int last, int width) { + entries.add(new int[] {first, last, width}); + } + + /** + * add an entry for a range of CIDs (/W2 element on p 210) + * + * @param first the first CID in the range + * @param last the last CID in the range + * @param width the width for all CIDs in the range + * @param posX the x component for the vertical position vector + * @param posY the y component for the vertical position vector + */ + public void addEntry(int first, int last, int width, int posX, int posY) { + entries.add(new int[] {first, last, width, posX, posY}); + } + + public byte[] toPDF() { + return toPDFString().getBytes(); + } + + public String toPDFString() { + StringBuffer p = new StringBuffer(); + p.append("[ "); + int len = entries.size(); + for (int i = 0; i<len; i++) { + Object entry = entries.elementAt(i); + if (entry instanceof int[]) { + int[] line = (int[])entry; + for (int j = 0; j<line.length; j++) { + p.append(line[j]); p.append(" "); + } + } else { + ((Entry)entry).fillInPDF(p); + } + } + p.append("]"); + return p.toString(); + } + + /** inner class for entries in the form "c [w ...]" */ + private static class Entry { + private static final StringBuffer p = new StringBuffer(); + private int start; + private int[] metrics; + public Entry (int s, int[] m) { + start = s; + metrics = m; + } + public void fillInPDF(StringBuffer p) { + p.setLength(0); + p.append(start); p.append(" ["); + for (int i = 0; i < metrics.length; i++) { + p.append(this.metrics[i]); + p.append(" "); + } + p.append("] "); + } + } +} diff --git a/src/org/apache/fop/render/pdf/Font.java b/src/org/apache/fop/render/pdf/Font.java index 88e677cd1..2801d558a 100644 --- a/src/org/apache/fop/render/pdf/Font.java +++ b/src/org/apache/fop/render/pdf/Font.java @@ -67,6 +67,13 @@ public abstract class Font implements FontMetric { * get the base font name */ public abstract String fontName(); + + /** + * get the subtype of the font, default is TYPE1 + */ + public byte getSubType() { + return org.apache.fop.pdf.PDFFont.TYPE1; + } } diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index d1cb17ae5..dfe2d5b52 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -65,6 +65,7 @@ import org.apache.fop.svg.PathPoint; import org.apache.fop.pdf.*; import org.apache.fop.layout.*; import org.apache.fop.image.*; +import org.apache.fop.configuration.Configuration; import org.w3c.dom.*; import org.w3c.dom.svg.*; @@ -143,7 +144,7 @@ public class PDFRenderer implements Renderer { /** the current colour for use in svg */ private PDFColor currentColour = new PDFColor(0, 0, 0); - + // previous values used for text-decoration drawing int prevUnderlineXEndPos; int prevUnderlineYEndPos; @@ -160,23 +161,30 @@ public class PDFRenderer implements Renderer { /** true if a TJ command is left to be written */ boolean textOpen = false; + /** the previous Y coordinate of the last word written. Used to decide if we can draw the next word on the same line. */ int prevWordY = 0; + /** the previous X coordinate of the last word written. used to calculate how much space between two words */ int prevWordX = 0; + /** The width of the previous word. Used to calculate space between */ int prevWordWidth = 0; + /** a number formatter to trim off extra precision we don't need*/ static java.text.NumberFormat numFormat; + + boolean useKerning; + + // initialize the static number formatter static { numFormat = java.text.NumberFormat.getNumberInstance(); numFormat.setMaximumFractionDigits(2); numFormat.setGroupingUsed(false); - } @@ -185,6 +193,10 @@ public class PDFRenderer implements Renderer { */ public PDFRenderer() { this.pdfDoc = new PDFDocument(); + + String cfgKern = Configuration.getStringValue("use-kerning"); + useKerning = ("yes".equals(cfgKern) || "true".equals(cfgKern)); + } /** @@ -357,7 +369,7 @@ public class PDFRenderer implements Renderer { this.currentYPosition -= area.getYPosition(); this.currentAreaContainerXPosition += area.getXPosition(); } - + this.currentXPosition = this.currentAreaContainerXPosition; int w, h; int rx = this.currentAreaContainerXPosition; @@ -375,13 +387,13 @@ public class PDFRenderer implements Renderer { // floats & footnotes stuff renderAreaContainer(area.getBeforeFloatReferenceArea()); renderAreaContainer(area.getFootnoteReferenceArea()); - + // main reference area Enumeration e = area.getMainReferenceArea().getChildren().elements(); while (e.hasMoreElements()) { Box b = (Box) e.nextElement(); b.render(this); // span areas - } + } if (area.getPosition() != Position.STATIC) { this.currentYPosition = saveY; @@ -396,9 +408,9 @@ public class PDFRenderer implements Renderer { while (e.hasMoreElements()) { Box b = (Box) e.nextElement(); b.render(this); // column areas - } + } } - + private void doFrame(Area area) { int w, h; int rx = this.currentAreaContainerXPosition; @@ -620,14 +632,25 @@ public class PDFRenderer implements Renderer { * @param area inline area to render */ public void renderWordArea(WordArea area) { - char ch; + // char ch; StringBuffer pdf = new StringBuffer(); + Hashtable kerning = null; + boolean kerningAvailable = false; + + if (useKerning) { + kerning = area.getFontState().getKerning(); + if (kerning != null && !kerning.isEmpty()) { + kerningAvailable = true; + } + } + String name = area.getFontState().getFontName(); int size = area.getFontState().getFontSize(); PDFColor theAreaColor = new PDFColor((double) area.getRed(), - (double) area.getGreen(), (double) area.getBlue()); + (double) area.getGreen(), + (double) area.getBlue()); if ((!name.equals(this.currentFontName)) || (size != this.currentFontSize)) { @@ -638,12 +661,14 @@ public class PDFRenderer implements Renderer { pdf = pdf.append("/" + name + " " + (size / 1000) + " Tf\n"); } + if (!(theAreaColor.equals(this.currentFill))) { closeText(); this.currentFill = theAreaColor; pdf.append(this.currentFill.getColorSpaceOut(true)); } + int rx = this.currentXPosition; int bl = this.currentYPosition; @@ -671,8 +696,8 @@ public class PDFRenderer implements Renderer { if (area.getLineThrough()) { int yPos = bl + area.getFontState().getAscender() * 3/8; - addLine(rx, yPos, rx + area.getContentWidth(), - yPos, size/14, theAreaColor); + addLine(rx, yPos, rx + area.getContentWidth(), + yPos, size/14, theAreaColor); prevLineThroughXEndPos = rx + area.getContentWidth(); prevLineThroughYEndPos = yPos; prevLineThroughSize = size/14; @@ -702,8 +727,13 @@ public class PDFRenderer implements Renderer { else { // original text render code sets the text transformation matrix // for every word. - pdf.append("1 0 0 1 " +(rx / 1000f) + " " + (bl / 1000f) + - " Tm ("); + pdf.append("1 0 0 1 " +(rx / 1000f) + " " + (bl / 1000f) + " Tm "); + if (kerningAvailable) { + pdf.append(" [("); + } + else { + pdf.append(" ("); + } } String s; @@ -719,30 +749,38 @@ public class PDFRenderer implements Renderer { int l = s.length(); for (int i = 0; i < l; i++) { - ch = s.charAt(i); + char ch = s.charAt(i); + String prepend = ""; + if (ch > 127) { pdf.append("\\"); pdf.append(Integer.toOctalString((int) ch)); } else { switch (ch) { - case '(' : - pdf.append("\\("); - break; - case ')' : - pdf.append("\\)"); - break; - case '\\' : - pdf.append("\\\\"); - break; - default : - pdf.append(ch); - break; + case '(': + case ')': + case '\\': + prepend = "\\"; + break; } - } + pdf.append(prepend+ch); + } + if (kerningAvailable && (i+1) < l) { + pdf.append(addKerning((new Character(ch)).toString(), + (new Character(s.charAt(i+1))).toString(), + kerning)); + } + } pdf.append(") "); if (!OPTIMIZE_TEXT) { - pdf.append("Tj\n"); + if (kerningAvailable) { + pdf.append("] TJ\n"); + } + else { + pdf.append("Tj\n"); + } + } @@ -831,6 +869,22 @@ public class PDFRenderer implements Renderer { this.currentXPosition = rx; } + + private StringBuffer addKerning(String ch1, String ch2, Hashtable kerning) { + Hashtable h2=(Hashtable)kerning.get(ch1); + int pwdt=0; + StringBuffer buf=new StringBuffer(""); + + if (h2!=null) { + Integer wdt=(Integer)h2.get(ch2); + if (wdt!=null) { + pwdt=-wdt.intValue(); + buf=buf.append(") " + pwdt + " ("); + } + } + return buf; + } + /** * render page into PDF * diff --git a/src/org/apache/fop/tools/xslt/TraxTransform.java b/src/org/apache/fop/tools/xslt/TraxTransform.java index d93a611be..82808ae5d 100644 --- a/src/org/apache/fop/tools/xslt/TraxTransform.java +++ b/src/org/apache/fop/tools/xslt/TraxTransform.java @@ -57,6 +57,7 @@ package org.apache.fop.tools.xslt; import javax.xml.transform.*; import java.io.FileInputStream; +import java.io.InputStream; import java.io.Writer; import java.util.Hashtable; @@ -133,6 +134,15 @@ public class TraxTransform new javax.xml.transform.stream.StreamResult(output)); } + public static void transform(Document xmlSource, + InputStream xsl, + Document outputDoc) + { + transform(new javax.xml.transform.dom.DOMSource(xmlSource), + new javax.xml.transform.stream.StreamSource(xsl), + new javax.xml.transform.dom.DOMResult(outputDoc)); + } + public static void transform(Source xmlSource, Source xslSource, Result result) @@ -156,5 +166,5 @@ public class TraxTransform } } - + } diff --git a/src/org/apache/fop/tools/xslt/XSLTransform.java b/src/org/apache/fop/tools/xslt/XSLTransform.java index 0d876158d..c30d7eef5 100644 --- a/src/org/apache/fop/tools/xslt/XSLTransform.java +++ b/src/org/apache/fop/tools/xslt/XSLTransform.java @@ -54,7 +54,7 @@ package org.apache.fop.tools.xslt; -import java.io.Writer; +import java.io.*; import java.lang.reflect.*; @@ -94,6 +94,18 @@ public class XSLTransform transform(params, argTypes); } + + public static void transform(org.w3c.dom.Document xmlSource, + InputStream xsl, + org.w3c.dom.Document outputDoc) + throws Exception + { + Class[] argTypes = {org.w3c.dom.Document.class, InputStream.class, + org.w3c.dom.Document.class}; + Object[] params = {xmlSource, xsl, outputDoc}; + transform(params, argTypes); + + } private static void transform(Object[] args, Class[] argTypes) diff --git a/src/org/apache/fop/tools/xslt/Xalan1Transform.java b/src/org/apache/fop/tools/xslt/Xalan1Transform.java index 6455f7770..ed04b46e1 100644 --- a/src/org/apache/fop/tools/xslt/Xalan1Transform.java +++ b/src/org/apache/fop/tools/xslt/Xalan1Transform.java @@ -57,6 +57,7 @@ package org.apache.fop.tools.xslt; import org.apache.xalan.xslt.*; import java.io.FileInputStream; +import java.io.InputStream; import java.util.Hashtable; import org.w3c.dom.Document; @@ -78,20 +79,13 @@ public class Xalan1Transform } // Use XSLTProcessor to instantiate an XSLTProcessor. - org.apache.xalan.xslt.XSLTProcessor processor = - org.apache.xalan.xslt.XSLTProcessorFactory.getProcessor + XSLTProcessor processor = XSLTProcessorFactory.getProcessor (new org.apache.xalan.xpath.xdom.XercesLiaison()); - org.apache.xalan.xslt.XSLTInputSource xslSheet = - new org.apache.xalan.xslt.XSLTInputSource (xsltFilename); + XSLTInputSource xslSheet = new XSLTInputSource (xsltFilename); // Perform the transformation. - /* - System.out.println("****************************"); - System.out.println("new xslt compile \nin: " + xsltFilename); - System.out.println("****************************"); - */ StylesheetRoot compiledSheet = processor.processStylesheet(xslSheet); if (cache) { @@ -126,11 +120,8 @@ public class Xalan1Transform java.net.MalformedURLException, org.xml.sax.SAXException { - // Create the 3 objects the XSLTProcessor needs to perform the transformation. - /* org.apache.xalan.xslt.XSLTInputSource source = - new org.apache.xalan.xslt.XSLTInputSource (xmlSource); */ - org.apache.xalan.xslt.XSLTResultTarget xmlResult = - new org.apache.xalan.xslt.XSLTResultTarget (outputFile); + + XSLTResultTarget xmlResult = new XSLTResultTarget (outputFile); StylesheetRoot stylesheet = getStylesheet(xslURL,true); @@ -147,11 +138,9 @@ public class Xalan1Transform java.net.MalformedURLException, org.xml.sax.SAXException { - // Create the 3 objects the XSLTProcessor needs to perform the transformation. - org.apache.xalan.xslt.XSLTInputSource source = - new org.apache.xalan.xslt.XSLTInputSource (xmlSource); - org.apache.xalan.xslt.XSLTResultTarget xmlResult = - new org.apache.xalan.xslt.XSLTResultTarget (outputFile); + + XSLTInputSource source = new XSLTInputSource (xmlSource); + XSLTResultTarget xmlResult = new XSLTResultTarget (outputFile); StylesheetRoot stylesheet = getStylesheet(xslURL,true); @@ -160,4 +149,24 @@ public class Xalan1Transform (new org.apache.xalan.xpath.xdom.XercesLiaison()), source, xmlResult); } + + public static void transform(Document xmlSource, + InputStream xsl, + Document outputDoc) + throws java.io.IOException, + java.net.MalformedURLException, + org.xml.sax.SAXException + { + + XSLTInputSource source = new XSLTInputSource (xmlSource); + XSLTInputSource xslSheet = new XSLTInputSource(xsl); + XSLTResultTarget xmlResult = new XSLTResultTarget (outputDoc); + + + // Perform the transformation. + XSLTProcessor processor = + XSLTProcessorFactory.getProcessor(new org.apache.xalan.xpath.xdom.XercesLiaison()); + + processor.process(source, xslSheet, xmlResult); + } } |