diff options
-rw-r--r-- | src/org/apache/fop/fonts/FontFileReader.java | 432 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/PFMFile.java | 417 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFCmapEntry.java | 66 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFDirTabEntry.java | 94 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFFile.java | 1312 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFMtxEntry.java | 75 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/TTFSegEntry.java | 66 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/apps/FontPostProcess.xsl | 2 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/apps/PFMReader.java | 358 | ||||
-rw-r--r-- | src/org/apache/fop/fonts/apps/TTFReader.java | 563 | ||||
-rw-r--r-- | src/org/apache/fop/layout/LineArea.java | 65 | ||||
-rw-r--r-- | src/org/apache/fop/render/pdf/FontReader.java | 134 | ||||
-rw-r--r-- | src/org/apache/fop/render/pdf/PDFRenderer.java | 582 | ||||
-rw-r--r-- | src/org/apache/fop/render/pdf/fonts/MultiByteFont.java | 300 | ||||
-rw-r--r-- | src/org/apache/fop/render/pdf/fonts/SingleByteFont.java | 14 |
15 files changed, 2102 insertions, 2378 deletions
diff --git a/src/org/apache/fop/fonts/FontFileReader.java b/src/org/apache/fop/fonts/FontFileReader.java index f6bc3cff9..e6c7ce859 100644 --- a/src/org/apache/fop/fonts/FontFileReader.java +++ b/src/org/apache/fop/fonts/FontFileReader.java @@ -1,52 +1,8 @@ /* -- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts; import java.io.FileInputStream; @@ -58,170 +14,220 @@ import java.io.IOException; 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 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 */ - 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"); - } + 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; + } + + /** + * Write a USHort at a given position + */ + public final void writeTTFUShort(int pos, int val) throws IOException { + if ((pos + 2) > fsize) + throw new java.io.EOFException("Reached EOF"); + byte b1 = (byte)((val >> 8) & 0xff); + byte b2 = (byte)(val & 0xff); + file[pos] = b1; + file[pos + 1] = b2; + } + + /** Read 2 bytes signed from InputStream at position pos + without changing current position */ + public final short readTTFShort(long pos) throws IOException { + long cp = getCurrentPos(); + seek_set(pos); + short ret = readTTFShort(); + seek_set(cp); + return ret; + } + + /** Read 2 bytes unsigned from InputStream at position pos + without changing current position */ + public final int readTTFUShort(long pos) throws IOException { + long cp = getCurrentPos(); + seek_set(pos); + int ret = readTTFUShort(); + seek_set(cp); + return 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"); + } + + /** + * Return a copy of the internal array + * @throws IOException if out of bounds + */ + public byte[] getBytes(int offset, + int length) throws java.io.IOException { + if ((offset + length) > fsize) + throw new java.io.IOException("Reached EOF"); + + byte[] ret = new byte[length]; + System.arraycopy(file, offset, ret, 0, length); + return ret; + } + + } diff --git a/src/org/apache/fop/fonts/PFMFile.java b/src/org/apache/fop/fonts/PFMFile.java index f1cae42d3..83c265437 100644 --- a/src/org/apache/fop/fonts/PFMFile.java +++ b/src/org/apache/fop/fonts/PFMFile.java @@ -1,52 +1,8 @@ /*-- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts; @@ -61,40 +17,40 @@ import java.util.Hashtable; public class PFMFile { //Header stuff - private String windowsName; - private String postscriptName; - private short dfItalic; - private int dfWeight; - private short dfCharSet; - private short dfPitchAndFamily; - private int dfAvgWidth; - private int dfMaxWidth; - private int dfMinWidth; - private short dfFirstChar; - private short dfLastChar; + private String windowsName; + private String postscriptName; + private short dfItalic; + private int dfWeight; + private short dfCharSet; + private short dfPitchAndFamily; + private int dfAvgWidth; + private int dfMaxWidth; + private int dfMinWidth; + private short dfFirstChar; + private short dfLastChar; //Extension stuff //--- //Extend Text Metrics - private int etmCapHeight; - private int etmXHeight; - private int etmLowerCaseAscent; - private int etmLowerCaseDescent; + private int etmCapHeight; + private int etmXHeight; + private int etmLowerCaseAscent; + private int etmLowerCaseDescent; //Extent table - private int[] extentTable; + private int[] extentTable; - private Hashtable kerningTab; + private Hashtable kerningTab; public PFMFile() { - kerningTab=new Hashtable(); + kerningTab = new Hashtable(); } /** - * Parses a PFM file - * - * @param inStream The stream from which to read the PFM file. - */ + * Parses a PFM file + * + * @param inStream The stream from which to read the PFM file. + */ public void load(InputStream inStream) throws IOException { InputStream bufin = new BufferedInputStream(inStream, 1024); bufin.mark(1024); @@ -103,8 +59,8 @@ public class PFMFile { long filesize = in.readInt(); bufin.reset(); - byte[] buf = new byte[(int)filesize]; - bufin.read(buf, 0, (int)filesize); + byte[] buf = new byte[(int) filesize]; + bufin.read(buf, 0, (int) filesize); bufin = new ByteArrayInputStream(buf); in = new PFMInputStream(bufin); @@ -113,10 +69,10 @@ public class PFMFile { } /** - * Parses the header of the PFM file. - * - * @param inStream The stream from which to read the PFM file. - */ + * Parses the header of the PFM file. + * + * @param inStream The stream from which to read the PFM file. + */ private void loadHeader(PFMInputStream inStream) throws IOException { inStream.skip(80); dfItalic = inStream.readByte(); @@ -128,9 +84,9 @@ public class PFMFile { dfAvgWidth = inStream.readShort(); dfMaxWidth = inStream.readShort(); dfFirstChar = inStream.readByte(); - dfLastChar = inStream.readByte(); + dfLastChar = inStream.readByte(); inStream.skip(8); - long faceOffset = inStream.readInt(); + long faceOffset = inStream.readInt(); inStream.reset(); inStream.skip(faceOffset); @@ -141,10 +97,10 @@ public class PFMFile { } /** - * Parses the extension part of the PFM file. - * - * @param inStream The stream from which to read the PFM file. - */ + * Parses the extension part of the PFM file. + * + * @param inStream The stream from which to read the PFM file. + */ private void loadExtension(PFMInputStream inStream) throws IOException { int size = inStream.readShort(); long extMetricsOffset = inStream.readInt(); @@ -155,11 +111,11 @@ public class PFMFile { long driverInfoOffset = inStream.readInt(); if (kernPairOffset > 0) { - inStream.reset(); - inStream.skip(kernPairOffset); - loadKernPairs(inStream); + inStream.reset(); + inStream.skip(kernPairOffset); + loadKernPairs(inStream); } - + inStream.reset(); inStream.skip(driverInfoOffset); postscriptName = inStream.readString(); @@ -178,190 +134,195 @@ public class PFMFile { } /** - * Parses the kernPairs part of the pfm file - * - * @param inStream The stream from which to read the PFM file. - */ + * 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(new Integer(g1)); - if (adjTab==null) - adjTab=new Hashtable(); - adjTab.put(new Integer(g2), new Integer(adj)); - kerningTab.put(new Integer(g1), adjTab); + 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(new Integer(g1)); + if (adjTab == null) + adjTab = new Hashtable(); + adjTab.put(new Integer(g2), new Integer(adj)); + kerningTab.put(new Integer(g1), adjTab); } } /** - * Parses the extended metrics part of the PFM file. - * - * @param inStream The stream from which to read the PFM file. - */ - private void loadExtMetrics(PFMInputStream inStream) throws IOException { + * Parses the extended metrics part of the PFM file. + * + * @param inStream The stream from which to read the PFM file. + */ + private void loadExtMetrics(PFMInputStream inStream) + throws IOException { int size = inStream.readShort(); inStream.skip(12); - etmCapHeight = inStream.readShort(); - etmXHeight = inStream.readShort(); - etmLowerCaseAscent = inStream.readShort(); + etmCapHeight = inStream.readShort(); + etmXHeight = inStream.readShort(); + etmLowerCaseAscent = inStream.readShort(); etmLowerCaseDescent = inStream.readShort(); } /** - * Parses the extent table of the PFM file. - * - * @param inStream The stream from which to read the PFM file. - */ - private void loadExtentTable(PFMInputStream inStream) throws IOException { - extentTable = new int[dfLastChar-dfFirstChar]; + * Parses the extent table of the PFM file. + * + * @param inStream The stream from which to read the PFM file. + */ + private void loadExtentTable(PFMInputStream inStream) + throws IOException { + extentTable = new int[dfLastChar - dfFirstChar + 1]; dfMinWidth = dfMaxWidth; - for (short i = dfFirstChar; i < dfLastChar; i++) { - extentTable[i-dfFirstChar] = inStream.readShort(); - if (extentTable[i-dfFirstChar] < dfMinWidth) { - dfMinWidth = extentTable[i-dfFirstChar]; + for (short i = dfFirstChar; i <= dfLastChar; i++) { + extentTable[i - dfFirstChar] = inStream.readShort(); + if (extentTable[i - dfFirstChar] < dfMinWidth) { + dfMinWidth = extentTable[i - dfFirstChar]; } } } /** - * Returns the Windows name of the font. - * - * @return The Windows name. - */ + * Returns the Windows name of the font. + * + * @return The Windows name. + */ public String getWindowsName() { 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. - * - * @return The Postscript name. - */ + * 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. + * + * @return The Postscript name. + */ public String getPostscriptName() { return postscriptName; } /** - * Returns the charset used for the font. - * - * @return The charset (0=WinAnsi). - */ + * Returns the charset used for the font. + * + * @return The charset (0=WinAnsi). + */ public short getCharSet() { return dfCharSet; } /** - * Returns the charset of the font as a string. - * - * @return The name of the charset. - */ + * Returns the charset of the font as a string. + * + * @return The name of the charset. + */ public String getCharSetName() { switch (dfCharSet) { - case 0: return "WinAnsi"; - case 128: return "Shift-JIS (Japanese)"; - default: return "Unknown"; + case 0: + return "WinAnsi"; + case 128: + return "Shift-JIS (Japanese)"; + default: + return "Unknown"; } } /** - * Returns the number of the character that defines - * the first entry in the widths list. - * - * @return The number of the first character. - */ + * Returns the number of the character that defines + * the first entry in the widths list. + * + * @return The number of the first character. + */ public short getFirstChar() { return dfFirstChar; } /** - * Returns the number of the character that defines - * the last entry in the widths list. - * - * @return The number of the last character. - */ + * Returns the number of the character that defines + * the last entry in the widths list. + * + * @return The number of the last character. + */ public short getLastChar() { return dfLastChar; } /** - * Returns the CapHeight parameter for the font (height of uppercase H). - * - * @return The CapHeight parameter. - */ + * Returns the CapHeight parameter for the font (height of uppercase H). + * + * @return The CapHeight parameter. + */ public int getCapHeight() { return etmCapHeight; } /** - * Returns the XHeight parameter for the font (height of lowercase x). - * - * @return The CapHeight parameter. - */ + * Returns the XHeight parameter for the font (height of lowercase x). + * + * @return The CapHeight parameter. + */ public int getXHeight() { return etmXHeight; } /** - * Returns the LowerCaseAscent parameter for the font (height of lowercase d). - * - * @return The LowerCaseAscent parameter. - */ + * Returns the LowerCaseAscent parameter for the font (height of lowercase d). + * + * @return The LowerCaseAscent parameter. + */ public int getLowerCaseAscent() { return etmLowerCaseAscent; } /** - * Returns the LowerCaseDescent parameter for the font (height of lowercase p). - * - * @return The LowerCaseDescent parameter. - */ + * Returns the LowerCaseDescent parameter for the font (height of lowercase p). + * + * @return The LowerCaseDescent parameter. + */ public int getLowerCaseDescent() { return etmLowerCaseDescent; } /** - * Tells whether the font has proportional character spacing. - * - * @return ex. true for Times, false for Courier. - */ + * Tells whether the font has proportional character spacing. + * + * @return ex. true for Times, false for Courier. + */ public boolean getIsProportional() { return ((dfPitchAndFamily & 1) == 1); } /** - * Returns the bounding box for the font. - * Note: this value is just an approximation, - * it does not really exist in the PFM file. - * - * @return The calculated Font BBox. - */ + * Returns the bounding box for the font. + * Note: this value is just an approximation, + * it does not really exist in the PFM file. + * + * @return The calculated Font BBox. + */ public int[] getFontBBox() { int[] bbox = new int[4]; @@ -378,44 +339,54 @@ public class PFMFile { } /** - * Returns the characteristics flags for the font as - * needed for a PDF font descriptor (See PDF specs). - * - * @return The characteristics flags. - */ + * Returns the characteristics flags for the font as + * needed for a PDF font descriptor (See PDF specs). + * + * @return The characteristics flags. + */ public int getFlags() { int flags = 0; - if (!getIsProportional()) { flags |= 1; } - if ((dfPitchAndFamily & 16) == 16) { flags |= 2; } - if ((dfPitchAndFamily & 64) == 64) { flags |= 4; } - if (dfCharSet == 0) { flags |= 6; } - if (dfItalic != 0) { flags |= 7; } + if (!getIsProportional()) { + flags |= 1; + } + if ((dfPitchAndFamily & 16) == 16) { + flags |= 2; + } + if ((dfPitchAndFamily & 64) == 64) { + flags |= 4; + } + if (dfCharSet == 0) { + flags |= 6; + } + if (dfItalic != 0) { + flags |= 7; + } return flags; } /** - * Returns the width of the dominant vertical stems of the font. - * Note: this value is just an approximation, - * it does not really exist in the PFM file. - * - * @return The vertical stem width. - */ + * Returns the width of the dominant vertical stems of the font. + * Note: this value is just an approximation, + * it does not really exist in the PFM file. + * + * @return The vertical stem width. + */ public int getStemV() { //Just guessing.... if (dfItalic != 0) { - return (int)Math.round(dfMinWidth * 0.25); + return (int) Math.round(dfMinWidth * 0.25); } else { - return (int)Math.round(dfMinWidth * 0.6); + return (int) Math.round(dfMinWidth * 0.6); } } /** - * Returns the italic angle of the font. - * Note: this value is just an approximation, - * it does not really exist in the PFM file. - * - * @return The italic angle. - */ + * Returns the italic angle of the font. + * Note: this value is just an approximation, + * it does not really exist in the PFM file. + * + * @return The italic angle. + */ public int getItalicAngle() { if (dfItalic != 0) { return -16; //Just guessing.... @@ -425,12 +396,12 @@ public class PFMFile { } /** - * Returns the width of a character - * - * @param which The number of the character for which the width is requested. - * @return The width of a character. - */ + * Returns the width of a character + * + * @param which The number of the character for which the width is requested. + * @return The width of a character. + */ public int getCharWidth(short which) { - return extentTable[which-dfFirstChar]; + return extentTable[which - dfFirstChar]; } } diff --git a/src/org/apache/fop/fonts/TTFCmapEntry.java b/src/org/apache/fop/fonts/TTFCmapEntry.java index 3e8dd746a..b4a9c3bbc 100644 --- a/src/org/apache/fop/fonts/TTFCmapEntry.java +++ b/src/org/apache/fop/fonts/TTFCmapEntry.java @@ -1,52 +1,8 @@ /* -- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts; @@ -58,16 +14,14 @@ public class TTFCmapEntry { public int unicodeStart; public int unicodeEnd; public int glyphStartIndex; - + TTFCmapEntry() { unicodeStart = 0; unicodeEnd = 0; glyphStartIndex = 0; } - TTFCmapEntry (int unicodeStart, - int unicodeEnd, - int glyphStartIndex) { + TTFCmapEntry (int unicodeStart, int unicodeEnd, int glyphStartIndex) { this.unicodeStart = unicodeStart; this.unicodeEnd = unicodeEnd; this.glyphStartIndex = glyphStartIndex; @@ -75,13 +29,13 @@ public class TTFCmapEntry { public boolean equals (Object o) { if (o instanceof TTFCmapEntry) { - TTFCmapEntry ce = (TTFCmapEntry)o; + TTFCmapEntry ce = (TTFCmapEntry) o; if (ce.unicodeStart == this.unicodeStart && - ce.unicodeEnd == this.unicodeEnd && - ce.glyphStartIndex == this.glyphStartIndex) + ce.unicodeEnd == this.unicodeEnd && + ce.glyphStartIndex == this.glyphStartIndex) return true; } return false; } - + } diff --git a/src/org/apache/fop/fonts/TTFDirTabEntry.java b/src/org/apache/fop/fonts/TTFDirTabEntry.java index 30f0c4cfe..9a2b0ea12 100644 --- a/src/org/apache/fop/fonts/TTFDirTabEntry.java +++ b/src/org/apache/fop/fonts/TTFDirTabEntry.java @@ -1,52 +1,8 @@ /* -- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts; import java.io.*; @@ -56,32 +12,32 @@ class TTFDirTabEntry { int checksum; long offset; long length; - + TTFDirTabEntry() { tag = new byte[4]; } - - /** Read Dir Tab, return tag name */ + + /** 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(); - + 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)); - */ + + 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 index 02c49bfe1..682233dbc 100644 --- a/src/org/apache/fop/fonts/TTFFile.java +++ b/src/org/apache/fop/fonts/TTFFile.java @@ -1,52 +1,8 @@ /* -- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts; import java.io.*; @@ -64,33 +20,34 @@ public class TTFFile { static final int NMACGLYPHS = 258; static final int MAX_CHAR_CODE = 255; static final int ENC_BUF_SIZE = 1024; - - static String encoding="WinAnsiEncoding"; // Deafult encoding - short firstChar=0; - boolean is_embeddable=true; - boolean hasSerifs=true; - Hashtable dirTabs; // Table directory + + static String encoding = "WinAnsiEncoding"; // Deafult encoding + short firstChar = 0; + boolean is_embeddable = true; + boolean hasSerifs = true; + Hashtable dirTabs; // Table directory Hashtable kerningTab; // for CIDs Hashtable ansiKerningTab; // For winAnsiEncoding Vector cmaps; Vector unicodeMapping; // - - int upem; // unitsPerEm from "head" table + + int upem; // unitsPerEm from "head" table int nhmtx; // Number of horizontal metrics int post_format; int loca_format; + long lastLoca = 0; // offset to last loca int nglyphs; // Number of glyphs in font (read from "maxp" table) int nmglyphs; // Used in fixWidths - remove? - + TTFMtxEntry mtx_tab[]; // Contains glyph data - int[] mtx_encoded=null; - - String fontName=""; - String fullName=""; - String notice=""; - String familyName=""; - String subFamilyName=""; - + int[] mtx_encoded = null; + + String fontName = ""; + String fullName = ""; + String notice = ""; + String familyName = ""; + String subFamilyName = ""; + long italicAngle = 0; long isFixedPitch = 0; int fontBBox1 = 0; @@ -108,158 +65,157 @@ public class TTFFile { int ansiWidth[]; Hashtable ansiIndex; - - /** 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) { + + /** 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); + + in.seek_set(dt.offset + offset); } - - /** Convert from truetype unit to pdf unit based on the - * unitsPerEm field in the "head" table - @param n truetype unit - @return pdf unit - */ + + /** Convert from truetype unit to pdf unit based on the + * unitsPerEm field in the "head" table + @param n truetype unit + @return pdf unit + */ 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); + 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; + ret = (n / upem) * 1000 + ((n % upem) * 1000) / upem; } - + return ret; } - - /** Read the cmap table, - * return false if the table is not present or only unsupported - * tables are present. Currently only unicode cmaps are supported. - * Set the unicodeIndex in the TTFMtxEntries and fills in the - * cmaps vector. - */ - private boolean readCMAP(FontFileReader in) - throws IOException { + + /** Read the cmap table, + * return false if the table is not present or only unsupported + * tables are present. Currently only unicode cmaps are supported. + * Set the unicodeIndex in the TTFMtxEntries and fills in the + * cmaps vector. + */ + private boolean readCMAP(FontFileReader in) throws IOException { unicodeMapping = new Vector(); - - /** Read CMAP table and correct mtx_tab.index*/ - int mtxPtr=0; - + + /** Read CMAP table and correct mtx_tab.index*/ + int mtxPtr = 0; + seek_tab(in, "cmap", 2); - int num_cmap=in.readTTFUShort(); // Number of cmap subtables - long cmap_unioffset=0; - - //System.out.println(num_cmap+" cmap tables"); - - /* Read offset for all tables - We are only interested in the unicode table - */ - for (int i=0; i< num_cmap; i++) { - int cmap_pid=in.readTTFUShort(); - int cmap_eid=in.readTTFUShort(); - long cmap_offset=in.readTTFULong(); - - //System.out.println("Platform ID: "+cmap_pid+ - // " Encoding: "+cmap_eid); - - if (cmap_pid==3 && cmap_eid==1) - cmap_unioffset=cmap_offset; + int num_cmap = in.readTTFUShort(); // Number of cmap subtables + long cmap_unioffset = 0; + + //System.out.println(num_cmap+" cmap tables"); + + /* Read offset for all tables + We are only interested in the unicode table + */ + for (int i = 0; i < num_cmap; i++) { + int cmap_pid = in.readTTFUShort(); + int cmap_eid = in.readTTFUShort(); + long cmap_offset = in.readTTFULong(); + + //System.out.println("Platform ID: "+cmap_pid+ + // " Encoding: "+cmap_eid); + + if (cmap_pid == 3 && cmap_eid == 1) + cmap_unioffset = cmap_offset; } - + if (cmap_unioffset <= 0) { System.out.println("Unicode cmap table not present"); return false; } - - // Read unicode cmap + + // Read unicode cmap seek_tab(in, "cmap", cmap_unioffset); - int cmap_format=in.readTTFUShort(); - int cmap_length=in.readTTFUShort(); - - //System.out.println("CMAP format: "+cmap_format); - if (cmap_format==4) { + int cmap_format = in.readTTFUShort(); + int cmap_length = in.readTTFUShort(); + + //System.out.println("CMAP format: "+cmap_format); + if (cmap_format == 4) { in.skip(2); // Skip version number - int cmap_segCountX2=in.readTTFUShort(); - int cmap_searchRange=in.readTTFUShort(); - int cmap_entrySelector=in.readTTFUShort(); - int cmap_rangeShift=in.readTTFUShort(); + int cmap_segCountX2 = in.readTTFUShort(); + int cmap_searchRange = in.readTTFUShort(); + int cmap_entrySelector = in.readTTFUShort(); + int cmap_rangeShift = in.readTTFUShort(); + + /* + System.out.println("segCountX2 : "+cmap_segCountX2); + System.out.println("searchRange : "+cmap_searchRange); + System.out.println("entrySelector: "+cmap_entrySelector); + System.out.println("rangeShift : "+cmap_rangeShift); + */ - /* - System.out.println("segCountX2 : "+cmap_segCountX2); - System.out.println("searchRange : "+cmap_searchRange); - System.out.println("entrySelector: "+cmap_entrySelector); - System.out.println("rangeShift : "+cmap_rangeShift); - */ - - int cmap_endCounts[]=new int[cmap_segCountX2/2]; - int cmap_startCounts[]=new int[cmap_segCountX2/2]; - int cmap_deltas[]=new int[cmap_segCountX2/2]; - int cmap_rangeOffsets[]=new int[cmap_segCountX2/2]; - - for (int i=0; i < (cmap_segCountX2/2); i++) { - cmap_endCounts[i]=in.readTTFUShort(); + int cmap_endCounts[] = new int[cmap_segCountX2 / 2]; + int cmap_startCounts[] = new int[cmap_segCountX2 / 2]; + int cmap_deltas[] = new int[cmap_segCountX2 / 2]; + int cmap_rangeOffsets[] = new int[cmap_segCountX2 / 2]; + + for (int i = 0; i < (cmap_segCountX2 / 2); i++) { + cmap_endCounts[i] = in.readTTFUShort(); } - + in.skip(2); // Skip reservedPad - - for (int i=0; i < (cmap_segCountX2/2); i++) { - cmap_startCounts[i]=in.readTTFUShort(); + + for (int i = 0; i < (cmap_segCountX2 / 2); i++) { + cmap_startCounts[i] = in.readTTFUShort(); } - - for (int i=0; i < (cmap_segCountX2/2); i++) { - cmap_deltas[i]=in.readTTFShort(); + + for (int i = 0; i < (cmap_segCountX2 / 2); i++) { + cmap_deltas[i] = in.readTTFShort(); } - - int startRangeOffset=in.getCurrentPos(); - - for (int i=0; i < (cmap_segCountX2/2); i++) { - cmap_rangeOffsets[i]=in.readTTFShort(); + + int startRangeOffset = in.getCurrentPos(); + + for (int i = 0; i < (cmap_segCountX2 / 2); i++) { + cmap_rangeOffsets[i] = in.readTTFShort(); } - - int glyphIdArrayOffset=in.getCurrentPos(); - - // Insert the unicode id for the glyphs in mtx_tab - // and fill in the cmaps Vector - + + int glyphIdArrayOffset = in.getCurrentPos(); + + // Insert the unicode id for the glyphs in mtx_tab + // and fill in the cmaps Vector + for (int i = 0; i < cmap_startCounts.length; i++) { - /* - System.out.println(i+ ": "+cmap_startCounts[i]+ - " - "+cmap_endCounts[i]); - */ - for (int j=cmap_startCounts[i]; - j <= cmap_endCounts[i]; j++) { - - // Update lastChar - if (j < 256 && j > lastChar) - lastChar = (short)j; - + /* + System.out.println(i+ ": "+cmap_startCounts[i]+ + " - "+cmap_endCounts[i]); + */ + for (int j = cmap_startCounts[i]; + j <= cmap_endCounts[i]; j++) { + + // Update lastChar + if (j < 256 && j > lastChar) + lastChar = (short) j; + if (mtxPtr < mtx_tab.length) { if (cmap_rangeOffsets[i] != 0) { - int glyphOffset = glyphIdArrayOffset+ - ((cmap_rangeOffsets[i]/2)+ - (j-cmap_startCounts[i])+ - (i)- - cmap_segCountX2/2)*2; + int glyphOffset = glyphIdArrayOffset + + ((cmap_rangeOffsets[i] / 2) + + (j - cmap_startCounts[i]) + (i) - + cmap_segCountX2 / 2) * 2; in.seek_set(glyphOffset); - int glyphIdx=(in.readTTFUShort()+ - cmap_deltas[i]) & 0xffff; + int glyphIdx = (in.readTTFUShort() + + cmap_deltas[i]) & 0xffff; unicodeMapping.addElement( - new UnicodeMapping(glyphIdx, j)); - mtx_tab[glyphIdx].unicodeIndex.addElement(new Integer(j)); + new UnicodeMapping(glyphIdx, j)); + mtx_tab[glyphIdx].unicodeIndex.addElement( + new Integer(j)); - // Also add winAnsiWidth + // Also add winAnsiWidth if (false) { int d = j; if (j > 127) @@ -268,71 +224,89 @@ public class TTFFile { if (d < ansiWidth.length) ansiWidth[d] = mtx_tab[glyphIdx].wx; } else { - Vector v= - (Vector)ansiIndex.get(new Integer(j)); + Vector v = (Vector) ansiIndex.get( + new Integer(j)); if (v != null) { - for (Enumeration e=v.elements(); - e.hasMoreElements();) { - Integer aIdx = (Integer)e.nextElement(); - ansiWidth[aIdx.intValue()]= - mtx_tab[glyphIdx].wx; - /* - System.out.println("Added width "+ - mtx_tab[glyphIdx].wx + - " uni: " + j + - " ansi: " + aIdx.intValue()); - */ + for (Enumeration e = v.elements(); + e.hasMoreElements();) { + Integer aIdx = + (Integer) e.nextElement(); + ansiWidth[aIdx.intValue()] = + mtx_tab[glyphIdx].wx; + /* + System.out.println("Added width "+ + mtx_tab[glyphIdx].wx + + " uni: " + j + + " ansi: " + aIdx.intValue()); + */ } } } - /* - System.out.println("Idx: "+ - glyphIdx + - " Delta: " + cmap_deltas[i]+ - " Unicode: " + j + - " name: " + - mtx_tab[glyphIdx].name); - */ - - } else { - int glyphIdx=(j+cmap_deltas[i]) & 0xffff; - - mtx_tab[glyphIdx].unicodeIndex.addElement(new Integer(j)); - + /* + System.out.println("Idx: "+ + glyphIdx + + " Delta: " + cmap_deltas[i]+ + " Unicode: " + j + + " name: " + + mtx_tab[glyphIdx].name); + */ + + } + else { + + int glyphIdx = (j + cmap_deltas[i]) & 0xffff; + + if (glyphIdx < mtx_tab.length) + mtx_tab[glyphIdx] .unicodeIndex.addElement( + new Integer(j)); + else + System.out.println("Glyph " + + glyphIdx + " out of range: " + + mtx_tab.length); + unicodeMapping.addElement( - new UnicodeMapping(glyphIdx, - j)); + new UnicodeMapping(glyphIdx, j)); + if (glyphIdx < mtx_tab.length) + mtx_tab[glyphIdx] .unicodeIndex.addElement( + new Integer(j)); + else + System.out.println("Glyph " + + glyphIdx + " out of range: " + + mtx_tab.length); + - // Also add winAnsiWidth + + // Also add winAnsiWidth if (false) { int d = j; if (j > 127) d = (int) org.apache.fop.render.pdf.CodePointMapping.map[j]; - + if (d < ansiWidth.length) ansiWidth[d] = mtx_tab[glyphIdx].wx; } else { - Vector v= - (Vector)ansiIndex.get(new Integer(j)); + Vector v = (Vector) ansiIndex.get( + new Integer(j)); if (v != null) { - for (Enumeration e=v.elements(); - e.hasMoreElements();) { - Integer aIdx = (Integer)e.nextElement(); - ansiWidth[aIdx.intValue()]= - mtx_tab[glyphIdx].wx; + for (Enumeration e = v.elements(); + e.hasMoreElements();) { + Integer aIdx = + (Integer) e.nextElement(); + ansiWidth[aIdx.intValue()] = + mtx_tab[glyphIdx].wx; } } } - - /* - System.out.println("IIdx: "+ - mtxPtr + - " Delta: " + cmap_deltas[i]+ - " Unicode: " + j + - " name: " + - mtx_tab[(j+cmap_deltas[i]) & 0xffff].name); - */ + + /* + System.out.println("IIdx: "+ + mtxPtr + + " Delta: " + cmap_deltas[i]+ + " Unicode: " + j + + " name: " + + mtx_tab[(j+cmap_deltas[i]) & 0xffff].name); + */ } mtxPtr++; } @@ -341,16 +315,16 @@ public class TTFFile { } return true; } - - - - /** - * Print first char/last char - */ + + + + /** + * Print first char/last char + */ private void print_max_min() { - int min=255; - int max=0; - for (int i=0; i < mtx_tab.length; i++) { + int min = 255; + int max = 0; + for (int i = 0; i < mtx_tab.length; i++) { if (mtx_tab[i].index < min) min = mtx_tab[i].index; if (mtx_tab[i].index > max) @@ -361,26 +335,26 @@ public class TTFFile { } public void readFont(FontFileReader in) throws IOException { - readFont(in, (String)null); + readFont(in, (String) null); } - /** initialize the ansiWidths array (for winAnsiEncoding) - * and fill with the missingwidth - */ + /** initialize the ansiWidths array (for winAnsiEncoding) + * and fill with the missingwidth + */ private void initAnsiWidths() { - ansiWidth=new int[256]; + ansiWidth = new int[256]; for (int i = 0; i < 256; i++) ansiWidth[i] = mtx_tab[0].wx; - // Create an index hash to the ansiWidth - // Can't just index the winAnsiEncoding when inserting widths - // same char (eg bullet) is repeated more than one place - ansiIndex=new Hashtable(); - for (int i=32; i < Glyphs.winAnsiEncoding.length; i++) { + // Create an index hash to the ansiWidth + // Can't just index the winAnsiEncoding when inserting widths + // same char (eg bullet) is repeated more than one place + ansiIndex = new Hashtable(); + for (int i = 32; i < Glyphs.winAnsiEncoding.length; i++) { Integer ansi = new Integer(i); - Integer uni = new Integer((int)Glyphs.winAnsiEncoding[i]); - - Vector v = (Vector)ansiIndex.get(uni); + Integer uni = new Integer((int) Glyphs.winAnsiEncoding[i]); + + Vector v = (Vector) ansiIndex.get(uni); if (v == null) { v = new Vector(); ansiIndex.put(uni, v); @@ -389,23 +363,26 @@ public class TTFFile { } } - - /** - * Read the font data - * If the fontfile is a TrueType Collection (.ttf file) - * The name of the font to read data for must be supplied, - * else the name is ignored - */ - public void readFont(FontFileReader in, String name) throws IOException { - - /* Check if TrueType collection, and that the name - exists in the collection - */ - if (!checkTTC(in, name)) + + /** + * Read the font data + * If the fontfile is a TrueType Collection (.ttc file) + * The name of the font to read data for must be supplied, + * else the name is ignored + */ + public void readFont(FontFileReader in, + String name) throws IOException { + + /* Check if TrueType collection, and that the name + exists in the collection + */ + if (!checkTTC(in, name, true)) throw new IOException("Failed to read font"); - + readDirTabs(in); readFontHeader(in); + getNumGlyphs(in); + System.out.println("Number of glyphs in font: " + nglyphs); readHorizontalHeader(in); readHorizontalMetrics(in); initAnsiWidths(); @@ -417,8 +394,8 @@ public class TTFFile { readPCLT(in); readCMAP(in); // Read cmap table and fill in ansiwidths createCMaps(); // Create cmaps for bfentries - //print_max_min(); - + //print_max_min(); + readKerning(in); } @@ -427,26 +404,26 @@ public class TTFFile { TTFCmapEntry tce = new TTFCmapEntry(); Enumeration e = unicodeMapping.elements(); - UnicodeMapping um = (UnicodeMapping)e.nextElement(); + UnicodeMapping um = (UnicodeMapping) e.nextElement(); UnicodeMapping lastMapping = um; - + tce.unicodeStart = um.uIdx; tce.glyphStartIndex = um.gIdx; while (e.hasMoreElements()) { - um = (UnicodeMapping)e.nextElement(); - if (((lastMapping.uIdx+1) != um.uIdx) || - ((lastMapping.gIdx+1) != um.gIdx)) { + um = (UnicodeMapping) e.nextElement(); + if (((lastMapping.uIdx + 1) != um.uIdx) || + ((lastMapping.gIdx + 1) != um.gIdx)) { tce.unicodeEnd = lastMapping.uIdx; cmaps.addElement(tce); - + tce = new TTFCmapEntry(); tce.unicodeStart = um.uIdx; tce.glyphStartIndex = um.gIdx; } lastMapping = um; } - + tce.unicodeEnd = um.uIdx; cmaps.addElement(tce); } @@ -457,51 +434,52 @@ public class TTFFile { 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("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.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)+"]"); + 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 ttfFile = new TTFFile(); + FontFileReader reader = new FontFileReader(args[0]); - String name=null; + String name = null; if (args.length >= 2) - name=args[1]; - + name = args[1]; + ttfFile.readFont(reader, name); ttfFile.printStuff(); - + } catch (IOException ioe) { System.out.println(ioe.toString()); } } - + public String getWindowsName() { - return new String(familyName+","+subFamilyName); + return new String(familyName + ","+subFamilyName); } - + public String getPostscriptName() { if ("Regular".equals(subFamilyName) || - "Roman".equals(subFamilyName)) + "Roman".equals(subFamilyName)) return familyName; else - return familyName+","+subFamilyName; + return familyName + ","+subFamilyName; } public String getFamilyName() { return familyName; @@ -510,14 +488,14 @@ public class TTFFile { return encoding; } public int getCapHeight() { - return (int)get_ttf_funit(capHeight); + return (int) get_ttf_funit(capHeight); } public int getXHeight() { - return (int)get_ttf_funit(xHeight); + return (int) get_ttf_funit(xHeight); } - + public int getFlags() { - int flags=32; // Use Adobe Standard charset + int flags = 32; // Use Adobe Standard charset if (italicAngle != 0) flags = flags | 64; if (isFixedPitch != 0) @@ -527,39 +505,43 @@ public class TTFFile { 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))); - + String ia = Short.toString((short)(italicAngle / 0x10000)); + + // This is the correct italic angle, however only int italic + // angles are supported at the moment so this is commented out. + /* + if ((italicAngle % 0x10000) > 0 ) + ia=ia+(comma+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); - + 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); + return (int) get_ttf_funit(ascender); } - + public int getLowerCaseDescent() { - return (int)get_ttf_funit(descender); + return (int) get_ttf_funit(descender); } - - // This is only for WinAnsiEncoding, so the last char is - // the last char < 256 + + // This is only for WinAnsiEncoding, so the last char is + // the last char < 256 public short getLastChar() { return lastChar; } @@ -571,192 +553,195 @@ public class TTFFile { public int[] getWidths() { int[] wx = new int[mtx_tab.length]; for (int i = 0; i < wx.length; i++) - wx[i] = (int)get_ttf_funit(mtx_tab[i].wx); + wx[i] = (int) get_ttf_funit(mtx_tab[i].wx); return wx; } - + public int getCharWidth(int idx) { - return (int)get_ttf_funit(ansiWidth[idx]); + return (int) get_ttf_funit(ansiWidth[idx]); } - + public Hashtable getKerning() { return kerningTab; } - + public Hashtable getAnsiKerning() { return ansiKerningTab; } - + public boolean isEmbeddable() { return is_embeddable; } - - - /** - * Read Table Directory from the current position in the - * FontFileReader and fill the global Hashtable dirTabs - * with the table name (String) as key and a TTFDirTabEntry - * as value. - */ - private void readDirTabs(FontFileReader in) throws IOException { + + + /** + * Read Table Directory from the current position in the + * FontFileReader and fill the global Hashtable dirTabs + * with the table name (String) as key and a TTFDirTabEntry + * as value. + */ + protected void readDirTabs(FontFileReader in) throws IOException { in.skip(4); // TTF_FIXED_SIZE - int ntabs=in.readTTFUShort(); + int ntabs = in.readTTFUShort(); in.skip(6); // 3xTTF_USHORT_SIZE - - dirTabs=new Hashtable(); - TTFDirTabEntry[] pd=new TTFDirTabEntry[ntabs]; - //System.out.println("Reading " + ntabs + " dir tables"); - for (int i=0; i < ntabs; i++) { - pd[i]=new TTFDirTabEntry(); - dirTabs.put(pd[i].read(in), - pd[i]); + + dirTabs = new Hashtable(); + TTFDirTabEntry[] pd = new TTFDirTabEntry[ntabs]; + //System.out.println("Reading " + ntabs + " dir tables"); + for (int i = 0; i < ntabs; i++) { + pd[i] = new TTFDirTabEntry(); + dirTabs.put(pd[i].read(in), pd[i]); } } - /** - * Read the "head" table, this reads the bounding box and - * sets the upem (unitsPerEM) variable - */ - private void readFontHeader(FontFileReader in) throws IOException { - seek_tab(in, "head", 2*4 + 2*4 + 2); - upem=in.readTTFUShort(); + /** + * Read the "head" table, this reads the bounding box and + * sets the upem (unitsPerEM) variable + */ + protected void readFontHeader(FontFileReader in) throws IOException { + 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(); + + fontBBox1 = in.readTTFShort(); + fontBBox2 = in.readTTFShort(); + fontBBox3 = in.readTTFShort(); + fontBBox4 = in.readTTFShort(); + + in.skip(2 + 2 + 2); + + loca_format = in.readTTFShort(); } - /** - * Read the number of glyphs from the "maxp" table - */ - private void getNumGlyphs(FontFileReader in) throws IOException { + /** + * Read the number of glyphs from the "maxp" table + */ + protected void getNumGlyphs(FontFileReader in) throws IOException { seek_tab(in, "maxp", 4); - nglyphs=in.readTTFUShort(); - System.out.println("Number of glyphs in font: " + nglyphs); + nglyphs = in.readTTFUShort(); } - /** Read the "hhea" table to find the ascender and descender and - * size of "hmtx" table, i.e. a fixed size font might have only - * one width - */ - private void readHorizontalHeader(FontFileReader in) throws IOException { + /** Read the "hhea" table to find the ascender and descender and + * size of "hmtx" table, i.e. a fixed size font might have only + * one width + */ + protected void readHorizontalHeader(FontFileReader in) + throws IOException { 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("Number of horizontal metrics: " + nhmtx); + 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("Number of horizontal metrics: " + nhmtx); } - /** - * Read "hmtx" table and put the horizontal metrics - * in the mtx_tab array. If the number of metrics is less - * than the number of glyphs (eg fixed size fonts), extend - * the mtx_tab array and fill in the missing widths - */ - private void readHorizontalMetrics(FontFileReader in) throws IOException { + /** + * Read "hmtx" table and put the horizontal metrics + * in the mtx_tab array. If the number of metrics is less + * than the number of glyphs (eg fixed size fonts), extend + * the mtx_tab array and fill in the missing widths + */ + protected void readHorizontalMetrics(FontFileReader in) + throws IOException { seek_tab(in, "hmtx", 0); - - int mtx_size=(nglyphs > nhmtx) ? nglyphs : nhmtx; - mtx_tab=new TTFMtxEntry[mtx_size]; - - //System.out.println("*** Widths array: \n"); - for (int i=0; i < mtx_size; i++) - mtx_tab[i]=new TTFMtxEntry(); - for (int i=0; i < nhmtx; i++) { - mtx_tab[i].wx=in.readTTFUShort(); - /* - System.out.println(" width["+i+"] = "+ - get_ttf_funit(mtx_tab[i].wx)+";"); - */ - in.skip(2); // Skip left side bearing + + int mtx_size = (nglyphs > nhmtx) ? nglyphs : nhmtx; + mtx_tab = new TTFMtxEntry[mtx_size]; + + //System.out.println("*** Widths array: \n"); + for (int i = 0; i < mtx_size; i++) + mtx_tab[i] = new TTFMtxEntry(); + for (int i = 0; i < nhmtx; i++) { + mtx_tab[i].wx = in.readTTFUShort(); + mtx_tab[i].lsb = in.readTTFUShort(); + /* + System.out.println(" width["+i+"] = "+ + get_ttf_funit(mtx_tab[i].wx)+";"); + */ } if (nhmtx < mtx_size) { - // Fill in the missing widths - int lastWidth=mtx_tab[nhmtx-1].wx; - for (int i=nhmtx; i < mtx_size; i++) { - mtx_tab[i].wx=lastWidth; + // Fill in the missing widths + int lastWidth = mtx_tab[nhmtx - 1].wx; + for (int i = nhmtx; i < mtx_size; i++) { + mtx_tab[i].wx = lastWidth; + mtx_tab[i].lsb = in.readTTFUShort(); } } } - /** - * Read the "post" table - * containing the postscript names of the glyphs. - */ - private final void readPostscript(FontFileReader in) throws IOException { + /** + * Read the "post" table + * containing the postscript names of the glyphs. + */ + private final void readPostscript(FontFileReader in) + throws IOException { String[] ps_glyphs_buf; int i, k, l; - + seek_tab(in, "post", 0); - post_format=in.readTTFLong(); - italicAngle=in.readTTFULong(); - underlinePosition=in.readTTFShort(); - underlineThickness=in.readTTFShort(); - isFixedPitch=in.readTTFULong(); - - in.skip(4*4); - - //System.out.println("Post format: "+post_format); + post_format = in.readTTFLong(); + italicAngle = in.readTTFULong(); + underlinePosition = in.readTTFShort(); + underlineThickness = in.readTTFShort(); + isFixedPitch = in.readTTFULong(); + + in.skip(4 * 4); + + //System.out.println("Post format: "+post_format); 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]; + //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"); - int numGlyphStrings=0; + case 0x00020000: + //System.out.println("Postscript format 2"); + int numGlyphStrings = 0; l = in.readTTFUShort(); // Num Glyphs - //short minIndex=256; - for (i=0; i < l ; i++) { // Read indexes - mtx_tab[i].index=in.readTTFUShort(); - //if (minIndex > mtx_tab[i].index) - //minIndex=(short)mtx_tab[i].index; - + //short minIndex=256; + for (i = 0; i < l ; i++) { // Read indexes + mtx_tab[i].index = in.readTTFUShort(); + //if (minIndex > mtx_tab[i].index) + //minIndex=(short)mtx_tab[i].index; + if (mtx_tab[i].index > 257) numGlyphStrings++; - - //System.out.println("Post index: "+mtx_tab[i].index); + + //System.out.println("Post index: "+mtx_tab[i].index); } - //firstChar=minIndex; - ps_glyphs_buf=new String[numGlyphStrings]; - //System.out.println("Reading " + numGlyphStrings + - // " glyphnames"+ - // ", was n num glyphs="+l); - for (i=0; i < ps_glyphs_buf.length; i++) { - ps_glyphs_buf[i]=in.readTTFString(in.readTTFUByte()); + //firstChar=minIndex; + ps_glyphs_buf = new String[numGlyphStrings]; + //System.out.println("Reading " + numGlyphStrings + + // " glyphnames"+ + // ", was n num glyphs="+l); + for (i = 0; i < ps_glyphs_buf.length; i++) { + ps_glyphs_buf[i] = in.readTTFString(in.readTTFUByte()); } - - for (i=0; i < l; i++) { + + for (i = 0; i < l; i++) { if (mtx_tab[i].index < NMACGLYPHS) { - mtx_tab[i].name = Glyphs.mac_glyph_names[mtx_tab[i].index]; + mtx_tab[i].name = + Glyphs.mac_glyph_names[mtx_tab[i].index]; } else { k = mtx_tab[i].index - NMACGLYPHS ; - /* - System.out.println(k+" i="+i+" mtx="+mtx_tab.length+ - " ps="+ps_glyphs_buf.length); - */ - mtx_tab[i].name=ps_glyphs_buf[k]; + /* + System.out.println(k+" i="+i+" mtx="+mtx_tab.length+ + " ps="+ps_glyphs_buf.length); + */ + mtx_tab[i].name = ps_glyphs_buf[k]; } } - + break; case 0x00030000: - // Postscript format 3 contains no glyph names + // Postscript format 3 contains no glyph names System.out.println("Postscript format 3"); break; default: @@ -766,308 +751,327 @@ public class TTFFile { } - /** - * Read the "OS/2" table - */ + /** + * Read the "OS/2" table + */ private final void readOS2(FontFileReader in) throws IOException { - // Check if font is embeddable + // 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) == fsType) - is_embeddable=false; + seek_tab(in, "OS/2", 2 * 4); + int fsType = in.readTTFUShort(); + if (fsType == 2) + is_embeddable = false; else - is_embeddable=true; + is_embeddable = true; } else - is_embeddable=true; + is_embeddable = true; } - /** - * Read the "loca" table - */ - private final void readIndexToLocation(FontFileReader in) - throws IOException { + /** + * Read the "loca" table + */ + protected final void readIndexToLocation(FontFileReader in) + throws IOException { seek_tab(in, "loca", 0); - for (int i=0; i < nglyphs ; i++) { + for (int i = 0; i < nglyphs ; i++) { mtx_tab[i].offset = (loca_format == 1 ? in.readTTFULong() : (in.readTTFUShort() << 1)); } + lastLoca = (loca_format == 1 ? in.readTTFULong() : + (in.readTTFUShort() << 1)); } - /** - * Read the "glyf" table to find the bounding boxes - */ + /** + * Read the "glyf" table to find the bounding boxes + */ private final void readGlyf(FontFileReader in) throws IOException { - TTFDirTabEntry dirTab = - (TTFDirTabEntry)dirTabs.get("glyf"); - for (int i=0; i < (nglyphs-1); i++) { - if (mtx_tab[i].offset != mtx_tab[i+1].offset) { + TTFDirTabEntry dirTab = (TTFDirTabEntry) dirTabs.get("glyf"); + for (int 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(); + 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]; + 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]; } } - - - long n=((TTFDirTabEntry)dirTabs.get("glyf")).offset; - for (int 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); + + + long n = ((TTFDirTabEntry) dirTabs.get("glyf")).offset; + for (int 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(); + 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]; + 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)); + //System.out.println(mtx_tab[i].toString(this)); } } - /** - * Read the "name" table - */ + /** + * Read the "name" table + */ private final void readName(FontFileReader in) throws IOException { int platform_id, encoding_id, language_id; - + seek_tab(in, "name", 2); int i = in.getCurrentPos(); int n = in.readTTFUShort(); int j = in.readTTFUShort() + i - 2; - i += 2*2; + i += 2 * 2; while (n-- > 0) { - //System.out.println("Iteration: "+n); + //System.out.println("Iteration: "+n); in.seek_set(i); - platform_id=in.readTTFUShort(); - encoding_id=in.readTTFUShort(); - language_id=in.readTTFUShort(); - - int k=in.readTTFUShort(); - int l=in.readTTFUShort(); - - if (((platform_id==1 || platform_id==3) && - (encoding_id==0 || encoding_id==1)) && - (k==1 || k==2 || k==0 || k==4 || k==6)) { -// if (k==1 || k==2 || k==0 || k==4 || k==6) { - in.seek_set(j+in.readTTFUShort()); + platform_id = in.readTTFUShort(); + encoding_id = in.readTTFUShort(); + language_id = in.readTTFUShort(); + + int k = in.readTTFUShort(); + int l = in.readTTFUShort(); + + if (((platform_id == 1 || platform_id == 3) && + (encoding_id == 0 || encoding_id == 1)) && + (k == 1 || k == 2 || k == 0 || k == 4 || k == 6)) { + // if (k==1 || k==2 || k==0 || k==4 || k==6) { + in.seek_set(j + in.readTTFUShort()); String txt = in.readTTFString(l); - //System.out.println(platform_id+" "+encoding_id+ - //" "+k+" "+txt); - 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; - } + //System.out.println(platform_id+" "+encoding_id+ + //" "+k+" "+txt); + 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; + i += 6 * 2; } } - /** - * Read the "PCLT" table to find xHeight and capHeight - */ + /** + * Read the "PCLT" table to find xHeight and capHeight + */ private final void readPCLT(FontFileReader in) throws IOException { - TTFDirTabEntry dirTab= - (TTFDirTabEntry)dirTabs.get("PCLT"); - if (dirTab!=null) { + TTFDirTabEntry 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; + 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; + hasSerifs = false; else - hasSerifs=true; - + hasSerifs = true; + } else { - // Approximate capHeight from height of "H" - // It's most unlikly that a font misses the PCLT table - // This also assumes that psocriptnames exists ("H") - // Should look it up int the cmap (that wouldn't help - // for charsets without H anyway...) - for (int i=0; i < mtx_tab.length; i++) { + // Approximate capHeight from height of "H" + // It's most unlikly that a font misses the PCLT table + // This also assumes that psocriptnames exists ("H") + // Should look it up int the cmap (that wouldn't help + // for charsets without H anyway...) + for (int 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]; + capHeight = mtx_tab[i].bbox[3] - mtx_tab[i].bbox[1]; } } } - /** - * Read the kerning table, create a table for both CIDs and - * winAnsiEncoding - */ + /** + * Read the kerning table, create a table for both CIDs and + * winAnsiEncoding + */ private final void readKerning(FontFileReader in) throws IOException { - // Read kerning - kerningTab=new Hashtable(); - TTFDirTabEntry dirTab= - (TTFDirTabEntry)dirTabs.get("kern"); - if (dirTab!=null) { + // Read kerning + kerningTab = new Hashtable(); + ansiKerningTab = new Hashtable(); + TTFDirTabEntry dirTab = (TTFDirTabEntry) dirTabs.get("kern"); + if (dirTab != null) { seek_tab(in, "kern", 2); - for (int n=in.readTTFUShort(); n > 0 ; n--) { - in.skip(2*2); - int k=in.readTTFUShort(); - if (!((k & 1)!=0) || (k & 2)!=0 || (k & 4)!=0) + for (int n = in.readTTFUShort(); n > 0 ; n--) { + in.skip(2 * 2); + int k = in.readTTFUShort(); + if (!((k & 1) != 0) || (k & 2) != 0 || (k & 4) != 0) return; - if ((k >> 8) !=0) + if ((k >> 8) != 0) continue; - - k=in.readTTFUShort(); + + k = in.readTTFUShort(); in.skip(3 * 2); while (k-- > 0) { - int i=in.readTTFUShort(); - int j=in.readTTFUShort(); - int kpx=in.readTTFShort(); + int i = in.readTTFUShort(); + int j = in.readTTFUShort(); + int kpx = in.readTTFShort(); if (kpx != 0) { - // CID table - Integer iObj=new Integer(i); - Hashtable adjTab= - (Hashtable)kerningTab.get(iObj); - if (adjTab==null) - adjTab=new java.util.Hashtable(); + // CID table + Integer iObj = new Integer(i); + Hashtable adjTab = (Hashtable) kerningTab.get(iObj); + if (adjTab == null) + adjTab = new java.util.Hashtable(); adjTab.put(new Integer(j), - new Integer((int)get_ttf_funit(kpx))); + new Integer((int) get_ttf_funit(kpx))); kerningTab.put(iObj, adjTab); } } } - //System.out.println(kerningTab.toString()); - - // Create winAnsiEncoded kerning table - - ansiKerningTab = new Hashtable(); + //System.out.println(kerningTab.toString()); + + // Create winAnsiEncoded kerning table + for (Enumeration ae = kerningTab.keys(); - ae.hasMoreElements();) { - Integer cidKey = (Integer)ae.nextElement(); + ae.hasMoreElements();) { + Integer cidKey = (Integer) ae.nextElement(); Hashtable akpx = new Hashtable(); - Hashtable ckpx = (Hashtable)kerningTab.get(cidKey); + Hashtable ckpx = (Hashtable) kerningTab.get(cidKey); for (Enumeration aee = ckpx.keys(); - aee.hasMoreElements();) { - Integer cidKey2 = (Integer)aee.nextElement(); - Integer kern = (Integer)ckpx.get(cidKey2); - - for (Enumeration uniMap = mtx_tab[cidKey2.intValue()].unicodeIndex.elements(); - uniMap.hasMoreElements();) { - Integer unicodeKey = (Integer)uniMap.nextElement(); - Integer[] ansiKeys = unicodeToWinAnsi(unicodeKey.intValue()); + aee.hasMoreElements();) { + Integer cidKey2 = (Integer) aee.nextElement(); + Integer kern = (Integer) ckpx.get(cidKey2); + + for (Enumeration uniMap = mtx_tab[cidKey2.intValue()] + .unicodeIndex.elements(); + uniMap.hasMoreElements();) { + Integer unicodeKey = (Integer) uniMap.nextElement(); + Integer[] ansiKeys = + unicodeToWinAnsi(unicodeKey.intValue()); for (int u = 0; u < ansiKeys.length; u++) { akpx.put(ansiKeys[u], kern); } } } - if (akpx.size() > 0) - for (Enumeration uniMap = mtx_tab[cidKey.intValue()].unicodeIndex.elements(); - uniMap.hasMoreElements();) { - Integer unicodeKey = (Integer)uniMap.nextElement(); - Integer[] ansiKeys = unicodeToWinAnsi(unicodeKey.intValue()); + if (akpx.size() > 0) + for (Enumeration uniMap = mtx_tab[cidKey.intValue()] + .unicodeIndex.elements(); + uniMap.hasMoreElements();) { + Integer unicodeKey = (Integer) uniMap.nextElement(); + Integer[] ansiKeys = + unicodeToWinAnsi(unicodeKey.intValue()); for (int u = 0; u < ansiKeys.length; u++) { ansiKerningTab.put(ansiKeys[u], akpx); + } } - } } } } - /** Return a vector with TTFCmapEntry - */ + /** Return a vector with TTFCmapEntry + */ public Vector getCMaps() { return cmaps; } - /** - * Check if this is a TrueType collection and that the given - * name exists in the collection. - * If it does, set offset in fontfile to the beginning of - * the Table Directory for that font - @ return true if not collection or font name present, false - otherwise - */ - private final boolean checkTTC(FontFileReader in, String name) - throws IOException { - String tag=in.readTTFString(4); - + /** + * Check if this is a TrueType collection and that the given + * name exists in the collection. + * If it does, set offset in fontfile to the beginning of + * the Table Directory for that font + @ return true if not collection or font name present, false + otherwise + */ + protected final boolean checkTTC(FontFileReader in, String name, + boolean verbose) throws IOException { + String tag = in.readTTFString(4); + if ("ttcf".equals(tag)) { - // This is a TrueType Collection + // This is a TrueType Collection in.skip(4); - - // Read directory offsets - int numDirectories=(int)in.readTTFULong(); - //int numDirectories=in.readTTFUShort(); - long[] dirOffsets=new long[numDirectories]; - for (int i=0; i < numDirectories; i++) { - dirOffsets[i]=in.readTTFULong(); - } - System.out.println("This is a TrueType collection file with"+ - numDirectories + " fonts"); - System.out.println("Containing the following fonts: "); - // Read all the directories and name tables to check - // If the font exists - this is a bit ugly, but... - boolean found=false; + // Read directory offsets + int numDirectories = (int) in.readTTFULong(); + //int numDirectories=in.readTTFUShort(); + long[] dirOffsets = new long[numDirectories]; + for (int i = 0; i < numDirectories; i++) { + dirOffsets[i] = in.readTTFULong(); + } - // Iterate through all name tables even if font - // Is found, just to show all the names - for (int i=0; (i < numDirectories); i++) { + if (verbose) { + System.out.println("This is a TrueType collection file with"+ + numDirectories + " fonts"); + System.out.println("Containing the following fonts: "); + } + // Read all the directories and name tables to check + // If the font exists - this is a bit ugly, but... + boolean found = false; + + // Iterate through all name tables even if font + // Is found, just to show all the names + long dirTabOffset = 0; + for (int i = 0; (i < numDirectories); i++) { in.seek_set(dirOffsets[i]); readDirTabs(in); + readName(in); - + if (fullName.equals(name)) { - found=true; - in.seek_set(dirOffsets[i]); - System.out.println("* " + fullName); + found = true; + dirTabOffset = dirOffsets[i]; + if (verbose) + System.out.println("* " + fullName); } else { - System.out.println(fullName); + if (verbose) + System.out.println(fullName); } - - // Reset names - notice=""; - fullName=""; - familyName=""; - fontName=""; - subFamilyName=""; + + // Reset names + notice = ""; + fullName = ""; + familyName = ""; + fontName = ""; + subFamilyName = ""; } + in.seek_set(dirTabOffset); return found; - } else { + } + else { in.seek_set(0); return true; } } - /* Helper classes, they are not very efficient, but that really - doesn't matter... */ + /* Helper classes, they are not very efficient, but that really + doesn't matter... */ private Integer[] unicodeToWinAnsi(int unicode) { - Vector ret=new Vector(); - for (int i=32; i < Glyphs.winAnsiEncoding.length; i++) + Vector ret = new Vector(); + for (int i = 32; i < Glyphs.winAnsiEncoding.length; i++) if (unicode == Glyphs.winAnsiEncoding[i]) ret.addElement(new Integer(i)); Integer[] itg = new Integer[ret.size()]; @@ -1078,8 +1082,8 @@ public class TTFFile { /** - * Key-value helper class - */ + * Key-value helper class + */ class UnicodeMapping { int uIdx; int gIdx; diff --git a/src/org/apache/fop/fonts/TTFMtxEntry.java b/src/org/apache/fop/fonts/TTFMtxEntry.java index e1333bd24..56b27e62e 100644 --- a/src/org/apache/fop/fonts/TTFMtxEntry.java +++ b/src/org/apache/fop/fonts/TTFMtxEntry.java @@ -1,52 +1,8 @@ /* -- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts; @@ -55,26 +11,27 @@ import java.util.Vector; class TTFMtxEntry { int wx; + int lsb; String name; int index; Vector unicodeIndex; int[] bbox; long offset; byte found; - + TTFMtxEntry() { - name=""; - found=0; + name = ""; + found = 0; unicodeIndex = new Vector(); - bbox=new int[4]; + 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)); + 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 index 9c7cbad8c..e63c024bd 100644 --- a/src/org/apache/fop/fonts/TTFSegEntry.java +++ b/src/org/apache/fop/fonts/TTFSegEntry.java @@ -1,61 +1,17 @@ /* -- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts; class TTFSegEntry { - int endCode; - int startCode; - int idDelta; - int idRangeOffset; - - TTFSegEntry() { - } + int endCode; + int startCode; + int idDelta; + int idRangeOffset; + + TTFSegEntry() { + } } diff --git a/src/org/apache/fop/fonts/apps/FontPostProcess.xsl b/src/org/apache/fop/fonts/apps/FontPostProcess.xsl index 5739a07e7..120fd36a3 100644 --- a/src/org/apache/fop/fonts/apps/FontPostProcess.xsl +++ b/src/org/apache/fop/fonts/apps/FontPostProcess.xsl @@ -13,7 +13,7 @@ <xsl:element name="widths"> <xsl:for-each select="char"> <xsl:variable name="char-num" select="@ansichar"/> - <xsl:variable name="char-name" select="document('charlist.xml')/font-mappings/map[@win-ansi=$char-num]/@adobe-name"/> + <xsl:variable name="char-name" select="document('file:charlist.xml')/font-mappings/map[@win-ansi=$char-num]/@adobe-name"/> <xsl:if test="$char-name!=''"> <xsl:element name="char"> <xsl:attribute name="name"><xsl:value-of select="$char-name"/></xsl:attribute> diff --git a/src/org/apache/fop/fonts/apps/PFMReader.java b/src/org/apache/fop/fonts/apps/PFMReader.java index 581ba20db..cf98ce434 100644 --- a/src/org/apache/fop/fonts/apps/PFMReader.java +++ b/src/org/apache/fop/fonts/apps/PFMReader.java @@ -1,52 +1,8 @@ /*-- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts.apps; @@ -73,106 +29,104 @@ public class 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("-")) { - if ((i+1) < args.length && !args[i+1].startsWith("-")) { - options.put(args[i], args[i+1]); - i++; - } else { - options.put(args[i], ""); - } - } 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 .ttf file, but\n"+ - " you can override that name to make sure that the\n"); - System.out.println(" embedded font is used (if you're embedding fonts)\n"); - System.out.println(" instead of installed fonts when viewing documents with Acrobat Reader.\n"); - } - - /** - * The main method for the PFM reader tool. - * - * @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. - */ + * 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("-")) { + if ((i + 1) < args.length && !args[i + 1].startsWith("-")) { + options.put(args[i], args[i + 1]); + i++; + } else { + options.put(args[i], ""); + } + } 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 .ttf file, but\n"+ + " you can override that name to make sure that the\n"); + System.out.println(" embedded font is used (if you're embedding fonts)\n"); + System.out.println(" instead of installed fonts when viewing documents with Acrobat Reader.\n"); + } + + + /** + * The main method for the PFM reader tool. + * + * @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) { - String embFile=null; - String embResource=null; - String className=null; - String fontName=null; - - Hashtable options=new Hashtable(); - String[] arguments=parseArguments(options, args); - + 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"); - + embFile = (String) options.get("-ef"); + if (options.get("-er") != null) - embResource=(String)options.get("-er"); - + embResource = (String) options.get("-er"); + if (options.get("-fn") != null) - fontName=(String)options.get("-fn"); - + 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) + 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); - + + org.w3c.dom.Document doc = + app.constructFontXML(pfm, fontName, className, + embResource, embFile); + app.writeFontXML(doc, arguments[1]); } } @@ -180,11 +134,11 @@ public class PFMReader { /** - * Read a PFM file and returns it as an object. - * - * @param filename The filename of the PFM file. - * @return The PFM as an object. - */ + * Read a PFM file and returns it as an object. + * + * @param filename The filename of the PFM file. + * @return The PFM as an object. + */ public PFMFile loadPFM(String filename) { try { System.out.println("Reading " + filename + "..."); @@ -200,10 +154,10 @@ public class PFMReader { } /** - * Displays a preview of the PFM file on the console. - * - * @param pfm The PFM file to preview. - */ + * Displays a preview of the PFM file on the console. + * + * @param pfm The PFM file to preview. + */ public void preview(PFMFile pfm) { PrintStream out = System.out; @@ -222,7 +176,7 @@ public class PFMReader { out.print("LowerCaseDescent: "); out.println(pfm.getLowerCaseDescent()); out.print("Having widths for "); - out.print(pfm.getLastChar()-pfm.getFirstChar()); + out.print(pfm.getLastChar() - pfm.getFirstChar()); out.print(" characters ("); out.print(pfm.getFirstChar()); out.print("-"); @@ -236,20 +190,20 @@ public class PFMReader { } /** - * Writes the generated DOM Document to a file. - * - * @param doc The DOM Document to save. - * @param target The target filename for the XML file. - */ + * 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 + 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.asDOMSerializer(); // As a DOM Serializer serial.serialize(doc.getDocumentElement()); out.close(); @@ -259,14 +213,14 @@ public class PFMReader { } /** - * 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(PFMFile pfm, String fontName, - String className, String resource, - String file) { + * 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(PFMFile pfm, + String fontName, String className, String resource, + String file) { System.out.println("Creating xml font file..."); System.out.println(); @@ -274,7 +228,7 @@ public class PFMReader { Element root = doc.createElement("font-metrics"); doc.appendChild(root); root.setAttribute("type", "TYPE1"); - + Element el = doc.createElement("font-name"); root.appendChild(el); el.appendChild(doc.createTextNode(pfm.getPostscriptName())); @@ -282,22 +236,22 @@ public class PFMReader { String s = pfm.getPostscriptName(); 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); + 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("embed"); root.appendChild(el); - if (file!=null) - el.setAttribute("file", file); - if (resource!=null) - el.setAttribute("class", resource); + if (file != null) + el.setAttribute("file", file); + if (resource != null) + el.setAttribute("class", resource); el = doc.createElement("encoding"); root.appendChild(el); - el.appendChild(doc.createTextNode(pfm.getCharSetName()+"Encoding")); + el.appendChild(doc.createTextNode(pfm.getCharSetName() + "Encoding")); el = doc.createElement("cap-height"); root.appendChild(el); @@ -323,7 +277,7 @@ public class PFMReader { root.appendChild(bbox); int[] bb = pfm.getFontBBox(); String[] names = {"left","bottom","right","top"}; - for (int i=0; i<4; i++) { + for (int i = 0; i < 4; i++) { el = doc.createElement(names[i]); bbox.appendChild(el); value = new Integer(bb[i]); @@ -358,48 +312,50 @@ public class PFMReader { Element widths = doc.createElement("widths"); root.appendChild(widths); - for (short i = pfm.getFirstChar(); i < pfm.getLastChar(); i++) { + for (short i = pfm.getFirstChar(); i <= pfm.getLastChar(); i++) { el = doc.createElement("char"); widths.appendChild(el); el.setAttribute("idx", Integer.toString(i)); - el.setAttribute("wdt", new Integer(pfm.getCharWidth(i)).toString()); + el.setAttribute("wdt", + 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(); ) { - Integer kpx2=(Integer)enum2.nextElement(); - el2=doc.createElement("pair"); - el2.setAttribute("kpx2", kpx2.toString()); - Integer val=(Integer)h2.get(kpx2); - el2.setAttribute("kern", val.toString()); - el.appendChild(el2); - } + // 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();) { + Integer kpx2 = (Integer) enum2.nextElement(); + el2 = doc.createElement("pair"); + el2.setAttribute("kpx2", kpx2.toString()); + Integer val = (Integer) h2.get(kpx2); + el2.setAttribute("kern", val.toString()); + el.appendChild(el2); + } } return doc; } - - 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(); - } + + 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 index e4ff7774b..61b3b01f6 100644 --- a/src/org/apache/fop/fonts/apps/TTFReader.java +++ b/src/org/apache/fop/fonts/apps/TTFReader.java @@ -1,52 +1,8 @@ /* -- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.fonts.apps; @@ -72,180 +28,182 @@ public class 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("-")) { - if ((i+1) < args.length && !args[i+1].startsWith("-")) { - options.put(args[i], args[i+1]); - i++; - } else { - options.put(args[i], ""); - } - } 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("-enc cid"); - System.out.println(" With this option you create a CID keyed font."); - System.out.println(" If you're going to use characters outside the"); - System.out.println(" pdfencoding range (almost the same as iso-8889-1)"); - System.out.println(" you must add this option."); - System.out.println("-ttcname <fontname>"); - System.out.println(" If you're reading data from a TrueType Collection"); - System.out.println(" (.ttc file) you must specify which font from the"); - System.out.println(" collection you will read metrics from. If you read"); - System.out.println(" from a .ttc file without this option, the fontnames"); - System.out.println(" will be listed for you."); - System.out.println(" -fn <fontname>\n"); - System.out.println(" default is to use the fontname in the .ttf file, but\n"+ - " you can override that name to make sure that the\n"); - System.out.println(" embedded font is used (if you're embedding fonts)\n"); - System.out.println(" instead of installed fonts when viewing documents with Acrobat Reader.\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. - */ + * 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("-")) { + if ((i + 1) < args.length && !args[i + 1].startsWith("-")) { + options.put(args[i], args[i + 1]); + i++; + } else { + options.put(args[i], ""); + } + } 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("-enc ansi"); + System.out.println(" With this option you create a WinAnsi encoded font.\n"); + System.out.println(" The default is to create a CID keyed font."); + System.out.println(" If you're not going to use characters outside the"); + System.out.println(" pdfencoding range (almost the same as iso-8889-1)"); + System.out.println(" you can add this option."); + System.out.println("-ttcname <fontname>"); + System.out.println(" If you're reading data from a TrueType Collection"); + System.out.println(" (.ttc file) you must specify which font from the"); + System.out.println(" collection you will read metrics from. If you read"); + System.out.println(" from a .ttc file without this option, the fontnames"); + System.out.println(" will be listed for you."); + System.out.println(" -fn <fontname>\n"); + System.out.println(" default is to use the fontname in the .ttf file, but\n"+ + " you can override that name to make sure that the\n"); + System.out.println(" embedded font is used (if you're embedding fonts)\n"); + System.out.println(" instead of installed fonts when viewing documents with Acrobat Reader.\n"); + } + + + /** + * The main method for the TTFReader tool. + * + * @param args Command-line arguments: [options] fontfile.ttf xmlfile.xml + * where options can be: + * -fn <fontname> + * default is to use the fontname in the .ttf file, but you can override + * that name to make sure that the embedded font is used instead of installed + * fonts when viewing documents with Acrobat Reader. + * -cn <classname> + * default is to use the fontname + * -ef <path to the truetype fontfile> + * will add the possibility to embed the font. When running fop, fop will look + * for this file to embed it + * -er <path to truetype fontfile relative to org/apache/fop/render/pdf/fonts> + * you can also include the fontfile in the fop.jar file when building fop. + * You can use both -ef and -er. The file specified in -ef will be searched first, + * then the -er file. + */ public static void main(String[] args) { - String embFile=null; - String embResource=null; - String className=null; - String fontName=null; - String ttcName=null; - boolean isCid=false; - - Hashtable options=new Hashtable(); - String[] arguments=parseArguments(options, args); - - TTFReader app = new TTFReader(); - app.invokedStandalone = true; - - System.out.println("TTF Reader v1.1"); - System.out.println(); - - if (options.get("-enc") != null) { - String enc = (String)options.get("-enc"); - if ("cid".equals(enc)) - isCid=true; - } - - if (options.get("-ttcname") != null) - ttcName=(String)options.get("-ttcname"); - - if (options.get("-ef") != null) - embFile=(String)options.get("-ef"); - - if (options.get("-er") != null) - embResource=(String)options.get("-er"); - - if (options.get("-fn") != null) - fontName=(String)options.get("-fn"); - - if (options.get("-cn") != null) - className=(String)options.get("-cn"); - - if (arguments.length != 2 || - options.get("-h") != null || - options.get("-help") != null || - options.get("--help") != null) - displayUsage(); - else { - TTFFile ttf = app.loadTTF(arguments[0], ttcName); - if (ttf != null) { - org.w3c.dom.Document doc = app.constructFontXML(ttf, - fontName, - className, - embResource, - embFile, - isCid, - ttcName); - - if (doc != null) { - app.writeFontXML(doc, arguments[1]); - } - - if (ttf.isEmbeddable()) - System.out.println("This font contains no embedding license restrictions"); - else - System.out.println("** Note: This font contains license retrictions for\n"+ - " embedding. This font can't be embedded."); - - } - } + String embFile = null; + String embResource = null; + String className = null; + String fontName = null; + String ttcName = null; + boolean isCid = true; + + Hashtable options = new Hashtable(); + String[] arguments = parseArguments(options, args); + + TTFReader app = new TTFReader(); + app.invokedStandalone = true; + + System.out.println("TTF Reader v1.1.1"); + System.out.println(); + + if (options.get("-enc") != null) { + String enc = (String) options.get("-enc"); + if ("ansi".equals(enc)) + isCid = false; + } + + if (options.get("-ttcname") != null) + ttcName = (String) options.get("-ttcname"); + + if (options.get("-ef") != null) + embFile = (String) options.get("-ef"); + + if (options.get("-er") != null) + embResource = (String) options.get("-er"); + + if (options.get("-fn") != null) + fontName = (String) options.get("-fn"); + + if (options.get("-cn") != null) + className = (String) options.get("-cn"); + + if (arguments.length != 2 || options.get("-h") != null || + options.get("-help") != null || + options.get("--help") != null) + displayUsage(); + else { + TTFFile ttf = app.loadTTF(arguments[0], ttcName); + if (ttf != null) { + org.w3c.dom.Document doc = + app.constructFontXML(ttf, fontName, className, + embResource, embFile, isCid, ttcName); + + if (isCid) + System.out.println("Creating CID encoded metrics"); + else + System.out.println("Creating WinAnsi encoded metrics"); + + if (doc != null) { + app.writeFontXML(doc, arguments[1]); + } + + if (ttf.isEmbeddable()) + System.out.println("This font contains no embedding license restrictions"); + else + System.out.println("** Note: This font contains license retrictions for\n"+ + " embedding. This font shouldn't be embedded."); + + } + } } - - /** - * Read a TTF file and returns it as an object. - * - * @param filename The filename of the PFM file. - * @return The TTF as an object. - */ - public TTFFile loadTTF(String fileName, String fontName) { - TTFFile ttfFile=new TTFFile(); - try { - System.out.println("Reading " + fileName + "..."); - System.out.println(); - - FontFileReader reader = new FontFileReader(fileName); - ttfFile.readFont(reader, fontName); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - return ttfFile; + + /** + * Read a TTF file and returns it as an object. + * + * @param filename The filename of the PFM file. + * @return The TTF as an object. + */ + public TTFFile loadTTF(String fileName, String fontName) { + TTFFile ttfFile = new TTFFile(); + try { + System.out.println("Reading " + fileName + "..."); + System.out.println(); + + FontFileReader reader = new FontFileReader(fileName); + ttfFile.readFont(reader, fontName); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + return ttfFile; } /** - * Writes the generated DOM Document to a file. - * - * @param doc The DOM Document to save. - * @param target The target filename for the XML file. - */ + * 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 + 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.asDOMSerializer(); // As a DOM Serializer serial.serialize(doc.getDocumentElement()); out.close(); @@ -255,15 +213,14 @@ public class TTFReader { } /** - * Generates the font metrics file from the TTF/TTC file. - * - * @param ttf 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, boolean isCid, - String ttcName) { + * Generates the font metrics file from the TTF/TTC file. + * + * @param ttf 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, boolean isCid, String ttcName) { System.out.println("Creating xml font file..."); System.out.println(); @@ -274,18 +231,18 @@ public class TTFReader { root.setAttribute("type", "TYPE0"); else root.setAttribute("type", "TRUETYPE"); - + Element el = doc.createElement("font-name"); root.appendChild(el); - // Note that the PostScript name usually is something like - // "Perpetua-Bold", but the TrueType spec says that in the ttf file - // it should be "Perpetua,Bold". + // Note that the PostScript name usually is something like + // "Perpetua-Bold", but the TrueType spec says that in the ttf file + // it should be "Perpetua,Bold". String s = stripWhiteSpace(ttf.getPostscriptName()); if (fontName != null) - el.appendChild(doc.createTextNode(stripWhiteSpace(fontName))); + el.appendChild(doc.createTextNode(stripWhiteSpace(fontName))); else el.appendChild(doc.createTextNode(s)); @@ -298,66 +255,62 @@ public class TTFReader { el = doc.createElement("cap-height"); root.appendChild(el); - Integer value = new Integer(ttf.getCapHeight()); - el.appendChild(doc.createTextNode(value.toString())); + el.appendChild( + doc.createTextNode(String.valueOf(ttf.getCapHeight()))); el = doc.createElement("x-height"); root.appendChild(el); - value = new Integer(ttf.getXHeight()); - el.appendChild(doc.createTextNode(value.toString())); - + el.appendChild( + doc.createTextNode(String.valueOf(ttf.getXHeight()))); + el = doc.createElement("ascender"); root.appendChild(el); - value = new Integer(ttf.getLowerCaseAscent()); - el.appendChild(doc.createTextNode(value.toString())); - + el.appendChild( doc.createTextNode( + String.valueOf(ttf.getLowerCaseAscent()))); + el = doc.createElement("descender"); root.appendChild(el); - value = new Integer(ttf.getLowerCaseDescent()); - el.appendChild(doc.createTextNode(value.toString())); + el.appendChild( doc.createTextNode( + String.valueOf(ttf.getLowerCaseDescent()))); Element bbox = doc.createElement("bbox"); root.appendChild(bbox); int[] bb = ttf.getFontBBox(); String[] names = {"left","bottom","right","top"}; - for (int i=0; i<4; i++) { + 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.appendChild(doc.createTextNode(String.valueOf(bb[i]))); } el = doc.createElement("flags"); root.appendChild(el); - value = new Integer(ttf.getFlags()); - el.appendChild(doc.createTextNode(value.toString())); - + el.appendChild(doc.createTextNode(String.valueOf(ttf.getFlags()))); + el = doc.createElement("stemv"); root.appendChild(el); - value = new Integer(ttf.getStemV()); - el.appendChild(doc.createTextNode(value.toString())); - + el.appendChild(doc.createTextNode(ttf.getStemV())); + el = doc.createElement("italicangle"); root.appendChild(el); - value = new Integer(ttf.getItalicAngle()); - el.appendChild(doc.createTextNode(value.toString())); + el.appendChild(doc.createTextNode(ttf.getItalicAngle())); if (ttcName != null) { el = doc.createElement("ttc-name"); root.appendChild(el); el.appendChild(doc.createTextNode(ttcName)); } - + el = doc.createElement("subtype"); root.appendChild(el); - - // Fill in extras for CID keyed fonts + + // Fill in extras for CID keyed fonts if (isCid) { el.appendChild(doc.createTextNode("TYPE0")); Element mel = doc.createElement("multibyte-extras"); root.appendChild(mel); - + el = doc.createElement("cid-type"); mel.appendChild(el); el.appendChild(doc.createTextNode("CIDFontType2")); @@ -368,117 +321,119 @@ public class TTFReader { el = doc.createElement("bfranges"); mel.appendChild(el); - for (Enumeration e=ttf.getCMaps().elements(); e.hasMoreElements();) { - TTFCmapEntry ce = (TTFCmapEntry)e.nextElement(); - Element el2=doc.createElement("bf"); + for (Enumeration e = ttf.getCMaps().elements(); + e.hasMoreElements();) { + TTFCmapEntry ce = (TTFCmapEntry) e.nextElement(); + Element el2 = doc.createElement("bf"); el.appendChild(el2); - el2.setAttribute("us", Integer.toString(ce.unicodeStart)); - el2.setAttribute("ue", Integer.toString(ce.unicodeEnd)); - el2.setAttribute("gi", Integer.toString(ce.glyphStartIndex)); + el2.setAttribute("us", String.valueOf(ce.unicodeStart)); + el2.setAttribute("ue", String.valueOf(ce.unicodeEnd)); + el2.setAttribute("gi", String.valueOf(ce.glyphStartIndex)); } - + el = doc.createElement("cid-widths"); el.setAttribute("start-index", "0"); mel.appendChild(el); int[] wx = ttf.getWidths(); for (int i = 0; i < wx.length; i++) { - Element wxel=doc.createElement("wx"); - wxel.setAttribute("w", Integer.toString(wx[i])); + Element wxel = doc.createElement("wx"); + wxel.setAttribute("w", String.valueOf(wx[i])); el.appendChild(wxel); } } else { - // Fill in extras for singlebyte fonts + // Fill in extras for singlebyte fonts el.appendChild(doc.createTextNode("TRUETYPE")); - Element sel=doc.createElement("singlebyte-extras"); + Element sel = doc.createElement("singlebyte-extras"); root.appendChild(sel); - + el = doc.createElement("encoding"); sel.appendChild(el); el.appendChild(doc.createTextNode(ttf.getCharSetName())); el = doc.createElement("first-char"); sel.appendChild(el); - value = new Integer(ttf.getFirstChar()); - el.appendChild(doc.createTextNode(value.toString())); - + el.appendChild( + doc.createTextNode(String.valueOf(ttf.getFirstChar()))); + el = doc.createElement("last-char"); sel.appendChild(el); - value = new Integer(ttf.getLastChar()); - el.appendChild(doc.createTextNode(value.toString())); - + el.appendChild( + doc.createTextNode(String.valueOf(ttf.getLastChar()))); + Element widths = doc.createElement("widths"); sel.appendChild(widths); - - for (short i = ttf.getFirstChar(); i < ttf.getLastChar(); i++) { + + for (short i = ttf.getFirstChar(); i <= ttf.getLastChar(); + i++) { el = doc.createElement("char"); widths.appendChild(el); - el.setAttribute("idx", Integer.toString(i)); - el.setAttribute("wdt", Integer.toString(ttf.getCharWidth(i))); + el.setAttribute("idx", String.valueOf(i)); + el.setAttribute("wdt", String.valueOf(ttf.getCharWidth(i))); } } - - // Get kerning + + // Get kerning Enumeration enum; if (isCid) - enum=ttf.getKerning().keys(); + enum = ttf.getKerning().keys(); else - enum=ttf.getAnsiKerning().keys(); - + enum = ttf.getAnsiKerning().keys(); + while (enum.hasMoreElements()) { - Integer kpx1=(Integer)enum.nextElement(); + Integer kpx1 = (Integer) enum.nextElement(); - el=doc.createElement("kerning"); + el = doc.createElement("kerning"); el.setAttribute("kpx1", kpx1.toString()); root.appendChild(el); - Element el2=null; - + Element el2 = null; + Hashtable h2; if (isCid) - h2 = (Hashtable)ttf.getKerning().get(kpx1); + h2 = (Hashtable) ttf.getKerning().get(kpx1); else - h2 = (Hashtable)ttf.getAnsiKerning().get(kpx1); - - for (Enumeration enum2=h2.keys(); enum2.hasMoreElements(); ) { - Integer kpx2=(Integer)enum2.nextElement(); + h2 = (Hashtable) ttf.getAnsiKerning().get(kpx1); + + for (Enumeration enum2 = h2.keys(); enum2.hasMoreElements();) { + Integer kpx2 = (Integer) enum2.nextElement(); if (isCid || kpx2.intValue() < 256) { - el2=doc.createElement("pair"); + el2 = doc.createElement("pair"); el2.setAttribute("kpx2", kpx2.toString()); - Integer val=(Integer)h2.get(kpx2); + Integer val = (Integer) h2.get(kpx2); el2.setAttribute("kern", val.toString()); el.appendChild(el2); } } } - + return doc; } - - + + private String stripWhiteSpace(String s) { char[] ch = new char[s.length()]; s.getChars(0, s.length(), ch, 0); StringBuffer stb = new StringBuffer(); for (int i = 0; i < ch.length; i++) - if (ch[i] != ' ' && ch[i] != '\r' && - ch[i] != '\n' && ch[i] != '\t') + if (ch[i] != ' ' && ch[i] != '\r' && ch[i] != '\n' && + ch[i] != '\t') stb.append(ch[i]); return stb.toString(); } - - 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(); - } + + 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/LineArea.java b/src/org/apache/fop/layout/LineArea.java index bbdc6f66f..1c0a94f3f 100644 --- a/src/org/apache/fop/layout/LineArea.java +++ b/src/org/apache/fop/layout/LineArea.java @@ -1,52 +1,8 @@ /*-- $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/>. - + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.layout; @@ -220,6 +176,8 @@ public class LineArea extends Area { data[count] = odata[count]; } + boolean isText = false; + /* iterate over each character */ for (int i = start; i < end; i++) { int charWidth; @@ -229,14 +187,12 @@ public class LineArea extends Area { (c == '\t'))) { c = data[i] = currentFontState.mapChar(c); charWidth = currentFontState.width(c); + isText = true; if (charWidth <= 0) charWidth = whitespaceWidth; } else { charWidth = whitespaceWidth; - } - - if ((c == ' ') || (c == '\n') || (c == '\r') || - (c == '\t')) { // whitespace + isText = false; if (prev == WHITESPACE) { @@ -370,11 +326,12 @@ public class LineArea extends Area { spaceWidth = whitespaceWidth; } else { // skip over it - start++; + wordStart++; } } - } else { // current is TEXT + } + if(isText) { // current is TEXT if (prev == WHITESPACE) { diff --git a/src/org/apache/fop/render/pdf/FontReader.java b/src/org/apache/fop/render/pdf/FontReader.java index 153ab4a36..ce79dce42 100644 --- a/src/org/apache/fop/render/pdf/FontReader.java +++ b/src/org/apache/fop/render/pdf/FontReader.java @@ -1,52 +1,8 @@ -/*-- $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/>. - +/*-- $Id$ -- + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." */ package org.apache.fop.render.pdf; @@ -81,7 +37,7 @@ public class FontReader extends DefaultHandler { private MultiByteFont multiFont = null; private SingleByteFont singleFont = null; private Font returnFont = null; - //private SingleByteFont singleFont = null; + //private SingleByteFont singleFont = null; private String text = null; private Vector cidWidths = null; @@ -90,7 +46,7 @@ public class FontReader extends DefaultHandler { private Hashtable currentKerning = null; private Vector bfranges = null; - + private void createFont(String path) throws IOException { XMLReader parser = ConfigurationReader.createParser(); if (parser == null) @@ -100,8 +56,8 @@ public class FontReader extends DefaultHandler { parser.setFeature("http://xml.org/sax/features/namespace-prefixes", false); } catch (SAXException e) { - throw new IOException ("You need a SAX parser which supports " + - "SAX version 2"); + throw new IOException ( + "You need a SAX parser which supports " + "SAX version 2"); } parser.setContentHandler(this); @@ -113,38 +69,38 @@ public class FontReader extends DefaultHandler { } } - /** - * Sets the path to embed a font. a null value disables font embedding - */ + /** + * Sets the path to embed a font. a null value disables font embedding + */ public void setFontEmbedPath(String path) { if (isCID) - multiFont.embedFileName=path; + multiFont.embedFileName = path; else - singleFont.embedFileName=path; + singleFont.embedFileName = path; } - - /** - * Enable/disable use of kerning for the font - */ + + /** + * Enable/disable use of kerning for the font + */ public void useKerning(boolean kern) { if (isCID) multiFont.useKerning = true; else singleFont.useKerning = true; } - - - /** - * Get the generated font object - */ + + + /** + * Get the generated font object + */ public Font getFont() { return returnFont; } - /** - * Construct a FontReader object from a path to a metric.xml file - * and read metric data - */ + /** + * Construct a FontReader object from a path to a metric.xml file + * and read metric data + */ public FontReader(String path) throws IOException { createFont(path); } @@ -176,25 +132,27 @@ public class FontReader extends DefaultHandler { } } else if ("embed".equals(localName)) { if (isCID) { - // This *is* annoying... should create a common - // interface for sing/multibytefonts... + // This *is* annoying... should create a common + // interface for sing/multibytefonts... multiFont.embedFileName = attributes.getValue("file"); multiFont.embedResourceName = attributes.getValue("class"); } else { singleFont.embedFileName = attributes.getValue("file"); singleFont.embedResourceName = attributes.getValue("class"); - } + } } else if ("cid-widths".equals(localName)) { cidWidthIndex = getInt(attributes.getValue("start-index")); cidWidths = new Vector(); } else if ("kerning".equals(localName)) { currentKerning = new Hashtable(); if (isCID) - multiFont.kerning.put(new Integer(attributes.getValue("kpx1")), - currentKerning); + multiFont.kerning.put( + new Integer(attributes.getValue("kpx1")), + currentKerning); else - singleFont.kerning.put(new Integer(attributes.getValue("kpx1")), - currentKerning); + singleFont.kerning.put( + new Integer(attributes.getValue("kpx1")), + currentKerning); } else if ("bfranges".equals(localName)) { bfranges = new Vector(); } else if ("bf".equals(localName)) { @@ -209,15 +167,16 @@ public class FontReader extends DefaultHandler { singleFont.width = new int[256]; } else if ("char".equals(localName)) { try { - singleFont.width[Integer.parseInt(attributes.getValue("idx"))] = + singleFont.width[ + Integer.parseInt(attributes.getValue("idx"))] = Integer.parseInt(attributes.getValue("wdt")); } catch (NumberFormatException ne) { System.out.println("Malformed width in metric file: " + ne.getMessage()); } } else if ("pair".equals(localName)) { - currentKerning.put(new Integer(attributes.getValue("kpx2")), - new Integer(attributes.getValue("kern"))); + currentKerning.put( new Integer(attributes.getValue("kpx2")), + new Integer(attributes.getValue("kern"))); } } @@ -228,13 +187,15 @@ public class FontReader extends DefaultHandler { } catch (Exception e) {} return ret; } - + public void endElement(String uri, String localName, String qName) { if ("font-name".equals(localName)) if (isCID) multiFont.fontName = text; else singleFont.fontName = text; + if ("ttc-name".equals(localName) && isCID) + multiFont.ttcName = text; else if ("cap-height".equals(localName)) if (isCID) multiFont.capHeight = getInt(text); @@ -307,14 +268,15 @@ public class FontReader extends DefaultHandler { } else if ("cid-widths".equals(localName)) { int[] wds = new int[cidWidths.size()]; int j = 0; - for (Enumeration e = cidWidths.elements(); e.hasMoreElements();) { - Integer i = (Integer)e.nextElement(); + for (Enumeration e = cidWidths.elements(); + e.hasMoreElements();) { + Integer i = (Integer) e.nextElement(); wds[j++] = i.intValue(); } multiFont.warray.addEntry(cidWidthIndex, wds); multiFont.width = wds; - + } else if ("bfranges".equals(localName)) { BFEntry[] entries = new BFEntry[bfranges.size()]; bfranges.copyInto(entries); @@ -328,7 +290,7 @@ public class FontReader extends DefaultHandler { System.arraycopy(ch, start, c, 0, length); text = new String(c); } - + } diff --git a/src/org/apache/fop/render/pdf/PDFRenderer.java b/src/org/apache/fop/render/pdf/PDFRenderer.java index fabbb1802..eb4ab80e3 100644 --- a/src/org/apache/fop/render/pdf/PDFRenderer.java +++ b/src/org/apache/fop/render/pdf/PDFRenderer.java @@ -37,7 +37,7 @@ import java.util.Hashtable; public class PDFRenderer extends PrintRenderer { private static final boolean OPTIMIZE_TEXT = true; - + /** the PDF Document being created */ protected PDFDocument pdfDoc; @@ -68,7 +68,7 @@ public class PDFRenderer extends PrintRenderer { int prevWordWidth = 0; private PDFOutline rootOutline; - + /** * create the PDF renderer */ @@ -77,20 +77,20 @@ public class PDFRenderer extends PrintRenderer { } /** - * set the PDF document's producer - * - * @param producer string indicating application producing PDF - */ + * set the PDF document's producer + * + * @param producer string indicating application producing PDF + */ public void setProducer(String producer) { this.pdfDoc.setProducer(producer); } /** - * render the areas into PDF - * - * @param areaTree the laid-out area tree - * @param stream the OutputStream to write the PDF to - */ + * render the areas into PDF + * + * @param areaTree the laid-out area tree + * @param stream the OutputStream to write the PDF to + */ public void render(AreaTree areaTree, OutputStream stream) throws IOException, FOPException { MessageHandler.logln("rendering areas to PDF"); @@ -108,15 +108,37 @@ public class PDFRenderer extends PrintRenderer { idReferences.getInvalidIds() + "\n"); } - renderRootExtensions(areaTree); - + renderRootExtensions(areaTree); + FontSetup.addToResources(this.pdfDoc, fontInfo); - + MessageHandler.logln("writing out PDF"); this.pdfDoc.output(stream); } /** + * add a line to the current stream + * + * @param x1 the start x location in millipoints + * @param y1 the start y location in millipoints + * @param x2 the end x location in millipoints + * @param y2 the end y location in millipoints + * @param th the thickness in millipoints + * @param r the red component + * @param g the green component + * @param b the blue component + */ + protected void addLine(int x1, int y1, int x2, int y2, int th, + PDFPathPaint stroke) { + closeText(); + + currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) + + (x1 / 1000f) + " "+ (y1 / 1000f) + " m " + + (x2 / 1000f) + " "+ (y2 / 1000f) + " l " + + (th / 1000f) + " w S\n" + "Q\nBT\n"); + } + + /** * add a line to the current stream * * @param x1 the start x location in millipoints @@ -124,72 +146,50 @@ public class PDFRenderer extends PrintRenderer { * @param x2 the end x location in millipoints * @param y2 the end y location in millipoints * @param th the thickness in millipoints + * @param rs the rule style * @param r the red component * @param g the green component * @param b the blue component */ protected void addLine(int x1, int y1, int x2, int y2, int th, - PDFPathPaint stroke) { - closeText(); - - currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) + - (x1 / 1000f) + " "+ (y1 / 1000f) + " m " + - (x2 / 1000f) + " "+ (y2 / 1000f) + " l " + - (th / 1000f) + " w S\n" + "Q\nBT\n"); - } - - /** - * add a line to the current stream - * - * @param x1 the start x location in millipoints - * @param y1 the start y location in millipoints - * @param x2 the end x location in millipoints - * @param y2 the end y location in millipoints - * @param th the thickness in millipoints - * @param rs the rule style - * @param r the red component - * @param g the green component - * @param b the blue component - */ - protected void addLine(int x1, int y1, int x2, int y2, int th, int rs, PDFPathPaint stroke) { - closeText(); + closeText(); currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) + - setRuleStylePattern(rs) + (x1 / 1000f) + " "+ (y1 / 1000f) + " m " + - (x2 / 1000f) + " "+ (y2 / 1000f) + " l " + - (th / 1000f) + " w S\n" + "Q\nBT\n"); + setRuleStylePattern(rs) + (x1 / 1000f) + " "+ + (y1 / 1000f) + " m " + (x2 / 1000f) + " "+ + (y2 / 1000f) + " l " + (th / 1000f) + " w S\n" + "Q\nBT\n"); } /** - * add a rectangle to the current stream - * - * @param x the x position of left edge in millipoints - * @param y the y position of top edge in millipoints - * @param w the width in millipoints - * @param h the height in millipoints - * @param stroke the stroke color/gradient - */ + * add a rectangle to the current stream + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param stroke the stroke color/gradient + */ protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke) { - closeText(); + closeText(); currentStream.add("ET\nq\n" + stroke.getColorSpaceOut(false) + (x / 1000f) + " " + (y / 1000f) + " " + (w / 1000f) + " " + (h / 1000f) + " re s\n" + "Q\nBT\n"); } /** - * add a filled rectangle to the current stream - * - * @param x the x position of left edge in millipoints - * @param y the y position of top edge in millipoints - * @param w the width in millipoints - * @param h the height in millipoints - * @param fill the fill color/gradient - * @param stroke the stroke color/gradient - */ + * add a filled rectangle to the current stream + * + * @param x the x position of left edge in millipoints + * @param y the y position of top edge in millipoints + * @param w the width in millipoints + * @param h the height in millipoints + * @param fill the fill color/gradient + * @param stroke the stroke color/gradient + */ protected void addRect(int x, int y, int w, int h, PDFPathPaint stroke, PDFPathPaint fill) { - closeText(); + closeText(); currentStream.add("ET\nq\n" + fill.getColorSpaceOut(true) + stroke.getColorSpaceOut(false) + (x / 1000f) + " " + (y / 1000f) + " " + (w / 1000f) + " " + (h / 1000f) + @@ -197,10 +197,10 @@ public class PDFRenderer extends PrintRenderer { } /** - * render image area to PDF - * - * @param area the image area to render - */ + * render image area to PDF + * + * @param area the image area to render + */ public void renderImageArea(ImageArea area) { // adapted from contribution by BoBoGi int x = this.currentAreaContainerXPosition + area.getXOffset(); @@ -213,8 +213,8 @@ public class PDFRenderer extends PrintRenderer { FopImage img = area.getImage(); if (img instanceof SVGImage) { try { - closeText(); - + closeText(); + SVGSVGElement svg = ((SVGImage) img).getSVGDocument().getRootElement(); currentStream.add("ET\nq\n" + (((float) w) / 1000f) + @@ -227,8 +227,8 @@ public class PDFRenderer extends PrintRenderer { } } else { int xObjectNum = this.pdfDoc.addImage(img); - closeText(); - + closeText(); + currentStream.add("ET\nq\n" + (((float) w) / 1000f) + " 0 0 " + (((float) h) / 1000f) + " " + (((float) x) / 1000f) + " " + @@ -269,8 +269,8 @@ public class PDFRenderer extends PrintRenderer { case VerticalAlign.BOTTOM: break; } - closeText(); - + closeText(); + // in general the content will not be text currentStream.add("ET\n"); // align and scale @@ -296,64 +296,66 @@ public class PDFRenderer extends PrintRenderer { currentStream.add("Q\n"); currentStream.add("BT\n"); this.currentXPosition += area.getEffectiveWidth(); -// this.currentYPosition -= area.getEffectiveHeight(); + // this.currentYPosition -= area.getEffectiveHeight(); } /** - * render SVG area to PDF - * - * @param area the SVG area to render - */ + * render SVG area to PDF + * + * @param area the SVG area to render + */ public void renderSVGArea(SVGArea area) { // place at the current instream offset int x = this.currentXPosition; - // Buggy: Method getXOffset() not found in class org.apache.fop.dom.svg.SVGArea + // Buggy: Method getXOffset() not found in class org.apache.fop.dom.svg.SVGArea //int x = this.currentAreaContainerXPosition + area.getXOffset(); int y = this.currentYPosition; SVGSVGElement svg = area.getSVGDocument().getRootElement(); int w = (int)(svg.getWidth().getBaseVal().getValue() * 1000); int h = (int)(svg.getHeight().getBaseVal().getValue() * 1000); - float sx = 1, sy = -1; - int xOffset = x, yOffset = y; - - // translate and scale according to viewbox. - if (svg.getViewBox () != null) { - SVGRect view = svg.getViewBox().getBaseVal(); - - // TODO take aspect constraints (attribute preserveAspectRatio) - // into account. - // Viewbox coordinates are all relative to the viewport - // (ie. the x,y,w and h values calculated above). - sx = svg.getWidth().getBaseVal().getValue() / view.getWidth (); - sy = svg.getHeight().getBaseVal().getValue() / view.getHeight (); - - // move the origin - xOffset -= (int)(sx * view.getX () * 1000f); - yOffset -= (int)(sy * view.getY () * 1000f); - - sy = -sy; - } + float sx = 1, sy = -1; + int xOffset = x, yOffset = y; + + // translate and scale according to viewbox. + if (svg.getViewBox () != null) { + SVGRect view = svg.getViewBox().getBaseVal(); + + // TODO take aspect constraints (attribute preserveAspectRatio) + // into account. + // Viewbox coordinates are all relative to the viewport + // (ie. the x,y,w and h values calculated above). + sx = svg.getWidth().getBaseVal().getValue() / view.getWidth (); + sy = svg.getHeight().getBaseVal().getValue() / + view.getHeight (); + + // move the origin + xOffset -= (int)(sx * view.getX () * 1000f); + yOffset -= (int)(sy * view.getY () * 1000f); + + sy = -sy; + } /* - * Clip to the svg area. - * Note: To have the svg overlay (under) a text area then use - * an fo:block-container - */ + * Clip to the svg area. + * Note: To have the svg overlay (under) a text area then use + * an fo:block-container + */ currentStream.add("q\n"); - if (w != 0 && h != 0) { - currentStream.add(x / 1000f + " " + y / 1000f + " m\n"); - currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n"); - currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f + " l\n"); - currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n"); - currentStream.add("h\n"); - currentStream.add("W\n"); - currentStream.add("n\n"); - } + if (w != 0 && h != 0) { + currentStream.add(x / 1000f + " " + y / 1000f + " m\n"); + currentStream.add((x + w) / 1000f + " " + y / 1000f + " l\n"); + currentStream.add((x + w) / 1000f + " " + (y - h) / 1000f + + " l\n"); + currentStream.add(x / 1000f + " " + (y - h) / 1000f + " l\n"); + currentStream.add("h\n"); + currentStream.add("W\n"); + currentStream.add("n\n"); + } // transform so that the coordinates (0,0) is from the top left // and positive is down and to the right. (0,0) is where the - // viewBox puts it. - currentStream.add(sx + " 0 0 " + sy + " " + - xOffset / 1000f + " " + yOffset / 1000f + " cm\n"); + // viewBox puts it. + currentStream.add(sx + " 0 0 " + sy + " " + xOffset / 1000f + + " " + yOffset / 1000f + " cm\n"); SVGRenderer svgRenderer = new SVGRenderer(area.getFontState(), pdfDoc, @@ -366,17 +368,17 @@ public class PDFRenderer extends PrintRenderer { } /** - * render inline area to PDF - * - * @param area inline area to render - */ + * render inline area to PDF + * + * @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; - + Hashtable kerning = null; + boolean kerningAvailable = false; + kerning = area.getFontState().getKerning(); if (kerning != null && !kerning.isEmpty()) { kerningAvailable = true; @@ -385,23 +387,23 @@ public class PDFRenderer extends PrintRenderer { String name = area.getFontState().getFontName(); int size = area.getFontState().getFontSize(); - // This assumes that *all* CIDFonts use a /ToUnicode mapping + // This assumes that *all* CIDFonts use a /ToUnicode mapping boolean useMultiByte = false; - Font f = (Font)area.getFontState().getFontInfo().getFonts().get(name); + Font f = (Font) area.getFontState().getFontInfo().getFonts().get( + name); if (f instanceof CIDFont) - useMultiByte=true; - //String startText = useMultiByte ? "<FEFF" : "("; + useMultiByte = true; + //String startText = useMultiByte ? "<FEFF" : "("; String startText = useMultiByte ? "<" : "("; String endText = useMultiByte ? ">" : ")"; - + 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)) { - closeText(); - + closeText(); + this.currentFontName = name; this.currentFontSize = size; pdf = pdf.append("/" + name + " " + (size / 1000) + " Tf\n"); @@ -409,48 +411,47 @@ public class PDFRenderer extends PrintRenderer { if (!(theAreaColor.equals(this.currentFill))) { - closeText(); - this.currentFill = theAreaColor; - pdf.append(this.currentFill.getColorSpaceOut(true)); + closeText(); + this.currentFill = theAreaColor; + pdf.append(this.currentFill.getColorSpaceOut(true)); } int rx = this.currentXPosition; int bl = this.currentYPosition; - addWordLines(area, rx, bl, size, theAreaColor); - - if (OPTIMIZE_TEXT) { - if (!textOpen || bl != prevWordY) { - closeText(); - - pdf.append("1 0 0 1 " +(rx / 1000f) + " " + - (bl / 1000f) + " Tm [" + startText); - prevWordY = bl; - textOpen = true; - } - else { - // express the space between words in thousandths of an em - int space = prevWordX - rx + prevWordWidth; - float emDiff = (float)space / (float)currentFontSize * 1000f; - pdf.append(emDiff + " " + startText); - } - prevWordWidth = area.getContentWidth(); - prevWordX = rx; - - } - else { - // original text render code sets the text transformation matrix - // for every word. - pdf.append("1 0 0 1 " +(rx / 1000f) + " " + (bl / 1000f) + " Tm "); - if (kerningAvailable) { - pdf.append(" [" + startText); - } - else { - pdf.append(" " + startText); - } - } - + addWordLines(area, rx, bl, size, theAreaColor); + + if (OPTIMIZE_TEXT) { + if (!textOpen || bl != prevWordY) { + closeText(); + + pdf.append("1 0 0 1 " +(rx / 1000f) + " " + + (bl / 1000f) + " Tm [" + startText); + prevWordY = bl; + textOpen = true; + } else { + // express the space between words in thousandths of an em + int space = prevWordX - rx + prevWordWidth; + float emDiff = + (float) space / (float) currentFontSize * 1000f; + pdf.append(emDiff + " " + startText); + } + prevWordWidth = area.getContentWidth(); + prevWordX = rx; + + } else { + // original text render code sets the text transformation matrix + // for every word. + pdf.append("1 0 0 1 " +(rx / 1000f) + " " + (bl / 1000f) + + " Tm "); + if (kerningAvailable) { + pdf.append(" [" + startText); + } else { + pdf.append(" " + startText); + } + } + String s; if (area.getPageNumberID() != null) { // this text is a page number, so resolve it s = idReferences.getPageNumber(area.getPageNumberID()); @@ -465,10 +466,10 @@ public class PDFRenderer extends PrintRenderer { for (int i = 0; i < l; i++) { char ch = s.charAt(i); - String prepend = ""; - + String prepend = ""; + if (!useMultiByte) { - if(ch > 127) { + if (ch > 127) { pdf.append("\\"); pdf.append(Integer.toOctalString((int) ch)); } else { @@ -479,115 +480,110 @@ public class PDFRenderer extends PrintRenderer { prepend = "\\"; break; } - pdf.append(getUnicodeString(prepend+ch, useMultiByte)); + pdf.append( + getUnicodeString(prepend + ch, useMultiByte)); } - } else { - pdf.append(getUnicodeString(prepend+ch, useMultiByte)); - } - - if (kerningAvailable && (i+1) < l) { - pdf.append(addKerning((new Integer((int)ch)), - (new Integer((int)s.charAt(i+1))), - kerning, - startText, endText)); + } else { + pdf.append(getUnicodeString(prepend + ch, useMultiByte)); + } + + if (kerningAvailable && (i + 1) < l) { + addKerning(pdf, (new Integer((int) ch)), + (new Integer((int) s.charAt(i + 1))), kerning, + startText, endText); } - + } pdf.append(endText + " "); - if (!OPTIMIZE_TEXT) { - if (kerningAvailable) { - pdf.append("] TJ\n"); - } - else { - pdf.append("Tj\n"); - } - - } - + if (!OPTIMIZE_TEXT) { + if (kerningAvailable) { + pdf.append("] TJ\n"); + } else { + pdf.append("Tj\n"); + } + + } + currentStream.add(pdf.toString()); this.currentXPosition += area.getContentWidth(); - + } - /** - * Convert a string to a unicode hex representation - */ - private String getUnicodeString(StringBuffer str, boolean useMultiByte) { + /** + * Convert a string to a unicode hex representation + */ + private String getUnicodeString(StringBuffer str, + boolean useMultiByte) { return getUnicodeString(str.toString(), useMultiByte); } - - /** - * Convert a string to a multibyte hex representation - */ + + /** + * Convert a string to a multibyte hex representation + */ private String getUnicodeString(String str, boolean useMultiByte) { if (!useMultiByte) { return str; } else { - StringBuffer buf = new StringBuffer(str.length()*4); + StringBuffer buf = new StringBuffer(str.length() * 4); byte[] uniBytes = null; try { uniBytes = str.getBytes("UnicodeBigUnmarked"); } catch (Exception e) { - // This should never fail + // This should never fail } - + for (int i = 0; i < uniBytes.length; i++) { - int b = (uniBytes[i] < 0) ? (int)(256+uniBytes[i]) - : (int)uniBytes[i]; - - String hexString=Integer.toHexString(b); - if (hexString.length()==1) - buf=buf.append("0"+hexString); + int b = (uniBytes[i] < 0) ? (int)(256 + uniBytes[i]) : + (int) uniBytes[i]; + + String hexString = Integer.toHexString(b); + if (hexString.length() == 1) + buf = buf.append("0"+hexString); else - buf=buf.append(hexString); + buf = buf.append(hexString); } return buf.toString(); } } - - + + /** Checks to see if we have some text rendering commands open - * still and writes out the TJ command to the stream if we do - */ - private void closeText() - { - if (OPTIMIZE_TEXT && textOpen) { - currentStream.add("] TJ\n"); - textOpen = false; - prevWordX = 0; - prevWordY = 0; - } + * still and writes out the TJ command to the stream if we do + */ + private void closeText() { + if (OPTIMIZE_TEXT && textOpen) { + currentStream.add("] TJ\n"); + textOpen = false; + prevWordX = 0; + prevWordY = 0; + } } - private StringBuffer addKerning(Integer ch1, Integer ch2, - Hashtable kerning, String startText, - String endText) { - 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(endText + " " + pwdt + " " + startText); - } - } - return buf; - } + private void addKerning(StringBuffer buf, Integer ch1, Integer ch2, + Hashtable kerning, String startText, String endText) { + Hashtable h2 = (Hashtable) kerning.get(ch1); + + if (h2 != null) { + Integer wdt = (Integer) h2.get(ch2); + if (wdt != null) { + buf.append(endText).append(' ').append(- + wdt.intValue()).append(' ').append(startText); + } + } + } /** - * render page into PDF - * - * @param page page to render - */ + * render page into PDF + * + * @param page page to render + */ public void renderPage(Page page) { - BodyAreaContainer body; + BodyAreaContainer body; AreaContainer before, after, start, end; currentStream = this.pdfDoc.makeStream(); @@ -600,7 +596,7 @@ public class PDFRenderer extends PrintRenderer { this.currentFontName = ""; this.currentFontSize = 0; - currentStream.add("BT\n"); + currentStream.add("BT\n"); renderBodyAreaContainer(body); @@ -612,20 +608,19 @@ public class PDFRenderer extends PrintRenderer { renderAreaContainer(after); } - if (start != null) { + if (start != null) { renderAreaContainer(start); } - if (end != null) { + if (end != null) { renderAreaContainer(end); } - closeText(); - + closeText(); + currentStream.add("ET\n"); currentPage = this.pdfDoc.makePage(this.pdfResources, currentStream, - page.getWidth() / 1000, - page.getHeight() / 1000, page); + page.getWidth() / 1000, page.getHeight() / 1000, page); if (page.hasLinks()) { currentAnnotList = this.pdfDoc.makeAnnotList(); @@ -654,8 +649,8 @@ public class PDFRenderer extends PrintRenderer { } /** - * defines a string containing dashArray and dashPhase for the rule style - */ + * defines a string containing dashArray and dashPhase for the rule style + */ private String setRuleStylePattern (int style) { String rs = ""; switch (style) { @@ -677,52 +672,49 @@ public class PDFRenderer extends PrintRenderer { return rs; } - protected void renderRootExtensions(AreaTree areaTree) - { - Vector v = areaTree.getExtensions(); - if (v != null) { - Enumeration e = v.elements(); - while (e.hasMoreElements()) { - ExtensionObj ext = (ExtensionObj)e.nextElement(); - if (ext instanceof Outline) { - renderOutline((Outline)ext); - } - } - } - + protected void renderRootExtensions(AreaTree areaTree) { + Vector v = areaTree.getExtensions(); + if (v != null) { + Enumeration e = v.elements(); + while (e.hasMoreElements()) { + ExtensionObj ext = (ExtensionObj) e.nextElement(); + if (ext instanceof Outline) { + renderOutline((Outline) ext); + } + } + } + } - private void renderOutline(Outline outline) - { - if (rootOutline == null) { - rootOutline = this.pdfDoc.makeOutlineRoot(); - } - PDFOutline pdfOutline = null; - Outline parent = outline.getParentOutline(); - if (parent == null) { - pdfOutline = this.pdfDoc.makeOutline(rootOutline, - outline.getLabel().toString(), - outline.getInternalDestination()); - } - else { - PDFOutline pdfParentOutline = (PDFOutline)parent.getRendererObject(); - if (pdfParentOutline == null) { - MessageHandler.errorln("Error: pdfParentOutline is null"); - } - else { - pdfOutline = this.pdfDoc.makeOutline(pdfParentOutline, - outline.getLabel().toString(), - outline.getInternalDestination()); - } - - } - outline.setRendererObject(pdfOutline); - - // handle sub outlines - Vector v = outline.getOutlines(); - Enumeration e = v.elements(); - while (e.hasMoreElements()) { - renderOutline((Outline)e.nextElement()); - } + private void renderOutline(Outline outline) { + if (rootOutline == null) { + rootOutline = this.pdfDoc.makeOutlineRoot(); + } + PDFOutline pdfOutline = null; + Outline parent = outline.getParentOutline(); + if (parent == null) { + pdfOutline = this.pdfDoc.makeOutline(rootOutline, + outline.getLabel().toString(), + outline.getInternalDestination()); + } else { + PDFOutline pdfParentOutline = + (PDFOutline) parent.getRendererObject(); + if (pdfParentOutline == null) { + MessageHandler.errorln("Error: pdfParentOutline is null"); + } else { + pdfOutline = this.pdfDoc.makeOutline(pdfParentOutline, + outline.getLabel().toString(), + outline.getInternalDestination()); + } + + } + outline.setRendererObject(pdfOutline); + + // handle sub outlines + Vector v = outline.getOutlines(); + Enumeration e = v.elements(); + while (e.hasMoreElements()) { + renderOutline((Outline) e.nextElement()); + } } } diff --git a/src/org/apache/fop/render/pdf/fonts/MultiByteFont.java b/src/org/apache/fop/render/pdf/fonts/MultiByteFont.java index 7b55e843d..f8305c3d6 100644 --- a/src/org/apache/fop/render/pdf/fonts/MultiByteFont.java +++ b/src/org/apache/fop/render/pdf/fonts/MultiByteFont.java @@ -1,17 +1,26 @@ - +/* $Id$ + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." + */ package org.apache.fop.render.pdf.fonts; import org.apache.fop.render.pdf.Font; import org.apache.fop.layout.FontDescriptor; import org.apache.fop.fonts.Glyphs; +import org.apache.fop.fonts.TTFSubSetFile; +import org.apache.fop.fonts.FontFileReader; import org.apache.fop.pdf.PDFStream; import org.apache.fop.pdf.PDFWArray; import org.apache.fop.pdf.PDFCIDFont; import org.apache.fop.render.pdf.CIDFont; import org.apache.fop.render.pdf.CMap; import org.apache.fop.pdf.PDFTTFStream; +import org.apache.fop.messaging.MessageHandler; import java.io.InputStream; +import java.io.IOException; import java.io.FileInputStream; import java.io.File; import java.io.BufferedInputStream; @@ -22,143 +31,185 @@ import java.util.Hashtable; */ public class MultiByteFont extends CIDFont implements FontDescriptor { public String fontName = null; + public String ttcName = null; public String encoding = "Identity-H"; - + public int capHeight = 0; public int xHeight = 0; public int ascender = 0; public int descender = 0; public int[] fontBBox = {0, 0, 0, 0}; - + public String embedFileName = null; public String embedResourceName = null; - public PDFTTFStream embeddedFont=null; - + public PDFTTFStream embeddedFont = null; + public int flags = 4; public int stemV = 0; public int italicAngle = 0; public int missingWidth = 0; public int defaultWidth = 0; public byte cidType = PDFCIDFont.CID_TYPE2; - - public Hashtable kerning=new Hashtable(); + + public Hashtable kerning = new Hashtable(); public boolean useKerning = true; - - public PDFWArray warray=new PDFWArray(); + private String namePrefix = null; // Quasi unique prefix + private static int uniqueCounter = 1; + public PDFWArray warray = new PDFWArray(); public int width[] = null; public BFEntry[] bfentries = null; - - public MultiByteFont() {} - + + /** usedGlyphs contains orginal, new glyph index */ + private Hashtable usedGlyphs = new Hashtable(); + /** usedGlyphsIndex contains new glyph, original index */ + private Hashtable usedGlyphsIndex = new Hashtable(); + int usedGlyphsCount = 0; + + public MultiByteFont() { + // Make sure that the 3 first glyphs are included + usedGlyphs.put(new Integer(0), new Integer(0)); + usedGlyphsIndex.put(new Integer(0), new Integer(0)); + usedGlyphsCount++; + usedGlyphs.put(new Integer(1), new Integer(1)); + usedGlyphsIndex.put(new Integer(1), new Integer(1)); + usedGlyphsCount++; + usedGlyphs.put(new Integer(2), new Integer(2)); + usedGlyphsIndex.put(new Integer(2), new Integer(2)); + usedGlyphsCount++; + + // Create a quasiunique prefix for fontname + int cnt = 0; + synchronized (this.getClass()) { + cnt = uniqueCounter++; + } + int ctm = (int)(System.currentTimeMillis() & 0xffff); + namePrefix = new String(cnt + "E"+ Integer.toHexString(ctm)); + } + public final boolean hasKerningInfo() { return (useKerning & kerning.isEmpty()); } - public final java.util.Hashtable getKerningInfo() {return kerning;} + public final java.util.Hashtable getKerningInfo() { + if (useKerning) + return kerning; + else + return new Hashtable(); + } public byte getSubType() { return org.apache.fop.pdf.PDFFont.TYPE0; } - public String getLang() {return null;} - public String getPanose() {return null;} - public int getAvgWidth() {return -1;} - public int getMinWidth() {return -1;} - public int getMaxWidth() {return -1;} - public int getleading() {return -1;} - public int getStemH() {return 0;} - public int getMissingWidth() {return missingWidth;} - public int getDefaultWidth() {return defaultWidth;} - public String getRegistry() {return "Adobe";} - public String getOrdering() {return "UCS";} - public int getSupplement() {return 0;} - public byte getCidType() {return cidType;} - public String getCidBaseFont() {return fontName;} - public String getCharEncoding() {return "Identity-H";} + public String getLang() { + return null; + } + public String getPanose() { + return null; + } + public int getAvgWidth() { + return -1; + } + public int getMinWidth() { + return -1; + } + public int getMaxWidth() { + return -1; + } + public int getleading() { + return -1; + } + public int getStemH() { + return 0; + } + public int getMissingWidth() { + return missingWidth; + } + public int getDefaultWidth() { + return defaultWidth; + } + public String getRegistry() { + return "Adobe"; + } + public String getOrdering() { + return "UCS"; + } + public int getSupplement() { + return 0; + } + public byte getCidType() { + return cidType; + } + public String getCidBaseFont() { + return isEmbeddable() ? namePrefix + fontName : fontName; + } + + public String getCharEncoding() { + return "Identity-H"; + } public PDFWArray getWidths() { + if (isEmbeddable()) { + // Create widths for reencoded chars + warray = new PDFWArray(); + int[] tmpWidth = new int[usedGlyphsCount]; + + for (int i = 0; i < usedGlyphsCount; i++) { + Integer nw = (Integer) usedGlyphsIndex.get(new Integer(i)); + int nwx = (nw == null) ? 0 : nw.intValue(); + tmpWidth[i] = width[nwx]; + } + warray.addEntry(0, tmpWidth); + } return warray; } public boolean isEmbeddable() { - return (embedFileName==null && embedResourceName==null) ? false : true; + return (embedFileName == null && embedResourceName == null) ? + false : true; } - - public PDFStream getFontFile(int i) { - InputStream instream=null; - int iniSize = 256000; - int incSize = 128000; - // Get file first - if (embedFileName!=null) - try { - File ef = new File(embedFileName); - iniSize = (int)ef.length()+1; - incSize = (int)ef.length()/10; - instream=new FileInputStream(embedFileName); - } catch (Exception e) { - System.out.println("Failed to embed fontfile: "+embedFileName); - } - - // Get resource - if (instream==null && embedResourceName!=null) + public PDFStream getFontFile(int i) { try { - instream=new BufferedInputStream(this.getClass().getResourceAsStream(embedResourceName)); - } catch (Exception e) { - System.out.println("Failed to embed fontresource: "+embedResourceName); + FontFileReader reader = new FontFileReader(embedFileName); + TTFSubSetFile subset = new TTFSubSetFile(); + + byte[] subsetFont = + subset.readFont(reader, ttcName, usedGlyphs); + // Only TrueType CID fonts are supported now + + embeddedFont = new PDFTTFStream(i, subsetFont.length); + embeddedFont.addFilter("flate"); + embeddedFont.addFilter("ascii-85"); + embeddedFont.setData(subsetFont, subsetFont.length); + } catch (IOException ioe) { + MessageHandler.error("Failed to embed font " + fontName + + ": " + ioe.getMessage()); + return (PDFStream) null; } - - if (instream==null) - return (PDFStream)null; - - // Read fontdata - byte[] file = new byte[iniSize]; - int fsize = 0; - - try { - int l = instream.read(file, 0, iniSize); - fsize += l; - - if (l==iniSize) { - // More to read - needs to extend - byte[] tmpbuf; - - while (l > 0) { - tmpbuf = new byte[file.length + incSize]; - System.arraycopy(file, 0, tmpbuf, 0, file.length); - l=instream.read(tmpbuf, file.length, incSize); - fsize += l; - file = tmpbuf; - - if (l < incSize) // whole file read. No need to loop again - l=0; - } - } - - // Only TrueType CID fonts are supported now - embeddedFont=new PDFTTFStream(i, fsize); - embeddedFont.addFilter("flate"); - embeddedFont.addFilter("ascii-85"); - embeddedFont.setData(file, fsize); - instream.close(); - } catch (Exception e) {} return (PDFStream) embeddedFont; } - + public String encoding() { return encoding; } - + public String fontName() { - return fontName; + return isEmbeddable() ? namePrefix + fontName : fontName; } - public int getAscender() {return ascender;} - public int getDescender() {return descender;} - public int getCapHeight() {return capHeight;} + public int getAscender() { + return ascender; + } + public int getDescender() { + return descender; + } + public int getCapHeight() { + return capHeight; + } public int getAscender(int size) { return size * ascender; @@ -201,36 +252,73 @@ public class MultiByteFont extends CIDFont implements FontDescriptor { } public int width(int i, int size) { - return size * width[i]; + if (isEmbeddable()) { + Integer idx = (Integer) usedGlyphsIndex.get(new Integer(i)); + return size * width[idx.intValue()]; + } else { + return size * width[i]; + } } public int[] getWidths(int size) { int[] arr = new int[width.length]; - System.arraycopy(width, 0, arr, 0, width.length-1); - for( int i = 0; i < arr.length; i++) arr[i] *= size; + System.arraycopy(width, 0, arr, 0, width.length - 1); + for (int i = 0; i < arr.length; i++) + arr[i] *= size; return arr; } + public Integer reMap(Integer i) { + if (isEmbeddable()) { + Integer ret = (Integer) usedGlyphsIndex.get(i); + if (ret == null) + ret = i; + return ret; + } else { + return i; + } + + } + public char mapChar(char c) { - int idx = (int)c; + int idx = (int) c; int retIdx = 0; for (int i = 0; (i < bfentries.length) && retIdx == 0; i++) { - - /* - System.out.println("us: "+bfentries[i].unicodeStart + - " ue: "+bfentries[i].unicodeEnd+ - " gi: "+bfentries[i].glyphStartIndex); - */ if (bfentries[i].unicodeStart <= idx && - bfentries[i].unicodeEnd >= idx) { - retIdx=bfentries[i].glyphStartIndex + idx - - bfentries[i].unicodeStart; + bfentries[i].unicodeEnd >= idx) { + retIdx = bfentries[i].glyphStartIndex + idx - + bfentries[i].unicodeStart; + } + } + + if (isEmbeddable()) { + // Reencode to a new subset font or get + // the reencoded value + Integer newIdx = (Integer) usedGlyphs.get(new Integer(retIdx)); + if (newIdx == null) { + usedGlyphs.put(new Integer(retIdx), + new Integer(usedGlyphsCount)); + usedGlyphsIndex.put(new Integer(usedGlyphsCount), + new Integer(retIdx)); + retIdx = usedGlyphsCount; + //System.out.println(c+"("+(int)c+") = "+retIdx); + usedGlyphsCount++; + } else { + retIdx = newIdx.intValue(); } } - //System.out.println("Map: "+ c + " (" + idx + ") = " + retIdx); - return (char)retIdx; + return (char) retIdx; } } + + + + + + + + + diff --git a/src/org/apache/fop/render/pdf/fonts/SingleByteFont.java b/src/org/apache/fop/render/pdf/fonts/SingleByteFont.java index 413d2e7d3..8a847e2c5 100644 --- a/src/org/apache/fop/render/pdf/fonts/SingleByteFont.java +++ b/src/org/apache/fop/render/pdf/fonts/SingleByteFont.java @@ -1,4 +1,9 @@ - +/* $Id$ + * + * Copyright (C) 2001 The Apache Software Foundation. All rights reserved. + * For details on use and redistribution please refer to the + * LICENSE file included with these sources." + */ package org.apache.fop.render.pdf.fonts; @@ -47,7 +52,12 @@ public class SingleByteFont extends Font implements FontDescriptor { return (useKerning & kerning.isEmpty()); } - public final java.util.Hashtable getKerningInfo() {return kerning;} + public final java.util.Hashtable getKerningInfo() { + if (useKerning) + return kerning; + else + return new Hashtable(); + } public byte getSubType() { return subType; |