diff options
Diffstat (limited to 'src')
105 files changed, 15812 insertions, 0 deletions
diff --git a/src/net/java/dev/typecast/ot/Disassembler.java b/src/net/java/dev/typecast/ot/Disassembler.java new file mode 100644 index 000000000..73e75cc39 --- /dev/null +++ b/src/net/java/dev/typecast/ot/Disassembler.java @@ -0,0 +1,109 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot; + +/** + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Disassembler.java,v 1.1.1.1 2004-12-05 23:14:25 davidsch Exp $ + */ +public class Disassembler { + + /** + * Advance the instruction pointer to the next executable opcode. + * This will be the next byte, unless the current opcode is a push + * instruction, in which case it will be the byte immediately beyond + * the last data byte. + * @param ip The current instruction pointer + * @return The new instruction pointer + */ + public static int advanceIP(short[] instructions, int ip) { + + // The high word specifies font, cvt, or glyph program + int i = ip & 0xffff; + int dataCount; + ip++; + if (Mnemonic.NPUSHB == instructions[i]) { + // Next byte is the data byte count + dataCount = instructions[++i]; + ip += dataCount + 1; + } else if (Mnemonic.NPUSHW == instructions[i]) { + // Next byte is the data word count + dataCount = instructions[++i]; + ip += dataCount*2 + 1; + } else if (Mnemonic.PUSHB == (instructions[i] & 0xf8)) { + dataCount = (short)((instructions[i] & 0x07) + 1); + ip += dataCount; + } else if (Mnemonic.PUSHW == (instructions[i] & 0xf8)) { + dataCount = (short)((instructions[i] & 0x07) + 1); + ip += dataCount*2; + } + return ip; + } + + public static short getPushCount(short[] instructions, int ip) { + short instr = instructions[ip & 0xffff]; + if ((Mnemonic.NPUSHB == instr) || (Mnemonic.NPUSHW == instr)) { + return instructions[(ip & 0xffff) + 1]; + } else if ((Mnemonic.PUSHB == (instr & 0xf8)) || (Mnemonic.PUSHW == (instr & 0xf8))) { + return (short)((instr & 0x07) + 1); + } + return 0; + } + + public static int[] getPushData(short[] instructions, int ip) { + int count = getPushCount(instructions, ip); + int[] data = new int[count]; + int i = ip & 0xffff; + short instr = instructions[i]; + if (Mnemonic.NPUSHB == instr) { + for (int j = 0; j < count; j++) { + data[j] = instructions[i + j + 2]; + } + } else if (Mnemonic.PUSHB == (instr & 0xf8)) { + for (int j = 0; j < count; j++) { + data[j] = instructions[i + j + 1]; + } + } else if (Mnemonic.NPUSHW == instr) { + for (int j = 0; j < count; j++) { + data[j] = (instructions[i + j*2 + 2] << 8) | instructions[i + j*2 + 3]; + } + } else if (Mnemonic.PUSHW == (instr & 0xf8)) { + for (int j = 0; j < count; j++) { + data[j] = (instructions[i + j*2 + 1] << 8) | instructions[i + j*2 + 2]; + } + } + return data; + } + + public static String disassemble(short[] instructions, int leadingSpaces) { + StringBuffer sb = new StringBuffer(); + int ip = 0; + while (ip < instructions.length) { + for (int i = 0; i < leadingSpaces; i++) { + sb.append(" "); + } + sb.append(ip).append(": "); + sb.append(Mnemonic.getMnemonic(instructions[ip])); + if (getPushCount(instructions, ip) > 0) { + int[] data = getPushData(instructions, ip); + for(int j = 0; j < data.length; j++) { + if ((instructions[ip] == Mnemonic.PUSHW) || + (instructions[ip] == Mnemonic.NPUSHW)) { + sb.append(" ").append((short) data[j]); + } else { + sb.append(" ").append(data[j]); + } + } + } + sb.append("\n"); + ip = advanceIP(instructions, ip); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/Fixed.java b/src/net/java/dev/typecast/ot/Fixed.java new file mode 100644 index 000000000..6f83e922c --- /dev/null +++ b/src/net/java/dev/typecast/ot/Fixed.java @@ -0,0 +1,852 @@ +/* + * $Id: Fixed.java,v 1.1.1.1 2004-12-05 23:14:26 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot; + +/** + * Functions for working with signed 16.16 fixed values + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Fixed.java,v 1.1.1.1 2004-12-05 23:14:26 davidsch Exp $ + */ +public class Fixed { + + // Tangent LUT + static private int[] t = { + 0x0, + 0x1, + 0x3, + 0x4, + 0x6, + 0x7, + 0x9, + 0xb, + 0xc, + 0xe, + 0xf, + 0x11, + 0x12, + 0x14, + 0x16, + 0x17, + 0x19, + 0x1a, + 0x1c, + 0x1d, + 0x1f, + 0x21, + 0x22, + 0x24, + 0x25, + 0x27, + 0x29, + 0x2a, + 0x2c, + 0x2e, + 0x2f, + 0x31, + 0x32, + 0x34, + 0x36, + 0x37, + 0x39, + 0x3b, + 0x3c, + 0x3e, + 0x40, + 0x41, + 0x43, + 0x45, + 0x46, + 0x48, + 0x4a, + 0x4b, + 0x4d, + 0x4f, + 0x51, + 0x52, + 0x54, + 0x56, + 0x58, + 0x59, + 0x5b, + 0x5d, + 0x5f, + 0x60, + 0x62, + 0x64, + 0x66, + 0x68, + 0x6a, + 0x6b, + 0x6d, + 0x6f, + 0x71, + 0x73, + 0x75, + 0x77, + 0x79, + 0x7b, + 0x7c, + 0x7e, + 0x80, + 0x82, + 0x84, + 0x86, + 0x88, + 0x8a, + 0x8c, + 0x8e, + 0x91, + 0x93, + 0x95, + 0x97, + 0x99, + 0x9b, + 0x9d, + 0x9f, + 0xa2, + 0xa4, + 0xa6, + 0xa8, + 0xab, + 0xad, + 0xaf, + 0xb1, + 0xb4, + 0xb6, + 0xb9, + 0xbb, + 0xbd, + 0xc0, + 0xc2, + 0xc5, + 0xc7, + 0xca, + 0xcc, + 0xcf, + 0xd2, + 0xd4, + 0xd7, + 0xda, + 0xdc, + 0xdf, + 0xe2, + 0xe5, + 0xe8, + 0xea, + 0xed, + 0xf0, + 0xf3, + 0xf6, + 0xf9, + 0xfc, + 0x100, + 0x103, + 0x106, + 0x109, + 0x10c, + 0x110, + 0x113, + 0x116, + 0x11a, + 0x11d, + 0x121, + 0x125, + 0x128, + 0x12c, + 0x130, + 0x134, + 0x137, + 0x13b, + 0x13f, + 0x143, + 0x148, + 0x14c, + 0x150, + 0x154, + 0x159, + 0x15d, + 0x162, + 0x166, + 0x16b, + 0x170, + 0x175, + 0x17a, + 0x17f, + 0x184, + 0x189, + 0x18e, + 0x194, + 0x199, + 0x19f, + 0x1a5, + 0x1ab, + 0x1b1, + 0x1b7, + 0x1bd, + 0x1c3, + 0x1ca, + 0x1d1, + 0x1d7, + 0x1de, + 0x1e6, + 0x1ed, + 0x1f4, + 0x1fc, + 0x204, + 0x20c, + 0x214, + 0x21d, + 0x225, + 0x22e, + 0x238, + 0x241, + 0x24b, + 0x255, + 0x25f, + 0x26a, + 0x274, + 0x280, + 0x28b, + 0x297, + 0x2a3, + 0x2b0, + 0x2bd, + 0x2cb, + 0x2d9, + 0x2e8, + 0x2f7, + 0x306, + 0x317, + 0x328, + 0x339, + 0x34b, + 0x35e, + 0x372, + 0x387, + 0x39d, + 0x3b3, + 0x3cb, + 0x3e4, + 0x3fe, + 0x419, + 0x435, + 0x454, + 0x474, + 0x495, + 0x4b9, + 0x4de, + 0x506, + 0x531, + 0x55e, + 0x58f, + 0x5c3, + 0x5fb, + 0x637, + 0x677, + 0x6bd, + 0x709, + 0x75c, + 0x7b7, + 0x81b, + 0x889, + 0x904, + 0x98d, + 0xa27, + 0xad5, + 0xb9c, + 0xc82, + 0xd8e, + 0xecb, + 0x1046, + 0x1217, + 0x145a, + 0x1744, + 0x1b26, + 0x2095, + 0x28bc, + 0x3651, + 0x517b, + 0xa2f8 + }; + + // Sine LUT + static private int[] s = { + 0x0, + 0x1, + 0x3, + 0x4, + 0x6, + 0x7, + 0x9, + 0xa, + 0xc, + 0xe, + 0xf, + 0x11, + 0x12, + 0x14, + 0x15, + 0x17, + 0x19, + 0x1a, + 0x1c, + 0x1d, + 0x1f, + 0x20, + 0x22, + 0x24, + 0x25, + 0x27, + 0x28, + 0x2a, + 0x2b, + 0x2d, + 0x2e, + 0x30, + 0x31, + 0x33, + 0x35, + 0x36, + 0x38, + 0x39, + 0x3b, + 0x3c, + 0x3e, + 0x3f, + 0x41, + 0x42, + 0x44, + 0x45, + 0x47, + 0x48, + 0x4a, + 0x4b, + 0x4d, + 0x4e, + 0x50, + 0x51, + 0x53, + 0x54, + 0x56, + 0x57, + 0x59, + 0x5a, + 0x5c, + 0x5d, + 0x5f, + 0x60, + 0x61, + 0x63, + 0x64, + 0x66, + 0x67, + 0x69, + 0x6a, + 0x6c, + 0x6d, + 0x6e, + 0x70, + 0x71, + 0x73, + 0x74, + 0x75, + 0x77, + 0x78, + 0x7a, + 0x7b, + 0x7c, + 0x7e, + 0x7f, + 0x80, + 0x82, + 0x83, + 0x84, + 0x86, + 0x87, + 0x88, + 0x8a, + 0x8b, + 0x8c, + 0x8e, + 0x8f, + 0x90, + 0x92, + 0x93, + 0x94, + 0x95, + 0x97, + 0x98, + 0x99, + 0x9b, + 0x9c, + 0x9d, + 0x9e, + 0x9f, + 0xa1, + 0xa2, + 0xa3, + 0xa4, + 0xa6, + 0xa7, + 0xa8, + 0xa9, + 0xaa, + 0xab, + 0xad, + 0xae, + 0xaf, + 0xb0, + 0xb1, + 0xb2, + 0xb3, + 0xb5, + 0xb6, + 0xb7, + 0xb8, + 0xb9, + 0xba, + 0xbb, + 0xbc, + 0xbd, + 0xbe, + 0xbf, + 0xc0, + 0xc1, + 0xc2, + 0xc3, + 0xc4, + 0xc5, + 0xc6, + 0xc7, + 0xc8, + 0xc9, + 0xca, + 0xcb, + 0xcc, + 0xcd, + 0xce, + 0xcf, + 0xd0, + 0xd1, + 0xd2, + 0xd3, + 0xd3, + 0xd4, + 0xd5, + 0xd6, + 0xd7, + 0xd8, + 0xd9, + 0xd9, + 0xda, + 0xdb, + 0xdc, + 0xdd, + 0xdd, + 0xde, + 0xdf, + 0xe0, + 0xe1, + 0xe1, + 0xe2, + 0xe3, + 0xe3, + 0xe4, + 0xe5, + 0xe6, + 0xe6, + 0xe7, + 0xe8, + 0xe8, + 0xe9, + 0xea, + 0xea, + 0xeb, + 0xeb, + 0xec, + 0xed, + 0xed, + 0xee, + 0xee, + 0xef, + 0xef, + 0xf0, + 0xf1, + 0xf1, + 0xf2, + 0xf2, + 0xf3, + 0xf3, + 0xf4, + 0xf4, + 0xf4, + 0xf5, + 0xf5, + 0xf6, + 0xf6, + 0xf7, + 0xf7, + 0xf7, + 0xf8, + 0xf8, + 0xf9, + 0xf9, + 0xf9, + 0xfa, + 0xfa, + 0xfa, + 0xfb, + 0xfb, + 0xfb, + 0xfb, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfd, + 0xfd, + 0xfd, + 0xfd, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff + }; + + // Cosine LUT + static private int[] c = { + 0x100, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfe, + 0xfd, + 0xfd, + 0xfd, + 0xfd, + 0xfc, + 0xfc, + 0xfc, + 0xfc, + 0xfb, + 0xfb, + 0xfb, + 0xfb, + 0xfa, + 0xfa, + 0xfa, + 0xf9, + 0xf9, + 0xf9, + 0xf8, + 0xf8, + 0xf7, + 0xf7, + 0xf7, + 0xf6, + 0xf6, + 0xf5, + 0xf5, + 0xf4, + 0xf4, + 0xf4, + 0xf3, + 0xf3, + 0xf2, + 0xf2, + 0xf1, + 0xf1, + 0xf0, + 0xef, + 0xef, + 0xee, + 0xee, + 0xed, + 0xed, + 0xec, + 0xeb, + 0xeb, + 0xea, + 0xea, + 0xe9, + 0xe8, + 0xe8, + 0xe7, + 0xe6, + 0xe6, + 0xe5, + 0xe4, + 0xe3, + 0xe3, + 0xe2, + 0xe1, + 0xe1, + 0xe0, + 0xdf, + 0xde, + 0xdd, + 0xdd, + 0xdc, + 0xdb, + 0xda, + 0xd9, + 0xd9, + 0xd8, + 0xd7, + 0xd6, + 0xd5, + 0xd4, + 0xd3, + 0xd3, + 0xd2, + 0xd1, + 0xd0, + 0xcf, + 0xce, + 0xcd, + 0xcc, + 0xcb, + 0xca, + 0xc9, + 0xc8, + 0xc7, + 0xc6, + 0xc5, + 0xc4, + 0xc3, + 0xc2, + 0xc1, + 0xc0, + 0xbf, + 0xbe, + 0xbd, + 0xbc, + 0xbb, + 0xba, + 0xb9, + 0xb8, + 0xb7, + 0xb6, + 0xb5, + 0xb3, + 0xb2, + 0xb1, + 0xb0, + 0xaf, + 0xae, + 0xad, + 0xab, + 0xaa, + 0xa9, + 0xa8, + 0xa7, + 0xa6, + 0xa4, + 0xa3, + 0xa2, + 0xa1, + 0x9f, + 0x9e, + 0x9d, + 0x9c, + 0x9b, + 0x99, + 0x98, + 0x97, + 0x95, + 0x94, + 0x93, + 0x92, + 0x90, + 0x8f, + 0x8e, + 0x8c, + 0x8b, + 0x8a, + 0x88, + 0x87, + 0x86, + 0x84, + 0x83, + 0x82, + 0x80, + 0x7f, + 0x7e, + 0x7c, + 0x7b, + 0x7a, + 0x78, + 0x77, + 0x75, + 0x74, + 0x73, + 0x71, + 0x70, + 0x6e, + 0x6d, + 0x6c, + 0x6a, + 0x69, + 0x67, + 0x66, + 0x64, + 0x63, + 0x61, + 0x60, + 0x5f, + 0x5d, + 0x5c, + 0x5a, + 0x59, + 0x57, + 0x56, + 0x54, + 0x53, + 0x51, + 0x50, + 0x4e, + 0x4d, + 0x4b, + 0x4a, + 0x48, + 0x47, + 0x45, + 0x44, + 0x42, + 0x41, + 0x3f, + 0x3e, + 0x3c, + 0x3b, + 0x39, + 0x38, + 0x36, + 0x35, + 0x33, + 0x31, + 0x30, + 0x2e, + 0x2d, + 0x2b, + 0x2a, + 0x28, + 0x27, + 0x25, + 0x24, + 0x22, + 0x20, + 0x1f, + 0x1d, + 0x1c, + 0x1a, + 0x19, + 0x17, + 0x15, + 0x14, + 0x12, + 0x11, + 0xf, + 0xe, + 0xc, + 0xa, + 0x9, + 0x7, + 0x6, + 0x4, + 0x3, + 0x1 + }; + + /** + * Yet to be implemented. + * @param num Input + * @return Output + */ + public static int arctan( int num ) { + return 0; + } + + /** + * 26.6 fixed number square root function. + * Simple (brain-dead) divide & conqure algorithm. + * @param num The 26.6 fixed number in question + * @return The resulting square root + */ + public static int squareRoot(int num) { + int n = num; + int divisor = num; + int nSquared; + + while (divisor != 0) { + divisor /= 2; + nSquared = (n * n) >> 6; + if (nSquared == num) { + break; + } else if (nSquared > num) { + n -= divisor; + } else { + n += divisor; + } + } + return n; + } + + public static float floatValue(long fixed) { + return (fixed >> 16) + (float)(fixed & 0xffff) / 0x10000; + } + + public static float roundedFloatValue(long fixed, int decimalPlaces) { + int factor = 10 * decimalPlaces; + return (float)((int)(floatValue(fixed) * factor)) / factor; + } +} diff --git a/src/net/java/dev/typecast/ot/Glyph.java b/src/net/java/dev/typecast/ot/Glyph.java new file mode 100644 index 000000000..a59d62684 --- /dev/null +++ b/src/net/java/dev/typecast/ot/Glyph.java @@ -0,0 +1,159 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot; + +import net.java.dev.typecast.ot.table.GlyphDescription; +import net.java.dev.typecast.ot.table.GlyfDescript; +import net.java.dev.typecast.ot.table.Charstring; +import net.java.dev.typecast.ot.table.CharstringType2; + +import net.java.dev.typecast.t2.T2Interpreter; + +/** + * An individual glyph within a font. + * @version $Id: Glyph.java,v 1.3 2007-02-21 12:23:54 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class Glyph { + + protected short _leftSideBearing; + protected int _advanceWidth; + private Point[] _points; + + /** + * Construct a Glyph from a TrueType outline described by + * a GlyphDescription. + * @param cs The Charstring describing the glyph. + * @param lsb The Left Side Bearing. + * @param advance The advance width. + */ + public Glyph(GlyphDescription gd, short lsb, int advance) { + _leftSideBearing = lsb; + _advanceWidth = advance; + describe(gd); + } + + /** + * Construct a Glyph from a PostScript outline described by a Charstring. + * @param cs The Charstring describing the glyph. + * @param lsb The Left Side Bearing. + * @param advance The advance width. + */ + public Glyph(Charstring cs, short lsb, int advance) { + _leftSideBearing = lsb; + _advanceWidth = advance; + if (cs instanceof CharstringType2) { + T2Interpreter t2i = new T2Interpreter(); + _points = t2i.execute((CharstringType2) cs); + } else { + //throw unsupported charstring type + } + } + + public int getAdvanceWidth() { + return _advanceWidth; + } + + public short getLeftSideBearing() { + return _leftSideBearing; + } + + public Point getPoint(int i) { + return _points[i]; + } + + public int getPointCount() { + return _points.length; + } + + /** + * Resets the glyph to the TrueType table settings + */ + public void reset() { + } + + /** + * @param factor a 16.16 fixed value + */ + public void scale(int factor) { + for (int i = 0; i < _points.length; i++) { + //points[i].x = ( points[i].x * factor ) >> 6; + //points[i].y = ( points[i].y * factor ) >> 6; + _points[i].x = ((_points[i].x<<10) * factor) >> 26; + _points[i].y = ((_points[i].y<<10) * factor) >> 26; + } + _leftSideBearing = (short)(( _leftSideBearing * factor) >> 6); + _advanceWidth = (_advanceWidth * factor) >> 6; + } + + /** + * Set the points of a glyph from the GlyphDescription + */ + private void describe(GlyphDescription gd) { + int endPtIndex = 0; + _points = new Point[gd.getPointCount() + 2]; + for (int i = 0; i < gd.getPointCount(); i++) { + boolean endPt = gd.getEndPtOfContours(endPtIndex) == i; + if (endPt) { + endPtIndex++; + } + _points[i] = new Point( + gd.getXCoordinate(i), + gd.getYCoordinate(i), + (gd.getFlags(i) & GlyfDescript.onCurve) != 0, + endPt); + } + + // Append the origin and advanceWidth points (n & n+1) + _points[gd.getPointCount()] = new Point(0, 0, true, true); + _points[gd.getPointCount()+1] = new Point(_advanceWidth, 0, true, true); + } +} diff --git a/src/net/java/dev/typecast/ot/Mnemonic.java b/src/net/java/dev/typecast/ot/Mnemonic.java new file mode 100644 index 000000000..5655c1e86 --- /dev/null +++ b/src/net/java/dev/typecast/ot/Mnemonic.java @@ -0,0 +1,397 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot; + +/** + * The Mnemonic representations of the TrueType instruction set. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Mnemonic.java,v 1.1.1.1 2004-12-05 23:14:30 davidsch Exp $ + */ +public class Mnemonic { + + public static final short SVTCA = 0x00; // [a] + public static final short SPVTCA = 0x02; // [a] + public static final short SFVTCA = 0x04; // [a] + public static final short SPVTL = 0x06; // [a] + public static final short SFVTL = 0x08; // [a] + public static final short SPVFS = 0x0A; + public static final short SFVFS = 0x0B; + public static final short GPV = 0x0C; + public static final short GFV = 0x0D; + public static final short SFVTPV = 0x0E; + public static final short ISECT = 0x0F; + public static final short SRP0 = 0x10; + public static final short SRP1 = 0x11; + public static final short SRP2 = 0x12; + public static final short SZP0 = 0x13; + public static final short SZP1 = 0x14; + public static final short SZP2 = 0x15; + public static final short SZPS = 0x16; + public static final short SLOOP = 0x17; + public static final short RTG = 0x18; + public static final short RTHG = 0x19; + public static final short SMD = 0x1A; + public static final short ELSE = 0x1B; + public static final short JMPR = 0x1C; + public static final short SCVTCI = 0x1D; + public static final short SSWCI = 0x1E; + public static final short SSW = 0x1F; + public static final short DUP = 0x20; + public static final short POP = 0x21; + public static final short CLEAR = 0x22; + public static final short SWAP = 0x23; + public static final short DEPTH = 0x24; + public static final short CINDEX = 0x25; + public static final short MINDEX = 0x26; + public static final short ALIGNPTS = 0x27; + public static final short UTP = 0x29; + public static final short LOOPCALL = 0x2A; + public static final short CALL = 0x2B; + public static final short FDEF = 0x2C; + public static final short ENDF = 0x2D; + public static final short MDAP = 0x2E; // [a] + public static final short IUP = 0x30; // [a] + public static final short SHP = 0x32; + public static final short SHC = 0x34; // [a] + public static final short SHZ = 0x36; // [a] + public static final short SHPIX = 0x38; + public static final short IP = 0x39; + public static final short MSIRP = 0x3A; // [a] + public static final short ALIGNRP = 0x3C; + public static final short RTDG = 0x3D; + public static final short MIAP = 0x3E; // [a] + public static final short NPUSHB = 0x40; + public static final short NPUSHW = 0x41; + public static final short WS = 0x42; + public static final short RS = 0x43; + public static final short WCVTP = 0x44; + public static final short RCVT = 0x45; + public static final short GC = 0x46; // [a] + public static final short SCFS = 0x48; + public static final short MD = 0x49; // [a] + public static final short MPPEM = 0x4B; + public static final short MPS = 0x4C; + public static final short FLIPON = 0x4D; + public static final short FLIPOFF = 0x4E; + public static final short DEBUG = 0x4F; + public static final short LT = 0x50; + public static final short LTEQ = 0x51; + public static final short GT = 0x52; + public static final short GTEQ = 0x53; + public static final short EQ = 0x54; + public static final short NEQ = 0x55; + public static final short ODD = 0x56; + public static final short EVEN = 0x57; + public static final short IF = 0x58; + public static final short EIF = 0x59; + public static final short AND = 0x5A; + public static final short OR = 0x5B; + public static final short NOT = 0x5C; + public static final short DELTAP1 = 0x5D; + public static final short SDB = 0x5E; + public static final short SDS = 0x5F; + public static final short ADD = 0x60; + public static final short SUB = 0x61; + public static final short DIV = 0x62; + public static final short MUL = 0x63; + public static final short ABS = 0x64; + public static final short NEG = 0x65; + public static final short FLOOR = 0x66; + public static final short CEILING = 0x67; + public static final short ROUND = 0x68; // [ab] + public static final short NROUND = 0x6C; // [ab] + public static final short WCVTF = 0x70; + public static final short DELTAP2 = 0x71; + public static final short DELTAP3 = 0x72; + public static final short DELTAC1 = 0x73; + public static final short DELTAC2 = 0x74; + public static final short DELTAC3 = 0x75; + public static final short SROUND = 0x76; + public static final short S45ROUND = 0x77; + public static final short JROT = 0x78; + public static final short JROF = 0x79; + public static final short ROFF = 0x7A; + public static final short RUTG = 0x7C; + public static final short RDTG = 0x7D; + public static final short SANGW = 0x7E; + public static final short AA = 0x7F; + public static final short FLIPPT = 0x80; + public static final short FLIPRGON = 0x81; + public static final short FLIPRGOFF = 0x82; + public static final short SCANCTRL = 0x85; + public static final short SDPVTL = 0x86; // [a] + public static final short GETINFO = 0x88; + public static final short IDEF = 0x89; + public static final short ROLL = 0x8A; + public static final short MAX = 0x8B; + public static final short MIN = 0x8C; + public static final short SCANTYPE = 0x8D; + public static final short INSTCTRL = 0x8E; + public static final short PUSHB = 0xB0; // [abc] + public static final short PUSHW = 0xB8; // [abc] + public static final short MDRP = 0xC0; // [abcde] + public static final short MIRP = 0xE0; // [abcde] + + /** + * Gets the mnemonic text for the specified opcode + * @param opcode The opcode for which the mnemonic is required + * @return The mnemonic, with a description + */ + public static String getMnemonic(short opcode) { + if (opcode >= MIRP) return "MIRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]"; + else if (opcode >= MDRP) return "MDRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]"; + else if (opcode >= PUSHW) return "PUSHW["+((opcode&7)+1)+"]"; + else if (opcode >= PUSHB) return "PUSHB["+((opcode&7)+1)+"]"; + else if (opcode >= INSTCTRL) return "INSTCTRL"; + else if (opcode >= SCANTYPE) return "SCANTYPE"; + else if (opcode >= MIN) return "MIN"; + else if (opcode >= MAX) return "MAX"; + else if (opcode >= ROLL) return "ROLL"; + else if (opcode >= IDEF) return "IDEF"; + else if (opcode >= GETINFO) return "GETINFO"; + else if (opcode >= SDPVTL) return "SDPVTL["+(opcode&1)+"]"; + else if (opcode >= SCANCTRL) return "SCANCTRL"; + else if (opcode >= FLIPRGOFF) return "FLIPRGOFF"; + else if (opcode >= FLIPRGON) return "FLIPRGON"; + else if (opcode >= FLIPPT) return "FLIPPT"; + else if (opcode >= AA) return "AA"; + else if (opcode >= SANGW) return "SANGW"; + else if (opcode >= RDTG) return "RDTG"; + else if (opcode >= RUTG) return "RUTG"; + else if (opcode >= ROFF) return "ROFF"; + else if (opcode >= JROF) return "JROF"; + else if (opcode >= JROT) return "JROT"; + else if (opcode >= S45ROUND) return "S45ROUND"; + else if (opcode >= SROUND) return "SROUND"; + else if (opcode >= DELTAC3) return "DELTAC3"; + else if (opcode >= DELTAC2) return "DELTAC2"; + else if (opcode >= DELTAC1) return "DELTAC1"; + else if (opcode >= DELTAP3) return "DELTAP3"; + else if (opcode >= DELTAP2) return "DELTAP2"; + else if (opcode >= WCVTF) return "WCVTF"; + else if (opcode >= NROUND) return "NROUND["+(opcode&3)+"]"; + else if (opcode >= ROUND) return "ROUND["+(opcode&3)+"]"; + else if (opcode >= CEILING) return "CEILING"; + else if (opcode >= FLOOR) return "FLOOR"; + else if (opcode >= NEG) return "NEG"; + else if (opcode >= ABS) return "ABS"; + else if (opcode >= MUL) return "MUL"; + else if (opcode >= DIV) return "DIV"; + else if (opcode >= SUB) return "SUB"; + else if (opcode >= ADD) return "ADD"; + else if (opcode >= SDS) return "SDS"; + else if (opcode >= SDB) return "SDB"; + else if (opcode >= DELTAP1) return "DELTAP1"; + else if (opcode >= NOT) return "NOT"; + else if (opcode >= OR) return "OR"; + else if (opcode >= AND) return "AND"; + else if (opcode >= EIF) return "EIF"; + else if (opcode >= IF) return "IF"; + else if (opcode >= EVEN) return "EVEN"; + else if (opcode >= ODD) return "ODD"; + else if (opcode >= NEQ) return "NEQ"; + else if (opcode >= EQ) return "EQ"; + else if (opcode >= GTEQ) return "GTEQ"; + else if (opcode >= GT) return "GT"; + else if (opcode >= LTEQ) return "LTEQ"; + else if (opcode >= LT) return "LT"; + else if (opcode >= DEBUG) return "DEBUG"; + else if (opcode >= FLIPOFF) return "FLIPOFF"; + else if (opcode >= FLIPON) return "FLIPON"; + else if (opcode >= MPS) return "MPS"; + else if (opcode >= MPPEM) return "MPPEM"; + else if (opcode >= MD) return "MD["+(opcode&1)+"]"; + else if (opcode >= SCFS) return "SCFS"; + else if (opcode >= GC) return "GC["+(opcode&1)+"]"; + else if (opcode >= RCVT) return "RCVT"; + else if (opcode >= WCVTP) return "WCVTP"; + else if (opcode >= RS) return "RS"; + else if (opcode >= WS) return "WS"; + else if (opcode >= NPUSHW) return "NPUSHW"; + else if (opcode >= NPUSHB) return "NPUSHB"; + else if (opcode >= MIAP) return "MIAP["+((opcode&1)==0?"nrd+nci":"rd+ci")+"]"; + else if (opcode >= RTDG) return "RTDG"; + else if (opcode >= ALIGNRP) return "ALIGNRP"; + else if (opcode >= MSIRP) return "MSIRP["+(opcode&1)+"]"; + else if (opcode >= IP) return "IP"; + else if (opcode >= SHPIX) return "SHPIX"; + else if (opcode >= SHZ) return "SHZ["+(opcode&1)+"]"; + else if (opcode >= SHC) return "SHC["+(opcode&1)+"]"; + else if (opcode >= SHP) return "SHP"; + else if (opcode >= IUP) return "IUP["+((opcode&1)==0?"y":"x")+"]"; + else if (opcode >= MDAP) return "MDAP["+((opcode&1)==0?"nrd":"rd")+"]"; + else if (opcode >= ENDF) return "ENDF"; + else if (opcode >= FDEF) return "FDEF"; + else if (opcode >= CALL) return "CALL"; + else if (opcode >= LOOPCALL) return "LOOPCALL"; + else if (opcode >= UTP) return "UTP"; + else if (opcode >= ALIGNPTS) return "ALIGNPTS"; + else if (opcode >= MINDEX) return "MINDEX"; + else if (opcode >= CINDEX) return "CINDEX"; + else if (opcode >= DEPTH) return "DEPTH"; + else if (opcode >= SWAP) return "SWAP"; + else if (opcode >= CLEAR) return "CLEAR"; + else if (opcode >= POP) return "POP"; + else if (opcode >= DUP) return "DUP"; + else if (opcode >= SSW) return "SSW"; + else if (opcode >= SSWCI) return "SSWCI"; + else if (opcode >= SCVTCI) return "SCVTCI"; + else if (opcode >= JMPR) return "JMPR"; + else if (opcode >= ELSE) return "ELSE"; + else if (opcode >= SMD) return "SMD"; + else if (opcode >= RTHG) return "RTHG"; + else if (opcode >= RTG) return "RTG"; + else if (opcode >= SLOOP) return "SLOOP"; + else if (opcode >= SZPS) return "SZPS"; + else if (opcode >= SZP2) return "SZP2"; + else if (opcode >= SZP1) return "SZP1"; + else if (opcode >= SZP0) return "SZP0"; + else if (opcode >= SRP2) return "SRP2"; + else if (opcode >= SRP1) return "SRP1"; + else if (opcode >= SRP0) return "SRP0"; + else if (opcode >= ISECT) return "ISECT"; + else if (opcode >= SFVTPV) return "SFVTPV"; + else if (opcode >= GFV) return "GFV"; + else if (opcode >= GPV) return "GPV"; + else if (opcode >= SFVFS) return "SFVFS"; + else if (opcode >= SPVFS) return "SPVFS"; + else if (opcode >= SFVTL) return "SFVTL["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else if (opcode >= SPVTL) return "SPVTL["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else if (opcode >= SFVTCA) return "SFVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else if (opcode >= SPVTCA) return "SPVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else if (opcode >= SVTCA) return "SVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]"; + else return "????"; + } + + public static String getComment(short opcode) { + if (opcode >= MIRP) return "MIRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]\t\tMove Indirect Relative Point"; + else if (opcode >= MDRP) return "MDRP["+((opcode&16)==0?"nrp0,":"srp0,")+((opcode&8)==0?"nmd,":"md,")+((opcode&4)==0?"nrd,":"rd,")+(opcode&3)+"]\t\tMove Direct Relative Point"; + else if (opcode >= PUSHW) return "PUSHW["+((opcode&7)+1)+"]"; + else if (opcode >= PUSHB) return "PUSHB["+((opcode&7)+1)+"]"; + else if (opcode >= INSTCTRL) return "INSTCTRL\tINSTruction Execution ConTRol"; + else if (opcode >= SCANTYPE) return "SCANTYPE\tSCANTYPE"; + else if (opcode >= MIN) return "MIN\t\tMINimum of top two stack elements"; + else if (opcode >= MAX) return "MAX\t\tMAXimum of top two stack elements"; + else if (opcode >= ROLL) return "ROLL\t\tROLL the top three stack elements"; + else if (opcode >= IDEF) return "IDEF\t\tInstruction DEFinition"; + else if (opcode >= GETINFO) return "GETINFO\tGET INFOrmation"; + else if (opcode >= SDPVTL) return "SDPVTL["+(opcode&1)+"]\tSet Dual Projection_Vector To Line"; + else if (opcode >= SCANCTRL) return "SCANCTRL\tSCAN conversion ConTRoL"; + else if (opcode >= FLIPRGOFF) return "FLIPRGOFF\tFLIP RanGe OFF"; + else if (opcode >= FLIPRGON) return "FLIPRGON\tFLIP RanGe ON"; + else if (opcode >= FLIPPT) return "FLIPPT\tFLIP PoinT"; + else if (opcode >= AA) return "AA"; + else if (opcode >= SANGW) return "SANGW\t\tSet Angle _Weight"; + else if (opcode >= RDTG) return "RDTG\t\tRound Down To Grid"; + else if (opcode >= RUTG) return "RUTG\t\tRound Up To Grid"; + else if (opcode >= ROFF) return "ROFF\t\tRound OFF"; + else if (opcode >= JROF) return "JROF\t\tJump Relative On False"; + else if (opcode >= JROT) return "JROT\t\tJump Relative On True"; + else if (opcode >= S45ROUND) return "S45ROUND\tSuper ROUND 45 degrees"; + else if (opcode >= SROUND) return "SROUND\tSuper ROUND"; + else if (opcode >= DELTAC3) return "DELTAC3\tDELTA exception C3"; + else if (opcode >= DELTAC2) return "DELTAC2\tDELTA exception C2"; + else if (opcode >= DELTAC1) return "DELTAC1\tDELTA exception C1"; + else if (opcode >= DELTAP3) return "DELTAP3\tDELTA exception P3"; + else if (opcode >= DELTAP2) return "DELTAP2\tDELTA exception P2"; + else if (opcode >= WCVTF) return "WCVTF\t\tWrite Control Value Table in FUnits"; + else if (opcode >= NROUND) return "NROUND["+(opcode&3)+"]"; + else if (opcode >= ROUND) return "ROUND["+(opcode&3)+"]"; + else if (opcode >= CEILING) return "CEILING\tCEILING"; + else if (opcode >= FLOOR) return "FLOOR\t\tFLOOR"; + else if (opcode >= NEG) return "NEG\t\tNEGate"; + else if (opcode >= ABS) return "ABS\t\tABSolute value"; + else if (opcode >= MUL) return "MUL\t\tMULtiply"; + else if (opcode >= DIV) return "DIV\t\tDIVide"; + else if (opcode >= SUB) return "SUB\t\tSUBtract"; + else if (opcode >= ADD) return "ADD\t\tADD"; + else if (opcode >= SDS) return "SDS\t\tSet Delta_Shift in the graphics state"; + else if (opcode >= SDB) return "SDB\t\tSet Delta_Base in the graphics state"; + else if (opcode >= DELTAP1) return "DELTAP1\tDELTA exception P1"; + else if (opcode >= NOT) return "NOT\t\tlogical NOT"; + else if (opcode >= OR) return "OR\t\t\tlogical OR"; + else if (opcode >= AND) return "AND\t\tlogical AND"; + else if (opcode >= EIF) return "EIF\t\tEnd IF"; + else if (opcode >= IF) return "IF\t\t\tIF test"; + else if (opcode >= EVEN) return "EVEN"; + else if (opcode >= ODD) return "ODD"; + else if (opcode >= NEQ) return "NEQ\t\tNot EQual"; + else if (opcode >= EQ) return "EQ\t\t\tEQual"; + else if (opcode >= GTEQ) return "GTEQ\t\tGreater Than or Equal"; + else if (opcode >= GT) return "GT\t\t\tGreater Than"; + else if (opcode >= LTEQ) return "LTEQ\t\tLess Than or Equal"; + else if (opcode >= LT) return "LT\t\t\tLess Than"; + else if (opcode >= DEBUG) return "DEBUG"; + else if (opcode >= FLIPOFF) return "FLIPOFF\tSet the auto_flip Boolean to OFF"; + else if (opcode >= FLIPON) return "FLIPON\tSet the auto_flip Boolean to ON"; + else if (opcode >= MPS) return "MPS\t\tMeasure Point Size"; + else if (opcode >= MPPEM) return "MPPEM\t\tMeasure Pixels Per EM"; + else if (opcode >= MD) return "MD["+(opcode&1)+"]\t\t\tMeasure Distance"; + else if (opcode >= SCFS) return "SCFS\t\tSets Coordinate From the Stack using projection_vector and freedom_vector"; + else if (opcode >= GC) return "GC["+(opcode&1)+"]\t\t\tGet Coordinate projected onto the projection_vector"; + else if (opcode >= RCVT) return "RCVT\t\tRead Control Value Table"; + else if (opcode >= WCVTP) return "WCVTP\t\tWrite Control Value Table in Pixel units"; + else if (opcode >= RS) return "RS\t\t\tRead Store"; + else if (opcode >= WS) return "WS\t\t\tWrite Store"; + else if (opcode >= NPUSHW) return "NPUSHW"; + else if (opcode >= NPUSHB) return "NPUSHB"; + else if (opcode >= MIAP) return "MIAP["+((opcode&1)==0?"nrd+nci":"rd+ci")+"]\t\tMove Indirect Absolute Point"; + else if (opcode >= RTDG) return "RTDG\t\tRound To Double Grid"; + else if (opcode >= ALIGNRP) return "ALIGNRP\tALIGN Relative Point"; + else if (opcode >= MSIRP) return "MSIRP["+(opcode&1)+"]\t\tMove Stack Indirect Relative Point"; + else if (opcode >= IP) return "IP\t\t\tInterpolate Point by the last relative stretch"; + else if (opcode >= SHPIX) return "SHPIX\t\tSHift point by a PIXel amount"; + else if (opcode >= SHZ) return "SHZ["+(opcode&1)+"]\t\tSHift Zone by the last pt"; + else if (opcode >= SHC) return "SHC["+(opcode&1)+"]\t\tSHift Contour by the last point"; + else if (opcode >= SHP) return "SHP\t\tSHift Point by the last point"; + else if (opcode >= IUP) return "IUP["+((opcode&1)==0?"y":"x")+"]\t\tInterpolate Untouched Points through the outline"; + else if (opcode >= MDAP) return "MDAP["+((opcode&1)==0?"nrd":"rd")+"]\t\tMove Direct Absolute Point"; + else if (opcode >= ENDF) return "ENDF\t\tEND Function definition"; + else if (opcode >= FDEF) return "FDEF\t\tFunction DEFinition "; + else if (opcode >= CALL) return "CALL\t\tCALL function"; + else if (opcode >= LOOPCALL) return "LOOPCALL\tLOOP and CALL function"; + else if (opcode >= UTP) return "UTP\t\tUnTouch Point"; + else if (opcode >= ALIGNPTS) return "ALIGNPTS\tALIGN Points"; + else if (opcode >= MINDEX) return "MINDEX\tMove the INDEXed element to the top of the stack"; + else if (opcode >= CINDEX) return "CINDEX\tCopy the INDEXed element to the top of the stack"; + else if (opcode >= DEPTH) return "DEPTH\t\tReturns the DEPTH of the stack"; + else if (opcode >= SWAP) return "SWAP\t\tSWAP the top two elements on the stack"; + else if (opcode >= CLEAR) return "CLEAR\t\tClear the entire stack"; + else if (opcode >= POP) return "POP\t\tPOP top stack element"; + else if (opcode >= DUP) return "DUP\t\tDuplicate top stack element"; + else if (opcode >= SSW) return "SSW\t\tSet Single-width"; + else if (opcode >= SSWCI) return "SSWCI\t\tSet Single_Width_Cut_In"; + else if (opcode >= SCVTCI) return "SCVTCI\tSet Control Value Table Cut In"; + else if (opcode >= JMPR) return "JMPR\t\tJuMP"; + else if (opcode >= ELSE) return "ELSE"; + else if (opcode >= SMD) return "SMD\t\tSet Minimum_ Distance"; + else if (opcode >= RTHG) return "RTHG\t\tRound To Half Grid"; + else if (opcode >= RTG) return "RTG\t\tRound To Grid"; + else if (opcode >= SLOOP) return "SLOOP\t\tSet LOOP variable"; + else if (opcode >= SZPS) return "SZPS\t\tSet Zone PointerS"; + else if (opcode >= SZP2) return "SZP2\t\tSet Zone Pointer 2"; + else if (opcode >= SZP1) return "SZP1\t\tSet Zone Pointer 1"; + else if (opcode >= SZP0) return "SZP0\t\tSet Zone Pointer 0"; + else if (opcode >= SRP2) return "SRP2\t\tSet Reference Point 2"; + else if (opcode >= SRP1) return "SRP1\t\tSet Reference Point 1"; + else if (opcode >= SRP0) return "SRP0\t\tSet Reference Point 0"; + else if (opcode >= ISECT) return "ISECT\t\tmoves point p to the InterSECTion of two lines"; + else if (opcode >= SFVTPV) return "SFVTPV\tSet Freedom_Vector To Projection Vector"; + else if (opcode >= GFV) return "GFV\t\tGet Freedom_Vector"; + else if (opcode >= GPV) return "GPV\t\tGet Projection_Vector"; + else if (opcode >= SFVFS) return "SFVFS\t\tSet Freedom_Vector From Stack"; + else if (opcode >= SPVFS) return "SPVFS\t\tSet Projection_Vector From Stack"; + else if (opcode >= SFVTL) return "SFVTL["+((opcode&1)==0?"y-axis":"x-axis")+"]\t\tSet Freedom_Vector To Line"; + else if (opcode >= SPVTL) return "SPVTL["+((opcode&1)==0?"y-axis":"x-axis")+"]\t\tSet Projection_Vector To Line"; + else if (opcode >= SFVTCA) return "SFVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]\tSet Freedom_Vector to Coordinate Axis"; + else if (opcode >= SPVTCA) return "SPVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]\tSet Projection_Vector To Coordinate Axis"; + else if (opcode >= SVTCA) return "SVTCA["+((opcode&1)==0?"y-axis":"x-axis")+"]\t\tSet freedom and projection Vectors To Coordinate Axis"; + else return "????"; + } +} diff --git a/src/net/java/dev/typecast/ot/OTFont.java b/src/net/java/dev/typecast/ot/OTFont.java new file mode 100644 index 000000000..d23228483 --- /dev/null +++ b/src/net/java/dev/typecast/ot/OTFont.java @@ -0,0 +1,265 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot; + +import java.io.DataInputStream; +import java.io.IOException; + +import net.java.dev.typecast.ot.table.DirectoryEntry; +import net.java.dev.typecast.ot.table.TTCHeader; +import net.java.dev.typecast.ot.table.TableDirectory; +import net.java.dev.typecast.ot.table.Table; +import net.java.dev.typecast.ot.table.Os2Table; +import net.java.dev.typecast.ot.table.CmapTable; +import net.java.dev.typecast.ot.table.GlyfTable; +import net.java.dev.typecast.ot.table.HeadTable; +import net.java.dev.typecast.ot.table.HheaTable; +import net.java.dev.typecast.ot.table.HmtxTable; +import net.java.dev.typecast.ot.table.LocaTable; +import net.java.dev.typecast.ot.table.MaxpTable; +import net.java.dev.typecast.ot.table.NameTable; +import net.java.dev.typecast.ot.table.PostTable; +import net.java.dev.typecast.ot.table.VheaTable; +import net.java.dev.typecast.ot.table.TableFactory; + +/** + * The TrueType font. + * @version $Id: OTFont.java,v 1.6 2007-01-31 01:49:18 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class OTFont { + + private OTFontCollection _fc; + private TableDirectory _tableDirectory = null; + private Table[] _tables; + private Os2Table _os2; + private CmapTable _cmap; + private GlyfTable _glyf; + private HeadTable _head; + private HheaTable _hhea; + private HmtxTable _hmtx; + private LocaTable _loca; + private MaxpTable _maxp; + private NameTable _name; + private PostTable _post; + private VheaTable _vhea; + + /** + * Constructor + */ + public OTFont(OTFontCollection fc) { + _fc = fc; + } + + public Table getTable(int tableType) { + for (int i = 0; i < _tables.length; i++) { + if ((_tables[i] != null) && (_tables[i].getType() == tableType)) { + return _tables[i]; + } + } + return null; + } + + public Os2Table getOS2Table() { + return _os2; + } + + public CmapTable getCmapTable() { + return _cmap; + } + + public HeadTable getHeadTable() { + return _head; + } + + public HheaTable getHheaTable() { + return _hhea; + } + + public HmtxTable getHmtxTable() { + return _hmtx; + } + + public LocaTable getLocaTable() { + return _loca; + } + + public MaxpTable getMaxpTable() { + return _maxp; + } + + public NameTable getNameTable() { + return _name; + } + + public PostTable getPostTable() { + return _post; + } + + public VheaTable getVheaTable() { + return _vhea; + } + + public int getAscent() { + return _hhea.getAscender(); + } + + public int getDescent() { + return _hhea.getDescender(); + } + + public int getNumGlyphs() { + return _maxp.getNumGlyphs(); + } + + public Glyph getGlyph(int i) { + return (_glyf.getDescription(i) != null) + ? new Glyph( + _glyf.getDescription(i), + _hmtx.getLeftSideBearing(i), + _hmtx.getAdvanceWidth(i)) + : null; + } + + public TableDirectory getTableDirectory() { + return _tableDirectory; + } + + private Table readTable( + DataInputStream dis, + int tablesOrigin, + int tag) throws IOException { + dis.reset(); + DirectoryEntry entry = _tableDirectory.getEntryByTag(tag); + if (entry == null) { + return null; + } + dis.skip(tablesOrigin + entry.getOffset()); + return TableFactory.create(_fc, this, entry, dis); + } + + /** + * @param dis OpenType/TrueType font file data. + * @param directoryOffset The Table Directory offset within the file. For a + * regular TTF/OTF file this will be zero, but for a TTC (Font Collection) + * the offset is retrieved from the TTC header. For a Mac font resource, + * offset is retrieved from the resource headers. + * @param tablesOrigin The point the table offsets are calculated from. + * Once again, in a regular TTF file, this will be zero. In a TTC is is + * also zero, but within a Mac resource, it is the beggining of the + * individual font resource data. + */ + protected void read( + DataInputStream dis, + int directoryOffset, + int tablesOrigin) throws IOException { + + // Load the table directory + dis.reset(); + dis.skip(directoryOffset); + _tableDirectory = new TableDirectory(dis); + _tables = new Table[_tableDirectory.getNumTables()]; + + // Load some prerequisite tables + _head = (HeadTable) readTable(dis, tablesOrigin, Table.head); + _hhea = (HheaTable) readTable(dis, tablesOrigin, Table.hhea); + _maxp = (MaxpTable) readTable(dis, tablesOrigin, Table.maxp); + _loca = (LocaTable) readTable(dis, tablesOrigin, Table.loca); + _vhea = (VheaTable) readTable(dis, tablesOrigin, Table.vhea); + + int index = 0; + _tables[index++] = _head; + _tables[index++] = _hhea; + _tables[index++] = _maxp; + if (_loca != null) { + _tables[index++] = _loca; + } + if (_vhea != null) { + _tables[index++] = _vhea; + } + + // Load all other tables + for (int i = 0; i < _tableDirectory.getNumTables(); i++) { + DirectoryEntry entry = _tableDirectory.getEntry(i); + if (entry.getTag() == Table.head + || entry.getTag() == Table.hhea + || entry.getTag() == Table.maxp + || entry.getTag() == Table.loca + || entry.getTag() == Table.vhea) { + continue; + } + dis.reset(); + dis.skip(tablesOrigin + entry.getOffset()); + _tables[index] = TableFactory.create(_fc, this, entry, dis); + ++index; + } + + // Get references to commonly used tables (these happen to be all the + // required tables) + _cmap = (CmapTable) getTable(Table.cmap); + _hmtx = (HmtxTable) getTable(Table.hmtx); + _name = (NameTable) getTable(Table.name); + _os2 = (Os2Table) getTable(Table.OS_2); + _post = (PostTable) getTable(Table.post); + + // If this is a TrueType outline, then we'll have at least the + // 'glyf' table (along with the 'loca' table) + _glyf = (GlyfTable) getTable(Table.glyf); + } + + public String toString() { + if (_tableDirectory != null) { + return _tableDirectory.toString(); + } else { + return "Empty font"; + } + } +} diff --git a/src/net/java/dev/typecast/ot/OTFontCollection.java b/src/net/java/dev/typecast/ot/OTFontCollection.java new file mode 100644 index 000000000..6f8754f59 --- /dev/null +++ b/src/net/java/dev/typecast/ot/OTFontCollection.java @@ -0,0 +1,169 @@ +/* + * $Id: OTFontCollection.java,v 1.6 2010-08-10 11:38:11 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot; + +import java.io.File; +import java.io.BufferedInputStream; +import java.io.DataInputStream; +import java.io.FileInputStream; +import java.io.IOException; + +import java.util.ArrayList; + +import net.java.dev.typecast.ot.mac.ResourceHeader; +import net.java.dev.typecast.ot.mac.ResourceMap; +import net.java.dev.typecast.ot.mac.ResourceReference; +import net.java.dev.typecast.ot.mac.ResourceType; +import net.java.dev.typecast.ot.table.DirectoryEntry; +import net.java.dev.typecast.ot.table.Table; +import net.java.dev.typecast.ot.table.TTCHeader; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: OTFontCollection.java,v 1.6 2010-08-10 11:38:11 davidsch Exp $ + */ +public class OTFontCollection { + + private String _pathName; + private String _fileName; + private TTCHeader _ttcHeader; + private OTFont[] _fonts; + private ArrayList<Table> _tables = new ArrayList<Table>(); + private boolean _resourceFork = false; + + /** Creates new FontCollection */ + protected OTFontCollection() { + } + + /** + * @param file The OpenType font file + */ + public static OTFontCollection create(File file) throws IOException { + OTFontCollection fc = new OTFontCollection(); + fc.read(file); + return fc; + } + + public String getPathName() { + return _pathName; + } + + public String getFileName() { + return _fileName; + } + + public OTFont getFont(int i) { + return _fonts[i]; + } + + public int getFontCount() { + return _fonts.length; + } + + public TTCHeader getTtcHeader() { + return _ttcHeader; + } + + public Table getTable(DirectoryEntry de) { + for (int i = 0; i < _tables.size(); i++) { + Table table = _tables.get(i); + if ((table.getDirectoryEntry().getTag() == de.getTag()) && + (table.getDirectoryEntry().getOffset() == de.getOffset())) { + return table; + } + } + return null; + } + + public void addTable(Table table) { + _tables.add(table); + } + + /** + * @param file The OpenType font file + */ + protected void read(File file) throws IOException { + _pathName = file.getPath(); + _fileName = file.getName(); + + if (!file.exists()) { + throw new IOException(); + } + + // Do we need to modify the path name to deal with font resources + // in a Mac resource fork? + if (file.length() == 0) { + file = new File(file, "..namedfork/rsrc"); + if (!file.exists()) { + throw new IOException(); + } + _resourceFork = true; + } + + DataInputStream dis = new DataInputStream( + new BufferedInputStream( + new FileInputStream(file), (int) file.length())); + dis.mark((int) file.length()); + + if (_resourceFork || _pathName.endsWith(".dfont")) { + + // This is a Macintosh font suitcase resource + ResourceHeader resourceHeader = new ResourceHeader(dis); + + // Seek to the map offset and read the map + dis.reset(); + dis.skip(resourceHeader.getMapOffset()); + ResourceMap map = new ResourceMap(dis); + + // Get the 'sfnt' resources + ResourceType resourceType = map.getResourceType("sfnt"); + + // Load the font data + _fonts = new OTFont[resourceType.getCount()]; + for (int i = 0; i < resourceType.getCount(); i++) { + ResourceReference resourceReference = resourceType.getReference(i); + _fonts[i] = new OTFont(this); + int offset = resourceHeader.getDataOffset() + + resourceReference.getDataOffset() + 4; + _fonts[i].read(dis, offset, offset); + } + + } else if (TTCHeader.isTTC(dis)) { + + // This is a TrueType font collection + dis.reset(); + _ttcHeader = new TTCHeader(dis); + _fonts = new OTFont[_ttcHeader.getDirectoryCount()]; + for (int i = 0; i < _ttcHeader.getDirectoryCount(); i++) { + _fonts[i] = new OTFont(this); + _fonts[i].read(dis, _ttcHeader.getTableDirectory(i), 0); + } + } else { + + // This is a standalone font file + _fonts = new OTFont[1]; + _fonts[0] = new OTFont(this); + _fonts[0].read(dis, 0, 0); + } + dis.close(); + } +} diff --git a/src/net/java/dev/typecast/ot/Point.java b/src/net/java/dev/typecast/ot/Point.java new file mode 100644 index 000000000..fae13b098 --- /dev/null +++ b/src/net/java/dev/typecast/ot/Point.java @@ -0,0 +1,29 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot; + +/** + * @version $Id: Point.java,v 1.1.1.1 2004-12-05 23:14:31 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class Point { + + public int x = 0; + public int y = 0; + public boolean onCurve = true; + public boolean endOfContour = false; + public boolean touched = false; + + public Point(int x, int y, boolean onCurve, boolean endOfContour) { + this.x = x; + this.y = y; + this.onCurve = onCurve; + this.endOfContour = endOfContour; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceData.java b/src/net/java/dev/typecast/ot/mac/ResourceData.java new file mode 100644 index 000000000..a1c12ffc0 --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceData.java @@ -0,0 +1,45 @@ +/* + * $Id: ResourceData.java,v 1.1.1.1 2004-12-05 23:14:31 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ResourceData.java,v 1.1.1.1 2004-12-05 23:14:31 davidsch Exp $ + */ +public class ResourceData { + + private byte[] data; + + /** Creates new ResourceData */ + public ResourceData(DataInput di) throws IOException { + int dataLen = di.readInt(); + data = new byte[dataLen]; + di.readFully(data); + } + + public byte[] getData() { + return data; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceFile.java b/src/net/java/dev/typecast/ot/mac/ResourceFile.java new file mode 100644 index 000000000..e9499d9e8 --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceFile.java @@ -0,0 +1,77 @@ +/* + * $Id: ResourceFile.java,v 1.2 2007-01-29 04:01:53 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.mac; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * Mac resource loading test. + * TODO: incorporate this into the test suite. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ResourceFile.java,v 1.2 2007-01-29 04:01:53 davidsch Exp $ + */ +public class ResourceFile { + + private ResourceHeader header; + private ResourceMap map; + + /** Creates new Resource */ + public ResourceFile(RandomAccessFile raf) throws IOException { + + // Read header at the beginning of the file + raf.seek(0); + header = new ResourceHeader(raf); + + // Seek to the map offset and read the map + raf.seek(header.getMapOffset()); + map = new ResourceMap(raf); + } + + public ResourceMap getResourceMap() { + return map; + } + + public static void main(String[] args) { + try { + //RandomAccessFile raf = new RandomAccessFile("/Library/Fonts/GillSans.dfont", "r"); + + // Tests loading a font from a resource fork on Mac OS X + RandomAccessFile raf = new RandomAccessFile("/Library/Fonts/Georgia/..namedfork/rsrc", "r"); + ResourceFile resource = new ResourceFile(raf); + for (int i = 0; i < resource.getResourceMap().getResourceTypeCount(); i++) { + System.out.println(resource.getResourceMap().getResourceType(i).getTypeAsString()); + } + + // Get the first 'sfnt' resource + ResourceType type = resource.getResourceMap().getResourceType("sfnt"); + ResourceReference reference = type.getReference(0); + + type = resource.getResourceMap().getResourceType("FOND"); + for (int i = 0; i < type.getCount(); ++i) { + reference = type.getReference(i); + System.out.println(reference.getName()); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceHeader.java b/src/net/java/dev/typecast/ot/mac/ResourceHeader.java new file mode 100644 index 000000000..bdfe15a72 --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceHeader.java @@ -0,0 +1,61 @@ +/* + * $Id: ResourceHeader.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ResourceHeader.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + */ +public class ResourceHeader { + + private int dataOffset; + private int mapOffset; + private int dataLen; + private int mapLen; + + /** Creates new ResourceHeader */ + public ResourceHeader(DataInput di) throws IOException { + dataOffset = di.readInt(); + mapOffset = di.readInt(); + dataLen = di.readInt(); + mapLen = di.readInt(); + } + + public int getDataOffset() { + return dataOffset; + } + + public int getMapOffset() { + return mapOffset; + } + + public int getDataLength() { + return dataLen; + } + + public int getMapLength() { + return mapLen; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceMap.java b/src/net/java/dev/typecast/ot/mac/ResourceMap.java new file mode 100644 index 000000000..ee98fd8eb --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceMap.java @@ -0,0 +1,83 @@ +/* + * $Id: ResourceMap.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ResourceMap.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + */ +public class ResourceMap { + + private byte[] headerCopy = new byte[16]; + private int nextResourceMap; + private int fileReferenceNumber; + private int attributes; + private ResourceType[] types; + + /** Creates new ResourceMap */ + public ResourceMap(DataInput di) throws IOException { + di.readFully(headerCopy); + nextResourceMap = di.readInt(); + fileReferenceNumber = di.readUnsignedShort(); + attributes = di.readUnsignedShort(); + int typeOffset = di.readUnsignedShort(); + int nameOffset = di.readUnsignedShort(); + int typeCount = di.readUnsignedShort() + 1; + + // Read types + types = new ResourceType[typeCount]; + for (int i = 0; i < typeCount; i++) { + types[i] = new ResourceType(di); + } + + // Read the references + for (int i = 0; i < typeCount; i++) { + types[i].readRefs(di); + } + + // Read the names + for (int i = 0; i < typeCount; i++) { + types[i].readNames(di); + } + } + + public ResourceType getResourceType(String typeName) { + for (int i = 0; i < types.length; i++) { + String s = types[i].getTypeAsString(); + if (types[i].getTypeAsString().equals(typeName)) { + return types[i]; + } + } + return null; + } + + public ResourceType getResourceType(int i) { + return types[i]; + } + + public int getResourceTypeCount() { + return types.length; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceReference.java b/src/net/java/dev/typecast/ot/mac/ResourceReference.java new file mode 100644 index 000000000..f7f6e0fdf --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceReference.java @@ -0,0 +1,81 @@ +/* + * $Id: ResourceReference.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ResourceReference.java,v 1.1.1.1 2004-12-05 23:14:32 davidsch Exp $ + */ +public class ResourceReference { + + private int id; + private short nameOffset; + private short attributes; + private int dataOffset; + private int handle; + private String name; + + /** Creates new ResourceReference */ + protected ResourceReference(DataInput di) throws IOException { + id = di.readUnsignedShort(); + nameOffset = di.readShort(); + attributes = (short) di.readUnsignedByte(); + dataOffset = (di.readUnsignedByte()<<16) | di.readUnsignedShort(); + handle = di.readInt(); + } + + protected void readName(DataInput di) throws IOException { + if (nameOffset > -1) { + int len = di.readUnsignedByte(); + byte[] buf = new byte[len]; + di.readFully(buf); + name = new String(buf); + } + } + + public int getId() { + return id; + } + + public short getNameOffset() { + return nameOffset; + } + + public short getAttributes() { + return attributes; + } + + public int getDataOffset() { + return dataOffset; + } + + public int getHandle() { + return handle; + } + + public String getName() { + return name; + } +} diff --git a/src/net/java/dev/typecast/ot/mac/ResourceType.java b/src/net/java/dev/typecast/ot/mac/ResourceType.java new file mode 100644 index 000000000..2c21e7a27 --- /dev/null +++ b/src/net/java/dev/typecast/ot/mac/ResourceType.java @@ -0,0 +1,82 @@ +/* + * $Id: ResourceType.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.mac; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ResourceType.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + */ +public class ResourceType { + + private int type; + private int count; + private int offset; + private ResourceReference[] references; + + /** Creates new ResourceType */ + protected ResourceType(DataInput di) throws IOException { + type = di.readInt(); + count = di.readUnsignedShort() + 1; + offset = di.readUnsignedShort(); + references = new ResourceReference[count]; + } + + protected void readRefs(DataInput di) throws IOException { + for (int i = 0; i < count; i++) { + references[i] = new ResourceReference(di); + } + } + + protected void readNames(DataInput di) throws IOException { + for (int i = 0; i < count; i++) { + references[i].readName(di); + } + } + + public int getType() { + return type; + } + + public String getTypeAsString() { + return new StringBuffer() + .append((char)((type>>24)&0xff)) + .append((char)((type>>16)&0xff)) + .append((char)((type>>8)&0xff)) + .append((char)((type)&0xff)) + .toString(); + } + + public int getCount() { + return count; + } + + public int getOffset() { + return offset; + } + + public ResourceReference getReference(int i) { + return references[i]; + } +} diff --git a/src/net/java/dev/typecast/ot/table/BaseTable.java b/src/net/java/dev/typecast/ot/table/BaseTable.java new file mode 100644 index 000000000..7e6c37a5e --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/BaseTable.java @@ -0,0 +1,436 @@ +/* + * $Id: BaseTable.java,v 1.3 2007-02-08 04:31:31 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * Baseline Table + * @version $Id: BaseTable.java,v 1.3 2007-02-08 04:31:31 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class BaseTable implements Table { + + private abstract class BaseCoord { + + public abstract int getBaseCoordFormat(); + + public abstract short getCoordinate(); + } + + private class BaseCoordFormat1 extends BaseCoord { + + private short _coordinate; + + protected BaseCoordFormat1(DataInput di) throws IOException { + _coordinate = di.readShort(); + } + + public int getBaseCoordFormat() { + return 1; + } + + public short getCoordinate() { + return _coordinate; + } + + } + + private class BaseCoordFormat2 extends BaseCoord { + + private short _coordinate; + private int _referenceGlyph; + private int _baseCoordPoint; + + protected BaseCoordFormat2(DataInput di) throws IOException { + _coordinate = di.readShort(); + _referenceGlyph = di.readUnsignedShort(); + _baseCoordPoint = di.readUnsignedShort(); + } + + public int getBaseCoordFormat() { + return 2; + } + + public short getCoordinate() { + return _coordinate; + } + + } + + private class BaseCoordFormat3 extends BaseCoord { + + private short _coordinate; + private int _deviceTableOffset; + + protected BaseCoordFormat3(DataInput di) throws IOException { + _coordinate = di.readShort(); + _deviceTableOffset = di.readUnsignedShort(); + } + + public int getBaseCoordFormat() { + return 2; + } + + public short getCoordinate() { + return _coordinate; + } + + } + + private class FeatMinMaxRecord { + + private int _tag; + private int _minCoordOffset; + private int _maxCoordOffset; + + protected FeatMinMaxRecord(DataInput di) throws IOException { + _tag = di.readInt(); + _minCoordOffset = di.readUnsignedShort(); + _maxCoordOffset = di.readUnsignedShort(); + } + } + + private class MinMax { + + private int _minCoordOffset; + private int _maxCoordOffset; + private int _featMinMaxCount; + private FeatMinMaxRecord[] _featMinMaxRecord; + + protected MinMax(int minMaxOffset) throws IOException { + DataInput di = getDataInputForOffset(minMaxOffset); + _minCoordOffset = di.readUnsignedShort(); + _maxCoordOffset = di.readUnsignedShort(); + _featMinMaxCount = di.readUnsignedShort(); + _featMinMaxRecord = new FeatMinMaxRecord[_featMinMaxCount]; + for (int i = 0; i < _featMinMaxCount; ++i) { + _featMinMaxRecord[i] = new FeatMinMaxRecord(di); + } + } + } + + private class BaseValues { + + private int _defaultIndex; + private int _baseCoordCount; + private int[] _baseCoordOffset; + private BaseCoord[] _baseCoords; + + protected BaseValues(int baseValuesOffset) throws IOException { + DataInput di = getDataInputForOffset(baseValuesOffset); + _defaultIndex = di.readUnsignedShort(); + _baseCoordCount = di.readUnsignedShort(); + _baseCoordOffset = new int[_baseCoordCount]; + for (int i = 0; i < _baseCoordCount; ++i) { + _baseCoordOffset[i] = di.readUnsignedShort(); + } + _baseCoords = new BaseCoord[_baseCoordCount]; + for (int i = 0; i < _baseCoordCount; ++i) { + int format = di.readUnsignedShort(); + switch (format) { + case 1: + _baseCoords[i] = new BaseCoordFormat1(di); + break; + case 2: + _baseCoords[i] = new BaseCoordFormat2(di); + break; + case 3: + _baseCoords[i] = new BaseCoordFormat3(di); + break; + } + } + } + } + + private class BaseLangSysRecord { + + private int _baseLangSysTag; + private int _minMaxOffset; + + protected BaseLangSysRecord(DataInput di) throws IOException { + _baseLangSysTag = di.readInt(); + _minMaxOffset = di.readUnsignedShort(); + } + + public int getBaseLangSysTag() { + return _baseLangSysTag; + } + + public int getMinMaxOffset() { + return _minMaxOffset; + } + } + + private class BaseScript { + + private int _thisOffset; + private int _baseValuesOffset; + private int _defaultMinMaxOffset; + private int _baseLangSysCount; + private BaseLangSysRecord[] _baseLangSysRecord; + private BaseValues _baseValues; + private MinMax[] _minMax; + + protected BaseScript(int baseScriptOffset) throws IOException { + _thisOffset = baseScriptOffset; + DataInput di = getDataInputForOffset(baseScriptOffset); + _baseValuesOffset = di.readUnsignedShort(); + _defaultMinMaxOffset = di.readUnsignedShort(); + _baseLangSysCount = di.readUnsignedShort(); + _baseLangSysRecord = new BaseLangSysRecord[_baseLangSysCount]; + for (int i = 0; i < _baseLangSysCount; ++i) { + _baseLangSysRecord[i] = new BaseLangSysRecord(di); + } + if (_baseValuesOffset > 0) { + _baseValues = new BaseValues(baseScriptOffset + _baseValuesOffset); + } + for (int i = 0; i < _baseLangSysCount; ++i) { + _minMax[i] = new MinMax(baseScriptOffset + _baseLangSysRecord[i].getMinMaxOffset()); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("\nBaseScript BaseScriptT").append(Integer.toHexString(_thisOffset)) + .append("\nBaseValuesT").append(Integer.toHexString(_thisOffset + _baseValuesOffset)) + .append("\nMinMaxT").append(Integer.toHexString(_thisOffset + _defaultMinMaxOffset)) + .append("\n").append(Integer.toHexString(_baseLangSysCount)); +// for (int i = 0; i < _baseLangSysCount; ++i) { +// sb.append("\n ; BaseScriptRecord[").append(i); +// sb.append("]\n'").append(tagAsString(_baseScriptRecord[i].getBaseScriptTag())).append("'"); +// sb.append("\nBaseScriptT").append(Integer.toHexString(_thisOffset + _baseScriptRecord[i].getBaseScriptOffset())); +// } +// for (int i = 0; i < _baseScriptCount; ++i) { +// sb.append("\n").append(_baseScripts[i].toString()); +// } + if (_baseValues != null) { + sb.append("\n").append(_baseValues.toString()); + } + return sb.toString(); + } + } + + private class BaseScriptRecord { + + private int _baseScriptTag; + private int _baseScriptOffset; + + protected BaseScriptRecord(DataInput di) throws IOException { + _baseScriptTag = di.readInt(); + _baseScriptOffset = di.readUnsignedShort(); + } + + public int getBaseScriptTag() { + return _baseScriptTag; + } + + public int getBaseScriptOffset() { + return _baseScriptOffset; + } + } + + private class BaseScriptList { + + private int _thisOffset; + private int _baseScriptCount; + private BaseScriptRecord[] _baseScriptRecord; + private BaseScript[] _baseScripts; + + protected BaseScriptList(int baseScriptListOffset) throws IOException { + _thisOffset = baseScriptListOffset; + DataInput di = getDataInputForOffset(baseScriptListOffset); + _baseScriptCount = di.readUnsignedShort(); + _baseScriptRecord = new BaseScriptRecord[_baseScriptCount]; + for (int i = 0; i < _baseScriptCount; ++i) { + _baseScriptRecord[i] = new BaseScriptRecord(di); + } + _baseScripts = new BaseScript[_baseScriptCount]; + for (int i = 0; i < _baseScriptCount; ++i) { + _baseScripts[i] = new BaseScript( + baseScriptListOffset + _baseScriptRecord[i].getBaseScriptOffset()); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("\nBaseScriptList BaseScriptListT").append(Integer.toHexString(_thisOffset)) + .append("\n").append(Integer.toHexString(_baseScriptCount)); + for (int i = 0; i < _baseScriptCount; ++i) { + sb.append("\n ; BaseScriptRecord[").append(i); + sb.append("]\n'").append(tagAsString(_baseScriptRecord[i].getBaseScriptTag())).append("'"); + sb.append("\nBaseScriptT").append(Integer.toHexString(_thisOffset + _baseScriptRecord[i].getBaseScriptOffset())); + } + for (int i = 0; i < _baseScriptCount; ++i) { + sb.append("\n").append(_baseScripts[i].toString()); + } + return sb.toString(); + } + } + + private class BaseTagList { + + private int _thisOffset; + private int _baseTagCount; + private int[] _baselineTag; + + protected BaseTagList(int baseTagListOffset) throws IOException { + _thisOffset = baseTagListOffset; + DataInput di = getDataInputForOffset(baseTagListOffset); + _baseTagCount = di.readUnsignedShort(); + _baselineTag = new int[_baseTagCount]; + for (int i = 0; i < _baseTagCount; ++i) { + _baselineTag[i] = di.readInt(); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("\nBaseTagList BaseTagListT").append(Integer.toHexString(_thisOffset)) + .append("\n").append(Integer.toHexString(_baseTagCount)); + for (int i = 0; i < _baseTagCount; ++i) { + sb.append("\n'").append(tagAsString(_baselineTag[i])).append("'"); + } + return sb.toString(); + } + } + + private class Axis { + + private int _thisOffset; + private int _baseTagListOffset; + private int _baseScriptListOffset; + private BaseTagList _baseTagList; + private BaseScriptList _baseScriptList; + + protected Axis(int axisOffset) throws IOException { + _thisOffset = axisOffset; + DataInput di = getDataInputForOffset(axisOffset); + _baseTagListOffset = di.readUnsignedShort(); + _baseScriptListOffset = di.readUnsignedShort(); + if (_baseTagListOffset != 0) { + _baseTagList = new BaseTagList(axisOffset + _baseTagListOffset); + } + if (_baseScriptListOffset != 0) { + _baseScriptList = new BaseScriptList( + axisOffset + _baseScriptListOffset); + } + } + + public String toString() { + return new StringBuffer() + .append("\nAxis AxisT").append(Integer.toHexString(_thisOffset)) + .append("\nBaseTagListT").append(Integer.toHexString(_thisOffset + _baseTagListOffset)) + .append("\nBaseScriptListT").append(Integer.toHexString(_thisOffset + _baseScriptListOffset)) + .append("\n").append(_baseTagList) + .append("\n").append(_baseScriptList) + .toString(); + } + } + + private DirectoryEntry _de; + private int _version; + private int _horizAxisOffset; + private int _vertAxisOffset; + private Axis _horizAxis; + private Axis _vertAxis; + private byte[] _buf; + + /** Creates a new instance of BaseTable */ + protected BaseTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + + // Load entire table into a buffer, and create another input stream + _buf = new byte[de.getLength()]; + di.readFully(_buf); + DataInput di2 = getDataInputForOffset(0); + + _version = di2.readInt(); + _horizAxisOffset = di2.readUnsignedShort(); + _vertAxisOffset = di2.readUnsignedShort(); + if (_horizAxisOffset != 0) { + _horizAxis = new Axis(_horizAxisOffset); + } + if (_vertAxisOffset != 0) { + _vertAxis = new Axis(_vertAxisOffset); + } + + // Let go of the buffer + _buf = null; + } + + private DataInput getDataInputForOffset(int offset) { + return new DataInputStream(new ByteArrayInputStream( + _buf, offset, + _de.getLength() - offset)); + } + +// private String valueAsShortHex(int value) { +// return String.format("%1$4x", value); +// } +// +// private String valueAsLongHex(int value) { +// return String.format("%1$8x", value); +// } + + static protected String tagAsString(int tag) { + char[] c = new char[4]; + c[0] = (char)((tag >> 24) & 0xff); + c[1] = (char)((tag >> 16) & 0xff); + c[2] = (char)((tag >> 8) & 0xff); + c[3] = (char)(tag & 0xff); + return String.valueOf(c); + } + + public int getType() { + return BASE; + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("; 'BASE' Table - Baseline\n;-------------------------------------\n\n") + .append("BASEHeader BASEHeaderT").append(Integer.toHexString(0)) + .append("\n").append(Integer.toHexString(_version)) + .append("\nAxisT").append(Integer.toHexString(_horizAxisOffset)) + .append("\nAxisT").append(Integer.toHexString(_vertAxisOffset)); + if (_horizAxis != null) { + sb.append("\n").append(_horizAxis.toString()); + } + if (_vertAxis != null) { + sb.append("\n").append(_vertAxis.toString()); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CffStandardStrings.java b/src/net/java/dev/typecast/ot/table/CffStandardStrings.java new file mode 100644 index 000000000..987ea886c --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CffStandardStrings.java @@ -0,0 +1,424 @@ +/* + * $Id: CffStandardStrings.java,v 1.1 2007-02-05 12:41:52 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +/** + * Compact Font Format Standard Strings. As per Appendix A of the Adobe + * CFF specification. + * @version $Id: CffStandardStrings.java,v 1.1 2007-02-05 12:41:52 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CffStandardStrings { + + public static final String[] standardStrings = { + ".notdef", + "space", + "exclam", + "quotedbl", + "numbersign", + "dollar", + "percent", + "ampersand", + "quoteright", + "parenleft", + "parenright", + "asterisk", + "plus", + "comma", + "hyphen", + "period", + "slash", + "zero", + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", + "colon", + "semicolon", + "less", + "equal", + "greater", + "question", + "at", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + "bracketleft", + "backslash", + "bracketright", + "asciicircum", + "underscore", + "quoteleft", + "a", + "b", + "c", + "d", + "e", + "f", + "g", + "h", + "i", + "j", + "k", + "l", + "m", + "n", + "o", + "p", + "q", + "r", + "s", + "t", + "u", + "v", + "w", + "x", + "y", + "z", + "braceleft", + "bar", + "braceright", + "asciitilde", + "exclamdown", + "cent", + "sterling", + "fraction", + "yen", + "florin", + "section", + "currency", + "quotesingle", + "quotedblleft", + "guillemotleft", + "guilsinglleft", + "guilsinglright", + "fi", + "fl", + "endash", + "dagger", + "daggerdbl", + "periodcentered", + "paragraph", + "bullet", + "quotesinglbase", + "quotedblbase", + "quotedblright", + "guillemotright", + "ellipsis", + "perthousand", + "questiondown", + "grave", + "acute", + "circumflex", + "tilde", + "macron", + "breve", + "dotaccent", + "dieresis", + "ring", + "cedilla", + "hungarumlaut", + "ogonek", + "caron", + "emdash", + "AE", + "ordfeminine", + "Lslash", + "Oslash", + "OE", + "ordmasculine", + "ae", + "dotlessi", + "lslash", + "oslash", + "oe", + "germandbls", + "onesuperior", + "logicalnot", + "mu", + "trademark", + "Eth", + "onehalf", + "plusminus", + "Thorn", + "onequarter", + "divide", + "brokenbar", + "degree", + "thorn", + "threequarters", + "twosuperior", + "registered", + "minus", + "eth", + "multiply", + "threesuperior", + "copyright", + "Aacute", + "Acircumflex", + "Adieresis", + "Agrave", + "Aring", + "Atilde", + "Ccedilla", + "Eacute", + "Ecircumflex", + "Edieresis", + "Egrave", + "Iacute", + "Icircumflex", + "Idieresis", + "Igrave", + "Ntilde", + "Oacute", + "Ocircumflex", + "Odieresis", + "Ograve", + "Otilde", + "Scaron", + "Uacute", + "Ucircumflex", + "Udieresis", + "Ugrave", + "Yacute", + "Ydieresis", + "Zcaron", + "aacute", + "acircumflex", + "adieresis", + "agrave", + "aring", + "atilde", + "ccedilla", + "eacute", + "ecircumflex", + "edieresis", + "egrave", + "iacute", + "icircumflex", + "idieresis", + "igrave", + "ntilde", + "oacute", + "ocircumflex", + "odieresis", + "ograve", + "otilde", + "scaron", + "uacute", + "ucircumflex", + "udieresis", + "ugrave", + "yacute", + "ydieresis", + "zcaron", + "exclamsmall", + "Hungarumlautsmall", + "dollaroldstyle", + "dollarsuperior", + "ampersandsmall", + "Acutesmall", + "parenleftsuperior", + "parenrightsuperior", + "twodotenleader", + "onedotenleader", + "zerooldstyle", + "oneoldstyle", + "twooldstyle", + "threeoldstyle", + "fouroldstyle", + "fiveoldstyle", + "sixoldstyle", + "sevenoldstyle", + "eightoldstyle", + "nineoldstyle", + "commasuperior", + "threequartersemdash", + "periodsuperior", + "questionsmall", + "asuperior", + "bsuperior", + "centsuperior", + "dsuperior", + "esuperior", + "isuperior", + "lsuperior", + "msuperior", + "nsuperior", + "osuperior", + "rsuperior", + "ssuperior", + "tsuperior", + "ff", + "ffi", + "ffl", + "parenleftinferior", + "parenrightinferior", + "Circumflexsmall", + "hyphensuperior", + "Gravesmall", + "Asmall", + "Bsmall", + "Csmall", + "Dsmall", + "Esmall", + "Fsmall", + "Gsmall", + "Hsmall", + "Ismall", + "Jsmall", + "Ksmall", + "Lsmall", + "Msmall", + "Nsmall", + "Osmall", + "Psmall", + "Qsmall", + "Rsmall", + "Ssmall", + "Tsmall", + "Usmall", + "Vsmall", + "Wsmall", + "Xsmall", + "Ysmall", + "Zsmall", + "colonmonetary", + "onefitted", + "rupiah", + "Tildesmall", + "exclamdownsmall", + "centoldstyle", + "Lslashsmall", + "Scaronsmall", + "Zcaronsmall", + "Dieresissmall", + "Brevesmall", + "Caronsmall", + "Dotaccentsmall", + "Macronsmall", + "figuredash", + "hypheninferior", + "Ogoneksmall", + "Ringsmall", + "Cedillasmall", + "questiondownsmall", + "oneeighth", + "threeeighths", + "fiveeighths", + "seveneighths", + "onethird", + "twothirds", + "zerosuperior", + "foursuperior", + "fivesuperior", + "sixsuperior", + "sevensuperior", + "eightsuperior", + "ninesuperior", + "zeroinferior", + "oneinferior", + "twoinferior", + "threeinferior", + "fourinferior", + "fiveinferior", + "sixinferior", + "seveninferior", + "eightinferior", + "nineinferior", + "centinferior", + "dollarinferior", + "periodinferior", + "commainferior", + "Agravesmall", + "Aacutesmall", + "Acircumflexsmall", + "Atildesmall", + "Adieresissmall", + "Aringsmall", + "AEsmall", + "Ccedillasmall", + "Egravesmall", + "Eacutesmall", + "Ecircumflexsmall", + "Edieresissmall", + "Igravesmall", + "Iacutesmall", + "Icircumflexsmall", + "Idieresissmall", + "Ethsmall", + "Ntildesmall", + "Ogravesmall", + "Oacutesmall", + "Ocircumflexsmall", + "Otildesmall", + "Odieresissmall", + "OEsmall", + "Oslashsmall", + "Ugravesmall", + "Uacutesmall", + "Ucircumflexsmall", + "Udieresissmall", + "Yacutesmall", + "Thornsmall", + "Ydieresissmall", + "001.000", + "001.001", + "001.002", + "001.003", + "Black", + "Bold", + "Book", + "Light", + "Medium", + "Regular", + "Roman", + "Semibold" + }; +} diff --git a/src/net/java/dev/typecast/ot/table/CffTable.java b/src/net/java/dev/typecast/ot/table/CffTable.java new file mode 100644 index 000000000..2bd0cec63 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CffTable.java @@ -0,0 +1,620 @@ +/* + * $Id: CffTable.java,v 1.4 2007-07-26 11:15:06 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; + +import java.util.ArrayList; +import java.util.Dictionary; +import java.util.Enumeration; +import java.util.Hashtable; + +/** + * Compact Font Format Table + * @version $Id: CffTable.java,v 1.4 2007-07-26 11:15:06 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CffTable implements Table { + + public class Dict { + + private Dictionary<Integer, Object> _entries = new Hashtable<Integer, Object>(); + private int[] _data; + private int _index; + + protected Dict(int[] data, int offset, int length) { + _data = data; + _index = offset; + while (_index < offset + length) { + addKeyAndValueEntry(); + } + } + + public Object getValue(int key) { + return _entries.get(key); + } + + private boolean addKeyAndValueEntry() { + ArrayList<Object> operands = new ArrayList<Object>(); + Object operand = null; + while (isOperandAtIndex()) { + operand = nextOperand(); + operands.add(operand); + } + int operator = _data[_index++]; + if (operator == 12) { + operator <<= 8; + operator |= _data[_index++]; + } + if (operands.size() == 1) { + _entries.put(operator, operand); + } else { + _entries.put(operator, operands); + } + return true; + } + + private boolean isOperandAtIndex() { + int b0 = _data[_index]; + if ((32 <= b0 && b0 <= 254) + || b0 == 28 + || b0 == 29 + || b0 == 30) { + return true; + } + return false; + } + + private boolean isOperatorAtIndex() { + int b0 = _data[_index]; + if (0 <= b0 && b0 <= 21) { + return true; + } + return false; + } + + private Object nextOperand() { + int b0 = _data[_index]; + if (32 <= b0 && b0 <= 246) { + + // 1 byte integer + ++_index; + return new Integer(b0 - 139); + } else if (247 <= b0 && b0 <= 250) { + + // 2 byte integer + int b1 = _data[_index + 1]; + _index += 2; + return new Integer((b0 - 247) * 256 + b1 + 108); + } else if (251 <= b0 && b0 <= 254) { + + // 2 byte integer + int b1 = _data[_index + 1]; + _index += 2; + return new Integer(-(b0 - 251) * 256 - b1 - 108); + } else if (b0 == 28) { + + // 3 byte integer + int b1 = _data[_index + 1]; + int b2 = _data[_index + 2]; + _index += 3; + return new Integer(b1 << 8 | b2); + } else if (b0 == 29) { + + // 5 byte integer + int b1 = _data[_index + 1]; + int b2 = _data[_index + 2]; + int b3 = _data[_index + 3]; + int b4 = _data[_index + 4]; + _index += 5; + return new Integer(b1 << 24 | b2 << 16 | b3 << 8 | b4); + } else if (b0 == 30) { + + // Real number + StringBuffer fString = new StringBuffer(); + int nibble1 = 0; + int nibble2 = 0; + ++_index; + while ((nibble1 != 0xf) && (nibble2 != 0xf)) { + nibble1 = _data[_index] >> 4; + nibble2 = _data[_index] & 0xf; + ++_index; + fString.append(decodeRealNibble(nibble1)); + fString.append(decodeRealNibble(nibble2)); + } + return new Float(fString.toString()); + } else { + return null; + } + } + + private String decodeRealNibble(int nibble) { + if (nibble < 0xa) { + return Integer.toString(nibble); + } else if (nibble == 0xa) { + return "."; + } else if (nibble == 0xb) { + return "E"; + } else if (nibble == 0xc) { + return "E-"; + } else if (nibble == 0xe) { + return "-"; + } + return ""; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + Enumeration<Integer> keys = _entries.keys(); + while (keys.hasMoreElements()) { + Integer key = keys.nextElement(); + if ((key.intValue() & 0xc00) == 0xc00) { + sb.append("12 ").append(key.intValue() & 0xff).append(": "); + } else { + sb.append(key.toString()).append(": "); + } + sb.append(_entries.get(key).toString()).append("\n"); + } + return sb.toString(); + } + } + + public class Index { + + private int _count; + private int _offSize; + private int[] _offset; + private int[] _data; + + protected Index(DataInput di) throws IOException { + _count = di.readUnsignedShort(); + _offset = new int[_count + 1]; + _offSize = di.readUnsignedByte(); + for (int i = 0; i < _count + 1; ++i) { + int thisOffset = 0; + for (int j = 0; j < _offSize; ++j) { + thisOffset |= di.readUnsignedByte() << ((_offSize - j - 1) * 8); + } + _offset[i] = thisOffset; + } + _data = new int[getDataLength()]; + for (int i = 0; i < getDataLength(); ++i) { + _data[i] = di.readUnsignedByte(); + } + } + + public int getCount() { + return _count; + } + + public int getOffset(int index) { + return _offset[index]; + } + + public int getDataLength() { + return _offset[_offset.length - 1] - 1; + } + + public int[] getData() { + return _data; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("DICT\n"); + sb.append("count: ").append(_count).append("\n"); + sb.append("offSize: ").append(_offSize).append("\n"); + for (int i = 0; i < _count + 1; ++i) { + sb.append("offset[").append(i).append("]: ").append(_offset[i]).append("\n"); + } + sb.append("data:"); + for (int i = 0; i < _data.length; ++i) { + if (i % 8 == 0) { + sb.append("\n"); + } else { + sb.append(" "); + } + sb.append(_data[i]); + } + sb.append("\n"); + return sb.toString(); + } + } + + public class TopDictIndex extends Index { + + protected TopDictIndex(DataInput di) throws IOException { + super(di); + } + + public Dict getTopDict(int index) { + int offset = getOffset(index) - 1; + int len = getOffset(index + 1) - offset - 1; + return new Dict(getData(), offset, len); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < getCount(); ++i) { + sb.append(getTopDict(i).toString()).append("\n"); + } + return sb.toString(); + } + } + + public class NameIndex extends Index { + + protected NameIndex(DataInput di) throws IOException { + super(di); + } + + public String getName(int index) { + String name = null; + int offset = getOffset(index) - 1; + int len = getOffset(index + 1) - offset - 1; + + // Ensure the name hasn't been deleted + if (getData()[offset] != 0) { + StringBuffer sb = new StringBuffer(); + for (int i = offset; i < offset + len; ++i) { + sb.append((char) getData()[i]); + } + name = sb.toString(); + } else { + name = "DELETED NAME"; + } + return name; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < getCount(); ++i) { + sb.append(getName(i)).append("\n"); + } + return sb.toString(); + } + } + + public class StringIndex extends Index { + + protected StringIndex(DataInput di) throws IOException { + super(di); + } + + public String getString(int index) { + if (index < CffStandardStrings.standardStrings.length) { + return CffStandardStrings.standardStrings[index]; + } else { + index -= CffStandardStrings.standardStrings.length; + if (index >= getCount()) { + return null; + } + int offset = getOffset(index) - 1; + int len = getOffset(index + 1) - offset - 1; + + StringBuffer sb = new StringBuffer(); + for (int i = offset; i < offset + len; ++i) { + sb.append((char) getData()[i]); + } + return sb.toString(); + } + } + + public String toString() { + int nonStandardBase = CffStandardStrings.standardStrings.length; + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < getCount(); ++i) { + sb.append(nonStandardBase + i).append(": "); + sb.append(getString(nonStandardBase + i)).append("\n"); + } + return sb.toString(); + } + } + + private class CharsetRange { + + private int _first; + private int _left; + + public int getFirst() { + return _first; + } + + protected void setFirst(int first) { + _first = first; + } + + public int getLeft() { + return _left; + } + + protected void setLeft(int left) { + _left = left; + } + } + + private class CharsetRange1 extends CharsetRange { + + protected CharsetRange1(DataInput di) throws IOException { + setFirst(di.readUnsignedShort()); + setLeft(di.readUnsignedByte()); + } + } + + private class CharsetRange2 extends CharsetRange { + + protected CharsetRange2(DataInput di) throws IOException { + setFirst(di.readUnsignedShort()); + setLeft(di.readUnsignedShort()); + } + } + + private abstract class Charset { + + public abstract int getFormat(); + + public abstract int getSID(int gid); + } + + private class CharsetFormat0 extends Charset { + + private int[] _glyph; + + protected CharsetFormat0(DataInput di, int glyphCount) throws IOException { + _glyph = new int[glyphCount - 1]; // minus 1 because .notdef is omitted + for (int i = 0; i < glyphCount - 1; ++i) { + _glyph[i] = di.readUnsignedShort(); + } + } + + public int getFormat() { + return 0; + } + + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + return _glyph[gid - 1]; + } + } + + private class CharsetFormat1 extends Charset { + + private ArrayList<CharsetRange> _charsetRanges = new ArrayList<CharsetRange>(); + + protected CharsetFormat1(DataInput di, int glyphCount) throws IOException { + int glyphsCovered = glyphCount - 1; // minus 1 because .notdef is omitted + while (glyphsCovered > 0) { + CharsetRange range = new CharsetRange1(di); + _charsetRanges.add(range); + glyphsCovered -= range.getLeft() + 1; + } + } + + public int getFormat() { + return 1; + } + + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + + // Count through the ranges to find the one of interest + int count = 0; + for (CharsetRange range : _charsetRanges) { + count += range.getLeft(); + if (gid < count) { + int sid = gid - count + range.getFirst(); + return sid; + } + } + return 0; + } + } + + private class CharsetFormat2 extends Charset { + + private ArrayList<CharsetRange> _charsetRanges = new ArrayList<CharsetRange>(); + + protected CharsetFormat2(DataInput di, int glyphCount) throws IOException { + int glyphsCovered = glyphCount - 1; // minus 1 because .notdef is omitted + while (glyphsCovered > 0) { + CharsetRange range = new CharsetRange2(di); + _charsetRanges.add(range); + glyphsCovered -= range.getLeft() + 1; + } + } + + public int getFormat() { + return 2; + } + + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + + // Count through the ranges to find the one of interest + int count = 0; + for (CharsetRange range : _charsetRanges) { + if (gid < range.getLeft() + count) { + int sid = gid - count + range.getFirst() - 1; + return sid; + } + count += range.getLeft(); + } + return 0; + } + } + + private DirectoryEntry _de; + private int _major; + private int _minor; + private int _hdrSize; + private int _offSize; + private NameIndex _nameIndex; + private TopDictIndex _topDictIndex; + private StringIndex _stringIndex; + private Index _globalSubrIndex; + private Index _charStringsIndexArray[]; + private Charset[] _charsets; + private Charstring[][] _charstringsArray; + + private byte[] _buf; + + /** Creates a new instance of CffTable */ + protected CffTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + + // Load entire table into a buffer, and create another input stream + _buf = new byte[de.getLength()]; + di.readFully(_buf); + DataInput di2 = getDataInputForOffset(0); + + // Header + _major = di2.readUnsignedByte(); + _minor = di2.readUnsignedByte(); + _hdrSize = di2.readUnsignedByte(); + _offSize = di2.readUnsignedByte(); + + // Name INDEX + di2 = getDataInputForOffset(_hdrSize); + _nameIndex = new NameIndex(di2); + + // Top DICT INDEX + _topDictIndex = new TopDictIndex(di2); + + // String INDEX + _stringIndex = new StringIndex(di2); + + // Global Subr INDEX + _globalSubrIndex = new Index(di2); + + // Encodings go here -- but since this is an OpenType font will this + // not always be a CIDFont? In which case there are no encodings + // within the CFF data. + + // Load each of the fonts + _charStringsIndexArray = new Index[_topDictIndex.getCount()]; + _charsets = new Charset[_topDictIndex.getCount()]; + _charstringsArray = new Charstring[_topDictIndex.getCount()][]; + for (int i = 0; i < _topDictIndex.getCount(); ++i) { + + // Charstrings INDEX + // We load this before Charsets because we may need to know the number + // of glyphs + Integer charStringsOffset = (Integer) _topDictIndex.getTopDict(i).getValue(17); + di2 = getDataInputForOffset(charStringsOffset); + _charStringsIndexArray[i] = new Index(di2); + int glyphCount = _charStringsIndexArray[i].getCount(); + + // Charsets + Integer charsetOffset = (Integer) _topDictIndex.getTopDict(i).getValue(15); + di2 = getDataInputForOffset(charsetOffset); + int format = di2.readUnsignedByte(); + switch (format) { + case 0: + _charsets[i] = new CharsetFormat0(di2, glyphCount); + break; + case 1: + _charsets[i] = new CharsetFormat1(di2, glyphCount); + break; + case 2: + _charsets[i] = new CharsetFormat2(di2, glyphCount); + break; + } + + // Create the charstrings + _charstringsArray[i] = new Charstring[glyphCount]; + for (int j = 0; j < glyphCount; ++j) { + int offset = _charStringsIndexArray[i].getOffset(j) - 1; + int len = _charStringsIndexArray[i].getOffset(j + 1) - offset - 1; + _charstringsArray[i][j] = new CharstringType2( + i, + _stringIndex.getString(_charsets[i].getSID(j)), + _charStringsIndexArray[i].getData(), + offset, + len, + null, + null); + } + } + } + + private DataInput getDataInputForOffset(int offset) { + return new DataInputStream(new ByteArrayInputStream( + _buf, offset, + _de.getLength() - offset)); + } + + public NameIndex getNameIndex() { + return _nameIndex; + } + + public Charset getCharset(int fontIndex) { + return _charsets[fontIndex]; + } + + public Charstring getCharstring(int fontIndex, int gid) { + return _charstringsArray[fontIndex][gid]; + } + + public int getCharstringCount(int fontIndex) { + return _charstringsArray[fontIndex].length; + } + + public int getType() { + return CFF; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'CFF' Table - Compact Font Format\n---------------------------------\n"); + sb.append("\nName INDEX\n"); + sb.append(_nameIndex.toString()); + sb.append("\nTop DICT INDEX\n"); + sb.append(_topDictIndex.toString()); + sb.append("\nString INDEX\n"); + sb.append(_stringIndex.toString()); + sb.append("\nGlobal Subr INDEX\n"); + sb.append(_globalSubrIndex.toString()); + for (int i = 0; i < _charStringsIndexArray.length; ++i) { + sb.append("\nCharStrings INDEX ").append(i).append("\n"); + sb.append(_charStringsIndexArray[i].toString()); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Charstring.java b/src/net/java/dev/typecast/ot/table/Charstring.java new file mode 100644 index 000000000..2439d6bc5 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Charstring.java @@ -0,0 +1,33 @@ +/* + * $Id: Charstring.java,v 1.2 2007-02-21 12:25:19 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +/** + * CFF Charstring + * @version $Id: Charstring.java,v 1.2 2007-02-21 12:25:19 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public abstract class Charstring { + + public abstract int getIndex(); + + public abstract String getName(); +} diff --git a/src/net/java/dev/typecast/ot/table/CharstringType2.java b/src/net/java/dev/typecast/ot/table/CharstringType2.java new file mode 100644 index 000000000..e47825cf3 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CharstringType2.java @@ -0,0 +1,235 @@ +/* + * $Id: CharstringType2.java,v 1.4 2007-07-26 11:13:44 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import net.java.dev.typecast.ot.table.CffTable; + +/** + * CFF Type 2 Charstring + * @version $Id: CharstringType2.java,v 1.4 2007-07-26 11:13:44 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CharstringType2 extends Charstring { + + private static final String[] _oneByteOperators = { + "-Reserved-", + "hstem", + "-Reserved-", + "vstem", + "vmoveto", + "rlineto", + "hlineto", + "vlineto", + "rrcurveto", + "-Reserved-", + "callsubr", + "return", + "escape", + "-Reserved-", + "endchar", + "-Reserved-", + "-Reserved-", + "-Reserved-", + "hstemhm", + "hintmask", + "cntrmask", + "rmoveto", + "hmoveto", + "vstemhm", + "rcurveline", + "rlinecurve", + "vvcurveto", + "hhcurveto", + "shortint", + "callgsubr", + "vhcurveto", + "hvcurveto" + }; + + private static final String[] _twoByteOperators = { + "-Reserved- (dotsection)", + "-Reserved-", + "-Reserved-", + "and", + "or", + "not", + "-Reserved-", + "-Reserved-", + "-Reserved-", + "abs", + "add", + "sub", + "div", + "-Reserved-", + "neg", + "eq", + "-Reserved-", + "-Reserved-", + "drop", + "-Reserved-", + "put", + "get", + "ifelse", + "random", + "mul", + "-Reserved-", + "sqrt", + "dup", + "exch", + "index", + "roll", + "-Reserved-", + "-Reserved-", + "-Reserved-", + "hflex", + "flex", + "hflex1", + "flex1", + "-Reserved-" + }; + + private int _index; + private String _name; + private int[] _data; + private int _offset; + private int _length; + private CffTable.Index _localSubrIndex; + private CffTable.Index _globalSubrIndex; + private int _ip; + + /** Creates a new instance of CharstringType2 */ + protected CharstringType2( + int index, + String name, + int[] data, + int offset, + int length, + CffTable.Index localSubrIndex, + CffTable.Index globalSubrIndex) { + _index = index; + _name = name; + _data = data; + _offset = offset; + _length = length; + _localSubrIndex = localSubrIndex; + _globalSubrIndex = globalSubrIndex; + } + + public int getIndex() { + return _index; + } + + public String getName() { + return _name; + } + + private void disassemble(StringBuffer sb) { + Number operand = null; + while (isOperandAtIndex()) { + operand = nextOperand(); + sb.append(operand).append(" "); + } + int operator = nextByte(); + String mnemonic; + if (operator == 12) { + operator = nextByte(); + + // Check we're not exceeding the upper limit of our mnemonics + if (operator > 38) { + operator = 38; + } + mnemonic = _twoByteOperators[operator]; + } else { + mnemonic = _oneByteOperators[operator]; + } + sb.append(mnemonic); + } + + public void resetIP() { + _ip = _offset; + } + + public boolean isOperandAtIndex() { + int b0 = _data[_ip]; + if ((32 <= b0 && b0 <= 255) || b0 == 28) { + return true; + } + return false; + } + + public Number nextOperand() { + int b0 = _data[_ip]; + if (32 <= b0 && b0 <= 246) { + + // 1 byte integer + ++_ip; + return new Integer(b0 - 139); + } else if (247 <= b0 && b0 <= 250) { + + // 2 byte integer + int b1 = _data[_ip + 1]; + _ip += 2; + return new Integer((b0 - 247) * 256 + b1 + 108); + } else if (251 <= b0 && b0 <= 254) { + + // 2 byte integer + int b1 = _data[_ip + 1]; + _ip += 2; + return new Integer(-(b0 - 251) * 256 - b1 - 108); + } else if (b0 == 28) { + + // 3 byte integer + int b1 = _data[_ip + 1]; + int b2 = _data[_ip + 2]; + _ip += 3; + return new Integer(b1 << 8 | b2); + } else if (b0 == 255) { + + // 16-bit signed integer with 16 bits of fraction + int b1 = (byte) _data[_ip + 1]; + int b2 = _data[_ip + 2]; + int b3 = _data[_ip + 3]; + int b4 = _data[_ip + 4]; + _ip += 5; + return new Float((b1 << 8 | b2) + ((b3 << 8 | b4) / 65536.0)); + } else { + return null; + } + } + + public int nextByte() { + return _data[_ip++]; + } + + public boolean moreBytes() { + return _ip < _offset + _length; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + resetIP(); + while (moreBytes()) { + disassemble(sb); + sb.append("\n"); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/ClassDef.java b/src/net/java/dev/typecast/ot/table/ClassDef.java new file mode 100644 index 000000000..9fa45c3c6 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ClassDef.java @@ -0,0 +1,33 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ClassDef.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + */ +public abstract class ClassDef { + + public abstract int getFormat(); + + protected static ClassDef read(RandomAccessFile raf) throws IOException { + ClassDef c = null; + int format = raf.readUnsignedShort(); + if (format == 1) { + c = new ClassDefFormat1(raf); + } else if (format == 2) { + c = new ClassDefFormat2(raf); + } + return c; + } +} diff --git a/src/net/java/dev/typecast/ot/table/ClassDefFormat1.java b/src/net/java/dev/typecast/ot/table/ClassDefFormat1.java new file mode 100644 index 000000000..07b85ddf9 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ClassDefFormat1.java @@ -0,0 +1,39 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ClassDefFormat1.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + */ +public class ClassDefFormat1 extends ClassDef { + + private int startGlyph; + private int glyphCount; + private int[] classValues; + + /** Creates new ClassDefFormat1 */ + public ClassDefFormat1(RandomAccessFile raf) throws IOException { + startGlyph = raf.readUnsignedShort(); + glyphCount = raf.readUnsignedShort(); + classValues = new int[glyphCount]; + for (int i = 0; i < glyphCount; i++) { + classValues[i] = raf.readUnsignedShort(); + } + } + + public int getFormat() { + return 1; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/ClassDefFormat2.java b/src/net/java/dev/typecast/ot/table/ClassDefFormat2.java new file mode 100644 index 000000000..f8b883c41 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ClassDefFormat2.java @@ -0,0 +1,37 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ClassDefFormat2.java,v 1.1.1.1 2004-12-05 23:14:33 davidsch Exp $ + */ +public class ClassDefFormat2 extends ClassDef { + + private int classRangeCount; + private RangeRecord[] classRangeRecords; + + /** Creates new ClassDefFormat2 */ + public ClassDefFormat2(RandomAccessFile raf) throws IOException { + classRangeCount = raf.readUnsignedShort(); + classRangeRecords = new RangeRecord[classRangeCount]; + for (int i = 0; i < classRangeCount; i++) { + classRangeRecords[i] = new RangeRecord(raf); + } + } + + public int getFormat() { + return 2; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat.java b/src/net/java/dev/typecast/ot/table/CmapFormat.java new file mode 100644 index 000000000..be88af1e6 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat.java @@ -0,0 +1,134 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: CmapFormat.java,v 1.3 2004-12-21 16:56:35 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public abstract class CmapFormat { + + public class Range { + + private int _startCode; + private int _endCode; + + protected Range(int startCode, int endCode) { + _startCode = startCode; + _endCode = endCode; + } + + public int getStartCode() { + return _startCode; + } + + public int getEndCode() { + return _endCode; + } + } + + protected int _format; + protected int _length; + protected int _language; + + protected CmapFormat(DataInput di) throws IOException { + _length = di.readUnsignedShort(); + _language = di.readUnsignedShort(); + } + + protected static CmapFormat create(int format, DataInput di) + throws IOException { + switch(format) { + case 0: + return new CmapFormat0(di); + case 2: + return new CmapFormat2(di); + case 4: + return new CmapFormat4(di); + case 6: + return new CmapFormat6(di); + default: + return new CmapFormatUnknown(format, di); + } + } + + public int getFormat() { + return _format; + } + + public int getLength() { + return _length; + } + + public int getLanguage() { + return _language; + } + + public abstract int getRangeCount(); + + public abstract Range getRange(int index) + throws ArrayIndexOutOfBoundsException; + + public abstract int mapCharCode(int charCode); + + public String toString() { + return new StringBuffer() + .append("format: ") + .append(_format) + .append(", length: ") + .append(_length) + .append(", language: ") + .append(_language).toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat0.java b/src/net/java/dev/typecast/ot/table/CmapFormat0.java new file mode 100644 index 000000000..80f42b227 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat0.java @@ -0,0 +1,92 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * Simple Macintosh cmap table, mapping only the ASCII character set to glyphs. + * + * @version $Id: CmapFormat0.java,v 1.2 2004-12-21 10:22:55 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CmapFormat0 extends CmapFormat { + + private int[] _glyphIdArray = new int[256]; + + protected CmapFormat0(DataInput di) throws IOException { + super(di); + _format = 0; + for (int i = 0; i < 256; i++) { + _glyphIdArray[i] = di.readUnsignedByte(); + } + } + + public int getRangeCount() { + return 1; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + if (index != 0) { + throw new ArrayIndexOutOfBoundsException(); + } + return new Range(0, 255); + } + + public int mapCharCode(int charCode) { + if (0 <= charCode && charCode < 256) { + return _glyphIdArray[charCode]; + } else { + return 0; + } + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat2.java b/src/net/java/dev/typecast/ot/table/CmapFormat2.java new file mode 100644 index 000000000..4eeaf420a --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat2.java @@ -0,0 +1,173 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * High-byte mapping through table cmap format. + * @version $Id: CmapFormat2.java,v 1.3 2004-12-21 16:56:54 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CmapFormat2 extends CmapFormat { + + private class SubHeader { + int _firstCode; + int _entryCount; + short _idDelta; + int _idRangeOffset; + int _arrayIndex; + } + + private int[] _subHeaderKeys = new int[256]; + private SubHeader[] _subHeaders; + private int[] _glyphIndexArray; + + protected CmapFormat2(DataInput di) throws IOException { + super(di); + _format = 2; + + int pos = 6; + + // Read the subheader keys, noting the highest value, as this will + // determine the number of subheaders to read. + int highest = 0; + for (int i = 0; i < 256; ++i) { + _subHeaderKeys[i] = di.readUnsignedShort(); + highest = Math.max(highest, _subHeaderKeys[i]); + pos += 2; + } + int subHeaderCount = highest / 8 + 1; + _subHeaders = new SubHeader[subHeaderCount]; + + // Read the subheaders, once again noting the highest glyphIndexArray + // index range. + int indexArrayOffset = 8 * subHeaderCount + 518; + highest = 0; + for (int i = 0; i < _subHeaders.length; ++i) { + SubHeader sh = new SubHeader(); + sh._firstCode = di.readUnsignedShort(); + sh._entryCount = di.readUnsignedShort(); + sh._idDelta = di.readShort(); + sh._idRangeOffset = di.readUnsignedShort(); + + // Calculate the offset into the _glyphIndexArray + pos += 8; + sh._arrayIndex = + (pos - 2 + sh._idRangeOffset - indexArrayOffset) / 2; + + // What is the highest range within the glyphIndexArray? + highest = Math.max(highest, sh._arrayIndex + sh._entryCount); + + _subHeaders[i] = sh; + } + + // Read the glyphIndexArray + _glyphIndexArray = new int[highest]; + for (int i = 0; i < _glyphIndexArray.length; ++i) { + _glyphIndexArray[i] = di.readUnsignedShort(); + } + } + + public int getRangeCount() { + return _subHeaders.length; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + if (index < 0 || index >= _subHeaders.length) { + throw new ArrayIndexOutOfBoundsException(); + } + + // Find the high-byte (if any) + int highByte = 0; + if (index != 0) { + for (int i = 0; i < 256; ++i) { + if (_subHeaderKeys[i] / 8 == index) { + highByte = i << 8; + break; + } + } + } + + return new Range( + highByte | _subHeaders[index]._firstCode, + highByte | (_subHeaders[index]._firstCode + + _subHeaders[index]._entryCount - 1)); + } + + public int mapCharCode(int charCode) { + + // Get the appropriate subheader + int index = 0; + int highByte = charCode >> 8; + if (highByte != 0) { + index = _subHeaderKeys[highByte] / 8; + } + SubHeader sh = _subHeaders[index]; + + // Is the charCode out-of-range? + int lowByte = charCode & 0xff; + if (lowByte < sh._firstCode || + lowByte >= (sh._firstCode + sh._entryCount)) { + return 0; + } + + // Now calculate the glyph index + int glyphIndex = + _glyphIndexArray[sh._arrayIndex + (lowByte - sh._firstCode)]; + if (glyphIndex != 0) { + glyphIndex += sh._idDelta; + glyphIndex %= 65536; + } + return glyphIndex; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat4.java b/src/net/java/dev/typecast/ot/table/CmapFormat4.java new file mode 100644 index 000000000..3748a8f84 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat4.java @@ -0,0 +1,165 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: CmapFormat4.java,v 1.3 2004-12-21 16:57:23 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CmapFormat4 extends CmapFormat { + + private int _segCountX2; + private int _searchRange; + private int _entrySelector; + private int _rangeShift; + private int[] _endCode; + private int[] _startCode; + private int[] _idDelta; + private int[] _idRangeOffset; + private int[] _glyphIdArray; + private int _segCount; + + protected CmapFormat4(DataInput di) throws IOException { + super(di); // 6 + _format = 4; + _segCountX2 = di.readUnsignedShort(); // +2 (8) + _segCount = _segCountX2 / 2; + _endCode = new int[_segCount]; + _startCode = new int[_segCount]; + _idDelta = new int[_segCount]; + _idRangeOffset = new int[_segCount]; + _searchRange = di.readUnsignedShort(); // +2 (10) + _entrySelector = di.readUnsignedShort(); // +2 (12) + _rangeShift = di.readUnsignedShort(); // +2 (14) + for (int i = 0; i < _segCount; i++) { + _endCode[i] = di.readUnsignedShort(); + } // + 2*segCount (2*segCount + 14) + di.readUnsignedShort(); // reservePad +2 (2*segCount + 16) + for (int i = 0; i < _segCount; i++) { + _startCode[i] = di.readUnsignedShort(); + } // + 2*segCount (4*segCount + 16) + for (int i = 0; i < _segCount; i++) { + _idDelta[i] = di.readUnsignedShort(); + } // + 2*segCount (6*segCount + 16) + for (int i = 0; i < _segCount; i++) { + _idRangeOffset[i] = di.readUnsignedShort(); + } // + 2*segCount (8*segCount + 16) + + // Whatever remains of this header belongs in glyphIdArray + int count = (_length - (8*_segCount + 16)) / 2; + _glyphIdArray = new int[count]; + for (int i = 0; i < count; i++) { + _glyphIdArray[i] = di.readUnsignedShort(); + } // + 2*count (8*segCount + 2*count + 18) + + // Are there any padding bytes we need to consume? +// int leftover = length - (8*segCount + 2*count + 18); +// if (leftover > 0) { +// di.skipBytes(leftover); +// } + } + + public int getRangeCount() { + return _segCount; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + if (index < 0 || index >= _segCount) { + throw new ArrayIndexOutOfBoundsException(); + } + return new Range(_startCode[index], _endCode[index]); + } + + public int mapCharCode(int charCode) { + try { + for (int i = 0; i < _segCount; i++) { + if (_endCode[i] >= charCode) { + if (_startCode[i] <= charCode) { + if (_idRangeOffset[i] > 0) { + return _glyphIdArray[_idRangeOffset[i]/2 + (charCode - _startCode[i]) - (_segCount - i)]; + } else { + return (_idDelta[i] + charCode) % 65536; + } + } else { + break; + } + } + } + } catch (ArrayIndexOutOfBoundsException e) { + System.err.println("error: Array out of bounds - " + e.getMessage()); + } + return 0; + } + + public String toString() { + return new StringBuffer() + .append(super.toString()) + .append(", segCountX2: ") + .append(_segCountX2) + .append(", searchRange: ") + .append(_searchRange) + .append(", entrySelector: ") + .append(_entrySelector) + .append(", rangeShift: ") + .append(_rangeShift) + .append(", endCode: ") + .append(_endCode) + .append(", startCode: ") + .append(_endCode) + .append(", idDelta: ") + .append(_idDelta) + .append(", idRangeOffset: ") + .append(_idRangeOffset).toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormat6.java b/src/net/java/dev/typecast/ot/table/CmapFormat6.java new file mode 100644 index 000000000..f9b398aab --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormat6.java @@ -0,0 +1,87 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * TODO: To be implemented + * @version $Id: CmapFormat6.java,v 1.2 2004-12-21 10:22:56 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CmapFormat6 extends CmapFormat { + + private short _firstCode; + private short _entryCount; + private short[] _glyphIdArray; + + protected CmapFormat6(DataInput di) throws IOException { + super(di); + _format = 6; + + // HACK: As this is not yet implemented, we need to skip over the bytes + // we should be consuming + //di.skipBytes(_length - 4); + } + + public int getRangeCount() { + return 0; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + throw new ArrayIndexOutOfBoundsException(); + } + + public int mapCharCode(int charCode) { + return 0; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapFormatUnknown.java b/src/net/java/dev/typecast/ot/table/CmapFormatUnknown.java new file mode 100644 index 000000000..01ca600f1 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapFormatUnknown.java @@ -0,0 +1,54 @@ +/* + * $Id: CmapFormatUnknown.java,v 1.1 2004-12-21 10:21:23 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * When we encounter a cmap format we don't understand, we can use this class + * to hold the bare minimum information about it. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: CmapFormatUnknown.java,v 1.1 2004-12-21 10:21:23 davidsch Exp $ + */ +public class CmapFormatUnknown extends CmapFormat { + + /** Creates a new instance of CmapFormatUnknown */ + protected CmapFormatUnknown(int format, DataInput di) throws IOException { + super(di); + _format = format; + + // We don't know how to handle this data, so we'll just skip over it + di.skipBytes(_length - 4); + } + + public int getRangeCount() { + return 0; + } + + public Range getRange(int index) throws ArrayIndexOutOfBoundsException { + throw new ArrayIndexOutOfBoundsException(); + } + + public int mapCharCode(int charCode) { + return 0; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapIndexEntry.java b/src/net/java/dev/typecast/ot/table/CmapIndexEntry.java new file mode 100644 index 000000000..c82e270fb --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapIndexEntry.java @@ -0,0 +1,117 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: CmapIndexEntry.java,v 1.2 2004-12-21 10:22:56 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CmapIndexEntry implements Comparable { + + private int _platformId; + private int _encodingId; + private int _offset; + private CmapFormat _format; + + protected CmapIndexEntry(DataInput di) throws IOException { + _platformId = di.readUnsignedShort(); + _encodingId = di.readUnsignedShort(); + _offset = di.readInt(); + } + + public int getPlatformId() { + return _platformId; + } + + public int getEncodingId() { + return _encodingId; + } + + public int getOffset() { + return _offset; + } + + public CmapFormat getFormat() { + return _format; + } + + public void setFormat(CmapFormat format) { + _format = format; + } + + public String toString() { + return new StringBuffer() + .append("platform id: ") + .append(_platformId) + .append(" (") + .append(ID.getPlatformName((short) _platformId)) + .append("), encoding id: ") + .append(_encodingId) + .append(" (") + .append(ID.getEncodingName((short) _platformId, (short) _encodingId)) + .append("), offset: ") + .append(_offset).toString(); + } + + public int compareTo(java.lang.Object obj) { + CmapIndexEntry entry = (CmapIndexEntry) obj; + if (getOffset() < entry.getOffset()) { + return -1; + } else if (getOffset() > entry.getOffset()) { + return 1; + } else { + return 0; + } + } +} diff --git a/src/net/java/dev/typecast/ot/table/CmapTable.java b/src/net/java/dev/typecast/ot/table/CmapTable.java new file mode 100644 index 000000000..de69cc1f0 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CmapTable.java @@ -0,0 +1,161 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +import java.util.Arrays; + +/** + * @version $Id: CmapTable.java,v 1.3 2004-12-21 10:22:56 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CmapTable implements Table { + + private DirectoryEntry _de; + private int _version; + private int _numTables; + private CmapIndexEntry[] _entries; + + protected CmapTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + _version = di.readUnsignedShort(); + _numTables = di.readUnsignedShort(); + long bytesRead = 4; + _entries = new CmapIndexEntry[_numTables]; + + // Get each of the index entries + for (int i = 0; i < _numTables; i++) { + _entries[i] = new CmapIndexEntry(di); + bytesRead += 8; + } + + // Sort into their order of offset + Arrays.sort(_entries); + + // Get each of the tables + int lastOffset = 0; + CmapFormat lastFormat = null; + for (int i = 0; i < _numTables; i++) { + if (_entries[i].getOffset() == lastOffset) { + + // This is a multiple entry + _entries[i].setFormat(lastFormat); + continue; + } else if (_entries[i].getOffset() > bytesRead) { + di.skipBytes(_entries[i].getOffset() - (int) bytesRead); + } else if (_entries[i].getOffset() != bytesRead) { + + // Something is amiss + throw new IOException(); + } + int formatType = di.readUnsignedShort(); + lastFormat = CmapFormat.create(formatType, di); + lastOffset = _entries[i].getOffset(); + _entries[i].setFormat(lastFormat); + bytesRead += lastFormat.getLength(); + } + } + + public int getVersion() { + return _version; + } + + public int getNumTables() { + return _numTables; + } + + public CmapIndexEntry getCmapIndexEntry(int i) { + return _entries[i]; + } + + public CmapFormat getCmapFormat(short platformId, short encodingId) { + + // Find the requested format + for (int i = 0; i < _numTables; i++) { + if (_entries[i].getPlatformId() == platformId + && _entries[i].getEncodingId() == encodingId) { + return _entries[i].getFormat(); + } + } + return null; + } + + public int getType() { + return cmap; + } + + public String toString() { + StringBuffer sb = new StringBuffer().append("cmap\n"); + + // Get each of the index entries + for (int i = 0; i < _numTables; i++) { + sb.append("\t").append(_entries[i].toString()).append("\n"); + } + + // Get each of the tables +// for (int i = 0; i < numTables; i++) { +// sb.append("\t").append(formats[i].toString()).append("\n"); +// } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Coverage.java b/src/net/java/dev/typecast/ot/table/Coverage.java new file mode 100644 index 000000000..3c6cf0409 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Coverage.java @@ -0,0 +1,83 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Coverage.java,v 1.3 2007-01-24 09:43:30 davidsch Exp $ + */ +public abstract class Coverage { + + public abstract int getFormat(); + + /** + * @param glyphId The ID of the glyph to find. + * @return The index of the glyph within the coverage, or -1 if the glyph + * can't be found. + */ + public abstract int findGlyph(int glyphId); + + protected static Coverage read(DataInput di) throws IOException { + Coverage c = null; + int format = di.readUnsignedShort(); + if (format == 1) { + c = new CoverageFormat1(di); + } else if (format == 2) { + c = new CoverageFormat2(di); + } + return c; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/CoverageFormat1.java b/src/net/java/dev/typecast/ot/table/CoverageFormat1.java new file mode 100644 index 000000000..a81eb0f1e --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CoverageFormat1.java @@ -0,0 +1,88 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: CoverageFormat1.java,v 1.2 2007-01-24 09:43:30 davidsch Exp $ + */ +public class CoverageFormat1 extends Coverage { + + private int _glyphCount; + private int[] _glyphIds; + + /** Creates new CoverageFormat1 */ + protected CoverageFormat1(DataInput di) throws IOException { + _glyphCount = di.readUnsignedShort(); + _glyphIds = new int[_glyphCount]; + for (int i = 0; i < _glyphCount; i++) { + _glyphIds[i] = di.readUnsignedShort(); + } + } + + public int getFormat() { + return 1; + } + + public int findGlyph(int glyphId) { + for (int i = 0; i < _glyphCount; i++) { + if (_glyphIds[i] == glyphId) { + return i; + } + } + return -1; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/CoverageFormat2.java b/src/net/java/dev/typecast/ot/table/CoverageFormat2.java new file mode 100644 index 000000000..a30489647 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CoverageFormat2.java @@ -0,0 +1,89 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: CoverageFormat2.java,v 1.2 2007-01-24 09:43:30 davidsch Exp $ + */ +public class CoverageFormat2 extends Coverage { + + private int _rangeCount; + private RangeRecord[] _rangeRecords; + + /** Creates new CoverageFormat2 */ + protected CoverageFormat2(DataInput di) throws IOException { + _rangeCount = di.readUnsignedShort(); + _rangeRecords = new RangeRecord[_rangeCount]; + for (int i = 0; i < _rangeCount; i++) { + _rangeRecords[i] = new RangeRecord(di); + } + } + + public int getFormat() { + return 2; + } + + public int findGlyph(int glyphId) { + for (int i = 0; i < _rangeCount; i++) { + int n = _rangeRecords[i].getCoverageIndex(glyphId); + if (n > -1) { + return n; + } + } + return -1; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/CvtTable.java b/src/net/java/dev/typecast/ot/table/CvtTable.java new file mode 100644 index 000000000..6035c6378 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/CvtTable.java @@ -0,0 +1,62 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: CvtTable.java,v 1.1.1.1 2004-12-05 23:14:36 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class CvtTable implements Table { + + private DirectoryEntry de; + private short[] values; + + protected CvtTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + int len = de.getLength() / 2; + values = new short[len]; + for (int i = 0; i < len; i++) { + values[i] = di.readShort(); + } + } + + public int getType() { + return cvt; + } + + public short[] getValues() { + return values; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'cvt ' Table - Control Value Table\n----------------------------------\n"); + sb.append("Size = ").append(0).append(" bytes, ").append(values.length).append(" entries\n"); + sb.append(" Values\n ------\n"); + for (int i = 0; i < values.length; i++) { + sb.append(" ").append(i).append(": ").append(values[i]).append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/Device.java b/src/net/java/dev/typecast/ot/table/Device.java new file mode 100644 index 000000000..75c302acd --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Device.java @@ -0,0 +1,50 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.RandomAccessFile; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Device.java,v 1.1.1.1 2004-12-05 23:14:37 davidsch Exp $ + */ +public class Device extends Object { + + private int startSize; + private int endSize; + private int deltaFormat; + private int[] deltaValues; + + /** Creates new Device */ + public Device(RandomAccessFile raf) throws IOException { + startSize = raf.readUnsignedShort(); + endSize = raf.readUnsignedShort(); + deltaFormat = raf.readUnsignedShort(); + int size = startSize - endSize; + switch (deltaFormat) { + case 1: + size = (size % 8 == 0) ? size / 8 : size / 8 + 1; + break; + case 2: + size = (size % 4 == 0) ? size / 4 : size / 4 + 1; + break; + case 3: + size = (size % 2 == 0) ? size / 2 : size / 2 + 1; + break; + } + deltaValues = new int[size]; + for (int i = 0; i < size; i++) { + deltaValues[i] = raf.readUnsignedShort(); + } + } + + +} diff --git a/src/net/java/dev/typecast/ot/table/DirectoryEntry.java b/src/net/java/dev/typecast/ot/table/DirectoryEntry.java new file mode 100644 index 000000000..c0f2f9bc1 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/DirectoryEntry.java @@ -0,0 +1,115 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: DirectoryEntry.java,v 1.2 2004-12-09 23:46:21 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class DirectoryEntry implements Cloneable { + + private int _tag; + private int _checksum; + private int _offset; + private int _length; + + protected DirectoryEntry(DataInput di) throws IOException { + _tag = di.readInt(); + _checksum = di.readInt(); + _offset = di.readInt(); + _length = di.readInt(); + } + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + + public int getChecksum() { + return _checksum; + } + + public int getLength() { + return _length; + } + + public int getOffset() { + return _offset; + } + + public int getTag() { + return _tag; + } + + public String getTagAsString() { + return new StringBuffer() + .append((char)((_tag>>24)&0xff)) + .append((char)((_tag>>16)&0xff)) + .append((char)((_tag>>8)&0xff)) + .append((char)((_tag)&0xff)) + .toString(); + } + + public String toString() { + return new StringBuffer() + .append("'").append(getTagAsString()) + .append("' - chksm = 0x").append(Integer.toHexString(_checksum)) + .append(", off = 0x").append(Integer.toHexString(_offset)) + .append(", len = ").append(_length) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/DsigEntry.java b/src/net/java/dev/typecast/ot/table/DsigEntry.java new file mode 100644 index 000000000..6ce41ec48 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/DsigEntry.java @@ -0,0 +1,43 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.DataInput; + +/** + * + * @version $Id: DsigEntry.java,v 1.1.1.1 2004-12-05 23:14:37 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class DsigEntry { + + private int format; + private int length; + private int offset; + + /** Creates new DsigEntry */ + protected DsigEntry(DataInput di) throws IOException { + format = di.readInt(); + length = di.readInt(); + offset = di.readInt(); + } + + public int getFormat() { + return format; + } + + public int getLength() { + return length; + } + + public int getOffset() { + return offset; + } +} diff --git a/src/net/java/dev/typecast/ot/table/DsigTable.java b/src/net/java/dev/typecast/ot/table/DsigTable.java new file mode 100644 index 000000000..8d63800d4 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/DsigTable.java @@ -0,0 +1,69 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.DataInput; + +/** + * + * @version $Id: DsigTable.java,v 1.1.1.1 2004-12-05 23:14:37 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class DsigTable implements Table { + + private DirectoryEntry de; + private int version; + private int numSigs; + private int flag; + private DsigEntry[] dsigEntry; + private SignatureBlock[] sigBlocks; + + /** Creates new DsigTable */ + protected DsigTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readInt(); + numSigs = di.readUnsignedShort(); + flag = di.readUnsignedShort(); + dsigEntry = new DsigEntry[numSigs]; + sigBlocks = new SignatureBlock[numSigs]; + for (int i = 0; i < numSigs; i++) { + dsigEntry[i] = new DsigEntry(di); + } + for (int i = 0; i < numSigs; i++) { + sigBlocks[i] = new SignatureBlock(di); + } + } + + /** + * Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return DSIG; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + + public String toString() { + StringBuffer sb = new StringBuffer().append("DSIG\n"); + for (int i = 0; i < numSigs; i++) { + sb.append(sigBlocks[i].toString()); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/Feature.java b/src/net/java/dev/typecast/ot/table/Feature.java new file mode 100644 index 000000000..34adf4662 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Feature.java @@ -0,0 +1,85 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Feature.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public class Feature { + + private int _featureParams; + private int _lookupCount; + private int[] _lookupListIndex; + + /** Creates new Feature */ + protected Feature(DataInput di) throws IOException { + _featureParams = di.readUnsignedShort(); + _lookupCount = di.readUnsignedShort(); + _lookupListIndex = new int[_lookupCount]; + for (int i = 0; i < _lookupCount; i++) { + _lookupListIndex[i] = di.readUnsignedShort(); + } + } + + public int getLookupCount() { + return _lookupCount; + } + + public int getLookupListIndex(int i) { + return _lookupListIndex[i]; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/FeatureList.java b/src/net/java/dev/typecast/ot/table/FeatureList.java new file mode 100644 index 000000000..8f17c461f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/FeatureList.java @@ -0,0 +1,118 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: FeatureList.java,v 1.3 2007-01-24 09:54:44 davidsch Exp $ + */ +public class FeatureList { + + private int _featureCount; + private FeatureRecord[] _featureRecords; + private Feature[] _features; + + /** Creates new FeatureList */ + public FeatureList(DataInputStream dis, int offset) throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _featureCount = dis.readUnsignedShort(); + _featureRecords = new FeatureRecord[_featureCount]; + _features = new Feature[_featureCount]; + for (int i = 0; i < _featureCount; i++) { + _featureRecords[i] = new FeatureRecord(dis); + } + for (int i = 0; i < _featureCount; i++) { + dis.reset(); + dis.skipBytes(offset + _featureRecords[i].getOffset()); + _features[i] = new Feature(dis); + } + } + + public int getFeatureCount() { + return _featureCount; + } + + public FeatureRecord getFeatureRecord(int i) { + return _featureRecords[i]; + } + + public Feature getFeature(int i) { + return _features[i]; + } + + public Feature findFeature(LangSys langSys, String tag) { + if (tag.length() != 4) { + return null; + } + int tagVal = ((tag.charAt(0)<<24) + | (tag.charAt(1)<<16) + | (tag.charAt(2)<<8) + | tag.charAt(3)); + for (int i = 0; i < _featureCount; i++) { + if (_featureRecords[i].getTag() == tagVal) { + if (langSys.isFeatureIndexed(i)) { + return _features[i]; + } + } + } + return null; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/FeatureRecord.java b/src/net/java/dev/typecast/ot/table/FeatureRecord.java new file mode 100644 index 000000000..7c2788892 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/FeatureRecord.java @@ -0,0 +1,88 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: FeatureRecord.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public class FeatureRecord { + + private int _tag; + private int _offset; + + /** Creates new FeatureRecord */ + protected FeatureRecord(DataInput di) throws IOException { + _tag = di.readInt(); + _offset = di.readUnsignedShort(); + } + + public int getTag() { + return _tag; + } + + public int getOffset() { + return _offset; + } + + public String getTagAsString() { + return new StringBuffer() + .append((char)((_tag>>24)&0xff)) + .append((char)((_tag>>16)&0xff)) + .append((char)((_tag>>8)&0xff)) + .append((char)((_tag)&0xff)) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/FeatureTags.java b/src/net/java/dev/typecast/ot/table/FeatureTags.java new file mode 100644 index 000000000..8d573d0c6 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/FeatureTags.java @@ -0,0 +1,63 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +/** + * Definition of Feature tags + * + * @version $Id: FeatureTags.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + * @author <a href="mailto:[email protected]">Vincent Hardy</a> + */ +public interface FeatureTags { + public static final String FEATURE_TAG_INIT = "init"; + public static final String FEATURE_TAG_MEDI = "medi"; + public static final String FEATURE_TAG_FINA = "fina"; +} diff --git a/src/net/java/dev/typecast/ot/table/FpgmTable.java b/src/net/java/dev/typecast/ot/table/FpgmTable.java new file mode 100644 index 000000000..37a2ae045 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/FpgmTable.java @@ -0,0 +1,46 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Disassembler; + +/** + * @version $Id: FpgmTable.java,v 1.1.1.1 2004-12-05 23:14:38 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class FpgmTable extends Program implements Table { + + private DirectoryEntry de; + + protected FpgmTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + readInstructions(di, de.getLength()); + } + + public int getType() { + return fpgm; + } + + public String toString() { + return Disassembler.disassemble(getInstructions(), 0); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/GaspRange.java b/src/net/java/dev/typecast/ot/table/GaspRange.java new file mode 100644 index 000000000..9f343e942 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GaspRange.java @@ -0,0 +1,45 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: GaspRange.java,v 1.1.1.1 2004-12-05 23:14:38 davidsch Exp $ + */ +public class GaspRange { + + public static final int GASP_GRIDFIT = 1; + public static final int GASP_DOGRAY = 2; + + private int rangeMaxPPEM; + private int rangeGaspBehavior; + + /** Creates new GaspRange */ + protected GaspRange(DataInput di) throws IOException { + rangeMaxPPEM = di.readUnsignedShort(); + rangeGaspBehavior = di.readUnsignedShort(); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(" rangeMaxPPEM: ").append(rangeMaxPPEM) + .append("\n rangeGaspBehavior: 0x").append(rangeGaspBehavior); + if ((rangeGaspBehavior & GASP_GRIDFIT) != 0) { + sb.append("- GASP_GRIDFIT "); + } + if ((rangeGaspBehavior & GASP_DOGRAY) != 0) { + sb.append("- GASP_DOGRAY"); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/GaspTable.java b/src/net/java/dev/typecast/ot/table/GaspTable.java new file mode 100644 index 000000000..50a1bcd93 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GaspTable.java @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: GaspTable.java,v 1.1.1.1 2004-12-05 23:14:39 davidsch Exp $ + */ +public class GaspTable implements Table { + + private DirectoryEntry de; + private int version; + private int numRanges; + private GaspRange[] gaspRange; + + /** Creates new GaspTable */ + protected GaspTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readUnsignedShort(); + numRanges = di.readUnsignedShort(); + gaspRange = new GaspRange[numRanges]; + for (int i = 0; i < numRanges; i++) { + gaspRange[i] = new GaspRange(di); + } + } + + public int getType() { + return gasp; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'gasp' Table - Grid-fitting And Scan-conversion Procedure\n---------------------------------------------------------"); + sb.append("\n 'gasp' version: ").append(version); + sb.append("\n numRanges: ").append(numRanges); + for (int i = 0; i < numRanges; i++) { + sb.append("\n\n gasp Range ").append(i).append("\n"); + sb.append(gaspRange[i].toString()); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfCompositeComp.java b/src/net/java/dev/typecast/ot/table/GlyfCompositeComp.java new file mode 100644 index 000000000..0a3f91a2a --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfCompositeComp.java @@ -0,0 +1,200 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: GlyfCompositeComp.java,v 1.3 2010-08-10 11:41:55 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class GlyfCompositeComp { + + public static final short ARG_1_AND_2_ARE_WORDS = 0x0001; + public static final short ARGS_ARE_XY_VALUES = 0x0002; + public static final short ROUND_XY_TO_GRID = 0x0004; + public static final short WE_HAVE_A_SCALE = 0x0008; + public static final short MORE_COMPONENTS = 0x0020; + public static final short WE_HAVE_AN_X_AND_Y_SCALE = 0x0040; + public static final short WE_HAVE_A_TWO_BY_TWO = 0x0080; + public static final short WE_HAVE_INSTRUCTIONS = 0x0100; + public static final short USE_MY_METRICS = 0x0200; + + private int _firstIndex; + private int _firstContour; + private short _argument1; + private short _argument2; + private int _flags; + private int _glyphIndex; + private double _xscale = 1.0; + private double _yscale = 1.0; + private double _scale01 = 0.0; + private double _scale10 = 0.0; + private int _xtranslate = 0; + private int _ytranslate = 0; + private int _point1 = 0; + private int _point2 = 0; + + protected GlyfCompositeComp(int firstIndex, int firstContour, DataInput di) + throws IOException { + _firstIndex = firstIndex; + _firstContour = firstContour; + _flags = di.readUnsignedShort(); + _glyphIndex = di.readUnsignedShort(); + + // Get the arguments as just their raw values + if ((_flags & ARG_1_AND_2_ARE_WORDS) != 0) { + _argument1 = di.readShort(); + _argument2 = di.readShort(); + } else { + _argument1 = (short) di.readByte(); + _argument2 = (short) di.readByte(); + } + + // Assign the arguments according to the flags + if ((_flags & ARGS_ARE_XY_VALUES) != 0) { + _xtranslate = _argument1; + _ytranslate = _argument2; + } else { + _point1 = _argument1; + _point2 = _argument2; + } + + // Get the scale values (if any) + if ((_flags & WE_HAVE_A_SCALE) != 0) { + int i = di.readShort(); + _xscale = _yscale = (double) i / (double) 0x4000; + } else if ((_flags & WE_HAVE_AN_X_AND_Y_SCALE) != 0) { + short i = di.readShort(); + _xscale = (double) i / (double) 0x4000; + i = di.readShort(); + _yscale = (double) i / (double) 0x4000; + } else if ((_flags & WE_HAVE_A_TWO_BY_TWO) != 0) { + int i = di.readShort(); + _xscale = (double) i / (double) 0x4000; + i = di.readShort(); + _scale01 = (double) i / (double) 0x4000; + i = di.readShort(); + _scale10 = (double) i / (double) 0x4000; + i = di.readShort(); + _yscale = (double) i / (double) 0x4000; + } + } + + public int getFirstIndex() { + return _firstIndex; + } + + public int getFirstContour() { + return _firstContour; + } + + public short getArgument1() { + return _argument1; + } + + public short getArgument2() { + return _argument2; + } + + public int getFlags() { + return _flags; + } + + public int getGlyphIndex() { + return _glyphIndex; + } + + public double getScale01() { + return _scale01; + } + + public double getScale10() { + return _scale10; + } + + public double getXScale() { + return _xscale; + } + + public double getYScale() { + return _yscale; + } + + public int getXTranslate() { + return _xtranslate; + } + + public int getYTranslate() { + return _ytranslate; + } + + /** + * Transforms an x-coordinate of a point for this component. + * @param x The x-coordinate of the point to transform + * @param y The y-coordinate of the point to transform + * @return The transformed x-coordinate + */ + public int scaleX(int x, int y) { + return (int)((double) x * _xscale + (double) y * _scale10); + } + + /** + * Transforms a y-coordinate of a point for this component. + * @param x The x-coordinate of the point to transform + * @param y The y-coordinate of the point to transform + * @return The transformed y-coordinate + */ + public int scaleY(int x, int y) { + return (int)((double) x * _scale01 + (double) y * _yscale); + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfCompositeDescript.java b/src/net/java/dev/typecast/ot/table/GlyfCompositeDescript.java new file mode 100644 index 000000000..97c0b0f79 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfCompositeDescript.java @@ -0,0 +1,202 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +import java.util.ArrayList; + +/** + * Glyph description for composite glyphs. Composite glyphs are made up of one + * or more simple glyphs, usually with some sort of transformation applied to + * each. + * + * @version $Id: GlyfCompositeDescript.java,v 1.5 2007-01-25 08:43:18 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class GlyfCompositeDescript extends GlyfDescript { + + private ArrayList<GlyfCompositeComp> _components = + new ArrayList<GlyfCompositeComp>(); + + public GlyfCompositeDescript( + GlyfTable parentTable, + int glyphIndex, + DataInput di) throws IOException { + super(parentTable, glyphIndex, (short) -1, di); + + // Get all of the composite components + GlyfCompositeComp comp; + int firstIndex = 0; + int firstContour = 0; + try { + do { + _components.add(comp = new GlyfCompositeComp(firstIndex, firstContour, di)); + GlyfDescript desc = parentTable.getDescription(comp.getGlyphIndex()); + if (desc != null) { + firstIndex += desc.getPointCount(); + firstContour += desc.getContourCount(); + } + } while ((comp.getFlags() & GlyfCompositeComp.MORE_COMPONENTS) != 0); + + // Are there hinting intructions to read? + if ((comp.getFlags() & GlyfCompositeComp.WE_HAVE_INSTRUCTIONS) != 0) { + readInstructions(di, di.readShort()); + } + } catch (IOException e) { + throw e; +// } catch (Exception e) { +// int foo = 0; + } + } + + public int getEndPtOfContours(int i) { + GlyfCompositeComp c = getCompositeCompEndPt(i); + if (c != null) { + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + return gd.getEndPtOfContours(i - c.getFirstContour()) + c.getFirstIndex(); + } + return 0; + } + + public byte getFlags(int i) { + GlyfCompositeComp c = getCompositeComp(i); + if (c != null) { + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + return gd.getFlags(i - c.getFirstIndex()); + } + return 0; + } + + public short getXCoordinate(int i) { + GlyfCompositeComp c = getCompositeComp(i); + if (c != null) { + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + int n = i - c.getFirstIndex(); + int x = gd.getXCoordinate(n); + int y = gd.getYCoordinate(n); + short x1 = (short) c.scaleX(x, y); + x1 += c.getXTranslate(); + return x1; + } + return 0; + } + + public short getYCoordinate(int i) { + GlyfCompositeComp c = getCompositeComp(i); + if (c != null) { + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + int n = i - c.getFirstIndex(); + int x = gd.getXCoordinate(n); + int y = gd.getYCoordinate(n); + short y1 = (short) c.scaleY(x, y); + y1 += c.getYTranslate(); + return y1; + } + return 0; + } + + public boolean isComposite() { + return true; + } + + public int getPointCount() { + GlyfCompositeComp c = _components.get(_components.size()-1); + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + if (gd != null) { + return c.getFirstIndex() + gd.getPointCount(); + } else { + return 0; + } + } + + public int getContourCount() { + GlyfCompositeComp c = _components.get(_components.size()-1); + return c.getFirstContour() + _parentTable.getDescription(c.getGlyphIndex()).getContourCount(); + } + + public int getComponentIndex(int i) { + return _components.get(i).getFirstIndex(); + } + + public int getComponentCount() { + return _components.size(); + } + + public GlyfCompositeComp getComponent(int i) { + return _components.get(i); + } + + protected GlyfCompositeComp getCompositeComp(int i) { + GlyfCompositeComp c; + for (int n = 0; n < _components.size(); n++) { + c = _components.get(n); + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + if (c.getFirstIndex() <= i && i < (c.getFirstIndex() + gd.getPointCount())) { + return c; + } + } + return null; + } + + protected GlyfCompositeComp getCompositeCompEndPt(int i) { + GlyfCompositeComp c; + for (int j = 0; j < _components.size(); j++) { + c = _components.get(j); + GlyphDescription gd = _parentTable.getDescription(c.getGlyphIndex()); + if (c.getFirstContour() <= i && i < (c.getFirstContour() + gd.getContourCount())) { + return c; + } + } + return null; + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfDescript.java b/src/net/java/dev/typecast/ot/table/GlyfDescript.java new file mode 100644 index 000000000..49ae5b494 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfDescript.java @@ -0,0 +1,124 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: GlyfDescript.java,v 1.3 2007-01-24 09:47:48 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public abstract class GlyfDescript extends Program implements GlyphDescription { + + // flags + public static final byte onCurve = 0x01; + public static final byte xShortVector = 0x02; + public static final byte yShortVector = 0x04; + public static final byte repeat = 0x08; + public static final byte xDual = 0x10; + public static final byte yDual = 0x20; + + protected GlyfTable _parentTable; + private int _glyphIndex; + private int _numberOfContours; + private short _xMin; + private short _yMin; + private short _xMax; + private short _yMax; + + protected GlyfDescript( + GlyfTable parentTable, + int glyphIndex, + short numberOfContours, + DataInput di) throws IOException { + _parentTable = parentTable; + _numberOfContours = numberOfContours; + _xMin = di.readShort(); + _yMin = di.readShort(); + _xMax = di.readShort(); + _yMax = di.readShort(); + } + + public int getNumberOfContours() { + return _numberOfContours; + } + + public int getGlyphIndex() { + return _glyphIndex; + } + + public short getXMaximum() { + return _xMax; + } + + public short getXMinimum() { + return _xMin; + } + + public short getYMaximum() { + return _yMax; + } + + public short getYMinimum() { + return _yMin; + } + + public String toString() { + return new StringBuffer() + .append(" numberOfContours: ").append(_numberOfContours) + .append("\n xMin: ").append(_xMin) + .append("\n yMin: ").append(_yMin) + .append("\n xMax: ").append(_xMax) + .append("\n yMax: ").append(_yMax) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfSimpleDescript.java b/src/net/java/dev/typecast/ot/table/GlyfSimpleDescript.java new file mode 100644 index 000000000..e2c3a2c84 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfSimpleDescript.java @@ -0,0 +1,245 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Disassembler; + +/** + * @version $Id: GlyfSimpleDescript.java,v 1.3 2007-01-24 09:47:47 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class GlyfSimpleDescript extends GlyfDescript { + + private int[] _endPtsOfContours; + private byte[] _flags; + private short[] _xCoordinates; + private short[] _yCoordinates; + private int _count; + + public GlyfSimpleDescript( + GlyfTable parentTable, + int glyphIndex, + short numberOfContours, + DataInput di) throws IOException { + super(parentTable, glyphIndex, numberOfContours, di); + + // Simple glyph description + _endPtsOfContours = new int[numberOfContours]; + for (int i = 0; i < numberOfContours; i++) { + _endPtsOfContours[i] = di.readShort(); + } + + // The last end point index reveals the total number of points + _count = _endPtsOfContours[numberOfContours-1] + 1; + _flags = new byte[_count]; + _xCoordinates = new short[_count]; + _yCoordinates = new short[_count]; + + int instructionCount = di.readShort(); + readInstructions(di, instructionCount); + readFlags(_count, di); + readCoords(_count, di); + } + + public int getEndPtOfContours(int i) { + return _endPtsOfContours[i]; + } + + public byte getFlags(int i) { + return _flags[i]; + } + + public short getXCoordinate(int i) { + return _xCoordinates[i]; + } + + public short getYCoordinate(int i) { + return _yCoordinates[i]; + } + + public boolean isComposite() { + return false; + } + + public int getPointCount() { + return _count; + } + + public int getContourCount() { + return getNumberOfContours(); + } + /* + public int getComponentIndex(int c) { + return 0; + } + + public int getComponentCount() { + return 1; + } + */ + /** + * The table is stored as relative values, but we'll store them as absolutes + */ + private void readCoords(int count, DataInput di) throws IOException { + short x = 0; + short y = 0; + for (int i = 0; i < count; i++) { + if ((_flags[i] & xDual) != 0) { + if ((_flags[i] & xShortVector) != 0) { + x += (short) di.readUnsignedByte(); + } + } else { + if ((_flags[i] & xShortVector) != 0) { + x += (short) -((short) di.readUnsignedByte()); + } else { + x += di.readShort(); + } + } + _xCoordinates[i] = x; + } + + for (int i = 0; i < count; i++) { + if ((_flags[i] & yDual) != 0) { + if ((_flags[i] & yShortVector) != 0) { + y += (short) di.readUnsignedByte(); + } + } else { + if ((_flags[i] & yShortVector) != 0) { + y += (short) -((short) di.readUnsignedByte()); + } else { + y += di.readShort(); + } + } + _yCoordinates[i] = y; + } + } + + /** + * The flags are run-length encoded + */ + private void readFlags(int flagCount, DataInput di) throws IOException { + try { + for (int index = 0; index < flagCount; index++) { + _flags[index] = di.readByte(); + if ((_flags[index] & repeat) != 0) { + int repeats = di.readByte(); + for (int i = 1; i <= repeats; i++) { + _flags[index + i] = _flags[index]; + } + index += repeats; + } + } + } catch (ArrayIndexOutOfBoundsException e) { + System.out.println("error: array index out of bounds"); + } + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(super.toString()); + sb.append("\n\n EndPoints\n ---------"); + for (int i = 0; i < _endPtsOfContours.length; i++) { + sb.append("\n ").append(i).append(": ").append(_endPtsOfContours[i]); + } + sb.append("\n\n Length of Instructions: "); + sb.append(getInstructions().length).append("\n"); + sb.append(Disassembler.disassemble(getInstructions(), 8)); + sb.append("\n Flags\n -----"); + for (int i = 0; i < _flags.length; i++) { + sb.append("\n ").append(i).append(": "); + if ((_flags[i] & 0x20) != 0) { + sb.append("YDual "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x10) != 0) { + sb.append("XDual "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x08) != 0) { + sb.append("Repeat "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x04) != 0) { + sb.append("Y-Short "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x02) != 0) { + sb.append("X-Short "); + } else { + sb.append(" "); + } + if ((_flags[i] & 0x01) != 0) { + sb.append("On"); + } else { + sb.append(" "); + } + } + sb.append("\n\n Coordinates\n -----------"); + short oldX = 0; + short oldY = 0; + for (int i = 0; i < _xCoordinates.length; i++) { + sb.append("\n ").append(i) + .append(": Rel (").append(_xCoordinates[i] - oldX) + .append(", ").append(_yCoordinates[i] - oldY) + .append(") -> Abs (").append(_xCoordinates[i]) + .append(", ").append(_yCoordinates[i]).append(")"); + oldX = _xCoordinates[i]; + oldY = _yCoordinates[i]; + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyfTable.java b/src/net/java/dev/typecast/ot/table/GlyfTable.java new file mode 100644 index 000000000..03f519db2 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyfTable.java @@ -0,0 +1,132 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; + +/** + * @version $Id: GlyfTable.java,v 1.6 2010-08-10 11:46:30 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class GlyfTable implements Table { + + private DirectoryEntry _de; + private GlyfDescript[] _descript; + + protected GlyfTable( + DirectoryEntry de, + DataInput di, + MaxpTable maxp, + LocaTable loca) throws IOException { + _de = (DirectoryEntry) de.clone(); + _descript = new GlyfDescript[maxp.getNumGlyphs()]; + + // Buffer the whole table so we can randomly access it + byte[] buf = new byte[de.getLength()]; + di.readFully(buf); + ByteArrayInputStream bais = new ByteArrayInputStream(buf); + + // Process all the simple glyphs + for (int i = 0; i < maxp.getNumGlyphs(); i++) { + int len = loca.getOffset(i + 1) - loca.getOffset(i); + if (len > 0) { + bais.reset(); + bais.skip(loca.getOffset(i)); + DataInputStream dis = new DataInputStream(bais); + short numberOfContours = dis.readShort(); + if (numberOfContours >= 0) { + _descript[i] = new GlyfSimpleDescript(this, i, numberOfContours, dis); + } + } else { + _descript[i] = null; + } + } + + // Now do all the composite glyphs + for (int i = 0; i < maxp.getNumGlyphs(); i++) { + int len = loca.getOffset(i + 1) - loca.getOffset(i); + if (len > 0) { + bais.reset(); + bais.skip(loca.getOffset(i)); + DataInputStream dis = new DataInputStream(bais); + short numberOfContours = dis.readShort(); + if (numberOfContours < 0) { + _descript[i] = new GlyfCompositeDescript(this, i, dis); + } + } + } + } + + public GlyfDescript getDescription(int i) { + if (i < _descript.length) { + return _descript[i]; + } else { + return null; + } + } + + public int getType() { + return glyf; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/GlyphDescription.java b/src/net/java/dev/typecast/ot/table/GlyphDescription.java new file mode 100644 index 000000000..b23f31364 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GlyphDescription.java @@ -0,0 +1,86 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +/** + * Specifies access to glyph description classes, simple and composite. + * @version $Id: GlyphDescription.java,v 1.3 2007-01-24 09:47:45 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public interface GlyphDescription { + + public int getGlyphIndex(); + + public int getEndPtOfContours(int i); + + public byte getFlags(int i); + + public short getXCoordinate(int i); + + public short getYCoordinate(int i); + + public short getXMaximum(); + + public short getXMinimum(); + + public short getYMaximum(); + + public short getYMinimum(); + + public boolean isComposite(); + + public int getPointCount(); + + public int getContourCount(); + + // public int getComponentIndex(int c); + // public int getComponentCount(); +} diff --git a/src/net/java/dev/typecast/ot/table/GposTable.java b/src/net/java/dev/typecast/ot/table/GposTable.java new file mode 100644 index 000000000..3efeeaa03 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GposTable.java @@ -0,0 +1,66 @@ +/* + * $Id: GposTable.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * TODO: To be implemented + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: GposTable.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class GposTable implements Table { + + private DirectoryEntry _de; + + protected GposTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + + // GPOS Header + int version = di.readInt(); + int scriptList = di.readInt(); + int featureList = di.readInt(); + int lookupList = di.readInt(); + } + + /** Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return GPOS; + } + + public String toString() { + return "GPOS"; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/GsubTable.java b/src/net/java/dev/typecast/ot/table/GsubTable.java new file mode 100644 index 000000000..d7f9c355f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/GsubTable.java @@ -0,0 +1,181 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.ByteArrayInputStream; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: GsubTable.java,v 1.3 2007-01-24 09:47:46 davidsch Exp $ + */ +public class GsubTable implements Table, LookupSubtableFactory { + + private DirectoryEntry _de; + private ScriptList _scriptList; + private FeatureList _featureList; + private LookupList _lookupList; + + protected GsubTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + + // Load into a temporary buffer, and create another input stream + byte[] buf = new byte[de.getLength()]; + di.readFully(buf); + DataInputStream dis = new DataInputStream(new ByteArrayInputStream(buf)); + + // GSUB Header + int version = dis.readInt(); + int scriptListOffset = dis.readUnsignedShort(); + int featureListOffset = dis.readUnsignedShort(); + int lookupListOffset = dis.readUnsignedShort(); + + // Script List + _scriptList = new ScriptList(dis, scriptListOffset); + + // Feature List + _featureList = new FeatureList(dis, featureListOffset); + + // Lookup List + _lookupList = new LookupList(dis, lookupListOffset, this); + } + + /** + * 1 - Single - Replace one glyph with one glyph + * 2 - Multiple - Replace one glyph with more than one glyph + * 3 - Alternate - Replace one glyph with one of many glyphs + * 4 - Ligature - Replace multiple glyphs with one glyph + * 5 - Context - Replace one or more glyphs in context + * 6 - Chaining - Context Replace one or more glyphs in chained context + */ + public LookupSubtable read( + int type, + DataInputStream dis, + int offset) throws IOException { + LookupSubtable s = null; + switch (type) { + case 1: + s = SingleSubst.read(dis, offset); + break; + case 2: +// s = MultipleSubst.read(dis, offset); + break; + case 3: +// s = AlternateSubst.read(dis, offset); + break; + case 4: + s = LigatureSubst.read(dis, offset); + break; + case 5: +// s = ContextSubst.read(dis, offset); + break; + case 6: +// s = ChainingSubst.read(dis, offset); + break; + } + return s; + } + + /** Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return GSUB; + } + + public ScriptList getScriptList() { + return _scriptList; + } + + public FeatureList getFeatureList() { + return _featureList; + } + + public LookupList getLookupList() { + return _lookupList; + } + + public String toString() { + return "GSUB"; + } + + public static String lookupTypeAsString(int type) { + switch (type) { + case 1: + return "Single"; + case 2: + return "Multiple"; + case 3: + return "Alternate"; + case 4: + return "Ligature"; + case 5: + return "Context"; + case 6: + return "Chaining"; + } + return "Unknown"; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/HdmxTable.java b/src/net/java/dev/typecast/ot/table/HdmxTable.java new file mode 100644 index 000000000..e47c0a316 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/HdmxTable.java @@ -0,0 +1,117 @@ +/* + * $Id: HdmxTable.java,v 1.2 2007-07-26 11:12:30 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * The Horizontal Device Metrics table for TrueType outlines. This stores + * integer advance widths scaled to specific pixel sizes. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: HdmxTable.java,v 1.2 2007-07-26 11:12:30 davidsch Exp $ + */ +public class HdmxTable implements Table { + + public class DeviceRecord { + + private short _pixelSize; + private short _maxWidth; + private short[] _widths; + + protected DeviceRecord(int numGlyphs, DataInput di) throws IOException { + _pixelSize = di.readByte(); + _maxWidth = di.readByte(); + _widths = new short[numGlyphs]; + for (int i = 0; i < numGlyphs; ++i) { + _widths[i] = di.readByte(); + } + } + + public short getPixelSize() { + return _pixelSize; + } + + public short getMaxWidth() { + return _maxWidth; + } + + public short[] getWidths() { + return _widths; + } + } + + private DirectoryEntry _de; + private int _version; + private short _numRecords; + private int _sizeDeviceRecords; + private DeviceRecord[] _records; + + /** Creates a new instance of HdmxTable */ + protected HdmxTable(DirectoryEntry de, DataInput di, MaxpTable maxp) + throws IOException { + _de = (DirectoryEntry) de.clone(); + _version = di.readUnsignedShort(); + _numRecords = di.readShort(); + _sizeDeviceRecords = di.readInt(); + _records = new DeviceRecord[_numRecords]; + + // Read the device records + for (int i = 0; i < _numRecords; ++i) { + _records[i] = new DeviceRecord(maxp.getNumGlyphs(), di); + } + } + + public int getType() { + return hdmx; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'hdmx' Table - Horizontal Device Metrics\n----------------------------------------\n"); + sb.append("Size = ").append(_de.getLength()).append(" bytes\n") + .append("\t'hdmx' version: ").append(_version).append("\n") + .append("\t# device records: ").append(_numRecords).append("\n") + .append("\tRecord length: ").append(_sizeDeviceRecords).append("\n"); + for (int i = 0; i < _numRecords; ++i) { + sb.append("\tDevRec ").append(i) + .append(": ppem = ").append(_records[i].getPixelSize()) + .append(", maxWid = ").append(_records[i].getMaxWidth()) + .append("\n"); + for (int j = 0; j < _records[i].getWidths().length; ++j) { + sb.append(" ").append(j).append(". ") + .append(_records[i].getWidths()[j]).append("\n"); + } + sb.append("\n\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/HeadTable.java b/src/net/java/dev/typecast/ot/table/HeadTable.java new file mode 100644 index 000000000..c99ae768d --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/HeadTable.java @@ -0,0 +1,205 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: HeadTable.java,v 1.2 2004-12-21 10:23:20 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class HeadTable implements Table { + + private DirectoryEntry _de; + private int _versionNumber; + private int _fontRevision; + private int _checkSumAdjustment; + private int _magicNumber; + private short _flags; + private short _unitsPerEm; + private long _created; + private long _modified; + private short _xMin; + private short _yMin; + private short _xMax; + private short _yMax; + private short _macStyle; + private short _lowestRecPPEM; + private short _fontDirectionHint; + private short _indexToLocFormat; + private short _glyphDataFormat; + + protected HeadTable(DirectoryEntry de, DataInput di) throws IOException { + this._de = (DirectoryEntry) de.clone(); + _versionNumber = di.readInt(); + _fontRevision = di.readInt(); + _checkSumAdjustment = di.readInt(); + _magicNumber = di.readInt(); + _flags = di.readShort(); + _unitsPerEm = di.readShort(); + _created = di.readLong(); + _modified = di.readLong(); + _xMin = di.readShort(); + _yMin = di.readShort(); + _xMax = di.readShort(); + _yMax = di.readShort(); + _macStyle = di.readShort(); + _lowestRecPPEM = di.readShort(); + _fontDirectionHint = di.readShort(); + _indexToLocFormat = di.readShort(); + _glyphDataFormat = di.readShort(); + } + + public int getCheckSumAdjustment() { + return _checkSumAdjustment; + } + + public long getCreated() { + return _created; + } + + public short getFlags() { + return _flags; + } + + public short getFontDirectionHint() { + return _fontDirectionHint; + } + + public int getFontRevision(){ + return _fontRevision; + } + + public short getGlyphDataFormat() { + return _glyphDataFormat; + } + + public short getIndexToLocFormat() { + return _indexToLocFormat; + } + + public short getLowestRecPPEM() { + return _lowestRecPPEM; + } + + public short getMacStyle() { + return _macStyle; + } + + public long getModified() { + return _modified; + } + + public int getType() { + return head; + } + + public short getUnitsPerEm() { + return _unitsPerEm; + } + + public int getVersionNumber() { + return _versionNumber; + } + + public short getXMax() { + return _xMax; + } + + public short getXMin() { + return _xMin; + } + + public short getYMax() { + return _yMax; + } + + public short getYMin() { + return _yMin; + } + + public String toString() { + return new StringBuffer() + .append("'head' Table - Font Header\n--------------------------") + .append("\n 'head' version: ").append(Fixed.floatValue(_versionNumber)) + .append("\n fontRevision: ").append(Fixed.roundedFloatValue(_fontRevision, 8)) + .append("\n checkSumAdjustment: 0x").append(Integer.toHexString(_checkSumAdjustment).toUpperCase()) + .append("\n magicNumber: 0x").append(Integer.toHexString(_magicNumber).toUpperCase()) + .append("\n flags: 0x").append(Integer.toHexString(_flags).toUpperCase()) + .append("\n unitsPerEm: ").append(_unitsPerEm) + .append("\n created: ").append(_created) + .append("\n modified: ").append(_modified) + .append("\n xMin: ").append(_xMin) + .append("\n yMin: ").append(_yMin) + .append("\n xMax: ").append(_xMax) + .append("\n yMax: ").append(_yMax) + .append("\n macStyle bits: ").append(Integer.toHexString(_macStyle).toUpperCase()) + .append("\n lowestRecPPEM: ").append(_lowestRecPPEM) + .append("\n fontDirectionHint: ").append(_fontDirectionHint) + .append("\n indexToLocFormat: ").append(_indexToLocFormat) + .append("\n glyphDataFormat: ").append(_glyphDataFormat) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/HheaTable.java b/src/net/java/dev/typecast/ot/table/HheaTable.java new file mode 100644 index 000000000..4b49f41be --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/HheaTable.java @@ -0,0 +1,135 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: HheaTable.java,v 1.2 2010-08-10 11:44:02 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class HheaTable implements Table { + + private DirectoryEntry de; + private int version; + private short ascender; + private short descender; + private short lineGap; + private short advanceWidthMax; + private short minLeftSideBearing; + private short minRightSideBearing; + private short xMaxExtent; + private short caretSlopeRise; + private short caretSlopeRun; + private short metricDataFormat; + private int numberOfHMetrics; + + protected HheaTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readInt(); + ascender = di.readShort(); + descender = di.readShort(); + lineGap = di.readShort(); + advanceWidthMax = di.readShort(); + minLeftSideBearing = di.readShort(); + minRightSideBearing = di.readShort(); + xMaxExtent = di.readShort(); + caretSlopeRise = di.readShort(); + caretSlopeRun = di.readShort(); + for (int i = 0; i < 5; i++) { + di.readShort(); + } + metricDataFormat = di.readShort(); + numberOfHMetrics = di.readUnsignedShort(); + } + + public short getAdvanceWidthMax() { + return advanceWidthMax; + } + + public short getAscender() { + return ascender; + } + + public short getCaretSlopeRise() { + return caretSlopeRise; + } + + public short getCaretSlopeRun() { + return caretSlopeRun; + } + + public short getDescender() { + return descender; + } + + public short getLineGap() { + return lineGap; + } + + public short getMetricDataFormat() { + return metricDataFormat; + } + + public short getMinLeftSideBearing() { + return minLeftSideBearing; + } + + public short getMinRightSideBearing() { + return minRightSideBearing; + } + + public int getNumberOfHMetrics() { + return numberOfHMetrics; + } + + public int getType() { + return hhea; + } + + public short getXMaxExtent() { + return xMaxExtent; + } + + public String toString() { + return new StringBuffer() + .append("'hhea' Table - Horizontal Header\n--------------------------------") + .append("\n 'hhea' version: ").append(Fixed.floatValue(version)) + .append("\n yAscender: ").append(ascender) + .append("\n yDescender: ").append(descender) + .append("\n yLineGap: ").append(lineGap) + .append("\n advanceWidthMax: ").append(advanceWidthMax) + .append("\n minLeftSideBearing: ").append(minLeftSideBearing) + .append("\n minRightSideBearing: ").append(minRightSideBearing) + .append("\n xMaxExtent: ").append(xMaxExtent) + .append("\n horizCaretSlopeNum: ").append(caretSlopeRise) + .append("\n horizCaretSlopeDenom: ").append(caretSlopeRun) + .append("\n reserved0: 0") + .append("\n reserved1: 0") + .append("\n reserved2: 0") + .append("\n reserved3: 0") + .append("\n reserved4: 0") + .append("\n metricDataFormat: ").append(metricDataFormat) + .append("\n numOf_LongHorMetrics: ").append(numberOfHMetrics) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/HmtxTable.java b/src/net/java/dev/typecast/ot/table/HmtxTable.java new file mode 100644 index 000000000..7b4cbae40 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/HmtxTable.java @@ -0,0 +1,141 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: HmtxTable.java,v 1.5 2007-07-26 11:11:48 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class HmtxTable implements Table { + + private DirectoryEntry _de; + private int[] _hMetrics = null; + private short[] _leftSideBearing = null; + + protected HmtxTable( + DirectoryEntry de, + DataInput di, + HheaTable hhea, + MaxpTable maxp) throws IOException { + _de = (DirectoryEntry) de.clone(); + _hMetrics = new int[hhea.getNumberOfHMetrics()]; + for (int i = 0; i < hhea.getNumberOfHMetrics(); ++i) { + _hMetrics[i] = + di.readUnsignedByte()<<24 + | di.readUnsignedByte()<<16 + | di.readUnsignedByte()<<8 + | di.readUnsignedByte(); + } + int lsbCount = maxp.getNumGlyphs() - hhea.getNumberOfHMetrics(); + _leftSideBearing = new short[lsbCount]; + for (int i = 0; i < lsbCount; ++i) { + _leftSideBearing[i] = di.readShort(); + } + } + + public int getAdvanceWidth(int i) { + if (_hMetrics == null) { + return 0; + } + if (i < _hMetrics.length) { + return _hMetrics[i] >> 16; + } else { + return _hMetrics[_hMetrics.length - 1] >> 16; + } + } + + public short getLeftSideBearing(int i) { + if (_hMetrics == null) { + return 0; + } + if (i < _hMetrics.length) { + return (short)(_hMetrics[i] & 0xffff); + } else { + return _leftSideBearing[i - _hMetrics.length]; + } + } + + public int getType() { + return hmtx; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'hmtx' Table - Horizontal Metrics\n---------------------------------\n"); + sb.append("Size = ").append(_de.getLength()).append(" bytes, ") + .append(_hMetrics.length).append(" entries\n"); + for (int i = 0; i < _hMetrics.length; i++) { + sb.append(" ").append(i) + .append(". advWid: ").append(getAdvanceWidth(i)) + .append(", LSdBear: ").append(getLeftSideBearing(i)) + .append("\n"); + } + for (int i = 0; i < _leftSideBearing.length; i++) { + sb.append(" LSdBear ").append(i + _hMetrics.length) + .append(": ").append(_leftSideBearing[i]) + .append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/ID.java b/src/net/java/dev/typecast/ot/table/ID.java new file mode 100644 index 000000000..5dc79d766 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ID.java @@ -0,0 +1,399 @@ +/* + * $Id: ID.java,v 1.1.1.1 2004-12-05 23:14:47 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ID.java,v 1.1.1.1 2004-12-05 23:14:47 davidsch Exp $ + */ +public abstract class ID { + + // Platform IDs + public static final short platformUnicode = 0; + public static final short platformMacintosh = 1; + public static final short platformISO = 2; + public static final short platformMicrosoft = 3; + + // Unicode Encoding IDs + public static final short encodingUnicode10Semantics = 0; + public static final short encodingUnicode11Semantics = 1; + public static final short encodingISO10646Semantics = 2; + public static final short encodingUnicode20Semantics = 3; + + // Microsoft Encoding IDs +// public static final short encodingUndefined = 0; +// public static final short encodingUGL = 1; + public static final short encodingSymbol = 0; + public static final short encodingUnicode = 1; + public static final short encodingShiftJIS = 2; + public static final short encodingPRC = 3; + public static final short encodingBig5 = 4; + public static final short encodingWansung = 5; + public static final short encodingJohab = 6; + public static final short encodingUCS4 = 10; + + // Macintosh Encoding IDs + public static final short encodingRoman = 0; + public static final short encodingJapanese = 1; + public static final short encodingChinese = 2; + public static final short encodingKorean = 3; + public static final short encodingArabic = 4; + public static final short encodingHebrew = 5; + public static final short encodingGreek = 6; + public static final short encodingRussian = 7; + public static final short encodingRSymbol = 8; + public static final short encodingDevanagari = 9; + public static final short encodingGurmukhi = 10; + public static final short encodingGujarati = 11; + public static final short encodingOriya = 12; + public static final short encodingBengali = 13; + public static final short encodingTamil = 14; + public static final short encodingTelugu = 15; + public static final short encodingKannada = 16; + public static final short encodingMalayalam = 17; + public static final short encodingSinhalese = 18; + public static final short encodingBurmese = 19; + public static final short encodingKhmer = 20; + public static final short encodingThai = 21; + public static final short encodingLaotian = 22; + public static final short encodingGeorgian = 23; + public static final short encodingArmenian = 24; + public static final short encodingMaldivian = 25; + public static final short encodingTibetan = 26; + public static final short encodingMongolian = 27; + public static final short encodingGeez = 28; + public static final short encodingSlavic = 29; + public static final short encodingVietnamese = 30; + public static final short encodingSindhi = 31; + public static final short encodingUninterp = 32; + + // ISO Encoding IDs + public static final short encodingASCII = 0; + public static final short encodingISO10646 = 1; + public static final short encodingISO8859_1 = 2; + + // Microsoft Language IDs + public static final short languageSQI = 0x041c; + public static final short languageEUQ = 0x042d; + public static final short languageBEL = 0x0423; + public static final short languageBGR = 0x0402; + public static final short languageCAT = 0x0403; + public static final short languageSHL = 0x041a; + public static final short languageCSY = 0x0405; + public static final short languageDAN = 0x0406; + public static final short languageNLD = 0x0413; + public static final short languageNLB = 0x0813; + public static final short languageENU = 0x0409; + public static final short languageENG = 0x0809; + public static final short languageENA = 0x0c09; + public static final short languageENC = 0x1009; + public static final short languageENZ = 0x1409; + public static final short languageENI = 0x1809; + public static final short languageETI = 0x0425; + public static final short languageFIN = 0x040b; + public static final short languageFRA = 0x040c; + public static final short languageFRB = 0x080c; + public static final short languageFRC = 0x0c0c; + public static final short languageFRS = 0x100c; + public static final short languageFRL = 0x140c; + public static final short languageDEU = 0x0407; + public static final short languageDES = 0x0807; + public static final short languageDEA = 0x0c07; + public static final short languageDEL = 0x1007; + public static final short languageDEC = 0x1407; + public static final short languageELL = 0x0408; + public static final short languageHUN = 0x040e; + public static final short languageISL = 0x040f; + public static final short languageITA = 0x0410; + public static final short languageITS = 0x0810; + public static final short languageLVI = 0x0426; + public static final short languageLTH = 0x0427; + public static final short languageNOR = 0x0414; + public static final short languageNON = 0x0814; + public static final short languagePLK = 0x0415; + public static final short languagePTB = 0x0416; + public static final short languagePTG = 0x0816; + public static final short languageROM = 0x0418; + public static final short languageRUS = 0x0419; + public static final short languageSKY = 0x041b; + public static final short languageSLV = 0x0424; + public static final short languageESP = 0x040a; + public static final short languageESM = 0x080a; + public static final short languageESN = 0x0c0a; + public static final short languageSVE = 0x041d; + public static final short languageTRK = 0x041f; + public static final short languageUKR = 0x0422; + + // Macintosh Language IDs + public static final short languageEnglish = 0; + public static final short languageFrench = 1; + public static final short languageGerman = 2; + public static final short languageItalian = 3; + public static final short languageDutch = 4; + public static final short languageSwedish = 5; + public static final short languageSpanish = 6; + public static final short languageDanish = 7; + public static final short languagePortuguese = 8; + public static final short languageNorwegian = 9; + public static final short languageHebrew = 10; + public static final short languageJapanese = 11; + public static final short languageArabic = 12; + public static final short languageFinnish = 13; + public static final short languageGreek = 14; + public static final short languageIcelandic = 15; + public static final short languageMaltese = 16; + public static final short languageTurkish = 17; + public static final short languageYugoslavian = 18; + public static final short languageChinese = 19; + public static final short languageUrdu = 20; + public static final short languageHindi = 21; + public static final short languageThai = 22; + + // Name IDs + public static final short nameCopyrightNotice = 0; + public static final short nameFontFamilyName = 1; + public static final short nameFontSubfamilyName = 2; + public static final short nameUniqueFontIdentifier = 3; + public static final short nameFullFontName = 4; + public static final short nameVersionString = 5; + public static final short namePostscriptName = 6; + public static final short nameTrademark = 7; + public static final short nameManufacturerName = 8; + public static final short nameDesigner = 9; + public static final short nameDescription = 10; + public static final short nameURLVendor = 11; + public static final short nameURLDesigner = 12; + public static final short nameLicenseDescription = 13; + public static final short nameLicenseInfoURL = 14; + public static final short namePreferredFamily = 16; + public static final short namePreferredSubfamily = 17; + public static final short nameCompatibleFull = 18; + public static final short nameSampleText = 19; + public static final short namePostScriptCIDFindfontName = 20; + + public static String getPlatformName(short platformId) { + switch (platformId) { + case platformUnicode: return "Unicode"; + case platformMacintosh: return "Macintosh"; + case platformISO: return "ISO"; + case platformMicrosoft: return "Microsoft"; + default: return "Custom"; + } + } + + public static String getEncodingName(short platformId, short encodingId) { + + if (platformId == platformUnicode) { + + // Unicode specific encodings + switch (encodingId) { + case encodingUnicode10Semantics: return "Unicode 1.0 semantics"; + case encodingUnicode11Semantics: return "Unicode 1.1 semantics"; + case encodingISO10646Semantics: return "ISO 10646:1993 semantics"; + case encodingUnicode20Semantics: return "Unicode 2.0 and onwards semantics"; + default: return ""; + } + + } else if (platformId == platformMacintosh) { + + // Macintosh specific encodings + switch (encodingId) { + case encodingRoman: return "Roman"; + case encodingJapanese: return "Japanese"; + case encodingChinese: return "Chinese"; + case encodingKorean: return "Korean"; + case encodingArabic: return "Arabi"; + case encodingHebrew: return "Hebrew"; + case encodingGreek: return "Greek"; + case encodingRussian: return "Russian"; + case encodingRSymbol: return "RSymbol"; + case encodingDevanagari: return "Devanagari"; + case encodingGurmukhi: return "Gurmukhi"; + case encodingGujarati: return "Gujarati"; + case encodingOriya: return "Oriya"; + case encodingBengali: return "Bengali"; + case encodingTamil: return "Tamil"; + case encodingTelugu: return "Telugu"; + case encodingKannada: return "Kannada"; + case encodingMalayalam: return "Malayalam"; + case encodingSinhalese: return "Sinhalese"; + case encodingBurmese: return "Burmese"; + case encodingKhmer: return "Khmer"; + case encodingThai: return "Thai"; + case encodingLaotian: return "Laotian"; + case encodingGeorgian: return "Georgian"; + case encodingArmenian: return "Armenian"; + case encodingMaldivian: return "Maldivian"; + case encodingTibetan: return "Tibetan"; + case encodingMongolian: return "Mongolian"; + case encodingGeez: return "Geez"; + case encodingSlavic: return "Slavic"; + case encodingVietnamese: return "Vietnamese"; + case encodingSindhi: return "Sindhi"; + case encodingUninterp: return "Uninterpreted"; + default: return ""; + } + + } else if (platformId == platformISO) { + + // ISO specific encodings + switch (encodingId) { + case encodingASCII: return "7-bit ASCII"; + case encodingISO10646: return "ISO 10646"; + case encodingISO8859_1: return "ISO 8859-1"; + default: return ""; + } + + } else if (platformId == platformMicrosoft) { + + // Windows specific encodings + switch (encodingId) { + case encodingSymbol: return "Symbol"; + case encodingUnicode: return "Unicode"; + case encodingShiftJIS: return "ShiftJIS"; + case encodingPRC: return "PRC"; + case encodingBig5: return "Big5"; + case encodingWansung: return "Wansung"; + case encodingJohab: return "Johab"; + case 7: return "Reserved"; + case 8: return "Reserved"; + case 9: return "Reserved"; + case encodingUCS4: return "UCS-4"; + default: return ""; + } + } + return ""; + } + + public static String getLanguageName(short platformId, short languageId) { + + if (platformId == platformMacintosh) { + switch (languageId) { + case languageEnglish: return "English"; + case languageFrench: return "French"; + case languageGerman: return "German"; + case languageItalian: return "Italian"; + case languageDutch: return "Dutch"; + case languageSwedish: return "Swedish"; + case languageSpanish: return "Spanish"; + case languageDanish: return "Danish"; + case languagePortuguese: return "Portuguese"; + case languageNorwegian: return "Norwegian"; + case languageHebrew: return "Hebrew"; + case languageJapanese: return "Japanese"; + case languageArabic: return "Arabic"; + case languageFinnish: return "Finnish"; + case languageGreek: return "Greek"; + case languageIcelandic: return "Icelandic"; + case languageMaltese: return "Maltese"; + case languageTurkish: return "Turkish"; + case languageYugoslavian: return "Yugoslavian"; + case languageChinese: return "Chinese"; + case languageUrdu: return "Urdu"; + case languageHindi: return "Hindi"; + case languageThai: return "Thai"; + default: return ""; + } + } else if (platformId == platformMicrosoft) { + switch (languageId) { + case languageSQI: return "Albanian (Albania)"; + case languageEUQ: return "Basque (Basque)"; + case languageBEL: return "Byelorussian (Byelorussia)"; + case languageBGR: return "Bulgarian (Bulgaria)"; + case languageCAT: return "Catalan (Catalan)"; + case languageSHL: return "Croatian (Croatian)"; + case languageCSY: return "Czech (Czech)"; + case languageDAN: return "Danish (Danish)"; + case languageNLD: return "Dutch (Dutch (Standard))"; + case languageNLB: return "Dutch (Belgian (Flemish))"; + case languageENU: return "English (American)"; + case languageENG: return "English (British)"; + case languageENA: return "English (Australian)"; + case languageENC: return "English (Canadian)"; + case languageENZ: return "English (New Zealand)"; + case languageENI: return "English (Ireland)"; + case languageETI: return "Estonian (Estonia)"; + case languageFIN: return "Finnish (Finnish)"; + case languageFRA: return "French (French (Standard))"; + case languageFRB: return "French (Belgian)"; + case languageFRC: return "French (Canadian)"; + case languageFRS: return "French (Swiss)"; + case languageFRL: return "French (Luxembourg)"; + case languageDEU: return "German (German (Standard))"; + case languageDES: return "German (Swiss)"; + case languageDEA: return "German (Austrian)"; + case languageDEL: return "German (Luxembourg)"; + case languageDEC: return "German (Liechtenstein)"; + case languageELL: return "Greek (Greek)"; + case languageHUN: return "Hungarian (Hungarian)"; + case languageISL: return "Icelandic (Icelandic)"; + case languageITA: return "Italian (Italian (Standard))"; + case languageITS: return "Italian (Swiss)"; + case languageLVI: return "Latvian (Latvia)"; + case languageLTH: return "Lithuanian (Lithuania)"; + case languageNOR: return "Norwegian (Norwegian (Bokmal))"; + case languageNON: return "Norwegian (Norwegian (Nynorsk))"; + case languagePLK: return "Polish (Polish)"; + case languagePTB: return "Portuguese (Portuguese (Brazilian))"; + case languagePTG: return "Portuguese (Portuguese (Standard))"; + case languageROM: return "Romanian (Romania)"; + case languageRUS: return "Russian (Russian)"; + case languageSKY: return "Slovak (Slovak)"; + case languageSLV: return "Slovenian (Slovenia)"; + case languageESP: return "Spanish (Spanish (Traditional Sort))"; + case languageESM: return "Spanish (Mexican)"; + case languageESN: return "Spanish (Spanish (Modern Sort))"; + case languageSVE: return "Swedish (Swedish)"; + case languageTRK: return "Turkish (Turkish)"; + case languageUKR: return "Ukrainian (Ukraine)"; + default: return ""; + } + } + return ""; + } + + public static String getNameName(short nameId) { + switch (nameId) { + case nameCopyrightNotice: return "Copyright notice"; + case nameFontFamilyName: return "Font Family name"; + case nameFontSubfamilyName: return "Font Subfamily name"; + case nameUniqueFontIdentifier: return "Unique font identifier"; + case nameFullFontName: return "Full font name"; + case nameVersionString: return "Version string"; + case namePostscriptName: return "Postscript name"; + case nameTrademark: return "Trademark"; + case nameManufacturerName: return "Manufacturer Name"; + case nameDesigner: return "Designer"; + case nameDescription: return "Description"; + case nameURLVendor: return "URL Vendor"; + case nameURLDesigner: return "URL Designer"; + case nameLicenseDescription: return "License Description"; + case nameLicenseInfoURL: return "License Info URL"; + case namePreferredFamily: return "Preferred Family"; + case namePreferredSubfamily: return "Preferred Subfamily"; + case nameCompatibleFull: return "Compatible Full"; + case nameSampleText: return "Sample text"; + case namePostScriptCIDFindfontName: return "PostScript CID findfont name"; + default: return ""; + } + } +} diff --git a/src/net/java/dev/typecast/ot/table/KernSubtable.java b/src/net/java/dev/typecast/ot/table/KernSubtable.java new file mode 100644 index 000000000..f55fa04fb --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KernSubtable.java @@ -0,0 +1,49 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: KernSubtable.java,v 1.1.1.1 2004-12-05 23:14:47 davidsch Exp $ + */ +public abstract class KernSubtable { + + /** Creates new KernSubtable */ + protected KernSubtable() { + } + + public abstract int getKerningPairCount(); + + public abstract KerningPair getKerningPair(int i); + + public static KernSubtable read(DataInput di) throws IOException { + KernSubtable table = null; + int version = di.readUnsignedShort(); + int length = di.readUnsignedShort(); + int coverage = di.readUnsignedShort(); + int format = coverage >> 8; + + switch (format) { + case 0: + table = new KernSubtableFormat0(di); + break; + case 2: + table = new KernSubtableFormat2(di); + break; + default: + break; + } + return table; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/KernSubtableFormat0.java b/src/net/java/dev/typecast/ot/table/KernSubtableFormat0.java new file mode 100644 index 000000000..e3b1c9cf9 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KernSubtableFormat0.java @@ -0,0 +1,47 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: KernSubtableFormat0.java,v 1.1.1.1 2004-12-05 23:14:48 davidsch Exp $ + */ +public class KernSubtableFormat0 extends KernSubtable { + + private int nPairs; + private int searchRange; + private int entrySelector; + private int rangeShift; + private KerningPair[] kerningPairs; + + /** Creates new KernSubtableFormat0 */ + protected KernSubtableFormat0(DataInput di) throws IOException { + nPairs = di.readUnsignedShort(); + searchRange = di.readUnsignedShort(); + entrySelector = di.readUnsignedShort(); + rangeShift = di.readUnsignedShort(); + kerningPairs = new KerningPair[nPairs]; + for (int i = 0; i < nPairs; i++) { + kerningPairs[i] = new KerningPair(di); + } + } + + public int getKerningPairCount() { + return nPairs; + } + + public KerningPair getKerningPair(int i) { + return kerningPairs[i]; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/KernSubtableFormat2.java b/src/net/java/dev/typecast/ot/table/KernSubtableFormat2.java new file mode 100644 index 000000000..5ff37c291 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KernSubtableFormat2.java @@ -0,0 +1,42 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: KernSubtableFormat2.java,v 1.1.1.1 2004-12-05 23:14:48 davidsch Exp $ + */ +public class KernSubtableFormat2 extends KernSubtable { + + private int rowWidth; + private int leftClassTable; + private int rightClassTable; + private int array; + + /** Creates new KernSubtableFormat2 */ + protected KernSubtableFormat2(DataInput di) throws IOException { + rowWidth = di.readUnsignedShort(); + leftClassTable = di.readUnsignedShort(); + rightClassTable = di.readUnsignedShort(); + array = di.readUnsignedShort(); + } + + public int getKerningPairCount() { + return 0; + } + + public KerningPair getKerningPair(int i) { + return null; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/KernTable.java b/src/net/java/dev/typecast/ot/table/KernTable.java new file mode 100644 index 000000000..81c4a998f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KernTable.java @@ -0,0 +1,62 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: KernTable.java,v 1.1.1.1 2004-12-05 23:14:48 davidsch Exp $ + */ +public class KernTable implements Table { + + private DirectoryEntry de; + private int version; + private int nTables; + private KernSubtable[] tables; + + /** Creates new KernTable */ + protected KernTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readUnsignedShort(); + nTables = di.readUnsignedShort(); + tables = new KernSubtable[nTables]; + for (int i = 0; i < nTables; i++) { + tables[i] = KernSubtable.read(di); + } + } + + public int getSubtableCount() { + return nTables; + } + + public KernSubtable getSubtable(int i) { + return tables[i]; + } + + /** Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return kern; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/KerningPair.java b/src/net/java/dev/typecast/ot/table/KerningPair.java new file mode 100644 index 000000000..de614235f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/KerningPair.java @@ -0,0 +1,44 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: KerningPair.java,v 1.1.1.1 2004-12-05 23:14:47 davidsch Exp $ + */ +public class KerningPair { + + private int left; + private int right; + private short value; + + /** Creates new KerningPair */ + protected KerningPair(DataInput di) throws IOException { + left = di.readUnsignedShort(); + right = di.readUnsignedShort(); + value = di.readShort(); + } + + public int getLeft() { + return left; + } + + public int getRight() { + return right; + } + + public short getValue() { + return value; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/LangSys.java b/src/net/java/dev/typecast/ot/table/LangSys.java new file mode 100644 index 000000000..9963bf6af --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LangSys.java @@ -0,0 +1,105 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: LangSys.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class LangSys { + + private int _lookupOrder; + private int _reqFeatureIndex; + private int _featureCount; + private int[] _featureIndex; + + /** Creates new LangSys */ + protected LangSys(DataInput di) throws IOException { + _lookupOrder = di.readUnsignedShort(); + _reqFeatureIndex = di.readUnsignedShort(); + _featureCount = di.readUnsignedShort(); + _featureIndex = new int[_featureCount]; + for (int i = 0; i < _featureCount; i++) { + _featureIndex[i] = di.readUnsignedShort(); + } + } + + public int getLookupOrder() { + return _lookupOrder; + } + + public int getReqFeatureIndex() { + return _reqFeatureIndex; + } + + public int getFeatureCount() { + return _featureCount; + } + + public int getFeatureIndex(int i) { + return _featureIndex[i]; + } + + protected boolean isFeatureIndexed(int n) { + for (int i = 0; i < _featureCount; i++) { + if (_featureIndex[i] == n) { + return true; + } + } + return false; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/LangSysRecord.java b/src/net/java/dev/typecast/ot/table/LangSysRecord.java new file mode 100644 index 000000000..a69c12a44 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LangSysRecord.java @@ -0,0 +1,88 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: LangSysRecord.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public class LangSysRecord { + + private int _tag; + private int _offset; + + /** Creates new LangSysRecord */ + public LangSysRecord(DataInput di) throws IOException { + _tag = di.readInt(); + _offset = di.readUnsignedShort(); + } + + public int getTag() { + return _tag; + } + + public int getOffset() { + return _offset; + } + + public String getTagAsString() { + return new StringBuffer() + .append((char)((_tag>>24)&0xff)) + .append((char)((_tag>>16)&0xff)) + .append((char)((_tag>>8)&0xff)) + .append((char)((_tag)&0xff)) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/Ligature.java b/src/net/java/dev/typecast/ot/table/Ligature.java new file mode 100644 index 000000000..36969ba7a --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Ligature.java @@ -0,0 +1,85 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Ligature.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public class Ligature { + + private int _ligGlyph; + private int _compCount; + private int[] _components; + + /** Creates new Ligature */ + public Ligature(DataInput di) throws IOException { + _ligGlyph = di.readUnsignedShort(); + _compCount = di.readUnsignedShort(); + _components = new int[_compCount - 1]; + for (int i = 0; i < _compCount - 1; i++) { + _components[i] = di.readUnsignedShort(); + } + } + + public int getGlyphCount() { + return _compCount; + } + + public int getGlyphId(int i) { + return (i == 0) ? _ligGlyph : _components[i-1]; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/LigatureSet.java b/src/net/java/dev/typecast/ot/table/LigatureSet.java new file mode 100644 index 000000000..fe6db0445 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LigatureSet.java @@ -0,0 +1,85 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: LigatureSet.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public class LigatureSet { + + private int _ligatureCount; + private int[] _ligatureOffsets; + private Ligature[] _ligatures; + + /** Creates new LigatureSet */ + public LigatureSet(DataInputStream dis, int offset) throws IOException { + dis.reset(); + dis.skipBytes(offset); + _ligatureCount = dis.readUnsignedShort(); + _ligatureOffsets = new int[_ligatureCount]; + _ligatures = new Ligature[_ligatureCount]; + for (int i = 0; i < _ligatureCount; i++) { + _ligatureOffsets[i] = dis.readUnsignedShort(); + } + for (int i = 0; i < _ligatureCount; i++) { + dis.reset(); + dis.skipBytes(offset + _ligatureOffsets[i]); + _ligatures[i] = new Ligature(dis); + } + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/LigatureSubst.java b/src/net/java/dev/typecast/ot/table/LigatureSubst.java new file mode 100644 index 000000000..73a8b9d36 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LigatureSubst.java @@ -0,0 +1,73 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: LigatureSubst.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public abstract class LigatureSubst extends LookupSubtable { + + public static LigatureSubst read(DataInputStream dis, int offset) throws IOException { + dis.reset(); + dis.skipBytes(offset); + int format = dis.readUnsignedShort(); + if (format == 1) { + return new LigatureSubstFormat1(dis, offset); + } + return null; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/LigatureSubstFormat1.java b/src/net/java/dev/typecast/ot/table/LigatureSubstFormat1.java new file mode 100644 index 000000000..b19b07111 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LigatureSubstFormat1.java @@ -0,0 +1,95 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: LigatureSubstFormat1.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class LigatureSubstFormat1 extends LigatureSubst { + + private int _coverageOffset; + private int _ligSetCount; + private int[] _ligatureSetOffsets; + private Coverage _coverage; + private LigatureSet[] _ligatureSets; + + /** Creates new LigatureSubstFormat1 */ + protected LigatureSubstFormat1( + DataInputStream dis, + int offset) throws IOException { + _coverageOffset = dis.readUnsignedShort(); + _ligSetCount = dis.readUnsignedShort(); + _ligatureSetOffsets = new int[_ligSetCount]; + _ligatureSets = new LigatureSet[_ligSetCount]; + for (int i = 0; i < _ligSetCount; i++) { + _ligatureSetOffsets[i] = dis.readUnsignedShort(); + } + dis.reset(); + dis.skipBytes(offset + _coverageOffset); + _coverage = Coverage.read(dis); + for (int i = 0; i < _ligSetCount; i++) { + _ligatureSets[i] = new LigatureSet(dis, offset + _ligatureSetOffsets[i]); + } + } + + public int getFormat() { + return 1; + } + + public String getTypeAsString() { + return "LigatureSubstFormat1"; + } +} diff --git a/src/net/java/dev/typecast/ot/table/LocaTable.java b/src/net/java/dev/typecast/ot/table/LocaTable.java new file mode 100644 index 000000000..5f62940df --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LocaTable.java @@ -0,0 +1,77 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: LocaTable.java,v 1.4 2010-08-10 11:45:43 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class LocaTable implements Table { + + private DirectoryEntry _de; + private int[] _offsets = null; + private short _factor = 0; + + protected LocaTable( + DirectoryEntry de, + DataInput di, + HeadTable head, + MaxpTable maxp) throws IOException { + _de = (DirectoryEntry) de.clone(); + _offsets = new int[maxp.getNumGlyphs() + 1]; + boolean shortEntries = head.getIndexToLocFormat() == 0; + if (shortEntries) { + _factor = 2; + for (int i = 0; i <= maxp.getNumGlyphs(); i++) { + _offsets[i] = di.readUnsignedShort(); + } + } else { + _factor = 1; + for (int i = 0; i <= maxp.getNumGlyphs(); i++) { + _offsets[i] = di.readInt(); + } + } + } + + public int getOffset(int i) { + if (_offsets == null) { + return 0; + } + return _offsets[i] * _factor; + } + + public int getType() { + return loca; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'loca' Table - Index To Location Table\n--------------------------------------\n") + .append("Size = ").append(_de.getLength()).append(" bytes, ") + .append(_offsets.length).append(" entries\n"); + for (int i = 0; i < _offsets.length; i++) { + sb.append(" Idx ").append(i) + .append(" -> glyfOff 0x").append(getOffset(i)).append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Lookup.java b/src/net/java/dev/typecast/ot/table/Lookup.java new file mode 100644 index 000000000..d6e46cd91 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Lookup.java @@ -0,0 +1,110 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Lookup.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class Lookup { + + // LookupFlag bit enumeration + public static final int IGNORE_BASE_GLYPHS = 0x0002; + public static final int IGNORE_BASE_LIGATURES = 0x0004; + public static final int IGNORE_BASE_MARKS = 0x0008; + public static final int MARK_ATTACHMENT_TYPE = 0xFF00; + + private int _type; + private int _flag; + private int _subTableCount; + private int[] _subTableOffsets; + private LookupSubtable[] _subTables; + + /** Creates new Lookup */ + public Lookup(LookupSubtableFactory factory, DataInputStream dis, int offset) + throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _type = dis.readUnsignedShort(); + _flag = dis.readUnsignedShort(); + _subTableCount = dis.readUnsignedShort(); + _subTableOffsets = new int[_subTableCount]; + _subTables = new LookupSubtable[_subTableCount]; + for (int i = 0; i < _subTableCount; i++) { + _subTableOffsets[i] = dis.readUnsignedShort(); + } + for (int i = 0; i < _subTableCount; i++) { + _subTables[i] = factory.read(_type, dis, offset + _subTableOffsets[i]); + } + } + + public int getType() { + return _type; + } + + public int getSubtableCount() { + return _subTableCount; + } + + public LookupSubtable getSubtable(int i) { + return _subTables[i]; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/LookupList.java b/src/net/java/dev/typecast/ot/table/LookupList.java new file mode 100644 index 000000000..9ac76aba5 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LookupList.java @@ -0,0 +1,108 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: LookupList.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class LookupList { + + private int _lookupCount; + private int[] _lookupOffsets; + private Lookup[] _lookups; + + /** Creates new LookupList */ + public LookupList(DataInputStream dis, int offset, LookupSubtableFactory factory) + throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _lookupCount = dis.readUnsignedShort(); + _lookupOffsets = new int[_lookupCount]; + _lookups = new Lookup[_lookupCount]; + for (int i = 0; i < _lookupCount; i++) { + _lookupOffsets[i] = dis.readUnsignedShort(); + } + for (int i = 0; i < _lookupCount; i++) { + _lookups[i] = new Lookup(factory, dis, offset + _lookupOffsets[i]); + } + } + + public int getLookupCount() { + return _lookupCount; + } + + public int getLookupOffset(int i) { + return _lookupOffsets[i]; + } + + public Lookup getLookup(int i) { + return _lookups[i]; + } + + public Lookup getLookup(Feature feature, int index) { + if (feature.getLookupCount() > index) { + int i = feature.getLookupListIndex(index); + return _lookups[i]; + } + return null; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/LookupSubtable.java b/src/net/java/dev/typecast/ot/table/LookupSubtable.java new file mode 100644 index 000000000..4d8dbb180 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LookupSubtable.java @@ -0,0 +1,60 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: LookupSubtable.java,v 1.2 2007-01-24 09:47:45 davidsch Exp $ + */ +public abstract class LookupSubtable { + public abstract String getTypeAsString(); +} diff --git a/src/net/java/dev/typecast/ot/table/LookupSubtableFactory.java b/src/net/java/dev/typecast/ot/table/LookupSubtableFactory.java new file mode 100644 index 000000000..2081e2ea6 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LookupSubtableFactory.java @@ -0,0 +1,64 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: LookupSubtableFactory.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public interface LookupSubtableFactory { + public LookupSubtable read(int type, DataInputStream dis, int offset) + throws IOException; +} diff --git a/src/net/java/dev/typecast/ot/table/LtshTable.java b/src/net/java/dev/typecast/ot/table/LtshTable.java new file mode 100644 index 000000000..12dca01f4 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/LtshTable.java @@ -0,0 +1,68 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @version $Id: LtshTable.java,v 1.1.1.1 2004-12-05 23:14:51 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class LtshTable implements Table { + + private DirectoryEntry de; + private int version; + private int numGlyphs; + private int[] yPels; + + /** Creates new LtshTable */ + protected LtshTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readUnsignedShort(); + numGlyphs = di.readUnsignedShort(); + yPels = new int[numGlyphs]; + for (int i = 0; i < numGlyphs; i++) { + yPels[i] = di.readUnsignedByte(); + } + } + + /** + * Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return LTSH; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'LTSH' Table - Linear Threshold Table\n-------------------------------------") + .append("\n 'LTSH' Version: ").append(version) + .append("\n Number of Glyphs: ").append(numGlyphs) + .append("\n\n Glyph # Threshold\n ------- ---------\n"); + for (int i = 0; i < numGlyphs; i++) { + sb.append(" ").append(i).append(". ").append(yPels[i]) + .append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/MaxpTable.java b/src/net/java/dev/typecast/ot/table/MaxpTable.java new file mode 100644 index 000000000..571d3ebfd --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/MaxpTable.java @@ -0,0 +1,162 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: MaxpTable.java,v 1.1.1.1 2004-12-05 23:14:52 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class MaxpTable implements Table { + + private DirectoryEntry de; + private int versionNumber; + private int numGlyphs; + private int maxPoints; + private int maxContours; + private int maxCompositePoints; + private int maxCompositeContours; + private int maxZones; + private int maxTwilightPoints; + private int maxStorage; + private int maxFunctionDefs; + private int maxInstructionDefs; + private int maxStackElements; + private int maxSizeOfInstructions; + private int maxComponentElements; + private int maxComponentDepth; + + protected MaxpTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + versionNumber = di.readInt(); + + // CFF fonts use version 0.5, TrueType fonts use version 1.0 + if (versionNumber == 0x00005000) { + numGlyphs = di.readUnsignedShort(); + } else if (versionNumber == 0x00010000) { + numGlyphs = di.readUnsignedShort(); + maxPoints = di.readUnsignedShort(); + maxContours = di.readUnsignedShort(); + maxCompositePoints = di.readUnsignedShort(); + maxCompositeContours = di.readUnsignedShort(); + maxZones = di.readUnsignedShort(); + maxTwilightPoints = di.readUnsignedShort(); + maxStorage = di.readUnsignedShort(); + maxFunctionDefs = di.readUnsignedShort(); + maxInstructionDefs = di.readUnsignedShort(); + maxStackElements = di.readUnsignedShort(); + maxSizeOfInstructions = di.readUnsignedShort(); + maxComponentElements = di.readUnsignedShort(); + maxComponentDepth = di.readUnsignedShort(); + } + } + + public int getVersionNumber() { + return versionNumber; + } + + public int getMaxComponentDepth() { + return maxComponentDepth; + } + + public int getMaxComponentElements() { + return maxComponentElements; + } + + public int getMaxCompositeContours() { + return maxCompositeContours; + } + + public int getMaxCompositePoints() { + return maxCompositePoints; + } + + public int getMaxContours() { + return maxContours; + } + + public int getMaxFunctionDefs() { + return maxFunctionDefs; + } + + public int getMaxInstructionDefs() { + return maxInstructionDefs; + } + + public int getMaxPoints() { + return maxPoints; + } + + public int getMaxSizeOfInstructions() { + return maxSizeOfInstructions; + } + + public int getMaxStackElements() { + return maxStackElements; + } + + public int getMaxStorage() { + return maxStorage; + } + + public int getMaxTwilightPoints() { + return maxTwilightPoints; + } + + public int getMaxZones() { + return maxZones; + } + + public int getNumGlyphs() { + return numGlyphs; + } + + public int getType() { + return maxp; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'maxp' Table - Maximum Profile\n------------------------------") + .append("\n 'maxp' version: ").append(Fixed.floatValue(versionNumber)) + .append("\n numGlyphs: ").append(numGlyphs); + if (versionNumber == 0x00010000) { + sb.append("\n maxPoints: ").append(maxPoints) + .append("\n maxContours: ").append(maxContours) + .append("\n maxCompositePoints: ").append(maxCompositePoints) + .append("\n maxCompositeContours: ").append(maxCompositeContours) + .append("\n maxZones: ").append(maxZones) + .append("\n maxTwilightPoints: ").append(maxTwilightPoints) + .append("\n maxStorage: ").append(maxStorage) + .append("\n maxFunctionDefs: ").append(maxFunctionDefs) + .append("\n maxInstructionDefs: ").append(maxInstructionDefs) + .append("\n maxStackElements: ").append(maxStackElements) + .append("\n maxSizeOfInstructions: ").append(maxSizeOfInstructions) + .append("\n maxComponentElements: ").append(maxComponentElements) + .append("\n maxComponentDepth: ").append(maxComponentDepth); + } else { + sb.append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/NameRecord.java b/src/net/java/dev/typecast/ot/table/NameRecord.java new file mode 100644 index 000000000..cdba03ef9 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/NameRecord.java @@ -0,0 +1,145 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * @version $Id: NameRecord.java,v 1.2 2004-12-09 23:47:23 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class NameRecord { + + private short _platformId; + private short _encodingId; + private short _languageId; + private short _nameId; + private short _stringLength; + private short _stringOffset; + private String _record; + + protected NameRecord(DataInput di) throws IOException { + _platformId = di.readShort(); + _encodingId = di.readShort(); + _languageId = di.readShort(); + _nameId = di.readShort(); + _stringLength = di.readShort(); + _stringOffset = di.readShort(); + } + + public short getEncodingId() { + return _encodingId; + } + + public short getLanguageId() { + return _languageId; + } + + public short getNameId() { + return _nameId; + } + + public short getPlatformId() { + return _platformId; + } + + public String getRecordString() { + return _record; + } + + protected void loadString(DataInput di) throws IOException { + StringBuffer sb = new StringBuffer(); + di.skipBytes(_stringOffset); + if (_platformId == ID.platformUnicode) { + + // Unicode (big-endian) + for (int i = 0; i < _stringLength/2; i++) { + sb.append(di.readChar()); + } + } else if (_platformId == ID.platformMacintosh) { + + // Macintosh encoding, ASCII + for (int i = 0; i < _stringLength; i++) { + sb.append((char) di.readByte()); + } + } else if (_platformId == ID.platformISO) { + + // ISO encoding, ASCII + for (int i = 0; i < _stringLength; i++) { + sb.append((char) di.readByte()); + } + } else if (_platformId == ID.platformMicrosoft) { + + // Microsoft encoding, Unicode + char c; + for (int i = 0; i < _stringLength/2; i++) { + c = di.readChar(); + sb.append(c); + } + } + _record = sb.toString(); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + + sb.append(" Platform ID: ").append(_platformId) + .append("\n Specific ID: ").append(_encodingId) + .append("\n Language ID: ").append(_languageId) + .append("\n Name ID: ").append(_nameId) + .append("\n Length: ").append(_stringLength) + .append("\n Offset: ").append(_stringOffset) + .append("\n\n").append(_record); + + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/NameTable.java b/src/net/java/dev/typecast/ot/table/NameTable.java new file mode 100644 index 000000000..05f823427 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/NameTable.java @@ -0,0 +1,131 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; + +/** + * The naming table allows multilingual strings to be associated with the + * OpenType font file. These strings can represent copyright notices, font + * names, family names, style names, and so on. + * @version $Id: NameTable.java,v 1.2 2004-12-09 23:47:23 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class NameTable implements Table { + + private DirectoryEntry _de; + private short _formatSelector; + private short _numberOfNameRecords; + private short _stringStorageOffset; + private NameRecord[] _records; + + protected NameTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + _formatSelector = di.readShort(); + _numberOfNameRecords = di.readShort(); + _stringStorageOffset = di.readShort(); + _records = new NameRecord[_numberOfNameRecords]; + + // Load the records, which contain the encoding information and string + // offsets + for (int i = 0; i < _numberOfNameRecords; i++) { + _records[i] = new NameRecord(di); + } + + // Load the string data into a buffer so the records can copy out the + // bits they are interested in + byte[] buffer = new byte[_de.getLength() - _stringStorageOffset]; + di.readFully(buffer); + + // Now let the records get their hands on them + for (int i = 0; i < _numberOfNameRecords; i++) { + _records[i].loadString( + new DataInputStream(new ByteArrayInputStream(buffer))); + } + } + + public short getNumberOfNameRecords() { + return _numberOfNameRecords; + } + + public NameRecord getRecord(int i) { + return _records[i]; + } + + public String getRecordString(short nameId) { + + // Search for the first instance of this name ID + for (int i = 0; i < _numberOfNameRecords; i++) { + if (_records[i].getNameId() == nameId) { + return _records[i].getRecordString(); + } + } + return ""; + } + + public int getType() { + return name; + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/Os2Table.java b/src/net/java/dev/typecast/ot/table/Os2Table.java new file mode 100644 index 000000000..bb3b60101 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Os2Table.java @@ -0,0 +1,358 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: Os2Table.java,v 1.2 2004-12-09 23:46:21 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class Os2Table implements Table { + + private DirectoryEntry _de; + private int _version; + private short _xAvgCharWidth; + private int _usWeightClass; + private int _usWidthClass; + private short _fsType; + private short _ySubscriptXSize; + private short _ySubscriptYSize; + private short _ySubscriptXOffset; + private short _ySubscriptYOffset; + private short _ySuperscriptXSize; + private short _ySuperscriptYSize; + private short _ySuperscriptXOffset; + private short _ySuperscriptYOffset; + private short _yStrikeoutSize; + private short _yStrikeoutPosition; + private short _sFamilyClass; + private Panose _panose; + private int _ulUnicodeRange1; + private int _ulUnicodeRange2; + private int _ulUnicodeRange3; + private int _ulUnicodeRange4; + private int _achVendorID; + private short _fsSelection; + private int _usFirstCharIndex; + private int _usLastCharIndex; + private short _sTypoAscender; + private short _sTypoDescender; + private short _sTypoLineGap; + private int _usWinAscent; + private int _usWinDescent; + private int _ulCodePageRange1; + private int _ulCodePageRange2; + private short _sxHeight; + private short _sCapHeight; + private int _usDefaultChar; + private int _usBreakChar; + private int _usMaxContext; + + protected Os2Table(DirectoryEntry de, DataInput di) throws IOException { + this._de = (DirectoryEntry) de.clone(); + _version = di.readUnsignedShort(); + _xAvgCharWidth = di.readShort(); + _usWeightClass = di.readUnsignedShort(); + _usWidthClass = di.readUnsignedShort(); + _fsType = di.readShort(); + _ySubscriptXSize = di.readShort(); + _ySubscriptYSize = di.readShort(); + _ySubscriptXOffset = di.readShort(); + _ySubscriptYOffset = di.readShort(); + _ySuperscriptXSize = di.readShort(); + _ySuperscriptYSize = di.readShort(); + _ySuperscriptXOffset = di.readShort(); + _ySuperscriptYOffset = di.readShort(); + _yStrikeoutSize = di.readShort(); + _yStrikeoutPosition = di.readShort(); + _sFamilyClass = di.readShort(); + byte[] buf = new byte[10]; + di.readFully(buf); + _panose = new Panose(buf); + _ulUnicodeRange1 = di.readInt(); + _ulUnicodeRange2 = di.readInt(); + _ulUnicodeRange3 = di.readInt(); + _ulUnicodeRange4 = di.readInt(); + _achVendorID = di.readInt(); + _fsSelection = di.readShort(); + _usFirstCharIndex = di.readUnsignedShort(); + _usLastCharIndex = di.readUnsignedShort(); + _sTypoAscender = di.readShort(); + _sTypoDescender = di.readShort(); + _sTypoLineGap = di.readShort(); + _usWinAscent = di.readUnsignedShort(); + _usWinDescent = di.readUnsignedShort(); + _ulCodePageRange1 = di.readInt(); + _ulCodePageRange2 = di.readInt(); + + // OpenType 1.3 + if (_version == 2) { + _sxHeight = di.readShort(); + _sCapHeight = di.readShort(); + _usDefaultChar = di.readUnsignedShort(); + _usBreakChar = di.readUnsignedShort(); + _usMaxContext = di.readUnsignedShort(); + } + } + + public int getVersion() { + return _version; + } + + public short getAvgCharWidth() { + return _xAvgCharWidth; + } + + public int getWeightClass() { + return _usWeightClass; + } + + public int getWidthClass() { + return _usWidthClass; + } + + public short getLicenseType() { + return _fsType; + } + + public short getSubscriptXSize() { + return _ySubscriptXSize; + } + + public short getSubscriptYSize() { + return _ySubscriptYSize; + } + + public short getSubscriptXOffset() { + return _ySubscriptXOffset; + } + + public short getSubscriptYOffset() { + return _ySubscriptYOffset; + } + + public short getSuperscriptXSize() { + return _ySuperscriptXSize; + } + + public short getSuperscriptYSize() { + return _ySuperscriptYSize; + } + + public short getSuperscriptXOffset() { + return _ySuperscriptXOffset; + } + + public short getSuperscriptYOffset() { + return _ySuperscriptYOffset; + } + + public short getStrikeoutSize() { + return _yStrikeoutSize; + } + + public short getStrikeoutPosition() { + return _yStrikeoutPosition; + } + + public short getFamilyClass() { + return _sFamilyClass; + } + + public Panose getPanose() { + return _panose; + } + + public int getUnicodeRange1() { + return _ulUnicodeRange1; + } + + public int getUnicodeRange2() { + return _ulUnicodeRange2; + } + + public int getUnicodeRange3() { + return _ulUnicodeRange3; + } + + public int getUnicodeRange4() { + return _ulUnicodeRange4; + } + + public int getVendorID() { + return _achVendorID; + } + + public short getSelection() { + return _fsSelection; + } + + public int getFirstCharIndex() { + return _usFirstCharIndex; + } + + public int getLastCharIndex() { + return _usLastCharIndex; + } + + public short getTypoAscender() { + return _sTypoAscender; + } + + public short getTypoDescender() { + return _sTypoDescender; + } + + public short getTypoLineGap() { + return _sTypoLineGap; + } + + public int getWinAscent() { + return _usWinAscent; + } + + public int getWinDescent() { + return _usWinDescent; + } + + public int getCodePageRange1() { + return _ulCodePageRange1; + } + + public int getCodePageRange2() { + return _ulCodePageRange2; + } + + public short getXHeight() { + return _sxHeight; + } + + public short getCapHeight() { + return _sCapHeight; + } + + public int getDefaultChar() { + return _usDefaultChar; + } + + public int getBreakChar() { + return _usBreakChar; + } + + public int getMaxContext() { + return _usMaxContext; + } + + public int getType() { + return OS_2; + } + + public String toString() { + return new StringBuffer() + .append("'OS/2' Table - OS/2 and Windows Metrics\n---------------------------------------") + .append("\n 'OS/2' version: ").append(_version) + .append("\n xAvgCharWidth: ").append(_xAvgCharWidth) + .append("\n usWeightClass: ").append(_usWeightClass) + .append("\n usWidthClass: ").append(_usWidthClass) + .append("\n fsType: 0x").append(Integer.toHexString(_fsType).toUpperCase()) + .append("\n ySubscriptXSize: ").append(_ySubscriptXSize) + .append("\n ySubscriptYSize: ").append(_ySubscriptYSize) + .append("\n ySubscriptXOffset: ").append(_ySubscriptXOffset) + .append("\n ySubscriptYOffset: ").append(_ySubscriptYOffset) + .append("\n ySuperscriptXSize: ").append(_ySuperscriptXSize) + .append("\n ySuperscriptYSize: ").append(_ySuperscriptYSize) + .append("\n ySuperscriptXOffset: ").append(_ySuperscriptXOffset) + .append("\n ySuperscriptYOffset: ").append(_ySuperscriptYOffset) + .append("\n yStrikeoutSize: ").append(_yStrikeoutSize) + .append("\n yStrikeoutPosition: ").append(_yStrikeoutPosition) + .append("\n sFamilyClass: ").append(_sFamilyClass>>8) + .append(" subclass = ").append(_sFamilyClass&0xff) + .append("\n PANOSE: ").append(_panose.toString()) + .append("\n Unicode Range 1( Bits 0 - 31 ): ").append(Integer.toHexString(_ulUnicodeRange1).toUpperCase()) + .append("\n Unicode Range 2( Bits 32- 63 ): ").append(Integer.toHexString(_ulUnicodeRange2).toUpperCase()) + .append("\n Unicode Range 3( Bits 64- 95 ): ").append(Integer.toHexString(_ulUnicodeRange3).toUpperCase()) + .append("\n Unicode Range 4( Bits 96-127 ): ").append(Integer.toHexString(_ulUnicodeRange4).toUpperCase()) + .append("\n achVendID: '").append(getVendorIDAsString()) + .append("'\n fsSelection: 0x").append(Integer.toHexString(_fsSelection).toUpperCase()) + .append("\n usFirstCharIndex: 0x").append(Integer.toHexString(_usFirstCharIndex).toUpperCase()) + .append("\n usLastCharIndex: 0x").append(Integer.toHexString(_usLastCharIndex).toUpperCase()) + .append("\n sTypoAscender: ").append(_sTypoAscender) + .append("\n sTypoDescender: ").append(_sTypoDescender) + .append("\n sTypoLineGap: ").append(_sTypoLineGap) + .append("\n usWinAscent: ").append(_usWinAscent) + .append("\n usWinDescent: ").append(_usWinDescent) + .append("\n CodePage Range 1( Bits 0 - 31 ): ").append(Integer.toHexString(_ulCodePageRange1).toUpperCase()) + .append("\n CodePage Range 2( Bits 32- 63 ): ").append(Integer.toHexString(_ulCodePageRange2).toUpperCase()) + .toString(); + } + + private String getVendorIDAsString() { + return new StringBuffer() + .append((char)((_achVendorID>>24)&0xff)) + .append((char)((_achVendorID>>16)&0xff)) + .append((char)((_achVendorID>>8)&0xff)) + .append((char)((_achVendorID)&0xff)) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Panose.java b/src/net/java/dev/typecast/ot/table/Panose.java new file mode 100644 index 000000000..fe0a357d2 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Panose.java @@ -0,0 +1,96 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +/** + * @version $Id: Panose.java,v 1.1.1.1 2004-12-05 23:14:54 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class Panose { + + byte bFamilyType = 0; + byte bSerifStyle = 0; + byte bWeight = 0; + byte bProportion = 0; + byte bContrast = 0; + byte bStrokeVariation = 0; + byte bArmStyle = 0; + byte bLetterform = 0; + byte bMidline = 0; + byte bXHeight = 0; + + /** Creates new Panose */ + public Panose(byte[] panose) { + bFamilyType = panose[0]; + bSerifStyle = panose[1]; + bWeight = panose[2]; + bProportion = panose[3]; + bContrast = panose[4]; + bStrokeVariation = panose[5]; + bArmStyle = panose[6]; + bLetterform = panose[7]; + bMidline = panose[8]; + bXHeight = panose[9]; + } + + public byte getFamilyType() { + return bFamilyType; + } + + public byte getSerifStyle() { + return bSerifStyle; + } + + public byte getWeight() { + return bWeight; + } + + public byte getProportion() { + return bProportion; + } + + public byte getContrast() { + return bContrast; + } + + public byte getStrokeVariation() { + return bStrokeVariation; + } + + public byte getArmStyle() { + return bArmStyle; + } + + public byte getLetterForm() { + return bLetterform; + } + + public byte getMidline() { + return bMidline; + } + + public byte getXHeight() { + return bXHeight; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append(String.valueOf(bFamilyType)).append(" ") + .append(String.valueOf(bSerifStyle)).append(" ") + .append(String.valueOf(bWeight)).append(" ") + .append(String.valueOf(bProportion)).append(" ") + .append(String.valueOf(bContrast)).append(" ") + .append(String.valueOf(bStrokeVariation)).append(" ") + .append(String.valueOf(bArmStyle)).append(" ") + .append(String.valueOf(bLetterform)).append(" ") + .append(String.valueOf(bMidline)).append(" ") + .append(String.valueOf(bXHeight)); + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/PcltTable.java b/src/net/java/dev/typecast/ot/table/PcltTable.java new file mode 100644 index 000000000..457aec2e1 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/PcltTable.java @@ -0,0 +1,105 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @version $Id: PcltTable.java,v 1.1.1.1 2004-12-05 23:14:54 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class PcltTable implements Table { + + private DirectoryEntry de; + private int version; + private long fontNumber; + private int pitch; + private int xHeight; + private int style; + private int typeFamily; + private int capHeight; + private int symbolSet; + private char[] typeface = new char[16]; + private short[] characterComplement = new short[8]; + private char[] fileName = new char[6]; + private short strokeWeight; + private short widthType; + private byte serifStyle; + private byte reserved; + + /** Creates new PcltTable */ + protected PcltTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readInt(); + fontNumber = di.readInt(); + pitch = di.readUnsignedShort(); + xHeight = di.readUnsignedShort(); + style = di.readUnsignedShort(); + typeFamily = di.readUnsignedShort(); + capHeight = di.readUnsignedShort(); + symbolSet = di.readUnsignedShort(); + for (int i = 0; i < 16; i++) { + typeface[i] = (char) di.readUnsignedByte(); + } + for (int i = 0; i < 8; i++) { + characterComplement[i] = (short) di.readUnsignedByte(); + } + for (int i = 0; i < 6; i++) { + fileName[i] = (char) di.readUnsignedByte(); + } + strokeWeight = (short) di.readUnsignedByte(); + widthType = (short) di.readUnsignedByte(); + serifStyle = di.readByte(); + reserved = di.readByte(); + } + + /** + * Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return PCLT; + } + + public String toString() { + return new StringBuffer() + .append("'PCLT' Table - Printer Command Language Table\n---------------------------------------------") + .append("\n version: 0x").append(Integer.toHexString(version).toUpperCase()) + .append("\n fontNumber: ").append(fontNumber).append(" (0x").append(Long.toHexString(fontNumber).toUpperCase()) + .append(")\n pitch: ").append(pitch) + .append("\n xHeight: ").append(xHeight) + .append("\n style: 0x").append(style) + .append("\n typeFamily: 0x").append(typeFamily>>12) + .append(" ").append(typeFamily & 0xfff) + .append("\n capHeight: ").append(capHeight) + .append("\n symbolSet: ").append(symbolSet) + .append("\n typeFace: ").append(new String(typeface)) + .append("\n characterComplement 0x") + .append(Integer.toHexString(characterComplement[0]).toUpperCase()) + .append("\n fileName: ").append(new String(fileName)) + .append("\n strokeWeight: ").append(strokeWeight) + .append("\n widthType: ").append(widthType) + .append("\n serifStyle: ").append(serifStyle) + .append("\n reserved: ").append(reserved) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/PostTable.java b/src/net/java/dev/typecast/ot/table/PostTable.java new file mode 100644 index 000000000..4a1b0650b --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/PostTable.java @@ -0,0 +1,422 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: PostTable.java,v 1.1.1.1 2004-12-05 23:14:56 davidsch Exp $ + */ +public class PostTable implements Table { + + /** + * TODO: Mac Glyph names for 210 & 257 + */ + private static final String[] macGlyphName = { + ".notdef", // 0 + "null", // 1 + "CR", // 2 + "space", // 3 + "exclam", // 4 + "quotedbl", // 5 + "numbersign", // 6 + "dollar", // 7 + "percent", // 8 + "ampersand", // 9 + "quotesingle", // 10 + "parenleft", // 11 + "parenright", // 12 + "asterisk", // 13 + "plus", // 14 + "comma", // 15 + "hyphen", // 16 + "period", // 17 + "slash", // 18 + "zero", // 19 + "one", // 20 + "two", // 21 + "three", // 22 + "four", // 23 + "five", // 24 + "six", // 25 + "seven", // 26 + "eight", // 27 + "nine", // 28 + "colon", // 29 + "semicolon", // 30 + "less", // 31 + "equal", // 32 + "greater", // 33 + "question", // 34 + "at", // 35 + "A", // 36 + "B", // 37 + "C", // 38 + "D", // 39 + "E", // 40 + "F", // 41 + "G", // 42 + "H", // 43 + "I", // 44 + "J", // 45 + "K", // 46 + "L", // 47 + "M", // 48 + "N", // 49 + "O", // 50 + "P", // 51 + "Q", // 52 + "R", // 53 + "S", // 54 + "T", // 55 + "U", // 56 + "V", // 57 + "W", // 58 + "X", // 59 + "Y", // 60 + "Z", // 61 + "bracketleft", // 62 + "backslash", // 63 + "bracketright", // 64 + "asciicircum", // 65 + "underscore", // 66 + "grave", // 67 + "a", // 68 + "b", // 69 + "c", // 70 + "d", // 71 + "e", // 72 + "f", // 73 + "g", // 74 + "h", // 75 + "i", // 76 + "j", // 77 + "k", // 78 + "l", // 79 + "m", // 80 + "n", // 81 + "o", // 82 + "p", // 83 + "q", // 84 + "r", // 85 + "s", // 86 + "t", // 87 + "u", // 88 + "v", // 89 + "w", // 90 + "x", // 91 + "y", // 92 + "z", // 93 + "braceleft", // 94 + "bar", // 95 + "braceright", // 96 + "asciitilde", // 97 + "Adieresis", // 98 + "Aring", // 99 + "Ccedilla", // 100 + "Eacute", // 101 + "Ntilde", // 102 + "Odieresis", // 103 + "Udieresis", // 104 + "aacute", // 105 + "agrave", // 106 + "acircumflex", // 107 + "adieresis", // 108 + "atilde", // 109 + "aring", // 110 + "ccedilla", // 111 + "eacute", // 112 + "egrave", // 113 + "ecircumflex", // 114 + "edieresis", // 115 + "iacute", // 116 + "igrave", // 117 + "icircumflex", // 118 + "idieresis", // 119 + "ntilde", // 120 + "oacute", // 121 + "ograve", // 122 + "ocircumflex", // 123 + "odieresis", // 124 + "otilde", // 125 + "uacute", // 126 + "ugrave", // 127 + "ucircumflex", // 128 + "udieresis", // 129 + "dagger", // 130 + "degree", // 131 + "cent", // 132 + "sterling", // 133 + "section", // 134 + "bullet", // 135 + "paragraph", // 136 + "germandbls", // 137 + "registered", // 138 + "copyright", // 139 + "trademark", // 140 + "acute", // 141 + "dieresis", // 142 + "notequal", // 143 + "AE", // 144 + "Oslash", // 145 + "infinity", // 146 + "plusminus", // 147 + "lessequal", // 148 + "greaterequal", // 149 + "yen", // 150 + "mu", // 151 + "partialdiff", // 152 + "summation", // 153 + "product", // 154 + "pi", // 155 + "integral'", // 156 + "ordfeminine", // 157 + "ordmasculine", // 158 + "Omega", // 159 + "ae", // 160 + "oslash", // 161 + "questiondown", // 162 + "exclamdown", // 163 + "logicalnot", // 164 + "radical", // 165 + "florin", // 166 + "approxequal", // 167 + "increment", // 168 + "guillemotleft",// 169 + "guillemotright",//170 + "ellipsis", // 171 + "nbspace", // 172 + "Agrave", // 173 + "Atilde", // 174 + "Otilde", // 175 + "OE", // 176 + "oe", // 177 + "endash", // 178 + "emdash", // 179 + "quotedblleft", // 180 + "quotedblright",// 181 + "quoteleft", // 182 + "quoteright", // 183 + "divide", // 184 + "lozenge", // 185 + "ydieresis", // 186 + "Ydieresis", // 187 + "fraction", // 188 + "currency", // 189 + "guilsinglleft",// 190 + "guilsinglright",//191 + "fi", // 192 + "fl", // 193 + "daggerdbl", // 194 + "middot", // 195 + "quotesinglbase",//196 + "quotedblbase", // 197 + "perthousand", // 198 + "Acircumflex", // 199 + "Ecircumflex", // 200 + "Aacute", // 201 + "Edieresis", // 202 + "Egrave", // 203 + "Iacute", // 204 + "Icircumflex", // 205 + "Idieresis", // 206 + "Igrave", // 207 + "Oacute", // 208 + "Ocircumflex", // 209 + "", // 210 + "Ograve", // 211 + "Uacute", // 212 + "Ucircumflex", // 213 + "Ugrave", // 214 + "dotlessi", // 215 + "circumflex", // 216 + "tilde", // 217 + "overscore", // 218 + "breve", // 219 + "dotaccent", // 220 + "ring", // 221 + "cedilla", // 222 + "hungarumlaut", // 223 + "ogonek", // 224 + "caron", // 225 + "Lslash", // 226 + "lslash", // 227 + "Scaron", // 228 + "scaron", // 229 + "Zcaron", // 230 + "zcaron", // 231 + "brokenbar", // 232 + "Eth", // 233 + "eth", // 234 + "Yacute", // 235 + "yacute", // 236 + "Thorn", // 237 + "thorn", // 238 + "minus", // 239 + "multiply", // 240 + "onesuperior", // 241 + "twosuperior", // 242 + "threesuperior",// 243 + "onehalf", // 244 + "onequarter", // 245 + "threequarters",// 246 + "franc", // 247 + "Gbreve", // 248 + "gbreve", // 249 + "Idot", // 250 + "Scedilla", // 251 + "scedilla", // 252 + "Cacute", // 253 + "cacute", // 254 + "Ccaron", // 255 + "ccaron", // 256 + "" // 257 + }; + + private DirectoryEntry de; + private int version; + private int italicAngle; + private short underlinePosition; + private short underlineThickness; + private int isFixedPitch; + private int minMemType42; + private int maxMemType42; + private int minMemType1; + private int maxMemType1; + + // v2 + private int numGlyphs; + private int[] glyphNameIndex; + private String[] psGlyphName; + + /** Creates new PostTable */ + protected PostTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + version = di.readInt(); + italicAngle = di.readInt(); + underlinePosition = di.readShort(); + underlineThickness = di.readShort(); + isFixedPitch = di.readInt(); + minMemType42 = di.readInt(); + maxMemType42 = di.readInt(); + minMemType1 = di.readInt(); + maxMemType1 = di.readInt(); + + if (version == 0x00020000) { + numGlyphs = di.readUnsignedShort(); + glyphNameIndex = new int[numGlyphs]; + for (int i = 0; i < numGlyphs; i++) { + glyphNameIndex[i] = di.readUnsignedShort(); + } + int h = highestGlyphNameIndex(); + if (h > 257) { + h -= 257; + psGlyphName = new String[h]; + for (int i = 0; i < h; i++) { + int len = di.readUnsignedByte(); + byte[] buf = new byte[len]; + di.readFully(buf); + psGlyphName[i] = new String(buf); + } + } + } else if (version == 0x00025000) { + } else if (version == 0x00030000) { + } + } + + public int getVersion() { + return version; + } + + private int highestGlyphNameIndex() { + int high = 0; + for (int i = 0; i < numGlyphs; i++) { + if (high < glyphNameIndex[i]) { + high = glyphNameIndex[i]; + } + } + return high; + } + + public String getGlyphName(int i) { + if (version == 0x00020000) { + return (glyphNameIndex[i] > 257) + ? psGlyphName[glyphNameIndex[i] - 258] + : macGlyphName[glyphNameIndex[i]]; + } else { + return null; + } + } + + private boolean isMacGlyphName(int i) { + if (version == 0x00020000) { + return glyphNameIndex[i] <= 257; + } else { + return false; + } + } + + /** Get the table type, as a table directory value. + * @return The table type + */ + public int getType() { + return post; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'post' Table - PostScript Metrics\n---------------------------------\n") + .append("\n 'post' version: ").append(Fixed.floatValue(version)) + .append("\n italicAngle: ").append(Fixed.floatValue(italicAngle)) + .append("\n underlinePosition: ").append(underlinePosition) + .append("\n underlineThickness: ").append(underlineThickness) + .append("\n isFixedPitch: ").append(isFixedPitch) + .append("\n minMemType42: ").append(minMemType42) + .append("\n maxMemType42: ").append(maxMemType42) + .append("\n minMemType1: ").append(minMemType1) + .append("\n maxMemType1: ").append(maxMemType1); + + if (version == 0x00020000) { + sb.append("\n\n Format 2.0: Non-Standard (for PostScript) TrueType Glyph Set.\n"); + sb.append(" numGlyphs: ").append(numGlyphs).append("\n"); + for (int i = 0; i < numGlyphs; i++) { + sb.append(" Glyf ").append(i).append(" -> "); + if (isMacGlyphName(i)) { + sb.append("Mac Glyph # ").append(glyphNameIndex[i]) + .append(", '").append(macGlyphName[glyphNameIndex[i]]).append("'\n"); + } else { + sb.append("PSGlyf Name # ").append(glyphNameIndex[i] - 257) + .append(", name= '").append(psGlyphName[glyphNameIndex[i] - 258]).append("'\n"); + } + } + sb.append("\n Full List of PSGlyf Names\n ------------------------\n"); + for (int i = 0; i < psGlyphName.length; i++) { + sb.append(" PSGlyf Name # ").append(i + 1) + .append(": ").append(psGlyphName[i]) + .append("\n"); + } + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/PrepTable.java b/src/net/java/dev/typecast/ot/table/PrepTable.java new file mode 100644 index 000000000..938b9b840 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/PrepTable.java @@ -0,0 +1,46 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Disassembler; + +/** + * @version $Id: PrepTable.java,v 1.1.1.1 2004-12-05 23:14:57 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class PrepTable extends Program implements Table { + + private DirectoryEntry de; + + public PrepTable(DirectoryEntry de, DataInput di) throws IOException { + this.de = (DirectoryEntry) de.clone(); + readInstructions(di, de.getLength()); + } + + public int getType() { + return prep; + } + + public String toString() { + return Disassembler.disassemble(getInstructions(), 0); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return de; + } + +} diff --git a/src/net/java/dev/typecast/ot/table/Program.java b/src/net/java/dev/typecast/ot/table/Program.java new file mode 100644 index 000000000..6fd02a469 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Program.java @@ -0,0 +1,41 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import java.io.ByteArrayInputStream; + +/** + * @version $Id: Program.java,v 1.1.1.1 2004-12-05 23:14:57 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public abstract class Program { + + private short[] instructions; + + public short[] getInstructions() { + return instructions; + } + + protected void readInstructions(DataInput di, int count) throws IOException { + instructions = new short[count]; + for (int i = 0; i < count; i++) { + instructions[i] = (short) di.readUnsignedByte(); + } + } +/* + protected void readInstructions(ByteArrayInputStream bais, int count) { + instructions = new short[count]; + for (int i = 0; i < count; i++) { + instructions[i] = (short) bais.read(); + } + } +*/ +} diff --git a/src/net/java/dev/typecast/ot/table/RangeRecord.java b/src/net/java/dev/typecast/ot/table/RangeRecord.java new file mode 100644 index 000000000..3bcb9ccb5 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/RangeRecord.java @@ -0,0 +1,87 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * Coverage Index (GlyphID) = StartCoverageIndex + GlyphID - Start GlyphID + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: RangeRecord.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class RangeRecord { + + private int _start; + private int _end; + private int _startCoverageIndex; + + /** Creates new RangeRecord */ + public RangeRecord(DataInput di) throws IOException { + _start = di.readUnsignedShort(); + _end = di.readUnsignedShort(); + _startCoverageIndex = di.readUnsignedShort(); + } + + public boolean isInRange(int glyphId) { + return (_start <= glyphId && glyphId <= _end); + } + + public int getCoverageIndex(int glyphId) { + if (isInRange(glyphId)) { + return _startCoverageIndex + glyphId - _start; + } + return -1; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/Script.java b/src/net/java/dev/typecast/ot/table/Script.java new file mode 100644 index 000000000..e3022c116 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Script.java @@ -0,0 +1,118 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Script.java,v 1.2 2007-01-24 09:47:47 davidsch Exp $ + */ +public class Script { + + private int _defaultLangSysOffset; + private int _langSysCount; + private LangSysRecord[] _langSysRecords; + private LangSys _defaultLangSys; + private LangSys[] _langSys; + + /** Creates new ScriptTable */ + protected Script(DataInputStream dis, int offset) throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _defaultLangSysOffset = dis.readUnsignedShort(); + _langSysCount = dis.readUnsignedShort(); + if (_langSysCount > 0) { + _langSysRecords = new LangSysRecord[_langSysCount]; + for (int i = 0; i < _langSysCount; i++) { + _langSysRecords[i] = new LangSysRecord(dis); + } + } + + // Read the LangSys tables + if (_langSysCount > 0) { + _langSys = new LangSys[_langSysCount]; + for (int i = 0; i < _langSysCount; i++) { + dis.reset(); + dis.skipBytes(offset + _langSysRecords[i].getOffset()); + _langSys[i] = new LangSys(dis); + } + } + if (_defaultLangSysOffset > 0) { + dis.reset(); + dis.skipBytes(offset + _defaultLangSysOffset); + _defaultLangSys = new LangSys(dis); + } + } + + public int getLangSysCount() { + return _langSysCount; + } + + public LangSysRecord getLangSysRecord(int i) { + return _langSysRecords[i]; + } + + public LangSys getDefaultLangSys() { + return _defaultLangSys; + } + + public LangSys getLangSys(int i) { + return _langSys[i]; + } +} + diff --git a/src/net/java/dev/typecast/ot/table/ScriptList.java b/src/net/java/dev/typecast/ot/table/ScriptList.java new file mode 100644 index 000000000..bd82a052f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ScriptList.java @@ -0,0 +1,115 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ScriptList.java,v 1.3 2007-01-24 09:54:44 davidsch Exp $ + */ +public class ScriptList { + + private int _scriptCount = 0; + private ScriptRecord[] _scriptRecords; + private Script[] _scripts; + + /** Creates new ScriptList */ + protected ScriptList(DataInputStream dis, int offset) throws IOException { + + // Ensure we're in the right place + dis.reset(); + dis.skipBytes(offset); + + // Start reading + _scriptCount = dis.readUnsignedShort(); + _scriptRecords = new ScriptRecord[_scriptCount]; + _scripts = new Script[_scriptCount]; + for (int i = 0; i < _scriptCount; i++) { + _scriptRecords[i] = new ScriptRecord(dis); + } + for (int i = 0; i < _scriptCount; i++) { + _scripts[i] = new Script(dis, offset + _scriptRecords[i].getOffset()); + } + } + + public int getScriptCount() { + return _scriptCount; + } + + public ScriptRecord getScriptRecord(int i) { + return _scriptRecords[i]; + } + + public Script getScript(int i) { + return _scripts[i]; + } + + public Script findScript(String tag) { + if (tag.length() != 4) { + return null; + } + int tagVal = ((tag.charAt(0)<<24) + | (tag.charAt(1)<<16) + | (tag.charAt(2)<<8) + | tag.charAt(3)); + for (int i = 0; i < _scriptCount; i++) { + if (_scriptRecords[i].getTag() == tagVal) { + return _scripts[i]; + } + } + return null; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/ScriptRecord.java b/src/net/java/dev/typecast/ot/table/ScriptRecord.java new file mode 100644 index 000000000..aea0bf0df --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ScriptRecord.java @@ -0,0 +1,88 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: ScriptRecord.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public class ScriptRecord { + + private int _tag; + private int _offset; + + /** Creates new ScriptRecord */ + protected ScriptRecord(DataInput di) throws IOException { + _tag = di.readInt(); + _offset = di.readUnsignedShort(); + } + + public int getTag() { + return _tag; + } + + public int getOffset() { + return _offset; + } + + public String getTagAsString() { + return new StringBuffer() + .append((char)((_tag>>24)&0xff)) + .append((char)((_tag>>16)&0xff)) + .append((char)((_tag>>8)&0xff)) + .append((char)((_tag)&0xff)) + .toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/ScriptTags.java b/src/net/java/dev/typecast/ot/table/ScriptTags.java new file mode 100644 index 000000000..eeb4f8e25 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/ScriptTags.java @@ -0,0 +1,61 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +/** + * Definition of Script tags + * + * @version $Id: ScriptTags.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + * @author <a href="mailto:[email protected]">Vincent Hardy</a> + */ +public interface ScriptTags { + public static final String SCRIPT_TAG_ARAB = "arab"; +} diff --git a/src/net/java/dev/typecast/ot/table/SignatureBlock.java b/src/net/java/dev/typecast/ot/table/SignatureBlock.java new file mode 100644 index 000000000..2e4acf525 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/SignatureBlock.java @@ -0,0 +1,46 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.IOException; +import java.io.DataInput; + +/** + * + * @version $Id: SignatureBlock.java,v 1.1.1.1 2004-12-05 23:14:58 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class SignatureBlock { + + private int reserved1; + private int reserved2; + private int signatureLen; + private byte[] signature; + + /** Creates new SignatureBlock */ + protected SignatureBlock(DataInput di) throws IOException { + reserved1 = di.readUnsignedShort(); + reserved2 = di.readUnsignedShort(); + signatureLen = di.readInt(); + signature = new byte[signatureLen]; + di.readFully(signature); + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < signatureLen; i += 16) { + if (signatureLen - i >= 16) { + sb.append(new String(signature, i, 16)).append("\n"); + } else { + sb.append(new String(signature, i, signatureLen - i)).append("\n"); + } + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/SingleSubst.java b/src/net/java/dev/typecast/ot/table/SingleSubst.java new file mode 100644 index 000000000..91c985883 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/SingleSubst.java @@ -0,0 +1,81 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: SingleSubst.java,v 1.2 2007-01-24 09:47:46 davidsch Exp $ + */ +public abstract class SingleSubst extends LookupSubtable { + + public abstract int getFormat(); + + public abstract int substitute(int glyphId); + + public static SingleSubst read(DataInputStream dis, int offset) throws IOException { + SingleSubst s = null; + dis.reset(); + dis.skipBytes(offset); + int format = dis.readUnsignedShort(); + if (format == 1) { + s = new SingleSubstFormat1(dis, offset); + } else if (format == 2) { + s = new SingleSubstFormat2(dis, offset); + } + return s; + } + +} + diff --git a/src/net/java/dev/typecast/ot/table/SingleSubstFormat1.java b/src/net/java/dev/typecast/ot/table/SingleSubstFormat1.java new file mode 100644 index 000000000..538c57f6d --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/SingleSubstFormat1.java @@ -0,0 +1,92 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: SingleSubstFormat1.java,v 1.2 2007-01-24 09:47:45 davidsch Exp $ + */ +public class SingleSubstFormat1 extends SingleSubst { + + private int _coverageOffset; + private short _deltaGlyphID; + private Coverage _coverage; + + /** Creates new SingleSubstFormat1 */ + protected SingleSubstFormat1(DataInputStream dis, int offset) throws IOException { + _coverageOffset = dis.readUnsignedShort(); + _deltaGlyphID = dis.readShort(); + dis.reset(); + dis.skipBytes(offset + _coverageOffset); + _coverage = Coverage.read(dis); + } + + public int getFormat() { + return 1; + } + + public int substitute(int glyphId) { + int i = _coverage.findGlyph(glyphId); + if (i > -1) { + return glyphId + _deltaGlyphID; + } + return glyphId; + } + + public String getTypeAsString() { + return "SingleSubstFormat1"; + } +} + diff --git a/src/net/java/dev/typecast/ot/table/SingleSubstFormat2.java b/src/net/java/dev/typecast/ot/table/SingleSubstFormat2.java new file mode 100644 index 000000000..74c68f71f --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/SingleSubstFormat2.java @@ -0,0 +1,97 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.IOException; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: SingleSubstFormat2.java,v 1.2 2007-01-24 09:47:48 davidsch Exp $ + */ +public class SingleSubstFormat2 extends SingleSubst { + + private int _coverageOffset; + private int _glyphCount; + private int[] _substitutes; + private Coverage _coverage; + + /** Creates new SingleSubstFormat2 */ + protected SingleSubstFormat2(DataInputStream dis, int offset) throws IOException { + _coverageOffset = dis.readUnsignedShort(); + _glyphCount = dis.readUnsignedShort(); + _substitutes = new int[_glyphCount]; + for (int i = 0; i < _glyphCount; i++) { + _substitutes[i] = dis.readUnsignedShort(); + } + dis.reset(); + dis.skipBytes(offset + _coverageOffset); + _coverage = Coverage.read(dis); + } + + public int getFormat() { + return 2; + } + + public int substitute(int glyphId) { + int i = _coverage.findGlyph(glyphId); + if (i > -1) { + return _substitutes[i]; + } + return glyphId; + } + + public String getTypeAsString() { + return "SingleSubstFormat2"; + } +} + diff --git a/src/net/java/dev/typecast/ot/table/TTCHeader.java b/src/net/java/dev/typecast/ot/table/TTCHeader.java new file mode 100644 index 000000000..2f38d33f4 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/TTCHeader.java @@ -0,0 +1,59 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * + * @version $Id: TTCHeader.java,v 1.1.1.1 2004-12-05 23:15:01 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class TTCHeader { + + public static final int ttcf = 0x74746366; + + private int ttcTag; + private int version; + private int directoryCount; + private int[] tableDirectory; + private int dsigTag; + private int dsigLength; + private int dsigOffset; + + /** Creates new TTCHeader */ + public TTCHeader(DataInput di) throws IOException { + ttcTag = di.readInt(); + version = di.readInt(); + directoryCount = di.readInt(); + tableDirectory = new int[directoryCount]; + for (int i = 0; i < directoryCount; i++) { + tableDirectory[i] = di.readInt(); + } + if (version == 0x00010000) { + dsigTag = di.readInt(); + } + dsigLength = di.readInt(); + dsigOffset = di.readInt(); + } + + public int getDirectoryCount() { + return directoryCount; + } + + public int getTableDirectory(int i) { + return tableDirectory[i]; + } + + public static boolean isTTC(DataInput di) throws IOException { + int ttcTag = di.readInt(); + return ttcTag == ttcf; + } +} diff --git a/src/net/java/dev/typecast/ot/table/Table.java b/src/net/java/dev/typecast/ot/table/Table.java new file mode 100644 index 000000000..ddbdc49e2 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/Table.java @@ -0,0 +1,67 @@ +/***************************************************************************** + * Copyright (C) The Apache Software Foundation. All rights reserved. * + * ------------------------------------------------------------------------- * + * This software is published under the terms of the Apache Software License * + * version 1.1, a copy of which has been included with this distribution in * + * the LICENSE file. * + *****************************************************************************/ + +package net.java.dev.typecast.ot.table; + +/** + * @version $Id: Table.java,v 1.1.1.1 2004-12-05 23:14:59 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public interface Table { + + // Table constants + public static final int BASE = 0x42415345; // Baseline data [OpenType] + public static final int CFF = 0x43464620; // PostScript font program (compact font format) [PostScript] + public static final int DSIG = 0x44534947; // Digital signature + public static final int EBDT = 0x45424454; // Embedded bitmap data + public static final int EBLC = 0x45424c43; // Embedded bitmap location data + public static final int EBSC = 0x45425343; // Embedded bitmap scaling data + public static final int GDEF = 0x47444546; // Glyph definition data [OpenType] + public static final int GPOS = 0x47504f53; // Glyph positioning data [OpenType] + public static final int GSUB = 0x47535542; // Glyph substitution data [OpenType] + public static final int JSTF = 0x4a535446; // Justification data [OpenType] + public static final int LTSH = 0x4c545348; // Linear threshold table + public static final int MMFX = 0x4d4d4658; // Multiple master font metrics [PostScript] + public static final int MMSD = 0x4d4d5344; // Multiple master supplementary data [PostScript] + public static final int OS_2 = 0x4f532f32; // OS/2 and Windows specific metrics [r] + public static final int PCLT = 0x50434c54; // PCL5 + public static final int VDMX = 0x56444d58; // Vertical Device Metrics table + public static final int cmap = 0x636d6170; // character to glyph mapping [r] + public static final int cvt = 0x63767420; // Control Value Table + public static final int fpgm = 0x6670676d; // font program + public static final int fvar = 0x66766172; // Apple's font variations table [PostScript] + public static final int gasp = 0x67617370; // grid-fitting and scan conversion procedure (grayscale) + public static final int glyf = 0x676c7966; // glyph data [r] + public static final int hdmx = 0x68646d78; // horizontal device metrics + public static final int head = 0x68656164; // font header [r] + public static final int hhea = 0x68686561; // horizontal header [r] + public static final int hmtx = 0x686d7478; // horizontal metrics [r] + public static final int kern = 0x6b65726e; // kerning + public static final int loca = 0x6c6f6361; // index to location [r] + public static final int maxp = 0x6d617870; // maximum profile [r] + public static final int name = 0x6e616d65; // naming table [r] + public static final int prep = 0x70726570; // CVT Program + public static final int post = 0x706f7374; // PostScript information [r] + public static final int vhea = 0x76686561; // Vertical Metrics header + public static final int vmtx = 0x766d7478; // Vertical Metrics + + /** + * Get the table type, as a table directory value. + * @return The table type + */ + public int getType(); + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry(); + +} diff --git a/src/net/java/dev/typecast/ot/table/TableDirectory.java b/src/net/java/dev/typecast/ot/table/TableDirectory.java new file mode 100644 index 000000000..2eff53dd9 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/TableDirectory.java @@ -0,0 +1,129 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * @version $Id: TableDirectory.java,v 1.2 2004-12-09 23:46:21 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class TableDirectory { + + private int _version = 0; + private short _numTables = 0; + private short _searchRange = 0; + private short _entrySelector = 0; + private short _rangeShift = 0; + private DirectoryEntry[] _entries; + + public TableDirectory(DataInput di) throws IOException { + _version = di.readInt(); + _numTables = di.readShort(); + _searchRange = di.readShort(); + _entrySelector = di.readShort(); + _rangeShift = di.readShort(); + _entries = new DirectoryEntry[_numTables]; + for (int i = 0; i < _numTables; i++) { + _entries[i] = new DirectoryEntry(di); + } + } + + public DirectoryEntry getEntry(int index) { + return _entries[index]; + } + + public DirectoryEntry getEntryByTag(int tag) { + for (int i = 0; i < _numTables; i++) { + if (_entries[i].getTag() == tag) { + return _entries[i]; + } + } + return null; + } + + public short getEntrySelector() { + return _entrySelector; + } + + public short getNumTables() { + return _numTables; + } + + public short getRangeShift() { + return _rangeShift; + } + + public short getSearchRange() { + return _searchRange; + } + + public int getVersion() { + return _version; + } + + public String toString() { + StringBuffer sb = new StringBuffer() + .append("Offset Table\n------ -----") + .append("\n sfnt version: ").append(Fixed.floatValue(_version)) + .append("\n numTables = ").append(_numTables) + .append("\n searchRange = ").append(_searchRange) + .append("\n entrySelector = ").append(_entrySelector) + .append("\n rangeShift = ").append(_rangeShift) + .append("\n\n"); + for (int i = 0; i < _numTables; i++) { + sb.append(i).append(". ").append(_entries[i].toString()).append("\n"); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/ot/table/TableException.java b/src/net/java/dev/typecast/ot/table/TableException.java new file mode 100644 index 000000000..02bc49eb5 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/TableException.java @@ -0,0 +1,46 @@ +/* + * $Id: TableException.java,v 1.1.1.1 2004-12-05 23:15:00 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +/** + * + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: TableException.java,v 1.1.1.1 2004-12-05 23:15:00 davidsch Exp $ + */ +public class TableException extends java.lang.Exception { + + private static final long serialVersionUID = 1L; + + /** + * Creates a new instance of <code>TableException</code> without detail message. + */ + public TableException() { + } + + + /** + * Constructs an instance of <code>TableException</code> with the specified detail message. + * @param msg the detail message. + */ + public TableException(String msg) { + super(msg); + } +} diff --git a/src/net/java/dev/typecast/ot/table/TableFactory.java b/src/net/java/dev/typecast/ot/table/TableFactory.java new file mode 100644 index 000000000..632abcf44 --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/TableFactory.java @@ -0,0 +1,185 @@ +/* + + ============================================================================ + The Apache Software License, Version 1.1 + ============================================================================ + + Copyright (C) 1999-2003 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 "Batik" 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 + + 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. For more information on the + Apache Software Foundation, please see <http://www.apache.org/>. + +*/ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInputStream; +import java.io.InputStream; +import java.io.IOException; +import net.java.dev.typecast.ot.OTFont; +import net.java.dev.typecast.ot.OTFontCollection; + +/** + * + * @version $Id: TableFactory.java,v 1.7 2007-02-05 12:39:51 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class TableFactory { + + public static Table create( + OTFontCollection fc, + OTFont font, + DirectoryEntry de, + DataInputStream dis) throws IOException { + Table t = null; + + // First, if we have a font collection, look for the table there + if (fc != null) { + t = fc.getTable(de); + if (t != null) { + return t; + } + } + + // Create the table + switch (de.getTag()) { + case Table.BASE: + t = new BaseTable(de, dis); + break; + case Table.CFF: + t = new CffTable(de, dis); + break; + case Table.DSIG: + t = new DsigTable(de, dis); + break; + case Table.EBDT: + break; + case Table.EBLC: + break; + case Table.EBSC: + break; + case Table.GDEF: + break; + case Table.GPOS: + t = new GposTable(de, dis); + break; + case Table.GSUB: + t = new GsubTable(de, dis); + break; + case Table.JSTF: + break; + case Table.LTSH: + t = new LtshTable(de, dis); + break; + case Table.MMFX: + break; + case Table.MMSD: + break; + case Table.OS_2: + t = new Os2Table(de, dis); + break; + case Table.PCLT: + t = new PcltTable(de, dis); + break; + case Table.VDMX: + t = new VdmxTable(de, dis); + break; + case Table.cmap: + t = new CmapTable(de, dis); + break; + case Table.cvt: + t = new CvtTable(de, dis); + break; + case Table.fpgm: + t = new FpgmTable(de, dis); + break; + case Table.fvar: + break; + case Table.gasp: + t = new GaspTable(de, dis); + break; + case Table.glyf: + t = new GlyfTable(de, dis, font.getMaxpTable(), font.getLocaTable()); + break; + case Table.hdmx: + t = new HdmxTable(de, dis, font.getMaxpTable()); + break; + case Table.head: + t = new HeadTable(de, dis); + break; + case Table.hhea: + t = new HheaTable(de, dis); + break; + case Table.hmtx: + t = new HmtxTable(de, dis, font.getHheaTable(), font.getMaxpTable()); + break; + case Table.kern: + t = new KernTable(de, dis); + break; + case Table.loca: + t = new LocaTable(de, dis, font.getHeadTable(), font.getMaxpTable()); + break; + case Table.maxp: + t = new MaxpTable(de, dis); + break; + case Table.name: + t = new NameTable(de, dis); + break; + case Table.prep: + t = new PrepTable(de, dis); + break; + case Table.post: + t = new PostTable(de, dis); + break; + case Table.vhea: + t = new VheaTable(de, dis); + break; + case Table.vmtx: + t = new VmtxTable(de, dis, font.getVheaTable(), font.getMaxpTable()); + break; + } + + // If we have a font collection, add this table to it + if ((fc != null) && (t != null)) { + fc.addTable(t); + } + return t; + } +} diff --git a/src/net/java/dev/typecast/ot/table/VdmxTable.java b/src/net/java/dev/typecast/ot/table/VdmxTable.java new file mode 100644 index 000000000..907133b6d --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/VdmxTable.java @@ -0,0 +1,197 @@ +/* + * $Id: VdmxTable.java,v 1.1 2007-01-30 05:25:35 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * The Vertical Device Metrics table for TrueType outlines. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: VdmxTable.java,v 1.1 2007-01-30 05:25:35 davidsch Exp $ + */ +public class VdmxTable implements Table { + + private class Ratio { + + private byte _bCharSet; + private byte _xRatio; + private byte _yStartRatio; + private byte _yEndRatio; + + protected Ratio(DataInput di) throws IOException { + _bCharSet = di.readByte(); + _xRatio = di.readByte(); + _yStartRatio = di.readByte(); + _yEndRatio = di.readByte(); + } + + public byte getBCharSet() { + return _bCharSet; + } + + public byte getXRatio() { + return _xRatio; + } + + public byte getYStartRatio() { + return _yStartRatio; + } + + public byte getYEndRatio() { + return _yEndRatio; + } + } + + private class VTableRecord { + + private int _yPelHeight; + private short _yMax; + private short _yMin; + + protected VTableRecord(DataInput di) throws IOException { + _yPelHeight = di.readUnsignedShort(); + _yMax = di.readShort(); + _yMin = di.readShort(); + } + + public int getYPelHeight() { + return _yPelHeight; + } + + public short getYMax() { + return _yMax; + } + + public short getYMin() { + return _yMin; + } + } + + private class Group { + + private int _recs; + private int _startsz; + private int _endsz; + private VTableRecord[] _entry; + + protected Group(DataInput di) throws IOException { + _recs = di.readUnsignedShort(); + _startsz = di.readUnsignedByte(); + _endsz = di.readUnsignedByte(); + _entry = new VTableRecord[_recs]; + for (int i = 0; i < _recs; ++i) { + _entry[i] = new VTableRecord(di); + } + } + + public int getRecs() { + return _recs; + } + + public int getStartSZ() { + return _startsz; + } + + public int getEndSZ() { + return _endsz; + } + + public VTableRecord[] getEntry() { + return _entry; + } + } + + private DirectoryEntry _de; + private int _version; + private int _numRecs; + private int _numRatios; + private Ratio[] _ratRange; + private int _offset[]; + private Group[] _groups; + + /** Creates a new instance of VdmxTable */ + protected VdmxTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + _version = di.readUnsignedShort(); + _numRecs = di.readUnsignedShort(); + _numRatios = di.readUnsignedShort(); + _ratRange = new Ratio[_numRatios]; + for (int i = 0; i < _numRatios; ++i) { + _ratRange[i] = new Ratio(di); + } + _offset = new int[_numRatios]; + for (int i = 0; i < _numRatios; ++i) { + _offset[i] = di.readUnsignedShort(); + } + _groups = new Group[_numRecs]; + for (int i = 0; i < _numRecs; ++i) { + _groups[i] = new Group(di); + } + } + + public int getType() { + return VDMX; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'VDMX' Table - Precomputed Vertical Device Metrics\n") + .append("--------------------------------------------------\n") + .append(" Version: ").append(_version).append("\n") + .append(" Number of Hgt Records: ").append(_numRecs).append("\n") + .append(" Number of Ratio Records: ").append(_numRatios).append("\n"); + for (int i = 0; i < _numRatios; ++i) { + sb.append("\n Ratio Record #").append(i + 1).append("\n") + .append("\tCharSetId ").append(_ratRange[i].getBCharSet()).append("\n") + .append("\txRatio ").append(_ratRange[i].getXRatio()).append("\n") + .append("\tyStartRatio ").append(_ratRange[i].getYStartRatio()).append("\n") + .append("\tyEndRatio ").append(_ratRange[i].getYEndRatio()).append("\n") + .append("\tRecord Offset ").append(_offset[i]).append("\n"); + } + sb.append("\n VDMX Height Record Groups\n") + .append(" -------------------------\n"); + for (int i = 0; i < _numRecs; ++i) { + Group group = _groups[i]; + sb.append(" ").append(i + 1) + .append(". Number of Hgt Records ").append(group.getRecs()).append("\n") + .append(" Starting Y Pel Height ").append(group.getStartSZ()).append("\n") + .append(" Ending Y Pel Height ").append(group.getEndSZ()).append("\n"); + for (int j = 0; j < group.getRecs(); ++j) { + sb.append("\n ").append(j + 1) + .append(". Pel Height= ").append(group.getEntry()[j].getYPelHeight()).append("\n") + .append(" yMax= ").append(group.getEntry()[j].getYMax()).append("\n") + .append(" yMin= ").append(group.getEntry()[j].getYMin()).append("\n"); + } + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/VheaTable.java b/src/net/java/dev/typecast/ot/table/VheaTable.java new file mode 100644 index 000000000..3863080cf --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/VheaTable.java @@ -0,0 +1,147 @@ +/* + * $Id: VheaTable.java,v 1.1 2007-01-31 01:17:40 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; +import net.java.dev.typecast.ot.Fixed; + +/** + * Vertical Header Table + * @version $Id: VheaTable.java,v 1.1 2007-01-31 01:17:40 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class VheaTable implements Table { + + private DirectoryEntry _de; + private int _version; + private short _ascent; + private short _descent; + private short _lineGap; + private short _advanceHeightMax; + private short _minTopSideBearing; + private short _minBottomSideBearing; + private short _yMaxExtent; + private short _caretSlopeRise; + private short _caretSlopeRun; + private short _metricDataFormat; + private int _numberOfLongVerMetrics; + + protected VheaTable(DirectoryEntry de, DataInput di) throws IOException { + _de = (DirectoryEntry) de.clone(); + _version = di.readInt(); + _ascent = di.readShort(); + _descent = di.readShort(); + _lineGap = di.readShort(); + _advanceHeightMax = di.readShort(); + _minTopSideBearing = di.readShort(); + _minBottomSideBearing = di.readShort(); + _yMaxExtent = di.readShort(); + _caretSlopeRise = di.readShort(); + _caretSlopeRun = di.readShort(); + for (int i = 0; i < 5; ++i) { + di.readShort(); + } + _metricDataFormat = di.readShort(); + _numberOfLongVerMetrics = di.readUnsignedShort(); + } + + public short getAdvanceHeightMax() { + return _advanceHeightMax; + } + + public short getAscent() { + return _ascent; + } + + public short getCaretSlopeRise() { + return _caretSlopeRise; + } + + public short getCaretSlopeRun() { + return _caretSlopeRun; + } + + public short getDescent() { + return _descent; + } + + public short getLineGap() { + return _lineGap; + } + + public short getMetricDataFormat() { + return _metricDataFormat; + } + + public short getMinTopSideBearing() { + return _minTopSideBearing; + } + + public short getMinBottomSideBearing() { + return _minBottomSideBearing; + } + + public int getNumberOfLongVerMetrics() { + return _numberOfLongVerMetrics; + } + + public int getType() { + return vhea; + } + + public short getYMaxExtent() { + return _yMaxExtent; + } + + public String toString() { + return new StringBuffer() + .append("'vhea' Table - Vertical Header\n------------------------------") + .append("\n 'vhea' version: ").append(Fixed.floatValue(_version)) + .append("\n xAscender: ").append(_ascent) + .append("\n xDescender: ").append(_descent) + .append("\n xLineGap: ").append(_lineGap) + .append("\n advanceHeightMax: ").append(_advanceHeightMax) + .append("\n minTopSideBearing: ").append(_minTopSideBearing) + .append("\n minBottomSideBearing: ").append(_minBottomSideBearing) + .append("\n yMaxExtent: ").append(_yMaxExtent) + .append("\n horizCaretSlopeNum: ").append(_caretSlopeRise) + .append("\n horizCaretSlopeDenom: ").append(_caretSlopeRun) + .append("\n reserved0: 0") + .append("\n reserved1: 0") + .append("\n reserved2: 0") + .append("\n reserved3: 0") + .append("\n reserved4: 0") + .append("\n metricDataFormat: ").append(_metricDataFormat) + .append("\n numOf_LongVerMetrics: ").append(_numberOfLongVerMetrics) + .toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/ot/table/VmtxTable.java b/src/net/java/dev/typecast/ot/table/VmtxTable.java new file mode 100644 index 000000000..b2d9a3c3e --- /dev/null +++ b/src/net/java/dev/typecast/ot/table/VmtxTable.java @@ -0,0 +1,112 @@ +/* + * $Id: VmtxTable.java,v 1.1 2007-01-31 01:18:04 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.ot.table; + +import java.io.DataInput; +import java.io.IOException; + +/** + * Vertical Metrics Table + * @version $Id: VmtxTable.java,v 1.1 2007-01-31 01:18:04 davidsch Exp $ + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + */ +public class VmtxTable implements Table { + + private DirectoryEntry _de; + private int[] _vMetrics = null; + private short[] _topSideBearing = null; + + protected VmtxTable( + DirectoryEntry de, + DataInput di, + VheaTable vhea, + MaxpTable maxp) throws IOException { + _de = (DirectoryEntry) de.clone(); + _vMetrics = new int[vhea.getNumberOfLongVerMetrics()]; + for (int i = 0; i < vhea.getNumberOfLongVerMetrics(); ++i) { + _vMetrics[i] = + di.readUnsignedByte()<<24 + | di.readUnsignedByte()<<16 + | di.readUnsignedByte()<<8 + | di.readUnsignedByte(); + } + int tsbCount = maxp.getNumGlyphs() - vhea.getNumberOfLongVerMetrics(); + _topSideBearing = new short[tsbCount]; + for (int i = 0; i < tsbCount; ++i) { + _topSideBearing[i] = di.readShort(); + } + } + + public int getAdvanceHeight(int i) { + if (_vMetrics == null) { + return 0; + } + if (i < _vMetrics.length) { + return _vMetrics[i] >> 16; + } else { + return _vMetrics[_vMetrics.length - 1] >> 16; + } + } + + public short getTopSideBearing(int i) { + if (_vMetrics == null) { + return 0; + } + if (i < _vMetrics.length) { + return (short)(_vMetrics[i] & 0xffff); + } else { + return _topSideBearing[i - _vMetrics.length]; + } + } + + public int getType() { + return vmtx; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + sb.append("'vmtx' Table - Vertical Metrics\n-------------------------------\n"); + sb.append("Size = ").append(_de.getLength()).append(" bytes, ") + .append(_vMetrics.length).append(" entries\n"); + for (int i = 0; i < _vMetrics.length; i++) { + sb.append(" ").append(i) + .append(". advHeight: ").append(getAdvanceHeight(i)) + .append(", TSdBear: ").append(getTopSideBearing(i)) + .append("\n"); + } + for (int i = 0; i < _topSideBearing.length; i++) { + sb.append(" TSdBear ").append(i + _vMetrics.length) + .append(": ").append(_topSideBearing[i]) + .append("\n"); + } + return sb.toString(); + } + + /** + * Get a directory entry for this table. This uniquely identifies the + * table in collections where there may be more than one instance of a + * particular table. + * @return A directory entry + */ + public DirectoryEntry getDirectoryEntry() { + return _de; + } +} diff --git a/src/net/java/dev/typecast/t2/T2Interpreter.java b/src/net/java/dev/typecast/t2/T2Interpreter.java new file mode 100644 index 000000000..6ae59cf8d --- /dev/null +++ b/src/net/java/dev/typecast/t2/T2Interpreter.java @@ -0,0 +1,1043 @@ +/* + * $Id: T2Interpreter.java,v 1.2 2007-07-26 11:10:18 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.t2; + +import java.util.ArrayList; + +import net.java.dev.typecast.ot.Point; + +import net.java.dev.typecast.ot.table.CharstringType2; + +/** + * Type 2 Charstring Interpreter. Operator descriptions are quoted from + * Adobe's Type 2 Charstring Format document -- 5117.Type2.pdf. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: T2Interpreter.java,v 1.2 2007-07-26 11:10:18 davidsch Exp $ + */ +public class T2Interpreter { + + private static final int ARGUMENT_STACK_LIMIT = 48; + private static final int SUBR_STACK_LIMIT = 10; + private static final int TRANSIENT_ARRAY_ELEMENT_COUNT = 32; + + private Number[] _argStack = new Number[ARGUMENT_STACK_LIMIT]; + private int _argStackIndex = 0; + private int[] _subrStack = new int[SUBR_STACK_LIMIT]; + private int _subrStackIndex = 0; + private Number[] _transientArray = new Number[TRANSIENT_ARRAY_ELEMENT_COUNT]; + + private ArrayList<Point> _points; + + /** Creates a new instance of T2Interpreter */ + public T2Interpreter() { + } + + /** + * Moves the current point to a position at the relative coordinates + * (dx1, dy1). + */ + private void _rmoveto() { + int dy1 = popArg().intValue(); + int dx1 = popArg().intValue(); + clearArg(); + Point lastPoint = getLastPoint(); + moveTo(lastPoint.x + dx1, lastPoint.y + dy1); + } + + /** + * Moves the current point dx1 units in the horizontal direction. + */ + private void _hmoveto() { + int dx1 = popArg().intValue(); + clearArg(); + Point lastPoint = getLastPoint(); + moveTo(lastPoint.x + dx1, lastPoint.y); + } + + /** + * Moves the current point dy1 units in the vertical direction. + */ + private void _vmoveto() { + int dy1 = popArg().intValue(); + clearArg(); + Point lastPoint = getLastPoint(); + moveTo(lastPoint.x, lastPoint.y + dy1); + } + + /** + * Appends a line from the current point to a position at the + * relative coordinates dxa, dya. Additional rlineto operations are + * performed for all subsequent argument pairs. The number of + * lines is determined from the number of arguments on the stack. + */ + private void _rlineto() { + int count = getArgCount() / 2; + int[] dx = new int[count]; + int[] dy = new int[count]; + for (int i = 0; i < count; ++i) { + dy[count - i - 1] = popArg().intValue(); + dx[count - i - 1] = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + lineTo(lastPoint.x + dx[i], lastPoint.y + dy[i]); + } + clearArg(); + } + + /** + * Appends a horizontal line of length dx1 to the current point. + * With an odd number of arguments, subsequent argument pairs + * are interpreted as alternating values of dy and dx, for which + * additional lineto operators draw alternating vertical and + * horizontal lines. With an even number of arguments, the + * arguments are interpreted as alternating horizontal and + * vertical lines. The number of lines is determined from the + * number of arguments on the stack. + */ + private void _hlineto() { + int count = getArgCount(); + Number[] nums = new Number[count]; + for (int i = 0; i < count; ++i) { + nums[count - i - 1] = popArg(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + if (i % 2 == 0) { + lineTo(lastPoint.x + nums[i].intValue(), lastPoint.y); + } else { + lineTo(lastPoint.x, lastPoint.y + nums[i].intValue()); + } + } + clearArg(); + } + + /** + * Appends a vertical line of length dy1 to the current point. With + * an odd number of arguments, subsequent argument pairs are + * interpreted as alternating values of dx and dy, for which + * additional lineto operators draw alternating horizontal and + * vertical lines. With an even number of arguments, the + * arguments are interpreted as alternating vertical and + * horizontal lines. The number of lines is determined from the + * number of arguments on the stack. + */ + private void _vlineto() { + int count = getArgCount(); + Number[] nums = new Number[count]; + for (int i = 0; i < count; ++i) { + nums[count - i - 1] = popArg(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + if (i % 2 == 0) { + lineTo(lastPoint.x, lastPoint.y + nums[i].intValue()); + } else { + lineTo(lastPoint.x + nums[i].intValue(), lastPoint.y); + } + } + clearArg(); + } + + /** + * Appends a Bezier curve, defined by dxa...dyc, to the current + * point. For each subsequent set of six arguments, an additional + * curve is appended to the current point. The number of curve + * segments is determined from the number of arguments on the + * number stack and is limited only by the size of the number + * stack. + */ + private void _rrcurveto() { + int count = getArgCount() / 6; + int[] dxa = new int[count]; + int[] dya = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + int[] dyc = new int[count]; + for (int i = 0; i < count; ++i) { + dyc[count - i - 1] = popArg().intValue(); + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dya[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x + dxa[i]; + int ya = lastPoint.y + dya[i]; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb + dxc[i]; + int yc = yb + dyc[i]; + curveTo(xa, ya, xb, yb, xc, yc); + } + clearArg(); + } + + /** + * Appends one or more Bezier curves, as described by the + * dxa...dxc set of arguments, to the current point. For each curve, + * if there are 4 arguments, the curve starts and ends horizontal. + * The first curve need not start horizontal (the odd argument + * case). Note the argument order for the odd argument case. + */ + private void _hhcurveto() { + int count = getArgCount() / 4; + int dy1 = 0; + int[] dxa = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + for (int i = 0; i < count; ++i) { + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + if (getArgCount() == 1) { + dy1 = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x + dxa[i]; + int ya = lastPoint.y + (i == 0 ? dy1 : 0); + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb + dxc[i]; + int yc = yb; + curveTo(xa, ya, xb, yb, xc, yc); + } + clearArg(); + } + + /** + * Appends one or more Bezier curves to the current point. The + * tangent for the first Bezier must be horizontal, and the second + * must be vertical (except as noted below). + * If there is a multiple of four arguments, the curve starts + * horizontal and ends vertical. Note that the curves alternate + * between start horizontal, end vertical, and start vertical, and + * end horizontal. The last curve (the odd argument case) need not + * end horizontal/vertical. + */ + private void _hvcurveto() { + if (getArgCount() % 8 <= 1) { + int count = getArgCount() / 8; + int[] dxa = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dyc = new int[count]; + int[] dyd = new int[count]; + int[] dxe = new int[count]; + int[] dye = new int[count]; + int[] dxf = new int[count]; + int dyf = 0; + if (getArgCount() % 8 == 1) { + dyf = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + dxf[count - i - 1] = popArg().intValue(); + dye[count - i - 1] = popArg().intValue(); + dxe[count - i - 1] = popArg().intValue(); + dyd[count - i - 1] = popArg().intValue(); + dyc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x + dxa[i]; + int ya = lastPoint.y; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb; + int yc = yb + dyc[i]; + int xd = xc; + int yd = yc + dyd[i]; + int xe = xd + dxe[i]; + int ye = yd + dye[i]; + int xf = xe + dxf[i]; + int yf = ye + dyf; + curveTo(xa, ya, xb, yb, xc, yc); + curveTo(xd, yd, xe, ye, xf, yf); + } + } else { + int count = getArgCount() / 8; + int[] dya = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + int[] dxd = new int[count]; + int[] dxe = new int[count]; + int[] dye = new int[count]; + int[] dyf = new int[count]; + int dxf = 0; + if (getArgCount() % 8 == 1) { + dxf = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + dyf[count - i - 1] = popArg().intValue(); + dye[count - i - 1] = popArg().intValue(); + dxe[count - i - 1] = popArg().intValue(); + dxd[count - i - 1] = popArg().intValue(); + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dya[count - i - 1] = popArg().intValue(); + } + int dy3 = popArg().intValue(); + int dy2 = popArg().intValue(); + int dx2 = popArg().intValue(); + int dx1 = popArg().intValue(); + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x; + int ya = lastPoint.y + dya[i]; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb + dxc[i]; + int yc = yb; + int xd = xc + dxd[i]; + int yd = yc; + int xe = xd + dxe[i]; + int ye = yd + dye[i]; + int xf = xe + dxf; + int yf = ye + dyf[i]; + curveTo(xa, ya, xb, yb, xc, yc); + curveTo(xd, yd, xe, ye, xf, yf); + + // What on earth do we do with dx1, dx2, dy2 and dy3? + } + } + clearArg(); + } + + /** + * Is equivalent to one rrcurveto for each set of six arguments + * dxa...dyc, followed by exactly one rlineto using the dxd, dyd + * arguments. The number of curves is determined from the count + * on the argument stack. + */ + private void _rcurveline() { + int count = (getArgCount() - 2) / 6; + int[] dxa = new int[count]; + int[] dya = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + int[] dyc = new int[count]; + int dyd = popArg().intValue(); + int dxd = popArg().intValue(); + for (int i = 0; i < count; ++i) { + dyc[count - i - 1] = popArg().intValue(); + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dya[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + int xc = 0; + int yc = 0; + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x + dxa[i]; + int ya = lastPoint.y + dya[i]; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + xc = xb + dxc[i]; + yc = yb + dyc[i]; + curveTo(xa, ya, xb, yb, xc, yc); + } + lineTo(xc + dxd, yc + dyd); + clearArg(); + } + + /** + * Is equivalent to one rlineto for each pair of arguments beyond + * the six arguments dxb...dyd needed for the one rrcurveto + * command. The number of lines is determined from the count of + * items on the argument stack. + */ + private void _rlinecurve() { + int count = (getArgCount() - 6) / 2; + int[] dxa = new int[count]; + int[] dya = new int[count]; + int dyd = popArg().intValue(); + int dxd = popArg().intValue(); + int dyc = popArg().intValue(); + int dxc = popArg().intValue(); + int dyb = popArg().intValue(); + int dxb = popArg().intValue(); + for (int i = 0; i < count; ++i) { + dya[count - i - 1] = popArg().intValue(); + dxa[count - i - 1] = popArg().intValue(); + } + int xa = 0; + int ya = 0; + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + xa = lastPoint.x + dxa[i]; + ya = lastPoint.y + dya[i]; + lineTo(xa, ya); + } + int xb = xa + dxb; + int yb = ya + dyb; + int xc = xb + dxc; + int yc = yb + dyc; + int xd = xc + dxd; + int yd = yc + dyd; + curveTo(xb, yb, xc, yc, xd, yd); + clearArg(); + } + + /** + * Appends one or more Bezier curves to the current point, where + * the first tangent is vertical and the second tangent is horizontal. + * This command is the complement of hvcurveto; see the + * description of hvcurveto for more information. + */ + private void _vhcurveto() { + if (getArgCount() % 8 <= 1) { + int count = getArgCount() / 8; + int[] dya = new int[count]; + int[] dxb = new int[count]; + int[] dyb = new int[count]; + int[] dxc = new int[count]; + int[] dxd = new int[count]; + int[] dxe = new int[count]; + int[] dye = new int[count]; + int[] dyf = new int[count]; + int dxf = 0; + if (getArgCount() % 8 == 1) { + dxf = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + dyf[count - i - 1] = popArg().intValue(); + dye[count - i - 1] = popArg().intValue(); + dxe[count - i - 1] = popArg().intValue(); + dxd[count - i - 1] = popArg().intValue(); + dxc[count - i - 1] = popArg().intValue(); + dyb[count - i - 1] = popArg().intValue(); + dxb[count - i - 1] = popArg().intValue(); + dya[count - i - 1] = popArg().intValue(); + } + for (int i = 0; i < count; ++i) { + Point lastPoint = getLastPoint(); + int xa = lastPoint.x; + int ya = lastPoint.y + dya[i]; + int xb = xa + dxb[i]; + int yb = ya + dyb[i]; + int xc = xb + dxc[i]; + int yc = yb; + int xd = xc + dxd[i]; + int yd = yc; + int xe = xd + dxe[i]; + int ye = yd + dye[i]; + int xf = xe + dxf; + int yf = ye + dyf[i]; + curveTo(xa, ya, xb, yb, xc, yc); + curveTo(xd, yd, xe, ye, xf, yf); + } + } else { + int foo = 0; + } + clearArg(); + } + + /** + * Appends one or more curves to the current point. If the argument + * count is a multiple of four, the curve starts and ends vertical. If + * the argument count is odd, the first curve does not begin with a + * vertical tangent. + */ + private void _vvcurveto() { + + clearArg(); + } + + /** + * Causes two B�zier curves, as described by the arguments (as + * shown in Figure 2 below), to be rendered as a straight line when + * the flex depth is less than fd /100 device pixels, and as curved lines + * when the flex depth is greater than or equal to fd/100 device + * pixels. + */ + private void _flex() { + + clearArg(); + } + + /** + * Causes the two curves described by the arguments dx1...dx6 to + * be rendered as a straight line when the flex depth is less than + * 0.5 (that is, fd is 50) device pixels, and as curved lines when the + * flex depth is greater than or equal to 0.5 device pixels. + */ + private void _hflex() { + + clearArg(); + } + + /** + * Causes the two curves described by the arguments to be + * rendered as a straight line when the flex depth is less than 0.5 + * device pixels, and as curved lines when the flex depth is greater + * than or equal to 0.5 device pixels. + */ + private void _hflex1() { + + clearArg(); + } + + /** + * Causes the two curves described by the arguments to be + * rendered as a straight line when the flex depth is less than 0.5 + * device pixels, and as curved lines when the flex depth is greater + * than or equal to 0.5 device pixels. + */ + private void _flex1() { + + clearArg(); + } + + /** + * Finishes a charstring outline definition, and must be the + * last operator in a character�s outline. + */ + private void _endchar() { + endContour(); + clearArg(); + } + + private void _hstem() { + + clearArg(); + } + + private void _vstem() { + + clearArg(); + } + + private void _hstemhm() { + + clearArg(); + } + + private void _vstemhm() { + + clearArg(); + } + + private void _hintmask() { + + clearArg(); + } + + private void _cntrmask() { + + clearArg(); + } + + /** + * Returns the absolute value of num. + */ + private void _abs() { + double num = popArg().doubleValue(); + pushArg(Math.abs(num)); + } + + /** + * Returns the sum of the two numbers num1 and num2. + */ + private void _add() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 + num2); + } + + /** + * Returns the result of subtracting num2 from num1. + */ + private void _sub() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 - num2); + } + + /** + * Returns the quotient of num1 divided by num2. The result is + * undefined if overflow occurs and is zero for underflow. + */ + private void _div() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 / num2); + } + + /** + * Returns the negative of num. + */ + private void _neg() { + double num = popArg().doubleValue(); + pushArg(-num); + } + + /** + * Returns a pseudo random number num2 in the range (0,1], that + * is, greater than zero and less than or equal to one. + */ + private void _random() { + pushArg(1.0 - Math.random()); + } + + /** + * Returns the product of num1 and num2. If overflow occurs, the + * result is undefined, and zero is returned for underflow. + */ + private void _mul() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 * num2); + } + + /** + * Returns the square root of num. If num is negative, the result is + * undefined. + */ + private void _sqrt() { + double num = popArg().doubleValue(); + pushArg(Math.sqrt(num)); + } + + /** + * Removes the top element num from the Type 2 argument stack. + */ + private void _drop() { + popArg(); + } + + /** + * Exchanges the top two elements on the argument stack. + */ + private void _exch() { + Number num2 = popArg(); + Number num1 = popArg(); + pushArg(num2); + pushArg(num1); + } + + /** + * Retrieves the element i from the top of the argument stack and + * pushes a copy of that element onto that stack. If i is negative, + * the top element is copied. If i is greater than X, the operation is + * undefined. + */ + private void _index() { + int i = popArg().intValue(); + Number[] nums = new Number[i]; + for (int j = 0; j < i; ++j) { + nums[j] = popArg(); + } + for (int j = i - 1; j >= 0; --j) { + pushArg(nums[j]); + } + pushArg(nums[i]); + } + + /** + * Performs a circular shift of the elements num(N�1) ... num0 on + * the argument stack by the amount J. Positive J indicates upward + * motion of the stack; negative J indicates downward motion. + * The value N must be a non-negative integer, otherwise the + * operation is undefined. + */ + private void _roll() { + int j = popArg().intValue(); + int n = popArg().intValue(); + Number[] nums = new Number[n]; + for (int i = 0; i < n; ++i) { + nums[i] = popArg(); + } + for (int i = n - 1; i >= 0; --i) { + pushArg(nums[(n + i + j) % n]); + } + } + + /** + * Duplicates the top element on the argument stack. + */ + private void _dup() { + Number any = popArg(); + pushArg(any); + pushArg(any); + } + + /** + * Stores val into the transient array at the location given by i. + */ + private void _put() { + int i = popArg().intValue(); + Number val = popArg(); + _transientArray[i] = val; + } + + /** + * Retrieves the value stored in the transient array at the location + * given by i and pushes the value onto the argument stack. If get + * is executed prior to put for i during execution of the current + * charstring, the value returned is undefined. + */ + private void _get() { + int i = popArg().intValue(); + pushArg(_transientArray[i]); + } + + /** + * Puts a 1 on the stack if num1 and num2 are both non-zero, and + * puts a 0 on the stack if either argument is zero. + */ + private void _and() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg((num1!=0.0) && (num2!=0.0) ? 1 : 0); + } + + /** + * Puts a 1 on the stack if either num1 or num2 are non-zero, and + * puts a 0 on the stack if both arguments are zero. + */ + private void _or() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg((num1!=0.0) || (num2!=0.0) ? 1 : 0); + } + + /** + * Returns a 0 if num1 is non-zero; returns a 1 if num1 is zero. + */ + private void _not() { + double num1 = popArg().doubleValue(); + pushArg((num1!=0.0) ? 0 : 1); + } + + /** + * Puts a 1 on the stack if num1 equals num2, otherwise a 0 (zero) + * is put on the stack. + */ + private void _eq() { + double num2 = popArg().doubleValue(); + double num1 = popArg().doubleValue(); + pushArg(num1 == num2 ? 1 : 0); + } + + /** + * Leaves the value s1 on the stack if v1 ? v2, or leaves s2 on the + * stack if v1 > v2. The value of s1 and s2 is usually the biased + * number of a subroutine. + */ + private void _ifelse() { + double v2 = popArg().doubleValue(); + double v1 = popArg().doubleValue(); + Number s2 = popArg(); + Number s1 = popArg(); + pushArg(v1 <= v2 ? s1 : s2); + } + + /** + * Calls a charstring subroutine with index subr# (actually the subr + * number plus the subroutine bias number, as described in section + * 2.3) in the Subrs array. Each element of the Subrs array is a + * charstring encoded like any other charstring. Arguments + * pushed on the Type 2 argument stack prior to calling the + * subroutine, and results pushed on this stack by the subroutine, + * act according to the manner in which the subroutine is coded. + * Calling an undefined subr (gsubr) has undefined results. + */ + private void _callsubr() { + + } + + /** + * Operates in the same manner as callsubr except that it calls a + * global subroutine. + */ + private void _callgsubr() { + + } + + /** + * Returns from either a local or global charstring subroutine, and + * continues execution after the corresponding call(g)subr. + */ + private void _return() { + + } + + public Point[] execute(CharstringType2 cs) { + _points = new ArrayList<Point>(); + cs.resetIP(); + while (cs.moreBytes()) { + while (cs.isOperandAtIndex()) { + pushArg(cs.nextOperand()); + } + int operator = cs.nextByte(); + if (operator == 12) { + operator = cs.nextByte(); + + // Two-byte operators + switch (operator) { + case T2Mnemonic.AND: + _and(); + break; + case T2Mnemonic.OR: + _or(); + break; + case T2Mnemonic.NOT: + _not(); + break; + case T2Mnemonic.ABS: + _abs(); + break; + case T2Mnemonic.ADD: + _add(); + break; + case T2Mnemonic.SUB: + _sub(); + break; + case T2Mnemonic.DIV: + _div(); + break; + case T2Mnemonic.NEG: + _neg(); + break; + case T2Mnemonic.EQ: + _eq(); + break; + case T2Mnemonic.DROP: + _drop(); + break; + case T2Mnemonic.PUT: + _put(); + break; + case T2Mnemonic.GET: + _get(); + break; + case T2Mnemonic.IFELSE: + _ifelse(); + break; + case T2Mnemonic.RANDOM: + _random(); + break; + case T2Mnemonic.MUL: + _mul(); + break; + case T2Mnemonic.SQRT: + _sqrt(); + break; + case T2Mnemonic.DUP: + _dup(); + break; + case T2Mnemonic.EXCH: + _exch(); + break; + case T2Mnemonic.INDEX: + _index(); + break; + case T2Mnemonic.ROLL: + _roll(); + break; + case T2Mnemonic.HFLEX: + _hflex(); + break; + case T2Mnemonic.FLEX: + _flex(); + break; + case T2Mnemonic.HFLEX1: + _hflex1(); + break; + case T2Mnemonic.FLEX1: + _flex1(); + break; + default: + //throw new Exception(); + return null; + } + } else { + + // One-byte operators + switch (operator) { + case T2Mnemonic.HSTEM: + _hstem(); + break; + case T2Mnemonic.VSTEM: + _vstem(); + break; + case T2Mnemonic.VMOVETO: + _vmoveto(); + break; + case T2Mnemonic.RLINETO: + _rlineto(); + break; + case T2Mnemonic.HLINETO: + _hlineto(); + break; + case T2Mnemonic.VLINETO: + _vlineto(); + break; + case T2Mnemonic.RRCURVETO: + _rrcurveto(); + break; + case T2Mnemonic.CALLSUBR: + _callsubr(); + break; + case T2Mnemonic.RETURN: + _return(); + break; + case T2Mnemonic.ENDCHAR: + _endchar(); + break; + case T2Mnemonic.HSTEMHM: + _hstemhm(); + break; + case T2Mnemonic.HINTMASK: + _hintmask(); + break; + case T2Mnemonic.CNTRMASK: + _cntrmask(); + break; + case T2Mnemonic.RMOVETO: + _rmoveto(); + break; + case T2Mnemonic.HMOVETO: + _hmoveto(); + break; + case T2Mnemonic.VSTEMHM: + _vstemhm(); + break; + case T2Mnemonic.RCURVELINE: + _rcurveline(); + break; + case T2Mnemonic.RLINECURVE: + _rlinecurve(); + break; + case T2Mnemonic.VVCURVETO: + _vvcurveto(); + break; + case T2Mnemonic.HHCURVETO: + _hhcurveto(); + break; + case T2Mnemonic.CALLGSUBR: + _callgsubr(); + break; + case T2Mnemonic.VHCURVETO: + _vhcurveto(); + break; + case T2Mnemonic.HVCURVETO: + _hvcurveto(); + break; + default: + //throw new Exception(); + return null; + } + } + } + Point[] pointArray = new Point[_points.size()]; + _points.toArray(pointArray); + return pointArray; + } + + /** + * The number of arguments on the argument stack + */ + private int getArgCount() { + return _argStackIndex; + } + + /** + * Pop a value off the argument stack + */ + private Number popArg() { + return _argStack[--_argStackIndex]; + } + + /** + * Push a value on to the argument stack + */ + private void pushArg(Number n) { + _argStack[_argStackIndex++] = n; + } + + /** + * Pop a value off the subroutine stack + */ + private int popSubr() { + return _subrStack[--_subrStackIndex]; + } + + /** + * Push a value on to the subroutine stack + */ + private void pushSubr(int n) { + _subrStack[_subrStackIndex++] = n; + } + + /** + * Clear the argument stack + */ + private void clearArg() { + _argStackIndex = 0; + } + + private Point getLastPoint() { + int size = _points.size(); + if (size > 0) { + return _points.get(size - 1); + } else { + return new Point(0, 0, true, false); + } + } + + private void moveTo(int x, int y) { + endContour(); + _points.add(new Point(x, y, true, false)); + } + + private void lineTo(int x, int y) { + _points.add(new Point(x, y, true, false)); + } + + private void curveTo(int cx1, int cy1, int cx2, int cy2, int x, int y) { + _points.add(new Point(cx1, cy1, false, false)); + _points.add(new Point(cx2, cy2, false, false)); + _points.add(new Point(x, y, true, false)); + } + + private void endContour() { + Point lastPoint = getLastPoint(); + if (lastPoint != null) { + lastPoint.endOfContour = true; + } + } +} diff --git a/src/net/java/dev/typecast/t2/T2Mnemonic.java b/src/net/java/dev/typecast/t2/T2Mnemonic.java new file mode 100644 index 000000000..810aea159 --- /dev/null +++ b/src/net/java/dev/typecast/t2/T2Mnemonic.java @@ -0,0 +1,86 @@ +/* + * $Id: T2Mnemonic.java,v 1.1 2007-02-21 12:30:48 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2007 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.t2; + +/** + * The Mnemonic representations of the Type 2 charstring instruction set. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: T2Mnemonic.java,v 1.1 2007-02-21 12:30:48 davidsch Exp $ + */ +public class T2Mnemonic { + + /** + * One byte operators + */ + public static final short HSTEM = 0x01; + public static final short VSTEM = 0x03; + public static final short VMOVETO = 0x04; + public static final short RLINETO = 0x05; + public static final short HLINETO = 0x06; + public static final short VLINETO = 0x07; + public static final short RRCURVETO = 0x08; + public static final short CALLSUBR = 0x0a; + public static final short RETURN = 0x0b; + public static final short ESCAPE = 0x0c; + public static final short ENDCHAR = 0x0e; + public static final short HSTEMHM = 0x12; + public static final short HINTMASK = 0x13; + public static final short CNTRMASK = 0x14; + public static final short RMOVETO = 0x15; + public static final short HMOVETO = 0x16; + public static final short VSTEMHM = 0x17; + public static final short RCURVELINE = 0x18; + public static final short RLINECURVE = 0x19; + public static final short VVCURVETO = 0x1a; + public static final short HHCURVETO = 0x1b; + public static final short CALLGSUBR = 0x1d; + public static final short VHCURVETO = 0x1e; + public static final short HVCURVETO = 0x1f; + + /** + * Two byte operators + */ + public static final short DOTSECTION = 0x00; + public static final short AND = 0x03; + public static final short OR = 0x04; + public static final short NOT = 0x05; + public static final short ABS = 0x09; + public static final short ADD = 0x0a; + public static final short SUB = 0x0b; + public static final short DIV = 0x0c; + public static final short NEG = 0x0e; + public static final short EQ = 0x0f; + public static final short DROP = 0x12; + public static final short PUT = 0x14; + public static final short GET = 0x15; + public static final short IFELSE = 0x16; + public static final short RANDOM = 0x17; + public static final short MUL = 0x18; + public static final short SQRT = 0x1a; + public static final short DUP = 0x1b; + public static final short EXCH = 0x1c; + public static final short INDEX = 0x1d; + public static final short ROLL = 0x1e; + public static final short HFLEX = 0x22; + public static final short FLEX = 0x23; + public static final short HFLEX1 = 0x24; + public static final short FLEX1 = 0x25; +} diff --git a/src/net/java/dev/typecast/tt/engine/GraphicsState.java b/src/net/java/dev/typecast/tt/engine/GraphicsState.java new file mode 100644 index 000000000..1c36bd3de --- /dev/null +++ b/src/net/java/dev/typecast/tt/engine/GraphicsState.java @@ -0,0 +1,50 @@ +/* + * $Id: GraphicsState.java,v 1.1.1.1 2004-12-05 23:15:01 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.tt.engine; + +/** + * Maintains the graphics state whilst interpreting hinting instructions. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: GraphicsState.java,v 1.1.1.1 2004-12-05 23:15:01 davidsch Exp $ + */ +class GraphicsState { + + public boolean auto_flip = true; + public int control_value_cut_in = 0; + public int delta_base = 9; + public int delta_shift = 3; + public int dual_projection_vectors; + public int[] freedom_vector = new int[2]; + public int zp0 = 1; + public int zp1 = 1; + public int zp2 = 1; + public int instruction_control = 0; + public int loop = 1; + public int minimum_distance = 1; + public int[] projection_vector = new int[2]; + public int round_state = 1; + public int rp0 = 0; + public int rp1 = 0; + public int rp2 = 0; + public int scan_control = 0; + public int single_width_cut_in = 0; + public int single_width_value = 0; +} diff --git a/src/net/java/dev/typecast/tt/engine/Interpreter.java b/src/net/java/dev/typecast/tt/engine/Interpreter.java new file mode 100644 index 000000000..6f436d764 --- /dev/null +++ b/src/net/java/dev/typecast/tt/engine/Interpreter.java @@ -0,0 +1,1357 @@ +/* + * $Id: Interpreter.java,v 1.1.1.1 2004-12-05 23:15:05 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.tt.engine; + +import net.java.dev.typecast.ot.Mnemonic; +import net.java.dev.typecast.ot.Point; + +/** + * The interpreter shall remain ignorant of the table structure - the table + * data will be extracted by supporting classes, whether it be the Parser + * or some other. + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Interpreter.java,v 1.1.1.1 2004-12-05 23:15:05 davidsch Exp $ + */ +public class Interpreter { + + private Parser parser = null; + private GraphicsState gs = new GraphicsState(); + private Point[][] zone = new Point[2][]; + private int[] stack = null; + private int[] store = null; + private int[] cvt = new int[256]; + private int[] functionMap = null; + private int stackIndex = 0; + private boolean inFuncDef = false; + + public Interpreter(int stackMax, int storeMax, int funcMax) { + zone[0] = new Point[256]; + zone[1] = new Point[256]; + stack = new int[stackMax]; + store = new int[storeMax]; + functionMap = new int[funcMax]; + } + + /** + * ABSolute value + */ + private void _abs() { + int n = pop(); + if (n >= 0) { + push(n); + } else { + push(-n); + } + } + + /** + * ADD + */ + private void _add() { + int n1 = pop(); + int n2 = pop(); + push(n2 + n1); + } + + private void _alignpts() { + pop(); + pop(); + } + + /** + * + * + * USES: loop + */ + private void _alignrp() { + while (gs.loop-- > 0) { + pop(); + } + gs.loop = 1; + } + + /** + * logical AND + */ + private void _and() { + int e2 = pop(); + int e1 = pop(); + push(((e1 != 0) && (e2 != 0)) ? 1 : 0); + } + + /** + * CALL function + */ + private void _call() { + execute(functionMap[pop()]); + } + + /** + * CEILING + */ + private void _ceiling() { + int n = pop(); + if (n >= 0) { + push((n & 0xffc0) + (((n & 0x3f) != 0) ? 0x40 : 0)); + } else { + push(n & 0xffc0); + } + } + + /** + * Copy the INDEXed element to the top of the stack + */ + private void _cindex() { + push(stack[stackIndex - pop()]); + } + + /** + * CLEAR the entire stack + */ + private void _clear() { + stackIndex = 0; + } + + private void _debug() { + pop(); + } + + /** + * DELTA exception C1 + */ + private void _deltac1() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception C2 + */ + private void _deltac2() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception C3 + */ + private void _deltac3() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception P1 + */ + private void _deltap1() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception P2 + */ + private void _deltap2() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * DELTA exception P3 + */ + private void _deltap3() { + int n = pop(); + for (int i = 0; i < n; i++) { + pop(); // pn + pop(); // argn + } + } + + /** + * Returns the DEPTH of the stack + */ + private void _depth() { + push(stackIndex); + } + + /** + * DIVide + */ + private void _div() { + int n1 = pop(); + int n2 = pop(); + push((n2 / n1) >> 6); + } + + /** + * DUPlicate top stack element + */ + private void _dup() { + int n = pop(); + push(n); + push(n); + } + + /** + * ELSE + */ + private int _else(int instructionIndex) { + return parser.handleElse(instructionIndex); + } + + /** + * EQual + */ + private void _eq() { + int e2 = pop(); + int e1 = pop(); + push((e1 == e2) ? 1 : 0); + } + + private void _even() { + pop(); + push(0); + } + + /** + * Function DEFinition + */ + private void _fdef(int instructionIndex) { + functionMap[pop()] = instructionIndex; + inFuncDef = true; + } + + /** + * Set the auto_FLIP boolean to OFF + */ + private void _flipoff() { + gs.auto_flip = false; + } + + /** + * Set the auto_FLIP boolean to ON + */ + private void _flipon() { + gs.auto_flip = true; + } + + /** + * FLIP PoinT + * + * USES: loop + */ + private void _flippt() { + while(gs.loop-- > 0) { + int index = pop(); + zone[gs.zp0][index].onCurve = !zone[gs.zp0][index].onCurve; + } + gs.loop = 1; + } + + /** + * FLIP RanGe OFF + */ + private void _fliprgoff() { + int end = pop(); + int start = pop(); + for (int i = start; i <= end; i++) { + zone[1][i].onCurve = false; + } + } + + /** + * FLIP RanGe ON + */ + private void _fliprgon() { + int end = pop(); + int start = pop(); + for (int i = start; i <= end; i++) { + zone[1][i].onCurve = true; + } + } + + /** + * FLOOR + */ + private void _floor() { + int n = pop(); + if (n >= 0) { + push(n & 0xffc0); + } else { + push((n & 0xffc0) - (((n & 0x3f) != 0) ? 0x40 : 0)); + } + } + + private void _gc(short param) { + pop(); + push(0); + } + + private void _getinfo() { + pop(); + push(0); + } + + /** + * Get Freedom_Vector + */ + private void _gfv() { + push(gs.freedom_vector[0]); + push(gs.freedom_vector[1]); + } + + /** + * Get Projection_Vector + */ + private void _gpv() { + push(gs.projection_vector[0]); + push(gs.projection_vector[1]); + } + + /** + * Greater Than + */ + private void _gt() { + int e2 = pop(); + int e1 = pop(); + push((e1 > e2) ? 1 : 0); + } + + /** + * Greater Than or EQual + */ + private void _gteq() { + int e2 = pop(); + int e1 = pop(); + push((e1 >= e2) ? 1 : 0); + } + + /** + * Instruction DEFinition + */ + private void _idef() { + pop(); + inFuncDef = true; + } + + /** + * IF test + */ + private int _if(int instructionIndex) { + return parser.handleIf(pop() != 0, instructionIndex); + } + + /** + * INSTruction Execution ConTRol + * + * INSTCTRL[] + * + * Code Range + * 0x8E + * + * Pops + * s: selector flag (int32) + * value: USHORT (padded to 32 bits) used to set value of instruction_control. + * + * Pushes + * - + * + * Sets + * instruction_control + * + * Sets the instruction control state variable making it possible to turn on or off + * the execution of instructions and to regulate use of parameters set in the CVT + * program. INSTCTRL[ ] can only be executed in the CVT program. + * + * This instruction clears and sets various control flags in the rasterizer. The + * selector flag determines valid values for the value argument. The value determines + * the new setting of the raterizer control flag. In version 1.0 there are only two + * flags in use: + * + * Selector flag 1 is used to inhibit grid-fitting. If s=1, valid values for the + * value argument are 0 (FALSE) and 1 (TRUE). If the value argument is set to TRUE + * (v=1), any instructions associated with glyphs will not be executed. For example, + * to inhibit grid-fitting when a glyph is being rotated or stretched, use the + * following sequence on the preprogram: + * + * PUSHB[000] 6 ; ask GETINFO to check for stretching or rotation + * GETINFO[] ; will push TRUE if glyph is stretched or rotated + * IF[] ; tests value at top of stack + * PUSHB[000] 1 ; value for INSTCTRL + * PUSHB[000] 1 ; selector for INSTCTRL + * INSTRCTRL[] ; based on selector and value will turn grid-fitting off + * EIF[] + * + * Selector flag 2 is used to establish that any parameters set in the CVT program + * should be ignored when instructions associated with glyphs are executed. These + * include, for example, the values for scantype and the CVT cut-in. If s=1, valid + * values for the value argument are 0 (FALSE) and 2 (TRUE). If the value argument is + * set to TRUE (v=2), the default values of those parameters will be used regardless + * of any changes that may have been made in those values by the preprogram. If the + * value argument is set to FALSE (v=0), parameter values changed by the CVT program + * will be used in glyph instructions. + */ + private void _instctrl() { + int s = pop(); + int v = pop(); + if (s == 1) { + gs.instruction_control |= v; + } else if (s == 2) { + gs.instruction_control |= v; + } + } + + private void _ip() { + pop(); + } + + private void _isect() { + pop(); + pop(); + pop(); + pop(); + pop(); + } + + private void _iup(short param) { + } + + /** + * JuMP Relative + */ + private int _jmpr(int instructionIndex) { + return instructionIndex += pop() - 1; + } + + /** + * Jump Relative On False + */ + private int _jrof(int instructionIndex) { + boolean test = pop() != 0; + int offset = pop(); + if (!test) { + instructionIndex += offset - 1; + } + return instructionIndex; + } + + /** + * Jump Relative On True + */ + private int _jrot(int instructionIndex) { + boolean test = pop() != 0; + int offset = pop(); + if (test) { + instructionIndex += offset - 1; + } + return instructionIndex; + } + + /** + * LOOP and CALL function + */ + private void _loopcall() { + int index = pop(); + int count = pop(); + for (int i = 0; i < count; i++) { + execute(functionMap[i]); + } + } + + /** + * Less Than + */ + private void _lt() { + int e2 = pop(); + int e1 = pop(); + push((e1 < e2) ? 1 : 0); + } + + /** + * Less Than or EQual + */ + private void _lteq() { + int e2 = pop(); + int e1 = pop(); + push((e1 <= e2) ? 1 : 0); + } + + /** + * MAXimum of top two stack elements + */ + private void _max() { + int n1 = pop(); + int n2 = pop(); + push((n1 > n2) ? n1 : n2); + } + + private void _md(short param) { + pop(); + pop(); + push(0); + } + + private void _mdap(short param) { + pop(); + } + + private void _mdrp(short param) { + pop(); + } + + private void _miap(short param) { + pop(); + pop(); + } + /** + * MINimum of top two stack elements + */ + private void _min() { + int n1 = pop(); + int n2 = pop(); + push((n1 < n2) ? n1 : n2); + } + + /** + * Move the INDEXed element to the top of the stack + */ + private void _mindex() { + // Move the indexed element to stackIndex, and shift the others down + int k = pop(); + int e = stack[stackIndex - k]; + for (int i = stackIndex - k; i < stackIndex - 1; i++) { + stack[i] = stack[i+1]; + } + stack[stackIndex - 1] = e; + } + + private void _mirp(short param) { + pop(); + pop(); + } + + private void _mppem() { + push(0); + } + + private void _mps() { + push(0); + } + + private void _msirp(short param) { + pop(); + pop(); + } + + /** + * MULtiply + */ + private void _mul() { + int n1 = pop(); + int n2 = pop(); + push((n1 * n2) >> 6); + } + + /** + * NEGate + */ + private void _neg() { + push(-pop()); + } + + /** + * Not EQual + */ + private void _neq() { + int e2 = pop(); + int e1 = pop(); + push((e1 != e2) ? 1 : 0); + } + + /** + * logical NOT + */ + private void _not() { + push((pop() != 0) ? 0 : 1); + } + + private void _nround(short param) { + pop(); + push(0); + } + + private void _odd() { + pop(); + push(0); + } + + /** + * logical OR + */ + private void _or() { + int e2 = pop(); + int e1 = pop(); + push(((e1 != 0) || (e2 != 0)) ? 1 : 0); + } + + /** + * PUSH N Bytes + * PUSH N Words + * PUSH Bytes + * PUSH Words + */ + private void _push(int[] data) { + for (int j = 0; j < data.length; j++) { + push(data[j]); + } + } + + /** + * Read Control Value Table + */ + private void _rcvt() { + push(cvt[pop()]); + } + + /** + * Round Down To Grid + */ + private void _rdtg() { + gs.round_state = 3; + } + + /** + * Round OFF + */ + private void _roff() { + gs.round_state = 5; + } + + /** + * ROLL the top three stack elements + */ + private void _roll() { + int a = pop(); + int b = pop(); + int c = pop(); + push(b); + push(a); + push(c); + } + + private void _round(short param) { + pop(); + push(0); + } + + /** + * Read Store + */ + private void _rs() { + push(store[pop()]); + } + + /** + * Round To Double Grid + */ + private void _rtdg() { + gs.round_state = 2; + } + + /** + * Round To Grid + */ + private void _rtg() { + gs.round_state = 1; + } + + /** + * Round To Half Grid + */ + private void _rthg() { + gs.round_state = 0; + } + + /** + * Round Up To Grid + */ + private void _rutg() { + gs.round_state = 4; + } + + private void _s45round() { + pop(); + } + + /** + * SCAN conversion ConTRoL + * + * SCANCTRL[ ] + * + * Code Range + * 0x85 + * + * Pops + * n: flags indicating when to turn on dropout control mode (16 bit word padded + * to 32 bits) + * + * Pushes + * - + * + * Sets + * scan_control + * + * SCANCTRL is used to set the value of the Graphics State variable scan_control + * which in turn determines whether the scan converter will activate dropout + * control for this glyph. Use of the dropout control mode is determined by three + * conditions: + * + * Is the glyph rotated? + * + * Is the glyph stretched? + * + * Is the current setting for ppem less than a specified threshold? + * + * The interpreter pops a word from the stack and looks at the lower 16 bits. + * + * Bits 0-7 represent the threshold value for ppem. A value of FF in bits 0-7 + * means invoke dropout_control for all sizes. A value of 0 in bits 0-7 means + * never invoke dropout_control. + * + * Bits 8-13 are used to turn on dropout_control in cases where the specified + * conditions are met. Bits 8, 9 and 10 are used to turn on the dropout_control + * mode (assuming other conditions do not block it). Bits 11, 12, and 13 are + * used to turn off the dropout mode unless other conditions force it. Bits 14 + * and 15 are reserved for future use. + * + * Bit Meaning if set + * --- -------------- + * 8 Set dropout_control to TRUE if other conditions do not block and ppem + * is less than or equal to the threshold value. + * + * 9 Set dropout_control to TRUE if other conditions do not block and the + * glyph is rotated. + * + * 10 Set dropout_control to TRUE if other conditions do not block and the + * glyph is stretched. + * + * 11 Set dropout_control to FALSE unless ppem is less than or equal to the + * threshold value. + * + * 12 Set dropout_control to FALSE unless the glyph is rotated. + * + * 13 Set dropout_control to FALSE unless the glyph is stretched. + * + * 14 Reserved for future use. + * + * 15 Reserved for future use. + * + * For example + * 0x0000 No dropout control is invoked + * 0x01FF Always do dropout control + * 0x0A10 Do dropout control if the glyph is rotated and has less than 16 + * pixels per-em + * + * The scan converter can operate in either a "normal" mode or in a "fix dropout" + * mode depending on the value of a set of enabling and disabling flags. + */ + private void _scanctrl() { + gs.scan_control = pop(); + } + + /** + * SCANTYPE + * + * SCANTYPE[] + * + * Code Range + * 0x8D + * + * Pops + * n: 16 bit integer + * + * Pushes + * - + * + * Sets + * scan_control + * + * Pops a 16-bit integer whose value is used to determine which rules the scan + * converter will use. If the value of the argument is 0, the fast scan converter + * will be used. If the value of the integer is 1 or 2, simple dropout control will + * be used. If the value of the integer is 4 or 5, smart dropout control will be + * used. More specifically, + * + * if n=0 rules 1, 2, and 3 are invoked (simple dropout control scan conversion + * including stubs) + * + * if n=1 rules 1, 2, and 4 are invoked (simple dropout control scan conversion + * excluding stubs) + * + * if n=2 rules 1 and 2 only are invoked (fast scan conversion; dropout control + * turned off) + * + * if n=3 same as n = 2 + * + * if n = 4 rules 1, 2, and 5 are invoked (smart dropout control scan conversion + * including stubs) + * + * if n = 5 rules 1, 2, and 6 are invoked (smart dropout control scan conversion + * excluding stubs) + * + * if n = 6 same as n = 2 + * + * if n = 7 same as n = 2 + * + * The scan conversion rules are shown here: + * + * Rule 1 + * If a pixel's center falls within the glyph outline, that pixel is turned on. + * + * Rule 2 + * If a contour falls exactly on a pixel's center, that pixel is turned on. + * + * Rule 3 + * If a scan line between two adjacent pixel centers (either vertical or + * horizontal) is intersected by both an on-Transition contour and an off-Transition + * contour and neither of the pixels was already turned on by rules 1 and 2, turn on + * the left-most pixel (horizontal scan line) or the bottom-most pixel (vertical scan + * line). This is "Simple" dropout control. + * + * Rule 4 + * Apply Rule 3 only if the two contours continue to intersect other scan lines in + * both directions. That is, do not turn on pixels for 'stubs.' The scanline segments + * that form a square with the intersected scan line segment are examined to verify + * that they are intersected by two contours. It is possible that these could be + * different contours than the ones intersecting the dropout scan line segment. This + * is very unlikely but may have to be controlled with grid-fitting in some exotic + * glyphs. + * + * Rule 5 + * If a scan line between two adjacent pixel centers (either vertical or horizontal) + * is intersected by both an on-Transition contour and an off-Transition contour and + * neither of the pixels was already turned on by rules 1 and 2, turn on the pixel + * which is closer to the midpoint between the on-Transition contour and off- + * Transition contour. This is "Smart" dropout control. + * + * Rule 6 + * Apply Rule 5 only if the two contours continue to intersect other scan lines in + * both directions. That is, do not turn on pixels for 'stubs.' + * + * New fonts wishing to use the new modes of the ScanType instruction, but still + * wishing to work correctly on old rasterizers that don't recognize the new modes + * should: + * + * First execute a ScanType instruction using an old mode which will give the best + * approximation to the desired new mode (e.g. Simple Stubs for Smart Stubs), and + * then + * + * Immediately execute another ScanType instruction with the desired new mode. + */ + private void _scantype() { + pop(); + } + + private void _scfs() { + pop(); + pop(); + } + + /** + * Set Control Value Table Cut In + */ + private void _scvtci() { + gs.control_value_cut_in = pop(); + } + + /** + * Set Delta_Base in the graphics state + */ + private void _sdb() { + gs.delta_base = pop(); + } + + /** + * Set Dual Projection_Vector To Line + */ + private void _sdpvtl(short param) { + pop(); + pop(); + } + + /** + * Set Delta_Shift in the graphics state + */ + private void _sds() { + gs.delta_shift = pop(); + } + + /** + * Set Freedom_Vector From Stack + */ + private void _sfvfs() { + gs.freedom_vector[1] = pop(); // y + gs.freedom_vector[0] = pop(); // x + } + + /* + * Set Freedom_Vector to Coordinate Axis + */ + private void _sfvtca(short param) { + if (param == 1) { + gs.freedom_vector[0] = 0x4000; + gs.freedom_vector[1] = 0x0000; + } else { + gs.freedom_vector[0] = 0x0000; + gs.freedom_vector[1] = 0x4000; + } + } + + /* + * Set Freedom_Vector To Line + */ + private void _sfvtl(short param) { + pop(); + pop(); + if (param == 1) { + gs.freedom_vector[0] = 0x0000; + gs.freedom_vector[1] = 0x0000; + } else { + gs.freedom_vector[0] = 0x0000; + gs.freedom_vector[1] = 0x0000; + } + } + + /** + * Set Freedom_Vector To Projection Vector + */ + private void _sfvtpv() { + gs.freedom_vector[0] = gs.projection_vector[0]; + gs.freedom_vector[1] = gs.projection_vector[1]; + } + + private void _shc(short param) { + pop(); + } + + /** + * SHift Point by the last point + * + * USES: loop + */ + private void _shp(short param) { + while(gs.loop-- > 0) { + pop(); + if(param == 0) { + } else { + } + } + gs.loop = 1; + } + + /** + * SHift Point by a PIXel amount + * + * USES: loop + */ + private void _shpix() { + pop(); // amount + while (gs.loop-- > 0) { + pop(); // p + } + gs.loop = 1; + } + + private void _shz(short param) { + pop(); + } + + /** + * Set LOOP variable + */ + private void _sloop() { + gs.loop = pop(); + } + + /** + * Set Minimum_Distance + */ + private void _smd() { + gs.minimum_distance = pop(); + } + + /** + * Set Projection_Vector From Stack + */ + private void _spvfs() { + gs.projection_vector[1] = pop(); // y + gs.projection_vector[0] = pop(); // x + } + + /* + * Set Projection_Vector To Coordinate Axis + */ + private void _spvtca(short param) { + if (param == 1) { + gs.projection_vector[0] = 0x4000; + gs.projection_vector[1] = 0x0000; + } else { + gs.projection_vector[0] = 0x0000; + gs.projection_vector[1] = 0x4000; + } + } + + /** + * Set Projection_Vector To Line + */ + private void _spvtl(short param) { + + // We'll get a copy of the line and normalize it - + // divide the x- and y-coords by the vector's dot product. + Point p1 = zone[gs.zp2][pop()]; + Point p2 = zone[gs.zp1][pop()]; + int x = p2.x - p1.x; + int y = p2.y - p1.y; + if(param == 1) { + gs.projection_vector[0] = 0x0000; + gs.projection_vector[1] = 0x0000; + } else { + gs.projection_vector[0] = 0x0000; + gs.projection_vector[1] = 0x0000; + } + } + + private void _sround() { + pop(); + } + + /** + * Set Reference Point 0 + */ + private void _srp0() { + gs.rp0 = pop(); + } + + /** + * Set Reference Point 1 + */ + private void _srp1() { + gs.rp1 = pop(); + } + + /** + * Set Reference Point 2 + */ + private void _srp2() { + gs.rp2 = pop(); + } + + /** + * Set Single-Width + */ + private void _ssw() { + gs.single_width_value = pop(); + } + + /** + * Set Single_Width_Cut_In + */ + private void _sswci() { + gs.single_width_cut_in = pop(); + } + + /** + * SUBtract + */ + private void _sub() { + int n1 = pop(); + int n2 = pop(); + push(n2 - n1); + } + + /** + * Set freedom and projection Vectors To Coordinate Axis + */ + private void _svtca(short param) { + if (param == 1) { + gs.projection_vector[0] = 0x4000; + gs.projection_vector[1] = 0x0000; + gs.freedom_vector[0] = 0x4000; + gs.freedom_vector[1] = 0x0000; + } else { + gs.projection_vector[0] = 0x0000; + gs.projection_vector[1] = 0x4000; + gs.freedom_vector[0] = 0x0000; + gs.freedom_vector[1] = 0x4000; + } + } + + /** + * SWAP the top two elements on the stack + */ + private void _swap() { + int n1 = pop(); + int n2 = pop(); + push(n1); + push(n2); + } + + /** + * Set Zone Pointer 0 + */ + private void _szp0() { + gs.zp0 = pop(); + } + + /** + * Set Zone Pointer 1 + */ + private void _szp1() { + gs.zp1 = pop(); + } + + /** + * Set Zone Pointer 2 + */ + private void _szp2() { + gs.zp2 = pop(); + } + + /** + * Set Zone PointerS + */ + private void _szps() { + gs.zp0 = gs.zp1 = gs.zp2 = pop(); + } + + private void _utp() { + pop(); + } + + /** + * Write Control Value Table in FUnits + */ + private void _wcvtf() { + int value = pop(); + // Conversion of value goes here + cvt[pop()] = value; + } + + /** + * Write Control Value Table in Pixel units + */ + private void _wcvtp() { + int value = pop(); + // Conversion of value goes here + cvt[pop()] = value; + } + + /** + * Write Store + */ + private void _ws() { + store[pop()] = pop(); + } + + public void execute(int ip) { + while (ip < ((ip & 0xffff0000) | parser.getISLength(ip >> 16))) { + short opcode = parser.getOpcode(ip); + if (inFuncDef) { + + // We're within a function definition, so don't execute the code + if (opcode == Mnemonic.ENDF) { + inFuncDef = false; + } + ip = parser.advanceIP(ip); + continue; + } + if (opcode >= Mnemonic.MIRP) _mirp((short)(opcode & 31)); + else if (opcode >= Mnemonic.MDRP) _mdrp((short)(opcode & 31)); + else if (opcode >= Mnemonic.PUSHW) _push(parser.getPushData(ip)); + else if (opcode >= Mnemonic.PUSHB) _push(parser.getPushData(ip)); + else if (opcode >= Mnemonic.INSTCTRL) _instctrl(); + else if (opcode >= Mnemonic.SCANTYPE) _scantype(); + else if (opcode >= Mnemonic.MIN) _min(); + else if (opcode >= Mnemonic.MAX) _max(); + else if (opcode >= Mnemonic.ROLL) _roll(); + else if (opcode >= Mnemonic.IDEF) _idef(); + else if (opcode >= Mnemonic.GETINFO) _getinfo(); + else if (opcode >= Mnemonic.SDPVTL) _sdpvtl((short)(opcode & 1)); + else if (opcode >= Mnemonic.SCANCTRL) _scanctrl(); + else if (opcode >= Mnemonic.FLIPRGOFF) _fliprgoff(); + else if (opcode >= Mnemonic.FLIPRGON) _fliprgon(); + else if (opcode >= Mnemonic.FLIPPT) _flippt(); + else if (opcode >= Mnemonic.AA); // AA (ignored) + else if (opcode >= Mnemonic.SANGW); // SANGW (ignored) + else if (opcode >= Mnemonic.RDTG) _rdtg(); + else if (opcode >= Mnemonic.RUTG) _rutg(); + else if (opcode >= Mnemonic.ROFF) _roff(); + else if (opcode >= Mnemonic.JROF) ip = _jrof(ip); + else if (opcode >= Mnemonic.JROT) ip = _jrot(ip); + else if (opcode >= Mnemonic.S45ROUND) _s45round(); + else if (opcode >= Mnemonic.SROUND) _sround(); + else if (opcode >= Mnemonic.DELTAC3) _deltac3(); + else if (opcode >= Mnemonic.DELTAC2) _deltac2(); + else if (opcode >= Mnemonic.DELTAC1) _deltac1(); + else if (opcode >= Mnemonic.DELTAP3) _deltap3(); + else if (opcode >= Mnemonic.DELTAP2) _deltap2(); + else if (opcode >= Mnemonic.WCVTF) _wcvtf(); + else if (opcode >= Mnemonic.NROUND) _nround((short)(opcode & 3)); + else if (opcode >= Mnemonic.ROUND) _round((short)(opcode & 3)); + else if (opcode >= Mnemonic.CEILING) _ceiling(); + else if (opcode >= Mnemonic.FLOOR) _floor(); + else if (opcode >= Mnemonic.NEG) _neg(); + else if (opcode >= Mnemonic.ABS) _abs(); + else if (opcode >= Mnemonic.MUL) _mul(); + else if (opcode >= Mnemonic.DIV) _div(); + else if (opcode >= Mnemonic.SUB) _sub(); + else if (opcode >= Mnemonic.ADD) _add(); + else if (opcode >= Mnemonic.SDS) _sds(); + else if (opcode >= Mnemonic.SDB) _sdb(); + else if (opcode >= Mnemonic.DELTAP1) _deltap1(); + else if (opcode >= Mnemonic.NOT) _not(); + else if (opcode >= Mnemonic.OR) _or(); + else if (opcode >= Mnemonic.AND) _and(); + else if (opcode >= Mnemonic.EIF); // EIF + else if (opcode >= Mnemonic.IF) ip = _if(ip); + else if (opcode >= Mnemonic.EVEN) _even(); + else if (opcode >= Mnemonic.ODD) _odd(); + else if (opcode >= Mnemonic.NEQ) _neq(); + else if (opcode >= Mnemonic.EQ) _eq(); + else if (opcode >= Mnemonic.GTEQ) _gteq(); + else if (opcode >= Mnemonic.GT) _gt(); + else if (opcode >= Mnemonic.LTEQ) _lteq(); + else if (opcode >= Mnemonic.LT) _lt(); + else if (opcode >= Mnemonic.DEBUG) _debug(); + else if (opcode >= Mnemonic.FLIPOFF) _flipoff(); + else if (opcode >= Mnemonic.FLIPON) _flipon(); + else if (opcode >= Mnemonic.MPS) _mps(); + else if (opcode >= Mnemonic.MPPEM) _mppem(); + else if (opcode >= Mnemonic.MD) _md((short)(opcode & 1)); + else if (opcode >= Mnemonic.SCFS) _scfs(); + else if (opcode >= Mnemonic.GC) _gc((short)(opcode & 1)); + else if (opcode >= Mnemonic.RCVT) _rcvt(); + else if (opcode >= Mnemonic.WCVTP) _wcvtp(); + else if (opcode >= Mnemonic.RS) _rs(); + else if (opcode >= Mnemonic.WS) _ws(); + else if (opcode >= Mnemonic.NPUSHW) _push(parser.getPushData(ip)); + else if (opcode >= Mnemonic.NPUSHB) _push(parser.getPushData(ip)); + else if (opcode >= Mnemonic.MIAP) _miap((short)(opcode & 1)); + else if (opcode >= Mnemonic.RTDG) _rtdg(); + else if (opcode >= Mnemonic.ALIGNRP) _alignrp(); + else if (opcode >= Mnemonic.IP) _ip(); + else if (opcode >= Mnemonic.MSIRP) _msirp((short)(opcode & 1)); + else if (opcode >= Mnemonic.SHPIX) _shpix(); + else if (opcode >= Mnemonic.SHZ) _shz((short)(opcode & 1)); + else if (opcode >= Mnemonic.SHC) _shc((short)(opcode & 1)); + else if (opcode >= Mnemonic.SHP) _shp((short)(opcode & 1)); + else if (opcode >= Mnemonic.IUP) _iup((short)(opcode & 1)); + else if (opcode >= Mnemonic.MDAP) _mdap((short)(opcode & 1)); + else if (opcode >= Mnemonic.ENDF) return; + else if (opcode >= Mnemonic.FDEF) _fdef(ip + 1); + else if (opcode >= Mnemonic.CALL) _call(); + else if (opcode >= Mnemonic.LOOPCALL) _loopcall(); + else if (opcode >= Mnemonic.UTP) _utp(); + else if (opcode >= Mnemonic.ALIGNPTS) _alignpts(); + else if (opcode >= Mnemonic.MINDEX) _mindex(); + else if (opcode >= Mnemonic.CINDEX) _cindex(); + else if (opcode >= Mnemonic.DEPTH) _depth(); + else if (opcode >= Mnemonic.SWAP) _swap(); + else if (opcode >= Mnemonic.CLEAR) _clear(); + else if (opcode >= Mnemonic.POP) pop(); + else if (opcode >= Mnemonic.DUP) _dup(); + else if (opcode >= Mnemonic.SSW) _ssw(); + else if (opcode >= Mnemonic.SSWCI) _sswci(); + else if (opcode >= Mnemonic.SCVTCI) _scvtci(); + else if (opcode >= Mnemonic.JMPR) ip = _jmpr(ip); + else if (opcode >= Mnemonic.ELSE) ip = _else(ip); + else if (opcode >= Mnemonic.SMD) _smd(); + else if (opcode >= Mnemonic.RTHG) _rthg(); + else if (opcode >= Mnemonic.RTG) _rtg(); + else if (opcode >= Mnemonic.SLOOP) _sloop(); + else if (opcode >= Mnemonic.SZPS) _szps(); + else if (opcode >= Mnemonic.SZP2) _szp2(); + else if (opcode >= Mnemonic.SZP1) _szp1(); + else if (opcode >= Mnemonic.SZP0) _szp0(); + else if (opcode >= Mnemonic.SRP2) _srp2(); + else if (opcode >= Mnemonic.SRP1) _srp1(); + else if (opcode >= Mnemonic.SRP0) _srp0(); + else if (opcode >= Mnemonic.ISECT) _isect(); + else if (opcode >= Mnemonic.SFVTPV) _sfvtpv(); + else if (opcode >= Mnemonic.GFV) _gfv(); + else if (opcode >= Mnemonic.GPV) _gpv(); + else if (opcode >= Mnemonic.SFVFS) _sfvfs(); + else if (opcode >= Mnemonic.SPVFS) _spvfs(); + else if (opcode >= Mnemonic.SFVTL) _sfvtl((short)(opcode & 1)); + else if (opcode >= Mnemonic.SPVTL) _spvtl((short)(opcode & 1)); + else if (opcode >= Mnemonic.SFVTCA) _sfvtca((short)(opcode & 1)); + else if (opcode >= Mnemonic.SPVTCA) _spvtca((short)(opcode & 1)); + else if (opcode >= Mnemonic.SVTCA) _svtca((short)(opcode & 1)); + ip = parser.advanceIP(ip); + } + } + + public Point[][] getZones() { + return zone; + } + + private int pop() { + return stack[--stackIndex]; + } + + private void push(int i) { + stack[stackIndex++] = i; + } + + public void runCvtProgram() { + execute(0x00010000); + } + + public void runFontProgram() { + execute(0); + } + + public void runGlyphProgram() { + // instruction_control can be set to stop glyphs grid-fitting + if ((gs.instruction_control & 1) == 0) { + execute(0x00020000); + } + } + + public void setParser(Parser p) { + parser = p; + } +} diff --git a/src/net/java/dev/typecast/tt/engine/Parser.java b/src/net/java/dev/typecast/tt/engine/Parser.java new file mode 100644 index 000000000..bfae53197 --- /dev/null +++ b/src/net/java/dev/typecast/tt/engine/Parser.java @@ -0,0 +1,192 @@ +/* + * $Id: Parser.java,v 1.1.1.1 2004-12-05 23:15:06 davidsch Exp $ + * + * Typecast - The Font Development Environment + * + * Copyright (c) 2004 David Schweinsberg + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.java.dev.typecast.tt.engine; + +import net.java.dev.typecast.ot.Mnemonic; + +/** + * @author <a href="mailto:[email protected]">David Schweinsberg</a> + * @version $Id: Parser.java,v 1.1.1.1 2004-12-05 23:15:06 davidsch Exp $ + */ +public class Parser { + + private short[][] instructions = new short[3][]; + + /** + * Advance the instruction pointer to the next executable opcode. + * This will be the next byte, unless the current opcode is a push + * instruction, in which case it will be the byte immediately beyond + * the last data byte. + * @param ip The current instruction pointer + * @return The new instruction pointer + */ + public int advanceIP(int ip) { + + // The high word specifies font, cvt, or glyph program + int prog = ip >> 16; + int i = ip & 0xffff; + int dataCount; + ip++; + if (Mnemonic.NPUSHB == instructions[prog][i]) { + // Next byte is the data byte count + dataCount = instructions[prog][++i]; + ip += dataCount + 1; + } else if (Mnemonic.NPUSHW == instructions[prog][i]) { + // Next byte is the data word count + dataCount = instructions[prog][++i]; + ip += dataCount*2 + 1; + } else if (Mnemonic.PUSHB == (instructions[prog][i] & 0xf8)) { + dataCount = (short)((instructions[prog][i] & 0x07) + 1); + ip += dataCount; + } else if (Mnemonic.PUSHW == (instructions[prog][i] & 0xf8)) { + dataCount = (short)((instructions[prog][i] & 0x07) + 1); + ip += dataCount*2; + } + return ip; + } + + public int getISLength(int prog) { + return instructions[prog].length; + } + + public short getOpcode(int ip) { + return instructions[ip >> 16][ip & 0xffff]; + } + + public short getPushCount(int ip) { + short instr = instructions[ip >> 16][ip & 0xffff]; + if ((Mnemonic.NPUSHB == instr) || (Mnemonic.NPUSHW == instr)) { + return instructions[ip >> 16][(ip & 0xffff) + 1]; + } else if ((Mnemonic.PUSHB == (instr & 0xf8)) || (Mnemonic.PUSHW == (instr & 0xf8))) { + return (short)((instr & 0x07) + 1); + } + return 0; + } + + public int[] getPushData(int ip) { + int count = getPushCount(ip); + int[] data = new int[count]; + int prog = ip >> 16; + int i = ip & 0xffff; + short instr = instructions[prog][i]; + if (Mnemonic.NPUSHB == instr) { + for (int j = 0; j < count; j++) { + data[j] = instructions[prog][i + j + 2]; + } + } else if (Mnemonic.PUSHB == (instr & 0xf8)) { + for (int j = 0; j < count; j++) { + data[j] = instructions[prog][i + j + 1]; + } + } else if (Mnemonic.NPUSHW == instr) { + for (int j = 0; j < count; j++) { + data[j] = (instructions[prog][i + j*2 + 2] << 8) | instructions[prog][i + j*2 + 3]; + } + } else if (Mnemonic.PUSHW == (instr & 0xf8)) { + for (int j = 0; j < count; j++) { + data[j] = (instructions[prog][i + j*2 + 1] << 8) | instructions[prog][i + j*2 + 2]; + } + } + return data; + } + + public int handleElse(int ip) { + while (instructions[ip >> 16][ip & 0xffff] != Mnemonic.EIF) { + ip = advanceIP(ip); + } + return ip; + } + + public int handleIf(boolean test, int ip) { + if (test == false) { + // The TrueType spec says that we merely jump to the *next* ELSE or EIF + // instruction in the instruction stream. So therefore no nesting! + // Looking at actual code, IF-ELSE-EIF can be nested! + while ((instructions[ip >> 16][ip & 0xffff] != Mnemonic.ELSE) + && (instructions[ip >> 16][ip & 0xffff] != Mnemonic.EIF)) { + ip = advanceIP(ip); + } + } + return ip; + } + + /** + * This program is run everytime we scale the font + */ + public void setCvtProgram(short[] program) { + instructions[1] = program; + } + + /** + * This program is only run once + */ + public void setFontProgram(short[] program) { + instructions[0] = program; + } + + /** + * This program is run everytime we scale the glyph + */ + public void setGlyphProgram(short[] program) { + instructions[2] = program; + } + + public String toString() { + StringBuffer sb = new StringBuffer(); + int ip = 0; + while (ip < instructions[0].length) { + sb.append(Mnemonic.getMnemonic(getOpcode(ip))); + if (getPushCount(ip) > 0) { + int[] data = getPushData(ip); + for(int j = 0; j < data.length; j++) + sb.append(" ").append(data[j]); + } + sb.append("\n"); + ip = advanceIP(ip); + } + sb.append("\n"); + ip = 0x10000; + while (ip < (0x10000 | instructions[1].length)) { + sb.append(Mnemonic.getMnemonic(getOpcode(ip))); + if(getPushCount(ip) > 0) { + int[] data = getPushData(ip); + for (int j = 0; j < data.length; j++) { + sb.append(" ").append(data[j]); + } + } + sb.append("\n"); + ip = advanceIP(ip); + } + sb.append("\n"); + ip = 0x20000; + while (ip < (0x20000 | instructions[2].length)) { + sb.append(Mnemonic.getMnemonic(getOpcode(ip))); + if (getPushCount(ip) > 0) { + int[] data = getPushData(ip); + for (int j = 0; j < data.length; j++) { + sb.append(" ").append(data[j]); + } + } + sb.append("\n"); + ip = advanceIP(ip); + } + return sb.toString(); + } +} |