diff options
author | David Schweinsberg <[email protected]> | 2015-12-29 23:29:26 -0800 |
---|---|---|
committer | David Schweinsberg <[email protected]> | 2015-12-29 23:29:26 -0800 |
commit | 0c64891ea399a9c5fd95753c549c604e46a7bc23 (patch) | |
tree | 94697d9142f2446ad0cfe9a43bf987b3e792bcbf | |
parent | b2d29d276feb057409d7b2abb30f218d4061b7c5 (diff) |
Moved CffTable inner classes out into CFF-specific package.
22 files changed, 844 insertions, 511 deletions
diff --git a/src/net/java/dev/typecast/app/editor/GlyphPanel.java b/src/net/java/dev/typecast/app/editor/GlyphPanel.java index 977d351..a992261 100644 --- a/src/net/java/dev/typecast/app/editor/GlyphPanel.java +++ b/src/net/java/dev/typecast/app/editor/GlyphPanel.java @@ -26,7 +26,7 @@ import net.java.dev.typecast.app.framework.EditorView; import net.java.dev.typecast.edit.GlyphEdit; import net.java.dev.typecast.ot.Glyph; import net.java.dev.typecast.ot.OTFont; -import net.java.dev.typecast.ot.table.Charstring; +import net.java.dev.typecast.t2.Charstring; import net.java.dev.typecast.ot.table.GlyphDescription; /** diff --git a/src/net/java/dev/typecast/app/editor/Main.java b/src/net/java/dev/typecast/app/editor/Main.java index a427e3b..034b191 100644 --- a/src/net/java/dev/typecast/app/editor/Main.java +++ b/src/net/java/dev/typecast/app/editor/Main.java @@ -388,7 +388,7 @@ public class Main { // Then add the panes we're interested in if (obj instanceof GlyphDescription - || obj instanceof net.java.dev.typecast.ot.table.Charstring) { + || obj instanceof net.java.dev.typecast.t2.Charstring) { _glyphPane = new GlyphPanel(_appPrefs); _glyphPane.setModel(font, obj); _tabbedPane.add(_glyphPane); diff --git a/src/net/java/dev/typecast/app/editor/TableTreeBuilder.java b/src/net/java/dev/typecast/app/editor/TableTreeBuilder.java index eacd719..39ad633 100644 --- a/src/net/java/dev/typecast/app/editor/TableTreeBuilder.java +++ b/src/net/java/dev/typecast/app/editor/TableTreeBuilder.java @@ -37,12 +37,13 @@ import net.java.dev.typecast.ot.table.GlyfCompositeDescript; import net.java.dev.typecast.ot.table.GlyfDescript; import net.java.dev.typecast.ot.table.GlyfTable; import net.java.dev.typecast.ot.table.CffTable; -import net.java.dev.typecast.ot.table.Charstring; +import net.java.dev.typecast.t2.Charstring; import net.java.dev.typecast.ot.table.GsubTable; import net.java.dev.typecast.ot.table.ID; import net.java.dev.typecast.ot.table.LangSys; import net.java.dev.typecast.ot.table.Lookup; import net.java.dev.typecast.ot.table.LookupSubtable; +import net.java.dev.typecast.t2.NameIndex; import net.java.dev.typecast.ot.table.NameRecord; import net.java.dev.typecast.ot.table.NameTable; import net.java.dev.typecast.ot.table.PostTable; @@ -241,7 +242,7 @@ public class TableTreeBuilder { } private static void addCffTable(OTFont font, TableTreeNode parent, CffTable ct) { - CffTable.NameIndex ni = ct.getNameIndex(); + NameIndex ni = ct.getNameIndex(); for (int i = 0; i < ni.getCount(); ++i) { TableTreeNode n = new TableTreeNode( ni.getName(i), diff --git a/src/net/java/dev/typecast/ot/Glyph.java b/src/net/java/dev/typecast/ot/Glyph.java index 2cd36bd..8dfa015 100644 --- a/src/net/java/dev/typecast/ot/Glyph.java +++ b/src/net/java/dev/typecast/ot/Glyph.java @@ -53,8 +53,9 @@ package net.java.dev.typecast.ot; import net.java.dev.typecast.ot.table.CffTable; 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.Charstring; +import net.java.dev.typecast.t2.CharstringType2; +import net.java.dev.typecast.t2.Index; import net.java.dev.typecast.t2.T2Interpreter; @@ -93,8 +94,8 @@ public class Glyph { Charstring cs, short lsb, int advance, - CffTable.Index localSubrIndex, - CffTable.Index globalSubrIndex) { + Index localSubrIndex, + Index globalSubrIndex) { _leftSideBearing = lsb; _advanceWidth = advance; if (cs instanceof CharstringType2) { diff --git a/src/net/java/dev/typecast/ot/table/CffTable.java b/src/net/java/dev/typecast/ot/table/CffTable.java index 2ed84e2..4136c7c 100644 --- a/src/net/java/dev/typecast/ot/table/CffTable.java +++ b/src/net/java/dev/typecast/ot/table/CffTable.java @@ -22,11 +22,19 @@ import java.io.ByteArrayInputStream; import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; import java.util.List; -import java.util.Map; +import net.java.dev.typecast.t2.CffFont; +import net.java.dev.typecast.t2.Charset; +import net.java.dev.typecast.t2.CharsetFormat0; +import net.java.dev.typecast.t2.CharsetFormat1; +import net.java.dev.typecast.t2.CharsetFormat2; +import net.java.dev.typecast.t2.Charstring; +import net.java.dev.typecast.t2.CharstringType2; +import net.java.dev.typecast.t2.Dict; +import net.java.dev.typecast.t2.Index; +import net.java.dev.typecast.t2.NameIndex; +import net.java.dev.typecast.t2.StringIndex; +import net.java.dev.typecast.t2.TopDictIndex; /** * Compact Font Format Table @@ -34,496 +42,6 @@ import java.util.Map; */ public class CffTable implements Table { - public static class Dict { - - private final Map<Integer, Object> _entries = new HashMap<>(); - private final int[] _data; - private int _index; - - protected Dict(int[] data, int offset, int length) { - _data = data; - _index = offset; - while (_index < offset + length) { - addKeyAndValueEntry(); - } - } - - protected Dict(DataInput di, int length) throws IOException { - _data = new int[length]; - for (int i = 0; i < length; ++i) { - _data[i] = di.readUnsignedByte(); - } - _index = 0; - while (_index < length) { - addKeyAndValueEntry(); - } - } - - public Object getValue(int key) { - return _entries.get(key); - } - - private boolean addKeyAndValueEntry() { - ArrayList<Object> operands = new ArrayList<>(); - 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]; - return (32 <= b0 && b0 <= 254) - || b0 == 28 - || b0 == 29 - || b0 == 30; - } - -// private boolean isOperatorAtIndex() { -// int b0 = _data[_index]; -// return 0 <= b0 && b0 <= 21; -// } - - private Object nextOperand() { - int b0 = _data[_index]; - if (32 <= b0 && b0 <= 246) { - - // 1 byte integer - ++_index; - return b0 - 139; - } else if (247 <= b0 && b0 <= 250) { - - // 2 byte integer - int b1 = _data[_index + 1]; - _index += 2; - return (b0 - 247) * 256 + b1 + 108; - } else if (251 <= b0 && b0 <= 254) { - - // 2 byte integer - int b1 = _data[_index + 1]; - _index += 2; - return -(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 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 b1 << 24 | b2 << 16 | b3 << 8 | b4; - } else if (b0 == 30) { - - // Real number - StringBuilder fString = new StringBuilder(); - 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 Float.valueOf(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 ""; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - Iterator<Integer> keys = _entries.keySet().iterator(); - while (keys.hasNext()) { - Integer key = keys.next(); - if ((key & 0xc00) == 0xc00) { - sb.append("12 ").append(key & 0xff).append(": "); - } else { - sb.append(key.toString()).append(": "); - } - sb.append(_entries.get(key).toString()).append("\n"); - } - return sb.toString(); - } - } - - public class Index { - - private final int _count; - private final int _offSize; - private final int[] _offset; - private final 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 final int getCount() { - return _count; - } - - public final int getOffset(int index) { - return _offset[index]; - } - - public final int getDataLength() { - return _offset[_offset.length - 1] - 1; - } - - public final int[] getData() { - return _data; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - 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); - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - 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) { - StringBuilder sb = new StringBuilder(); - for (int i = offset; i < offset + len; ++i) { - sb.append((char) getData()[i]); - } - name = sb.toString(); - } else { - name = "DELETED NAME"; - } - return name; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - 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; - - StringBuilder sb = new StringBuilder(); - for (int i = offset; i < offset + len; ++i) { - sb.append((char) getData()[i]); - } - return sb.toString(); - } - } - - @Override - public String toString() { - int nonStandardBase = CffStandardStrings.standardStrings.length; - StringBuilder sb = new StringBuilder(); - 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 final int getFirst() { - return _first; - } - - protected final void setFirst(int first) { - _first = first; - } - - public final int getLeft() { - return _left; - } - - protected final 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 final 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(); - } - } - - @Override - public int getFormat() { - return 0; - } - - @Override - public int getSID(int gid) { - if (gid == 0) { - return 0; - } - return _glyph[gid - 1]; - } - } - - private class CharsetFormat1 extends Charset { - - private final ArrayList<CharsetRange> _charsetRanges = new ArrayList<>(); - - 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; - } - } - - @Override - public int getFormat() { - return 1; - } - - @Override - public int getSID(int gid) { - if (gid == 0) { - return 0; - } - - // Count through the ranges to find the one of interest - int count = 1; - for (CharsetRange range : _charsetRanges) { - if (gid <= range.getLeft() + count) { - int sid = gid - count + range.getFirst(); - return sid; - } - count += range.getLeft() + 1; - } - return 0; - } - } - - private class CharsetFormat2 extends Charset { - - private final ArrayList<CharsetRange> _charsetRanges = new ArrayList<>(); - - 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; - } - } - - @Override - public int getFormat() { - return 2; - } - - @Override - public int getSID(int gid) { - if (gid == 0) { - return 0; - } - - // Count through the ranges to find the one of interest - int count = 1; - for (CharsetRange range : _charsetRanges) { - if (gid <= range.getLeft() + count) { - int sid = gid - count + range.getFirst(); - return sid; - } - count += range.getLeft() + 1; - } - return 0; - } - } - - public class CffFont { - private Index _charStringsIndex; - private Dict _privateDict; - private Index _localSubrsIndex; - private Charset _charset; - private Charstring[] _charstrings; - - public CffFont( - Index charStringsIndex, - Dict privateDict, - Index localSubrsIndex, - Charset charset, - Charstring[] charstrings) { - _charStringsIndex = charStringsIndex; - _privateDict = privateDict; - _localSubrsIndex = localSubrsIndex; - _charset = charset; - _charstrings = charstrings; - } - - public Index getCharStringsIndex() { - return _charStringsIndex; - } - - public Dict getPrivateDict() { - return _privateDict; - } - - public Index getLocalSubrsIndex() { - return _localSubrsIndex; - } - - public Charset getCharset() { - return _charset; - } - - public Charstring[] getCharstrings() { - return _charstrings; - } - } - private DirectoryEntry _de; private int _major; private int _minor; diff --git a/src/net/java/dev/typecast/t2/CffFont.java b/src/net/java/dev/typecast/t2/CffFont.java new file mode 100644 index 0000000..68d8bda --- /dev/null +++ b/src/net/java/dev/typecast/t2/CffFont.java @@ -0,0 +1,64 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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; + +/** + * + * @author dschweinsberg + */ +public class CffFont { + + private final Index _charStringsIndex; + private final Dict _privateDict; + private final Index _localSubrsIndex; + private final Charset _charset; + private final Charstring[] _charstrings; + + public CffFont( + Index charStringsIndex, + Dict privateDict, + Index localSubrsIndex, + Charset charset, + Charstring[] charstrings) { + _charStringsIndex = charStringsIndex; + _privateDict = privateDict; + _localSubrsIndex = localSubrsIndex; + _charset = charset; + _charstrings = charstrings; + } + + public Index getCharStringsIndex() { + return _charStringsIndex; + } + + public Dict getPrivateDict() { + return _privateDict; + } + + public Index getLocalSubrsIndex() { + return _localSubrsIndex; + } + + public Charset getCharset() { + return _charset; + } + + public Charstring[] getCharstrings() { + return _charstrings; + } +} diff --git a/src/net/java/dev/typecast/ot/table/CffStandardStrings.java b/src/net/java/dev/typecast/t2/CffStandardStrings.java index 326f115..a2f8cca 100644 --- a/src/net/java/dev/typecast/ot/table/CffStandardStrings.java +++ b/src/net/java/dev/typecast/t2/CffStandardStrings.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package net.java.dev.typecast.ot.table; +package net.java.dev.typecast.t2; /** * Compact Font Format Standard Strings. As per Appendix A of the Adobe diff --git a/src/net/java/dev/typecast/t2/Charset.java b/src/net/java/dev/typecast/t2/Charset.java new file mode 100644 index 0000000..e221828 --- /dev/null +++ b/src/net/java/dev/typecast/t2/Charset.java @@ -0,0 +1,33 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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; + +/** + * + * @author dschweinsberg + */ +public abstract class Charset { + + Charset() { + } + + public abstract int getFormat(); + + public abstract int getSID(int gid); + +} diff --git a/src/net/java/dev/typecast/t2/CharsetFormat0.java b/src/net/java/dev/typecast/t2/CharsetFormat0.java new file mode 100644 index 0000000..dfca79b --- /dev/null +++ b/src/net/java/dev/typecast/t2/CharsetFormat0.java @@ -0,0 +1,51 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; + +/** + * + * @author dschweinsberg + */ +public class CharsetFormat0 extends Charset { + + private final int[] _glyph; + + public 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(); + } + } // minus 1 because .notdef is omitted + + @Override + public int getFormat() { + return 0; + } + + @Override + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + return _glyph[gid - 1]; + } + +} diff --git a/src/net/java/dev/typecast/t2/CharsetFormat1.java b/src/net/java/dev/typecast/t2/CharsetFormat1.java new file mode 100644 index 0000000..1a0a64f --- /dev/null +++ b/src/net/java/dev/typecast/t2/CharsetFormat1.java @@ -0,0 +1,63 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; +import java.util.ArrayList; + +/** + * + * @author dschweinsberg + */ +public class CharsetFormat1 extends Charset { + + private final ArrayList<CharsetRange> _charsetRanges = new ArrayList<>(); + + public 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; + } + } + + @Override + public int getFormat() { + return 1; + } + + @Override + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + + // Count through the ranges to find the one of interest + int count = 1; + for (CharsetRange range : _charsetRanges) { + if (gid <= range.getLeft() + count) { + int sid = gid - count + range.getFirst(); + return sid; + } + count += range.getLeft() + 1; + } + return 0; + } +} diff --git a/src/net/java/dev/typecast/t2/CharsetFormat2.java b/src/net/java/dev/typecast/t2/CharsetFormat2.java new file mode 100644 index 0000000..6ccdd86 --- /dev/null +++ b/src/net/java/dev/typecast/t2/CharsetFormat2.java @@ -0,0 +1,63 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; +import java.util.ArrayList; + +/** + * + * @author dschweinsberg + */ +public class CharsetFormat2 extends Charset { + + private final ArrayList<CharsetRange> _charsetRanges = new ArrayList<>(); + + public 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; + } + } + + @Override + public int getFormat() { + return 2; + } + + @Override + public int getSID(int gid) { + if (gid == 0) { + return 0; + } + + // Count through the ranges to find the one of interest + int count = 1; + for (CharsetRange range : _charsetRanges) { + if (gid <= range.getLeft() + count) { + int sid = gid - count + range.getFirst(); + return sid; + } + count += range.getLeft() + 1; + } + return 0; + } +} diff --git a/src/net/java/dev/typecast/t2/CharsetRange.java b/src/net/java/dev/typecast/t2/CharsetRange.java new file mode 100644 index 0000000..452adc3 --- /dev/null +++ b/src/net/java/dev/typecast/t2/CharsetRange.java @@ -0,0 +1,48 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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; + +/** + * + * @author dschweinsberg + */ +public class CharsetRange { + + private int _first; + private int _left; + + CharsetRange() { + } + + public final int getFirst() { + return _first; + } + + protected final void setFirst(int first) { + _first = first; + } + + public final int getLeft() { + return _left; + } + + protected final void setLeft(int left) { + _left = left; + } + +} diff --git a/src/net/java/dev/typecast/t2/CharsetRange1.java b/src/net/java/dev/typecast/t2/CharsetRange1.java new file mode 100644 index 0000000..dff99d8 --- /dev/null +++ b/src/net/java/dev/typecast/t2/CharsetRange1.java @@ -0,0 +1,34 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; + +/** + * + * @author dschweinsberg + */ +public class CharsetRange1 extends CharsetRange { + + protected CharsetRange1(DataInput di) throws IOException { + setFirst(di.readUnsignedShort()); + setLeft(di.readUnsignedByte()); + } + +} diff --git a/src/net/java/dev/typecast/t2/CharsetRange2.java b/src/net/java/dev/typecast/t2/CharsetRange2.java new file mode 100644 index 0000000..18b2baf --- /dev/null +++ b/src/net/java/dev/typecast/t2/CharsetRange2.java @@ -0,0 +1,34 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; + +/** + * + * @author dschweinsberg + */ +public class CharsetRange2 extends CharsetRange { + + protected CharsetRange2(DataInput di) throws IOException { + setFirst(di.readUnsignedShort()); + setLeft(di.readUnsignedShort()); + } + +} diff --git a/src/net/java/dev/typecast/ot/table/Charstring.java b/src/net/java/dev/typecast/t2/Charstring.java index 65fcdef..36b8f77 100644 --- a/src/net/java/dev/typecast/ot/table/Charstring.java +++ b/src/net/java/dev/typecast/t2/Charstring.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package net.java.dev.typecast.ot.table; +package net.java.dev.typecast.t2; /** * CFF Charstring diff --git a/src/net/java/dev/typecast/ot/table/CharstringType2.java b/src/net/java/dev/typecast/t2/CharstringType2.java index 31d0d61..eb8bc69 100644 --- a/src/net/java/dev/typecast/ot/table/CharstringType2.java +++ b/src/net/java/dev/typecast/t2/CharstringType2.java @@ -16,7 +16,7 @@ * limitations under the License. */ -package net.java.dev.typecast.ot.table; +package net.java.dev.typecast.t2; /** * CFF Type 2 Charstring @@ -114,7 +114,7 @@ public class CharstringType2 extends Charstring { * @param data * @param offset * @param length */ - protected CharstringType2( + public CharstringType2( int index, String name, int[] data, diff --git a/src/net/java/dev/typecast/t2/Dict.java b/src/net/java/dev/typecast/t2/Dict.java new file mode 100644 index 0000000..d4c6d79 --- /dev/null +++ b/src/net/java/dev/typecast/t2/Dict.java @@ -0,0 +1,169 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * + * @author dschweinsberg + */ +public class Dict { + + private final Map<Integer, Object> _entries = new HashMap<>(); + private final int[] _data; + private int _index; + + public Dict(int[] data, int offset, int length) { + _data = data; + _index = offset; + while (_index < offset + length) { + addKeyAndValueEntry(); + } + } + + public Dict(DataInput di, int length) throws IOException { + _data = new int[length]; + for (int i = 0; i < length; ++i) { + _data[i] = di.readUnsignedByte(); + } + _index = 0; + while (_index < length) { + addKeyAndValueEntry(); + } + } + + public Object getValue(int key) { + return _entries.get(key); + } + + private boolean addKeyAndValueEntry() { + ArrayList<Object> operands = new ArrayList<>(); + 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]; + return (32 <= b0 && b0 <= 254) || b0 == 28 || b0 == 29 || b0 == 30; + } + + // private boolean isOperatorAtIndex() { + // int b0 = _data[_index]; + // return 0 <= b0 && b0 <= 21; + // } + private Object nextOperand() { + int b0 = _data[_index]; + if (32 <= b0 && b0 <= 246) { + // 1 byte integer + ++_index; + return b0 - 139; + } else if (247 <= b0 && b0 <= 250) { + // 2 byte integer + int b1 = _data[_index + 1]; + _index += 2; + return (b0 - 247) * 256 + b1 + 108; + } else if (251 <= b0 && b0 <= 254) { + // 2 byte integer + int b1 = _data[_index + 1]; + _index += 2; + return -(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 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 b1 << 24 | b2 << 16 | b3 << 8 | b4; + } else if (b0 == 30) { + // Real number + StringBuilder fString = new StringBuilder(); + 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 Float.valueOf(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 ""; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + Iterator<Integer> keys = _entries.keySet().iterator(); + while (keys.hasNext()) { + Integer key = keys.next(); + if ((key & 0xc00) == 0xc00) { + sb.append("12 ").append(key & 0xff).append(": "); + } else { + sb.append(key.toString()).append(": "); + } + sb.append(_entries.get(key).toString()).append("\n"); + } + return sb.toString(); + } + +} diff --git a/src/net/java/dev/typecast/t2/Index.java b/src/net/java/dev/typecast/t2/Index.java new file mode 100644 index 0000000..dcad83b --- /dev/null +++ b/src/net/java/dev/typecast/t2/Index.java @@ -0,0 +1,89 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; + +/** + * + * @author dschweinsberg + */ +public class Index { + + private final int _count; + private final int _offSize; + private final int[] _offset; + private final int[] _data; + + public 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 final int getCount() { + return _count; + } + + public final int getOffset(int index) { + return _offset[index]; + } + + public final int getDataLength() { + return _offset[_offset.length - 1] - 1; + } + + public final int[] getData() { + return _data; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + 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(); + } + +} diff --git a/src/net/java/dev/typecast/t2/NameIndex.java b/src/net/java/dev/typecast/t2/NameIndex.java new file mode 100644 index 0000000..3831070 --- /dev/null +++ b/src/net/java/dev/typecast/t2/NameIndex.java @@ -0,0 +1,57 @@ +/* + * Copyright 2015 dschweinsberg. + * + * 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.io.DataInput; +import java.io.IOException; + +/** + * + * @author dschweinsberg + */ +public class NameIndex extends Index { + + public 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) { + StringBuilder sb = new StringBuilder(); + for (int i = offset; i < offset + len; ++i) { + sb.append((char) getData()[i]); + } + name = sb.toString(); + } else { + name = "DELETED NAME"; + } + return name; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < getCount(); ++i) { + sb.append(getName(i)).append("\n"); + } + return sb.toString(); + } + +} diff --git a/src/net/java/dev/typecast/t2/StringIndex.java b/src/net/java/dev/typecast/t2/StringIndex.java new file mode 100644 index 0000000..ece39ab --- /dev/null +++ b/src/net/java/dev/typecast/t2/StringIndex.java @@ -0,0 +1,62 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; + +/** + * + * @author dschweinsberg + */ +public class StringIndex extends Index { + + public 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; + StringBuilder sb = new StringBuilder(); + for (int i = offset; i < offset + len; ++i) { + sb.append((char) getData()[i]); + } + return sb.toString(); + } + } + + @Override + public String toString() { + int nonStandardBase = CffStandardStrings.standardStrings.length; + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < getCount(); ++i) { + sb.append(nonStandardBase + i).append(": "); + sb.append(getString(nonStandardBase + i)).append("\n"); + } + return sb.toString(); + } + +} diff --git a/src/net/java/dev/typecast/t2/T2Interpreter.java b/src/net/java/dev/typecast/t2/T2Interpreter.java index c3d05ae..f15856d 100644 --- a/src/net/java/dev/typecast/t2/T2Interpreter.java +++ b/src/net/java/dev/typecast/t2/T2Interpreter.java @@ -20,8 +20,6 @@ package net.java.dev.typecast.t2; import java.util.ArrayList; import net.java.dev.typecast.ot.Point; -import net.java.dev.typecast.ot.table.CffTable; -import net.java.dev.typecast.ot.table.CharstringType2; /** * Type 2 Charstring Interpreter. Operator descriptions are quoted from @@ -43,11 +41,11 @@ public class T2Interpreter { private int _stemCount = 0; private ArrayList<Point> _points; - private final CffTable.Index _localSubrIndex; - private final CffTable.Index _globalSubrIndex; + private final Index _localSubrIndex; + private final Index _globalSubrIndex; /** Creates a new instance of T2Interpreter */ - public T2Interpreter(CffTable.Index localSubrIndex, CffTable.Index globalSubrIndex) { + public T2Interpreter(Index localSubrIndex, Index globalSubrIndex) { _localSubrIndex = localSubrIndex; _globalSubrIndex = globalSubrIndex; } diff --git a/src/net/java/dev/typecast/t2/TopDictIndex.java b/src/net/java/dev/typecast/t2/TopDictIndex.java new file mode 100644 index 0000000..cd22466 --- /dev/null +++ b/src/net/java/dev/typecast/t2/TopDictIndex.java @@ -0,0 +1,48 @@ +/* + * Typecast - The Font Development Environment + * + * Copyright (c) 2004-2015 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.io.DataInput; +import java.io.IOException; + +/** + * + * @author dschweinsberg + */ +public class TopDictIndex extends Index { + + public 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); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < getCount(); ++i) { + sb.append(getTopDict(i).toString()).append("\n"); + } + return sb.toString(); + } + +} |