summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <sgothel@jausoft.com>2011-03-25 02:33:11 +0100
committerSven Gothel <sgothel@jausoft.com>2011-03-25 02:33:11 +0100
commitf8d03d8cd64593fdb24057ce928a07137b57f49f (patch)
tree947df415cd66e7b584050d092df0dd4eaae8cce3
Import Typecast r106, http://typecast.dev.java.net/ - Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0
-rw-r--r--src/net/java/dev/typecast/ot/Disassembler.java109
-rw-r--r--src/net/java/dev/typecast/ot/Fixed.java852
-rw-r--r--src/net/java/dev/typecast/ot/Glyph.java159
-rw-r--r--src/net/java/dev/typecast/ot/Mnemonic.java397
-rw-r--r--src/net/java/dev/typecast/ot/OTFont.java265
-rw-r--r--src/net/java/dev/typecast/ot/OTFontCollection.java169
-rw-r--r--src/net/java/dev/typecast/ot/Point.java29
-rw-r--r--src/net/java/dev/typecast/ot/mac/ResourceData.java45
-rw-r--r--src/net/java/dev/typecast/ot/mac/ResourceFile.java77
-rw-r--r--src/net/java/dev/typecast/ot/mac/ResourceHeader.java61
-rw-r--r--src/net/java/dev/typecast/ot/mac/ResourceMap.java83
-rw-r--r--src/net/java/dev/typecast/ot/mac/ResourceReference.java81
-rw-r--r--src/net/java/dev/typecast/ot/mac/ResourceType.java82
-rw-r--r--src/net/java/dev/typecast/ot/table/BaseTable.java436
-rw-r--r--src/net/java/dev/typecast/ot/table/CffStandardStrings.java424
-rw-r--r--src/net/java/dev/typecast/ot/table/CffTable.java620
-rw-r--r--src/net/java/dev/typecast/ot/table/Charstring.java33
-rw-r--r--src/net/java/dev/typecast/ot/table/CharstringType2.java235
-rw-r--r--src/net/java/dev/typecast/ot/table/ClassDef.java33
-rw-r--r--src/net/java/dev/typecast/ot/table/ClassDefFormat1.java39
-rw-r--r--src/net/java/dev/typecast/ot/table/ClassDefFormat2.java37
-rw-r--r--src/net/java/dev/typecast/ot/table/CmapFormat.java134
-rw-r--r--src/net/java/dev/typecast/ot/table/CmapFormat0.java92
-rw-r--r--src/net/java/dev/typecast/ot/table/CmapFormat2.java173
-rw-r--r--src/net/java/dev/typecast/ot/table/CmapFormat4.java165
-rw-r--r--src/net/java/dev/typecast/ot/table/CmapFormat6.java87
-rw-r--r--src/net/java/dev/typecast/ot/table/CmapFormatUnknown.java54
-rw-r--r--src/net/java/dev/typecast/ot/table/CmapIndexEntry.java117
-rw-r--r--src/net/java/dev/typecast/ot/table/CmapTable.java161
-rw-r--r--src/net/java/dev/typecast/ot/table/Coverage.java83
-rw-r--r--src/net/java/dev/typecast/ot/table/CoverageFormat1.java88
-rw-r--r--src/net/java/dev/typecast/ot/table/CoverageFormat2.java89
-rw-r--r--src/net/java/dev/typecast/ot/table/CvtTable.java62
-rw-r--r--src/net/java/dev/typecast/ot/table/Device.java50
-rw-r--r--src/net/java/dev/typecast/ot/table/DirectoryEntry.java115
-rw-r--r--src/net/java/dev/typecast/ot/table/DsigEntry.java43
-rw-r--r--src/net/java/dev/typecast/ot/table/DsigTable.java69
-rw-r--r--src/net/java/dev/typecast/ot/table/Feature.java85
-rw-r--r--src/net/java/dev/typecast/ot/table/FeatureList.java118
-rw-r--r--src/net/java/dev/typecast/ot/table/FeatureRecord.java88
-rw-r--r--src/net/java/dev/typecast/ot/table/FeatureTags.java63
-rw-r--r--src/net/java/dev/typecast/ot/table/FpgmTable.java46
-rw-r--r--src/net/java/dev/typecast/ot/table/GaspRange.java45
-rw-r--r--src/net/java/dev/typecast/ot/table/GaspTable.java63
-rw-r--r--src/net/java/dev/typecast/ot/table/GlyfCompositeComp.java200
-rw-r--r--src/net/java/dev/typecast/ot/table/GlyfCompositeDescript.java202
-rw-r--r--src/net/java/dev/typecast/ot/table/GlyfDescript.java124
-rw-r--r--src/net/java/dev/typecast/ot/table/GlyfSimpleDescript.java245
-rw-r--r--src/net/java/dev/typecast/ot/table/GlyfTable.java132
-rw-r--r--src/net/java/dev/typecast/ot/table/GlyphDescription.java86
-rw-r--r--src/net/java/dev/typecast/ot/table/GposTable.java66
-rw-r--r--src/net/java/dev/typecast/ot/table/GsubTable.java181
-rw-r--r--src/net/java/dev/typecast/ot/table/HdmxTable.java117
-rw-r--r--src/net/java/dev/typecast/ot/table/HeadTable.java205
-rw-r--r--src/net/java/dev/typecast/ot/table/HheaTable.java135
-rw-r--r--src/net/java/dev/typecast/ot/table/HmtxTable.java141
-rw-r--r--src/net/java/dev/typecast/ot/table/ID.java399
-rw-r--r--src/net/java/dev/typecast/ot/table/KernSubtable.java49
-rw-r--r--src/net/java/dev/typecast/ot/table/KernSubtableFormat0.java47
-rw-r--r--src/net/java/dev/typecast/ot/table/KernSubtableFormat2.java42
-rw-r--r--src/net/java/dev/typecast/ot/table/KernTable.java62
-rw-r--r--src/net/java/dev/typecast/ot/table/KerningPair.java44
-rw-r--r--src/net/java/dev/typecast/ot/table/LangSys.java105
-rw-r--r--src/net/java/dev/typecast/ot/table/LangSysRecord.java88
-rw-r--r--src/net/java/dev/typecast/ot/table/Ligature.java85
-rw-r--r--src/net/java/dev/typecast/ot/table/LigatureSet.java85
-rw-r--r--src/net/java/dev/typecast/ot/table/LigatureSubst.java73
-rw-r--r--src/net/java/dev/typecast/ot/table/LigatureSubstFormat1.java95
-rw-r--r--src/net/java/dev/typecast/ot/table/LocaTable.java77
-rw-r--r--src/net/java/dev/typecast/ot/table/Lookup.java110
-rw-r--r--src/net/java/dev/typecast/ot/table/LookupList.java108
-rw-r--r--src/net/java/dev/typecast/ot/table/LookupSubtable.java60
-rw-r--r--src/net/java/dev/typecast/ot/table/LookupSubtableFactory.java64
-rw-r--r--src/net/java/dev/typecast/ot/table/LtshTable.java68
-rw-r--r--src/net/java/dev/typecast/ot/table/MaxpTable.java162
-rw-r--r--src/net/java/dev/typecast/ot/table/NameRecord.java145
-rw-r--r--src/net/java/dev/typecast/ot/table/NameTable.java131
-rw-r--r--src/net/java/dev/typecast/ot/table/Os2Table.java358
-rw-r--r--src/net/java/dev/typecast/ot/table/Panose.java96
-rw-r--r--src/net/java/dev/typecast/ot/table/PcltTable.java105
-rw-r--r--src/net/java/dev/typecast/ot/table/PostTable.java422
-rw-r--r--src/net/java/dev/typecast/ot/table/PrepTable.java46
-rw-r--r--src/net/java/dev/typecast/ot/table/Program.java41
-rw-r--r--src/net/java/dev/typecast/ot/table/RangeRecord.java87
-rw-r--r--src/net/java/dev/typecast/ot/table/Script.java118
-rw-r--r--src/net/java/dev/typecast/ot/table/ScriptList.java115
-rw-r--r--src/net/java/dev/typecast/ot/table/ScriptRecord.java88
-rw-r--r--src/net/java/dev/typecast/ot/table/ScriptTags.java61
-rw-r--r--src/net/java/dev/typecast/ot/table/SignatureBlock.java46
-rw-r--r--src/net/java/dev/typecast/ot/table/SingleSubst.java81
-rw-r--r--src/net/java/dev/typecast/ot/table/SingleSubstFormat1.java92
-rw-r--r--src/net/java/dev/typecast/ot/table/SingleSubstFormat2.java97
-rw-r--r--src/net/java/dev/typecast/ot/table/TTCHeader.java59
-rw-r--r--src/net/java/dev/typecast/ot/table/Table.java67
-rw-r--r--src/net/java/dev/typecast/ot/table/TableDirectory.java129
-rw-r--r--src/net/java/dev/typecast/ot/table/TableException.java46
-rw-r--r--src/net/java/dev/typecast/ot/table/TableFactory.java185
-rw-r--r--src/net/java/dev/typecast/ot/table/VdmxTable.java197
-rw-r--r--src/net/java/dev/typecast/ot/table/VheaTable.java147
-rw-r--r--src/net/java/dev/typecast/ot/table/VmtxTable.java112
-rw-r--r--src/net/java/dev/typecast/t2/T2Interpreter.java1043
-rw-r--r--src/net/java/dev/typecast/t2/T2Mnemonic.java86
-rw-r--r--src/net/java/dev/typecast/tt/engine/GraphicsState.java50
-rw-r--r--src/net/java/dev/typecast/tt/engine/Interpreter.java1357
-rw-r--r--src/net/java/dev/typecast/tt/engine/Parser.java192
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 0000000..73e75cc
--- /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:davidsch@dev.java.net">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 0000000..6f83e92
--- /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:davidsch@dev.java.net">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 0000000..a59d626
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..5655c1e
--- /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:davidsch@dev.java.net">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 0000000..d232284
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..6f8754f
--- /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:davidsch@dev.java.net">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 0000000..fae13b0
--- /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:davidsch@dev.java.net">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 0000000..a1c12ff
--- /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:davidsch@dev.java.net">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 0000000..e9499d9
--- /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:davidsch@dev.java.net">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 0000000..bdfe15a
--- /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:davidsch@dev.java.net">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 0000000..ee98fd8
--- /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:davidsch@dev.java.net">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 0000000..f7f6e0f
--- /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:davidsch@dev.java.net">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 0000000..2c21e7a
--- /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:davidsch@dev.java.net">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 0000000..7e6c37a
--- /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:davidsch@dev.java.net">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 0000000..987ea88
--- /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:davidsch@dev.java.net">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 0000000..2bd0cec
--- /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:davidsch@dev.java.net">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 0000000..2439d6b
--- /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:davidsch@dev.java.net">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 0000000..e47825c
--- /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:davidsch@dev.java.net">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 0000000..9fa45c3
--- /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:davidsch@dev.java.net">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 0000000..07b85dd
--- /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:davidsch@dev.java.net">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 0000000..f8b883c
--- /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:davidsch@dev.java.net">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 0000000..be88af1
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..80f42b2
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..4eeaf42
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..3748a8f
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..f9b398a
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..01ca600
--- /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:davidsch@dev.java.net">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 0000000..c82e270
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..de69cc1
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..3c6cf04
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..a81eb0f
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..a304896
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..6035c63
--- /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:davidsch@dev.java.net">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 0000000..75c302a
--- /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:davidsch@dev.java.net">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 0000000..c0f2f9b
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..6ce41ec
--- /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:davidsch@dev.java.net">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 0000000..8d63800
--- /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:davidsch@dev.java.net">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 0000000..34adf46
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..8f17c46
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..7c27888
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..8d573d0
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:vincent.hardy@eng.sun.com">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 0000000..37a2ae0
--- /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:davidsch@dev.java.net">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 0000000..9f343e9
--- /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:davidsch@dev.java.net">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 0000000..50a1bcd
--- /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:davidsch@dev.java.net">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 0000000..0a3f91a
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..97c0b0f
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..49ae5b4
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..e2c3a2c
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..03f519d
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..b23f313
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..3efeeaa
--- /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:davidsch@dev.java.net">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 0000000..d7f9c35
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..e47c0a3
--- /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:davidsch@dev.java.net">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 0000000..c99ae76
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..4b49f41
--- /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:davidsch@dev.java.net">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 0000000..7b4cbae
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..5dc79d7
--- /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:davidsch@dev.java.net">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 0000000..f55fa04
--- /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:davidsch@dev.java.net">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 0000000..e3b1c9c
--- /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:davidsch@dev.java.net">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 0000000..5ff37c2
--- /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:davidsch@dev.java.net">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 0000000..81c4a99
--- /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:davidsch@dev.java.net">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 0000000..de61423
--- /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:davidsch@dev.java.net">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 0000000..9963bf6
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..a69c12a
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..36969ba
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..fe6db04
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..73a8b9d
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..b19b071
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..5f62940
--- /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:davidsch@dev.java.net">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 0000000..d6e46cd
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..9ac76ab
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..4d8dbb1
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..2081e2e
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..12dca01
--- /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:davidsch@dev.java.net">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 0000000..571d3eb
--- /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:davidsch@dev.java.net">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 0000000..cdba03e
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..05f8234
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..bb3b601
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..fe0a357
--- /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:davidsch@dev.java.net">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 0000000..457aec2
--- /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:davidsch@dev.java.net">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 0000000..4a1b065
--- /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:davidsch@dev.java.net">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 0000000..938b9b8
--- /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:davidsch@dev.java.net">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 0000000..6fd02a4
--- /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:davidsch@dev.java.net">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 0000000..3bcb9cc
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..e3022c1
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..bd82a05
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..aea0bf0
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..eeb4f8e
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:vincent.hardy@eng.sun.com">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 0000000..2e4acf5
--- /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:davidsch@dev.java.net">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 0000000..91c9858
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..538c57f
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..74c68f7
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..2f38d33
--- /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:davidsch@dev.java.net">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 0000000..ddbdc49
--- /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:davidsch@dev.java.net">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 0000000..2eff53d
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..02bc49e
--- /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:davidsch@dev.java.net">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 0000000..632abcf
--- /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
+ apache@apache.org.
+
+ 5. Products derived from this software may not be called "Apache", nor may
+ "Apache" appear in their name, without prior written permission of the
+ Apache Software Foundation.
+
+ THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
+ DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+ This software consists of voluntary contributions made by many individuals
+ on behalf of the Apache Software Foundation. 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:davidsch@dev.java.net">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 0000000..907133b
--- /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:davidsch@dev.java.net">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 0000000..3863080
--- /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:davidsch@dev.java.net">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 0000000..b2d9a3c
--- /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:davidsch@dev.java.net">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 0000000..6ae59cf
--- /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:davidsch@dev.java.net">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 0000000..810aea1
--- /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:davidsch@dev.java.net">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 0000000..1c36bd3
--- /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:davidsch@dev.java.net">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 0000000..6f436d7
--- /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:davidsch@dev.java.net">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 0000000..bfae531
--- /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:davidsch@dev.java.net">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();
+ }
+}