From 10bc54d915b9b5dfcf0f3d8156396a7906cbfce0 Mon Sep 17 00:00:00 2001 From: David Schweinsberg Date: Wed, 30 Dec 2015 11:30:28 -0800 Subject: Renamed t2 package to cff to reflect broader scope --- .../java/dev/typecast/app/editor/GlyphPanel.java | 2 +- src/net/java/dev/typecast/app/editor/Main.java | 2 +- .../dev/typecast/app/editor/TableTreeBuilder.java | 4 +- src/net/java/dev/typecast/cff/CffFont.java | 64 ++ .../java/dev/typecast/cff/CffStandardStrings.java | 421 ++++++++ src/net/java/dev/typecast/cff/Charset.java | 33 + src/net/java/dev/typecast/cff/CharsetFormat0.java | 51 + src/net/java/dev/typecast/cff/CharsetFormat1.java | 63 ++ src/net/java/dev/typecast/cff/CharsetFormat2.java | 63 ++ src/net/java/dev/typecast/cff/CharsetRange.java | 48 + src/net/java/dev/typecast/cff/CharsetRange1.java | 34 + src/net/java/dev/typecast/cff/CharsetRange2.java | 34 + src/net/java/dev/typecast/cff/Charstring.java | 30 + src/net/java/dev/typecast/cff/CharstringType2.java | 228 +++++ src/net/java/dev/typecast/cff/Dict.java | 169 +++ src/net/java/dev/typecast/cff/Index.java | 89 ++ src/net/java/dev/typecast/cff/NameIndex.java | 57 ++ src/net/java/dev/typecast/cff/StringIndex.java | 62 ++ src/net/java/dev/typecast/cff/T2Interpreter.java | 1073 ++++++++++++++++++++ src/net/java/dev/typecast/cff/T2Mnemonic.java | 83 ++ src/net/java/dev/typecast/cff/TopDictIndex.java | 48 + src/net/java/dev/typecast/ot/Glyph.java | 9 +- src/net/java/dev/typecast/ot/table/CffTable.java | 24 +- src/net/java/dev/typecast/t2/CffFont.java | 64 -- .../java/dev/typecast/t2/CffStandardStrings.java | 421 -------- src/net/java/dev/typecast/t2/Charset.java | 33 - src/net/java/dev/typecast/t2/CharsetFormat0.java | 51 - src/net/java/dev/typecast/t2/CharsetFormat1.java | 63 -- src/net/java/dev/typecast/t2/CharsetFormat2.java | 63 -- src/net/java/dev/typecast/t2/CharsetRange.java | 48 - src/net/java/dev/typecast/t2/CharsetRange1.java | 34 - src/net/java/dev/typecast/t2/CharsetRange2.java | 34 - src/net/java/dev/typecast/t2/Charstring.java | 30 - src/net/java/dev/typecast/t2/CharstringType2.java | 228 ----- src/net/java/dev/typecast/t2/Dict.java | 169 --- src/net/java/dev/typecast/t2/Index.java | 89 -- src/net/java/dev/typecast/t2/NameIndex.java | 57 -- src/net/java/dev/typecast/t2/StringIndex.java | 62 -- src/net/java/dev/typecast/t2/T2Interpreter.java | 1073 -------------------- src/net/java/dev/typecast/t2/T2Mnemonic.java | 83 -- src/net/java/dev/typecast/t2/TopDictIndex.java | 48 - 41 files changed, 2670 insertions(+), 2671 deletions(-) create mode 100644 src/net/java/dev/typecast/cff/CffFont.java create mode 100644 src/net/java/dev/typecast/cff/CffStandardStrings.java create mode 100644 src/net/java/dev/typecast/cff/Charset.java create mode 100644 src/net/java/dev/typecast/cff/CharsetFormat0.java create mode 100644 src/net/java/dev/typecast/cff/CharsetFormat1.java create mode 100644 src/net/java/dev/typecast/cff/CharsetFormat2.java create mode 100644 src/net/java/dev/typecast/cff/CharsetRange.java create mode 100644 src/net/java/dev/typecast/cff/CharsetRange1.java create mode 100644 src/net/java/dev/typecast/cff/CharsetRange2.java create mode 100644 src/net/java/dev/typecast/cff/Charstring.java create mode 100644 src/net/java/dev/typecast/cff/CharstringType2.java create mode 100644 src/net/java/dev/typecast/cff/Dict.java create mode 100644 src/net/java/dev/typecast/cff/Index.java create mode 100644 src/net/java/dev/typecast/cff/NameIndex.java create mode 100644 src/net/java/dev/typecast/cff/StringIndex.java create mode 100644 src/net/java/dev/typecast/cff/T2Interpreter.java create mode 100644 src/net/java/dev/typecast/cff/T2Mnemonic.java create mode 100644 src/net/java/dev/typecast/cff/TopDictIndex.java delete mode 100644 src/net/java/dev/typecast/t2/CffFont.java delete mode 100644 src/net/java/dev/typecast/t2/CffStandardStrings.java delete mode 100644 src/net/java/dev/typecast/t2/Charset.java delete mode 100644 src/net/java/dev/typecast/t2/CharsetFormat0.java delete mode 100644 src/net/java/dev/typecast/t2/CharsetFormat1.java delete mode 100644 src/net/java/dev/typecast/t2/CharsetFormat2.java delete mode 100644 src/net/java/dev/typecast/t2/CharsetRange.java delete mode 100644 src/net/java/dev/typecast/t2/CharsetRange1.java delete mode 100644 src/net/java/dev/typecast/t2/CharsetRange2.java delete mode 100644 src/net/java/dev/typecast/t2/Charstring.java delete mode 100644 src/net/java/dev/typecast/t2/CharstringType2.java delete mode 100644 src/net/java/dev/typecast/t2/Dict.java delete mode 100644 src/net/java/dev/typecast/t2/Index.java delete mode 100644 src/net/java/dev/typecast/t2/NameIndex.java delete mode 100644 src/net/java/dev/typecast/t2/StringIndex.java delete mode 100644 src/net/java/dev/typecast/t2/T2Interpreter.java delete mode 100644 src/net/java/dev/typecast/t2/T2Mnemonic.java delete mode 100644 src/net/java/dev/typecast/t2/TopDictIndex.java diff --git a/src/net/java/dev/typecast/app/editor/GlyphPanel.java b/src/net/java/dev/typecast/app/editor/GlyphPanel.java index a992261..4271e75 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.t2.Charstring; +import net.java.dev.typecast.cff.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 034b191..ce173d3 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.t2.Charstring) { + || obj instanceof net.java.dev.typecast.cff.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 39ad633..6fc7519 100644 --- a/src/net/java/dev/typecast/app/editor/TableTreeBuilder.java +++ b/src/net/java/dev/typecast/app/editor/TableTreeBuilder.java @@ -37,13 +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.t2.Charstring; +import net.java.dev.typecast.cff.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.cff.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; diff --git a/src/net/java/dev/typecast/cff/CffFont.java b/src/net/java/dev/typecast/cff/CffFont.java new file mode 100644 index 0000000..1231a34 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +/** + * + * @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/cff/CffStandardStrings.java b/src/net/java/dev/typecast/cff/CffStandardStrings.java new file mode 100644 index 0000000..4da6167 --- /dev/null +++ b/src/net/java/dev/typecast/cff/CffStandardStrings.java @@ -0,0 +1,421 @@ +/* + * 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.cff; + +/** + * Compact Font Format Standard Strings. As per Appendix A of the Adobe + * CFF specification. + * @author David Schweinsberg + */ +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/cff/Charset.java b/src/net/java/dev/typecast/cff/Charset.java new file mode 100644 index 0000000..fd16acd --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +/** + * + * @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/cff/CharsetFormat0.java b/src/net/java/dev/typecast/cff/CharsetFormat0.java new file mode 100644 index 0000000..a7f97f5 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +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/cff/CharsetFormat1.java b/src/net/java/dev/typecast/cff/CharsetFormat1.java new file mode 100644 index 0000000..9b5e93a --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +import java.io.DataInput; +import java.io.IOException; +import java.util.ArrayList; + +/** + * + * @author dschweinsberg + */ +public class CharsetFormat1 extends Charset { + + private final ArrayList _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/cff/CharsetFormat2.java b/src/net/java/dev/typecast/cff/CharsetFormat2.java new file mode 100644 index 0000000..69fadf9 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +import java.io.DataInput; +import java.io.IOException; +import java.util.ArrayList; + +/** + * + * @author dschweinsberg + */ +public class CharsetFormat2 extends Charset { + + private final ArrayList _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/cff/CharsetRange.java b/src/net/java/dev/typecast/cff/CharsetRange.java new file mode 100644 index 0000000..b3d0888 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +/** + * + * @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/cff/CharsetRange1.java b/src/net/java/dev/typecast/cff/CharsetRange1.java new file mode 100644 index 0000000..dc33430 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +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/cff/CharsetRange2.java b/src/net/java/dev/typecast/cff/CharsetRange2.java new file mode 100644 index 0000000..9e14c44 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +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/cff/Charstring.java b/src/net/java/dev/typecast/cff/Charstring.java new file mode 100644 index 0000000..c093d3f --- /dev/null +++ b/src/net/java/dev/typecast/cff/Charstring.java @@ -0,0 +1,30 @@ +/* + * 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.cff; + +/** + * CFF Charstring + * @author David Schweinsberg + */ +public abstract class Charstring { + + public abstract int getIndex(); + + public abstract String getName(); +} diff --git a/src/net/java/dev/typecast/cff/CharstringType2.java b/src/net/java/dev/typecast/cff/CharstringType2.java new file mode 100644 index 0000000..b5da650 --- /dev/null +++ b/src/net/java/dev/typecast/cff/CharstringType2.java @@ -0,0 +1,228 @@ +/* + * 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.cff; + +/** + * CFF Type 2 Charstring + * @author David Schweinsberg + */ +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 final int _index; + private final String _name; + private final int[] _data; + private final int _offset; + private final int _length; + private int _ip; + + /** Creates a new instance of CharstringType2 + * @param index + * @param name + * @param data + * @param offset + * @param length */ + public CharstringType2( + int index, + String name, + int[] data, + int offset, + int length) { + _index = index; + _name = name; + _data = data; + _offset = offset; + _length = length; + } + + @Override + public int getIndex() { + return _index; + } + + @Override + public String getName() { + return _name; + } + + private void disassemble(StringBuilder sb) { + while (isOperandAtIndex()) { + Number 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]; + return (32 <= b0 && b0 <= 255) || b0 == 28; + } + + public Number nextOperand() { + int b0 = _data[_ip]; + if (32 <= b0 && b0 <= 246) { + + // 1 byte integer + ++_ip; + return b0 - 139; + } else if (247 <= b0 && b0 <= 250) { + + // 2 byte integer + int b1 = _data[_ip + 1]; + _ip += 2; + return (b0 - 247) * 256 + b1 + 108; + } else if (251 <= b0 && b0 <= 254) { + + // 2 byte integer + int b1 = _data[_ip + 1]; + _ip += 2; + return -(b0 - 251) * 256 - b1 - 108; + } else if (b0 == 28) { + + // 3 byte integer + int b1 = (byte)_data[_ip + 1]; + int b2 = _data[_ip + 2]; + _ip += 3; + return 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; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + resetIP(); + while (moreBytes()) { + disassemble(sb); + sb.append("\n"); + } + return sb.toString(); + } +} diff --git a/src/net/java/dev/typecast/cff/Dict.java b/src/net/java/dev/typecast/cff/Dict.java new file mode 100644 index 0000000..5c500d8 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +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 _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 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 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/cff/Index.java b/src/net/java/dev/typecast/cff/Index.java new file mode 100644 index 0000000..1e8fb81 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +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/cff/NameIndex.java b/src/net/java/dev/typecast/cff/NameIndex.java new file mode 100644 index 0000000..fa8bdab --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +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/cff/StringIndex.java b/src/net/java/dev/typecast/cff/StringIndex.java new file mode 100644 index 0000000..3a25967 --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +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/cff/T2Interpreter.java b/src/net/java/dev/typecast/cff/T2Interpreter.java new file mode 100644 index 0000000..b823454 --- /dev/null +++ b/src/net/java/dev/typecast/cff/T2Interpreter.java @@ -0,0 +1,1073 @@ +/* + * 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.cff; + +import java.util.ArrayList; +import net.java.dev.typecast.ot.Point; + +/** + * Type 2 Charstring Interpreter. Operator descriptions are quoted from + * Adobe's Type 2 Charstring Format document -- 5117.Type2.pdf. + * @author David Schweinsberg + */ +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 final Number[] _argStack = new Number[ARGUMENT_STACK_LIMIT]; + private int _argStackIndex = 0; + private final int[] _subrStack = new int[SUBR_STACK_LIMIT]; + private int _subrStackIndex = 0; + private final Number[] _transientArray = new Number[TRANSIENT_ARRAY_ELEMENT_COUNT]; + + private int _stemCount = 0; + + private ArrayList _points; + private final Index _localSubrIndex; + private final Index _globalSubrIndex; + + /** Creates a new instance of T2Interpreter */ + public T2Interpreter(Index localSubrIndex, Index globalSubrIndex) { + _localSubrIndex = localSubrIndex; + _globalSubrIndex = globalSubrIndex; + } + + /** + * 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() { + _stemCount += getArgCount() / 2; + clearArg(); + } + + private void _vstemhm() { + _stemCount += getArgCount() / 2; + clearArg(); + } + + private void _hintmask(CharstringType2 cs) { + _stemCount += getArgCount() / 2; + int maskLen = (_stemCount - 1) / 8 + 1; + for (int i = 0; i < maskLen; ++i) { + cs.nextByte(); + } + clearArg(); + } + + private void _cntrmask(CharstringType2 cs) { + _stemCount += getArgCount() / 2; + int maskLen = (_stemCount - 1) / 8 + 1; + for (int i = 0; i < maskLen; ++i) { + cs.nextByte(); + } + 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(CharstringType2 cs) { + int bias; + int subrsCount = _localSubrIndex.getCount(); + if (subrsCount < 1240) { + bias = 107; + } else if (subrsCount < 33900) { + bias = 1131; + } else { + bias = 32768; + } + int i = popArg().intValue(); + int offset = _localSubrIndex.getOffset(i + bias); + int offset2 = _localSubrIndex.getOffset(i + bias + 1); + } + + /** + * Operates in the same manner as callsubr except that it calls a + * global subroutine. + */ + private void _callgsubr(CharstringType2 cs) { + int bias; + int subrsCount = _localSubrIndex.getCount(); + if (subrsCount < 1240) { + bias = 107; + } else if (subrsCount < 33900) { + bias = 1131; + } else { + bias = 32768; + } + int i = popArg().intValue(); + int offset = _localSubrIndex.getOffset(i + bias); + + } + + /** + * Returns from either a local or global charstring subroutine, and + * continues execution after the corresponding call(g)subr. + */ + private void _return(CharstringType2 cs) { + //_ip = popSubr(); + } + + public Point[] execute(CharstringType2 cs) { + _points = new ArrayList<>(); + 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(cs); + break; + case T2Mnemonic.RETURN: + _return(cs); + break; + case T2Mnemonic.ENDCHAR: + _endchar(); + break; + case T2Mnemonic.HSTEMHM: + _hstemhm(); + break; + case T2Mnemonic.HINTMASK: + _hintmask(cs); + break; + case T2Mnemonic.CNTRMASK: + _cntrmask(cs); + 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(cs); + 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/cff/T2Mnemonic.java b/src/net/java/dev/typecast/cff/T2Mnemonic.java new file mode 100644 index 0000000..55e3507 --- /dev/null +++ b/src/net/java/dev/typecast/cff/T2Mnemonic.java @@ -0,0 +1,83 @@ +/* + * 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.cff; + +/** + * The Mnemonic representations of the Type 2 charstring instruction set. + * @author David Schweinsberg + */ +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/cff/TopDictIndex.java b/src/net/java/dev/typecast/cff/TopDictIndex.java new file mode 100644 index 0000000..d7b092e --- /dev/null +++ b/src/net/java/dev/typecast/cff/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.cff; + +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(); + } + +} diff --git a/src/net/java/dev/typecast/ot/Glyph.java b/src/net/java/dev/typecast/ot/Glyph.java index 8dfa015..0a5d6d2 100644 --- a/src/net/java/dev/typecast/ot/Glyph.java +++ b/src/net/java/dev/typecast/ot/Glyph.java @@ -53,11 +53,10 @@ 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.t2.Charstring; -import net.java.dev.typecast.t2.CharstringType2; -import net.java.dev.typecast.t2.Index; - -import net.java.dev.typecast.t2.T2Interpreter; +import net.java.dev.typecast.cff.Charstring; +import net.java.dev.typecast.cff.CharstringType2; +import net.java.dev.typecast.cff.Index; +import net.java.dev.typecast.cff.T2Interpreter; /** * An individual glyph within a font. diff --git a/src/net/java/dev/typecast/ot/table/CffTable.java b/src/net/java/dev/typecast/ot/table/CffTable.java index 4136c7c..9739381 100644 --- a/src/net/java/dev/typecast/ot/table/CffTable.java +++ b/src/net/java/dev/typecast/ot/table/CffTable.java @@ -23,18 +23,18 @@ import java.io.DataInput; import java.io.DataInputStream; import java.io.IOException; import java.util.List; -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; +import net.java.dev.typecast.cff.CffFont; +import net.java.dev.typecast.cff.Charset; +import net.java.dev.typecast.cff.CharsetFormat0; +import net.java.dev.typecast.cff.CharsetFormat1; +import net.java.dev.typecast.cff.CharsetFormat2; +import net.java.dev.typecast.cff.Charstring; +import net.java.dev.typecast.cff.CharstringType2; +import net.java.dev.typecast.cff.Dict; +import net.java.dev.typecast.cff.Index; +import net.java.dev.typecast.cff.NameIndex; +import net.java.dev.typecast.cff.StringIndex; +import net.java.dev.typecast.cff.TopDictIndex; /** * Compact Font Format Table diff --git a/src/net/java/dev/typecast/t2/CffFont.java b/src/net/java/dev/typecast/t2/CffFont.java deleted file mode 100644 index 68d8bda..0000000 --- a/src/net/java/dev/typecast/t2/CffFont.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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/t2/CffStandardStrings.java b/src/net/java/dev/typecast/t2/CffStandardStrings.java deleted file mode 100644 index a2f8cca..0000000 --- a/src/net/java/dev/typecast/t2/CffStandardStrings.java +++ /dev/null @@ -1,421 +0,0 @@ -/* - * 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; - -/** - * Compact Font Format Standard Strings. As per Appendix A of the Adobe - * CFF specification. - * @author David Schweinsberg - */ -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/t2/Charset.java b/src/net/java/dev/typecast/t2/Charset.java deleted file mode 100644 index e221828..0000000 --- a/src/net/java/dev/typecast/t2/Charset.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 deleted file mode 100644 index dfca79b..0000000 --- a/src/net/java/dev/typecast/t2/CharsetFormat0.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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 deleted file mode 100644 index 1a0a64f..0000000 --- a/src/net/java/dev/typecast/t2/CharsetFormat1.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 _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 deleted file mode 100644 index 6ccdd86..0000000 --- a/src/net/java/dev/typecast/t2/CharsetFormat2.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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 _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 deleted file mode 100644 index 452adc3..0000000 --- a/src/net/java/dev/typecast/t2/CharsetRange.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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 deleted file mode 100644 index dff99d8..0000000 --- a/src/net/java/dev/typecast/t2/CharsetRange1.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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 deleted file mode 100644 index 18b2baf..0000000 --- a/src/net/java/dev/typecast/t2/CharsetRange2.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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/t2/Charstring.java b/src/net/java/dev/typecast/t2/Charstring.java deleted file mode 100644 index 36b8f77..0000000 --- a/src/net/java/dev/typecast/t2/Charstring.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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; - -/** - * CFF Charstring - * @author David Schweinsberg - */ -public abstract class Charstring { - - public abstract int getIndex(); - - public abstract String getName(); -} diff --git a/src/net/java/dev/typecast/t2/CharstringType2.java b/src/net/java/dev/typecast/t2/CharstringType2.java deleted file mode 100644 index eb8bc69..0000000 --- a/src/net/java/dev/typecast/t2/CharstringType2.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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; - -/** - * CFF Type 2 Charstring - * @author David Schweinsberg - */ -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 final int _index; - private final String _name; - private final int[] _data; - private final int _offset; - private final int _length; - private int _ip; - - /** Creates a new instance of CharstringType2 - * @param index - * @param name - * @param data - * @param offset - * @param length */ - public CharstringType2( - int index, - String name, - int[] data, - int offset, - int length) { - _index = index; - _name = name; - _data = data; - _offset = offset; - _length = length; - } - - @Override - public int getIndex() { - return _index; - } - - @Override - public String getName() { - return _name; - } - - private void disassemble(StringBuilder sb) { - while (isOperandAtIndex()) { - Number 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]; - return (32 <= b0 && b0 <= 255) || b0 == 28; - } - - public Number nextOperand() { - int b0 = _data[_ip]; - if (32 <= b0 && b0 <= 246) { - - // 1 byte integer - ++_ip; - return b0 - 139; - } else if (247 <= b0 && b0 <= 250) { - - // 2 byte integer - int b1 = _data[_ip + 1]; - _ip += 2; - return (b0 - 247) * 256 + b1 + 108; - } else if (251 <= b0 && b0 <= 254) { - - // 2 byte integer - int b1 = _data[_ip + 1]; - _ip += 2; - return -(b0 - 251) * 256 - b1 - 108; - } else if (b0 == 28) { - - // 3 byte integer - int b1 = (byte)_data[_ip + 1]; - int b2 = _data[_ip + 2]; - _ip += 3; - return 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; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - resetIP(); - while (moreBytes()) { - disassemble(sb); - sb.append("\n"); - } - return sb.toString(); - } -} diff --git a/src/net/java/dev/typecast/t2/Dict.java b/src/net/java/dev/typecast/t2/Dict.java deleted file mode 100644 index d4c6d79..0000000 --- a/src/net/java/dev/typecast/t2/Dict.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 _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 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 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 deleted file mode 100644 index dcad83b..0000000 --- a/src/net/java/dev/typecast/t2/Index.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 deleted file mode 100644 index 3831070..0000000 --- a/src/net/java/dev/typecast/t2/NameIndex.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 deleted file mode 100644 index ece39ab..0000000 --- a/src/net/java/dev/typecast/t2/StringIndex.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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 deleted file mode 100644 index f15856d..0000000 --- a/src/net/java/dev/typecast/t2/T2Interpreter.java +++ /dev/null @@ -1,1073 +0,0 @@ -/* - * 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.util.ArrayList; -import net.java.dev.typecast.ot.Point; - -/** - * Type 2 Charstring Interpreter. Operator descriptions are quoted from - * Adobe's Type 2 Charstring Format document -- 5117.Type2.pdf. - * @author David Schweinsberg - */ -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 final Number[] _argStack = new Number[ARGUMENT_STACK_LIMIT]; - private int _argStackIndex = 0; - private final int[] _subrStack = new int[SUBR_STACK_LIMIT]; - private int _subrStackIndex = 0; - private final Number[] _transientArray = new Number[TRANSIENT_ARRAY_ELEMENT_COUNT]; - - private int _stemCount = 0; - - private ArrayList _points; - private final Index _localSubrIndex; - private final Index _globalSubrIndex; - - /** Creates a new instance of T2Interpreter */ - public T2Interpreter(Index localSubrIndex, Index globalSubrIndex) { - _localSubrIndex = localSubrIndex; - _globalSubrIndex = globalSubrIndex; - } - - /** - * 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() { - _stemCount += getArgCount() / 2; - clearArg(); - } - - private void _vstemhm() { - _stemCount += getArgCount() / 2; - clearArg(); - } - - private void _hintmask(CharstringType2 cs) { - _stemCount += getArgCount() / 2; - int maskLen = (_stemCount - 1) / 8 + 1; - for (int i = 0; i < maskLen; ++i) { - cs.nextByte(); - } - clearArg(); - } - - private void _cntrmask(CharstringType2 cs) { - _stemCount += getArgCount() / 2; - int maskLen = (_stemCount - 1) / 8 + 1; - for (int i = 0; i < maskLen; ++i) { - cs.nextByte(); - } - 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(CharstringType2 cs) { - int bias; - int subrsCount = _localSubrIndex.getCount(); - if (subrsCount < 1240) { - bias = 107; - } else if (subrsCount < 33900) { - bias = 1131; - } else { - bias = 32768; - } - int i = popArg().intValue(); - int offset = _localSubrIndex.getOffset(i + bias); - int offset2 = _localSubrIndex.getOffset(i + bias + 1); - } - - /** - * Operates in the same manner as callsubr except that it calls a - * global subroutine. - */ - private void _callgsubr(CharstringType2 cs) { - int bias; - int subrsCount = _localSubrIndex.getCount(); - if (subrsCount < 1240) { - bias = 107; - } else if (subrsCount < 33900) { - bias = 1131; - } else { - bias = 32768; - } - int i = popArg().intValue(); - int offset = _localSubrIndex.getOffset(i + bias); - - } - - /** - * Returns from either a local or global charstring subroutine, and - * continues execution after the corresponding call(g)subr. - */ - private void _return(CharstringType2 cs) { - //_ip = popSubr(); - } - - public Point[] execute(CharstringType2 cs) { - _points = new ArrayList<>(); - 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(cs); - break; - case T2Mnemonic.RETURN: - _return(cs); - break; - case T2Mnemonic.ENDCHAR: - _endchar(); - break; - case T2Mnemonic.HSTEMHM: - _hstemhm(); - break; - case T2Mnemonic.HINTMASK: - _hintmask(cs); - break; - case T2Mnemonic.CNTRMASK: - _cntrmask(cs); - 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(cs); - 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 deleted file mode 100644 index 09e7278..0000000 --- a/src/net/java/dev/typecast/t2/T2Mnemonic.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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; - -/** - * The Mnemonic representations of the Type 2 charstring instruction set. - * @author David Schweinsberg - */ -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/t2/TopDictIndex.java b/src/net/java/dev/typecast/t2/TopDictIndex.java deleted file mode 100644 index cd22466..0000000 --- a/src/net/java/dev/typecast/t2/TopDictIndex.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * 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(); - } - -} -- cgit v1.2.3