You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ga...@apache.org on 2016/03/16 20:19:25 UTC

svn commit: r1735284 - in /xmlgraphics/fop/branches/maven: ./ fop-core/src/main/java/org/apache/fop/fonts/truetype/ fop-core/src/main/java/org/apache/fop/layoutmgr/inline/ fop-core/src/test/java/org/apache/fop/fonts/ fop-core/src/test/java/org/apache/f...

Author: gadams
Date: Wed Mar 16 19:19:24 2016
New Revision: 1735284

URL: http://svn.apache.org/viewvc?rev=1735284&view=rev
Log:
Merge ^/xmlgraphics/fop/trunk.

Modified:
    xmlgraphics/fop/branches/maven/   (props changed)
    xmlgraphics/fop/branches/maven/README
    xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java
    xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFFile.java
    xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java
    xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
    xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java
    xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java
    xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java

Propchange: xmlgraphics/fop/branches/maven/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Wed Mar 16 19:19:24 2016
@@ -15,4 +15,4 @@
 /xmlgraphics/fop/branches/fop-0_95:684572,688085,688696
 /xmlgraphics/fop/branches/fop-1_0:959975-964707
 /xmlgraphics/fop/branches/fop-1_1:1357766-1400689,1400697
-/xmlgraphics/fop/trunk:1721689-1733494
+/xmlgraphics/fop/trunk:1721689-1735283

Modified: xmlgraphics/fop/branches/maven/README
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/maven/README?rev=1735284&r1=1735283&r2=1735284&view=diff
==============================================================================
--- xmlgraphics/fop/branches/maven/README (original)
+++ xmlgraphics/fop/branches/maven/README Wed Mar 16 19:19:24 2016
@@ -78,6 +78,18 @@ FOP.
 Otherwise, please follow the instructions found here:
 http://xmlgraphics.apache.org/fop/stable/compiling.html
 
+[TEMPORARY]
+
+Until the above referenced instructions are updated, one of the following
+may be used to build FOP:
+
+Building with Maven (preferred)
+
+% mvn clean install
+
+Building with Ant (deprecated)
+
+% ant -f fop/build.xml clean all
 
 How do I run FOP?
 -----------------
@@ -89,10 +101,25 @@ command-line.
 For more details, see:
 http://xmlgraphics.apache.org/fop/stable/running.html
 
+[TEMPORARY]
+
+Note that FOP command line scripts and build results from ant will be found
+under the ./fop sub-directory.
+
 ==============================================================================
   RELEASE NOTES
 ==============================================================================
 
+Version 2.2  (Forthcoming)
+===========
+
+Major Changes in Version 2.2
+----------------------------
+
+* Transition from Ant to Maven Build Process
+
+This release also contains a number of bug fixes.
+
 Version 2.1
 ===========
 

Modified: xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java?rev=1735284&r1=1735283&r2=1735284&view=diff
==============================================================================
--- xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java (original)
+++ xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OFFontLoader.java Wed Mar 16 19:19:24 2016
@@ -105,7 +105,7 @@ public class OFFontLoader extends FontLo
             FontFileReader reader = new FontFileReader(in);
             String header = readHeader(reader);
             boolean isCFF = header.equals("OTTO");
-            OpenFont otf = (isCFF) ? new OTFFile() : new TTFFile(useKerning, useAdvanced);
+            OpenFont otf = (isCFF) ? new OTFFile(useKerning, useAdvanced) : new TTFFile(useKerning, useAdvanced);
             boolean supported = otf.readFont(reader, header, ttcFontName);
             if (!supported) {
                 throw new IOException("The font does not have a Unicode cmap table: " + fontFileURI);

Modified: xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFFile.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFFile.java?rev=1735284&r1=1735283&r2=1735284&view=diff
==============================================================================
--- xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFFile.java (original)
+++ xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFFile.java Wed Mar 16 19:19:24 2016
@@ -37,6 +37,11 @@ public class OTFFile extends OpenFont {
     protected CFFFont fileFont;
 
     public OTFFile() throws IOException {
+        this(true, false);
+    }
+
+    public OTFFile(boolean useKerning, boolean useAdvanced) throws IOException {
+        super(useKerning, useAdvanced);
         checkForFontbox();
     }
 

Modified: xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java?rev=1735284&r1=1735283&r2=1735284&view=diff
==============================================================================
--- xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java (original)
+++ xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java Wed Mar 16 19:19:24 2016
@@ -31,6 +31,9 @@ import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
 import org.apache.fontbox.cff.CFFStandardString;
 import org.apache.fontbox.cff.encoding.CFFEncoding;
 
@@ -105,6 +108,8 @@ public class OTFSubSetFile extends OTFFi
     private static final int LOCAL_SUBROUTINE = 10;
     /** The operator used to identify a global subroutine reference */
     private static final int GLOBAL_SUBROUTINE = 29;
+    /** The parser used to parse type2 charstring */
+    private Type2Parser type2Parser;
 
     public OTFSubSetFile() throws IOException {
         super();
@@ -120,9 +125,9 @@ public class OTFSubSetFile extends OTFFi
      * Reads and creates a subset of the font.
      *
      * @param in FontFileReader to read from
-     * @param name Name to be checked for in the font file
+     * @param embeddedName Name to be checked for in the font file
      * @param header The header of the font file
-     * @param glyphs Map of glyphs (glyphs has old index as (Integer) key and
+     * @param usedGlyphs Map of glyphs (glyphs has old index as (Integer) key and
      * new index as (Integer) value)
      * @throws IOException in case of an I/O problem
      */
@@ -242,8 +247,8 @@ public class OTFSubSetFile extends OTFFi
     protected List<Integer> storeFDStrings(List<Integer> uniqueNewRefs) throws IOException {
         ArrayList<Integer> fontNameSIDs = new ArrayList<Integer>();
         List<FontDict> fdFonts = cffReader.getFDFonts();
-        for (int i = 0; i < uniqueNewRefs.size(); i++) {
-            FontDict fdFont = fdFonts.get(uniqueNewRefs.get(i));
+        for (Integer uniqueNewRef : uniqueNewRefs) {
+            FontDict fdFont = fdFonts.get(uniqueNewRef);
             byte[] fdFontByteData = fdFont.getByteData();
             Map<String, DICTEntry> fdFontDict = cffReader.parseDictData(fdFontByteData);
             fontNameSIDs.add(stringIndexData.size() + NUM_STANDARD_STRINGS);
@@ -254,8 +259,8 @@ public class OTFSubSetFile extends OTFFi
     }
 
     protected void writeBytes(byte[] out) {
-        for (int i = 0; i < out.length; i++) {
-            writeByte(out[i]);
+        for (byte anOut : out) {
+            writeByte(anOut);
         }
     }
 
@@ -317,7 +322,7 @@ public class OTFSubSetFile extends OTFFi
         cidEntryByteData = updateOffset(cidEntryByteData, dictEntry.getOperandLengths().get(0),
                 dictEntry.getOperandLengths().get(1), sidBStringIndex);
         cidEntryByteData = updateOffset(cidEntryByteData, dictEntry.getOperandLengths().get(0)
-                + dictEntry.getOperandLengths().get(1), dictEntry.getOperandLengths().get(2), 139);
+                + dictEntry.getOperandLengths().get(1), dictEntry.getOperandLengths().get(2), 0);
         writeBytes(cidEntryByteData);
     }
 
@@ -335,7 +340,7 @@ public class OTFSubSetFile extends OTFFi
         }
 
         byte[] newDictEntry = createNewRef(stringIndexData.size() + 390, dictEntry.getOperator(),
-                dictEntry.getOperandLength());
+                dictEntry.getOperandLength(), true);
         writeBytes(newDictEntry);
     }
 
@@ -356,7 +361,8 @@ public class OTFSubSetFile extends OTFFi
                 }
             } else {
                 int index = sid - NUM_STANDARD_STRINGS;
-                if (index <= cffReader.getStringIndex().getNumObjects()) {
+                //index is 0 based, should use < not <=
+                if (index < cffReader.getStringIndex().getNumObjects()) {
                     if (mbFont != null) {
                         mbFont.mapUsedGlyphName(subsetGlyphs.get(gid),
                                 new String(cffReader.getStringIndex().getValue(index)));
@@ -416,19 +422,22 @@ public class OTFSubSetFile extends OTFFi
             subsetFDSelect = new LinkedHashMap<Integer, FDIndexReference>();
 
             List<List<Integer>> foundLocalUniques = new ArrayList<List<Integer>>();
-            for (int i = 0; i < uniqueGroups.size(); i++) {
+            for (Integer uniqueGroup1 : uniqueGroups) {
                 foundLocalUniques.add(new ArrayList<Integer>());
             }
+            Map<Integer, Integer> gidHintMaskLengths = new HashMap<Integer, Integer>();
             for (int gid : subsetGlyphs.keySet()) {
                 int group = subsetGroups.get(gid);
                 localIndexSubr = cffReader.getFDFonts().get(group).getLocalSubrData();
                 localUniques = foundLocalUniques.get(uniqueGroups.indexOf(subsetGroups.get(gid)));
+                type2Parser = new Type2Parser();
 
                 FDIndexReference newFDReference = new FDIndexReference(
                         uniqueGroups.indexOf(subsetGroups.get(gid)), subsetGroups.get(gid));
                 subsetFDSelect.put(subsetGlyphs.get(gid), newFDReference);
                 byte[] data = charStringsIndex.getValue(gid);
                 preScanForSubsetIndexSize(data);
+                gidHintMaskLengths.put(gid, type2Parser.getMaskLength());
             }
 
             //Create the two lists which are to store the local and global subroutines
@@ -439,11 +448,11 @@ public class OTFSubSetFile extends OTFFi
             globalUniques.clear();
             localUniques = null;
 
-            for (int l = 0; l < foundLocalUniques.size(); l++) {
+            for (List<Integer> foundLocalUnique : foundLocalUniques) {
                 fdSubrs.add(new ArrayList<byte[]>());
             }
             List<List<Integer>> foundLocalUniquesB = new ArrayList<List<Integer>>();
-            for (int k = 0; k < uniqueGroups.size(); k++) {
+            for (Integer uniqueGroup : uniqueGroups) {
                 foundLocalUniquesB.add(new ArrayList<Integer>());
             }
             for (Integer gid : subsetGlyphs.keySet()) {
@@ -454,6 +463,8 @@ public class OTFSubSetFile extends OTFFi
                 subsetLocalIndexSubr = fdSubrs.get(subsetFDSelect.get(subsetGlyphs.get(gid)).getNewFDIndex());
                 subsetLocalSubrCount = foundLocalUniques.get(subsetFDSelect.get(subsetGlyphs.get(gid))
                         .getNewFDIndex()).size();
+                type2Parser = new Type2Parser();
+                type2Parser.setMaskLength(gidHintMaskLengths.get(gid));
                 data = readCharStringData(data, subsetLocalSubrCount);
                 subsetCharStringsIndex.add(data);
             }
@@ -490,13 +501,9 @@ public class OTFSubSetFile extends OTFFi
             privateDictOffsets.add(privateDictOffset);
             byte[] fdPrivateDictByteData = curFDFont.getPrivateDictData();
             if (fdPrivateDict.get("Subrs") != null) {
-                int encodingValue = 0;
-                if (fdPrivateDict.get("Subrs").getOperandLength() == 1) {
-                    encodingValue = 139;
-                }
                 fdPrivateDictByteData = updateOffset(fdPrivateDictByteData, fdPrivateDict.get("Subrs").getOffset(),
                         fdPrivateDict.get("Subrs").getOperandLength(),
-                        fdPrivateDictByteData.length + encodingValue);
+                        fdPrivateDictByteData.length);
             }
             writeBytes(fdPrivateDictByteData);
             writeIndex(fdSubrs.get(i));
@@ -515,8 +522,8 @@ public class OTFSubSetFile extends OTFFi
         writeByte(1); //First offset
 
         int count = 1;
-        for (int i = 0; i < uniqueNewRefs.size(); i++) {
-            FontDict fdFont = fdFonts.get(uniqueNewRefs.get(i));
+        for (Integer uniqueNewRef : uniqueNewRefs) {
+            FontDict fdFont = fdFonts.get(uniqueNewRef);
             count += fdFont.getByteData().length;
             writeByte(count);
         }
@@ -586,10 +593,12 @@ public class OTFSubSetFile extends OTFFi
 
         localUniques = new ArrayList<Integer>();
         globalUniques = new ArrayList<Integer>();
-
+        Map<Integer, Integer> gidHintMaskLengths = new HashMap<Integer, Integer>();
         for (int gid : subsetGlyphs.keySet()) {
+            type2Parser = new Type2Parser();
             byte[] data = charStringsIndex.getValue(gid);
             preScanForSubsetIndexSize(data);
+            gidHintMaskLengths.put(gid, type2Parser.getMaskLength());
         }
 
         //Store the size of each subset index and clear the unique arrays
@@ -600,44 +609,153 @@ public class OTFSubSetFile extends OTFFi
 
         for (int gid : subsetGlyphs.keySet()) {
             byte[] data = charStringsIndex.getValue(gid);
+            type2Parser = new Type2Parser();
             //Retrieve modified char string data and fill local / global subroutine arrays
+            type2Parser.setMaskLength(gidHintMaskLengths.get(gid));
             data = readCharStringData(data, subsetLocalSubrCount);
             subsetCharStringsIndex.add(data);
         }
     }
 
+    static class Type2Parser {
+        /**
+         * logging instance
+         */
+        protected Log log = LogFactory.getLog(Type2Parser.class);
+
+        private ArrayList<BytesNumber> stack = new ArrayList<BytesNumber>();
+        private int hstemCount;
+        private int vstemCount;
+        private int lastOp = -1;
+        private int maskLength = -1;
+
+        public void pushOperand(BytesNumber v) {
+            stack.add(v);
+        }
+
+        public BytesNumber popOperand() {
+            return stack.remove(stack.size() - 1);
+        }
+
+        public void clearStack() {
+            stack.clear();
+        }
+
+        public int[] getOperands(int numbers) {
+            int[] ret = new int[numbers];
+            while (numbers > 0) {
+                numbers--;
+                ret[numbers] = this.popOperand().getNumber();
+            }
+            return ret;
+        }
+
+        public void setMaskLength(int maskLength) {
+            this.maskLength = maskLength;
+        }
+
+        public int getMaskLength() {
+            // The number of data bytes for mask is exactly the number needed, one
+            // bit per hint, to reference the number of stem hints declared
+            // at the beginning of the charstring program.
+            if (maskLength > 0) {
+                return maskLength;
+            }
+            return 1 + (hstemCount + vstemCount  - 1) / 8;
+        }
+
+        public int exec(int b0, byte[] data, int dataPos) {
+            int posDelta = 0;
+            if ((b0 >= 0 && b0 <= 27) || (b0 >= 29 && b0 <= 31)) {
+                if (b0 == 12) {
+                    dataPos += 1;
+                    log.warn("May not guess the operand count correctly.");
+                    posDelta = 1;
+                } else if (b0 == 1 || b0 == 18) {
+                    // hstem(hm) operator
+                    hstemCount += stack.size() / 2;
+                    clearStack();
+                } else if (b0 == 19 || b0 == 20) {
+                    if (lastOp == 1 || lastOp == 18) {
+                        //If hstem and vstem hints are both declared at the beginning of
+                        //a charstring, and this sequence is followed directly by the
+                        //hintmask or cntrmask operators, the vstem hint operator need
+                        //not be included.
+                        vstemCount += stack.size() / 2;
+                    }
+                    clearStack();
+                    posDelta = getMaskLength();
+                } else if (b0 == 3 || b0 == 23) {
+                    // vstem(hm) operator
+                    vstemCount += stack.size() / 2;
+                    clearStack();
+                }
+                if (b0 != 11 && b0 != 12) {
+                    lastOp = b0;
+                }
+            } else if (b0 == 28 || (b0 >= 32 && b0 <= 255)) {
+                BytesNumber operand = readNumber(b0, data, dataPos);
+                pushOperand(operand);
+                posDelta = operand.getNumBytes() - 1;
+            } else {
+                throw new UnsupportedOperationException("Operator:" + b0 + " is not supported");
+            }
+            return posDelta;
+        }
+
+        private BytesNumber readNumber(int b0, byte[] input, int curPos) {
+            if (b0 == 28) {
+                int b1 = input[curPos + 1] & 0xff;
+                int b2 = input[curPos + 2] & 0xff;
+                return new BytesNumber((int) (short) (b1 << 8 | b2), 3);
+            } else if (b0 >= 32 && b0 <= 246) {
+                return new BytesNumber(b0 - 139, 1);
+            } else if (b0 >= 247 && b0 <= 250) {
+                int b1 = input[curPos + 1] & 0xff;
+                return new BytesNumber((b0 - 247) * 256 + b1 + 108, 2);
+            } else if (b0 >= 251 && b0 <= 254) {
+                int b1 = input[curPos + 1] & 0xff;
+                return new BytesNumber(-(b0 - 251) * 256 - b1 - 108, 2);
+            } else if (b0 == 255) {
+                int b1 = input[curPos + 1] & 0xff;
+                int b2 = input[curPos + 2] & 0xff;
+                int b3 = input[curPos + 3] & 0xff;
+                int b4 = input[curPos + 4] & 0xff;
+                return new BytesNumber((b1 << 24 | b2 << 16 | b3 << 8 | b4), 5);
+            } else {
+                throw new IllegalArgumentException();
+            }
+        }
+    }
     private void preScanForSubsetIndexSize(byte[] data) throws IOException {
         boolean hasLocalSubroutines = localIndexSubr != null && localIndexSubr.getNumObjects() > 0;
         boolean hasGlobalSubroutines = globalIndexSubr != null && globalIndexSubr.getNumObjects() > 0;
-        BytesNumber operand = new BytesNumber(-1, -1);
         for (int dataPos = 0; dataPos < data.length; dataPos++) {
             int b0 = data[dataPos] & 0xff;
             if (b0 == LOCAL_SUBROUTINE && hasLocalSubroutines) {
-                int subrNumber = getSubrNumber(localIndexSubr.getNumObjects(), operand.getNumber());
-
+                int subrNumber = getSubrNumber(localIndexSubr.getNumObjects(), type2Parser.popOperand().getNumber());
                 if (!localUniques.contains(subrNumber) && subrNumber < localIndexSubr.getNumObjects()) {
                     localUniques.add(subrNumber);
+                }
+                if (subrNumber < localIndexSubr.getNumObjects()) {
                     byte[] subr = localIndexSubr.getValue(subrNumber);
                     preScanForSubsetIndexSize(subr);
+                } else {
+                    throw new IllegalArgumentException("callsubr out of range");
                 }
-                operand.clearNumber();
             } else if (b0 == GLOBAL_SUBROUTINE && hasGlobalSubroutines) {
-                int subrNumber = getSubrNumber(globalIndexSubr.getNumObjects(), operand.getNumber());
-
+                int subrNumber = getSubrNumber(globalIndexSubr.getNumObjects(), type2Parser.popOperand().getNumber());
                 if (!globalUniques.contains(subrNumber) && subrNumber < globalIndexSubr.getNumObjects()) {
                     globalUniques.add(subrNumber);
+                }
+                if (subrNumber < globalIndexSubr.getNumObjects()) {
                     byte[] subr = globalIndexSubr.getValue(subrNumber);
                     preScanForSubsetIndexSize(subr);
+                } else {
+                    throw new IllegalArgumentException("callgsubr out of range");
                 }
-                operand.clearNumber();
-            } else if ((b0 >= 0 && b0 <= 27) || (b0 >= 29 && b0 <= 31)) {
-                operand.clearNumber();
-                if (b0 == 19 || b0 == 20) {
-                    dataPos += 1;
-                }
-            } else if (b0 == 28 || (b0 >= 32 && b0 <= 255)) {
-                operand = readNumber(b0, data, dataPos);
-                dataPos += operand.getNumBytes() - 1;
+            } else  {
+                dataPos += type2Parser.exec(b0, data, dataPos);
             }
         }
     }
@@ -650,10 +768,10 @@ public class OTFSubSetFile extends OTFFi
     private byte[] readCharStringData(byte[] data, int subsetLocalSubrCount) throws IOException {
         boolean hasLocalSubroutines = localIndexSubr != null && localIndexSubr.getNumObjects() > 0;
         boolean hasGlobalSubroutines = globalIndexSubr != null && globalIndexSubr.getNumObjects() > 0;
-        BytesNumber operand = new BytesNumber(-1, -1);
         for (int dataPos = 0; dataPos < data.length; dataPos++) {
             int b0 = data[dataPos] & 0xff;
             if (b0 == 10 && hasLocalSubroutines) {
+                BytesNumber operand = type2Parser.popOperand();
                 int subrNumber = getSubrNumber(localIndexSubr.getNumObjects(), operand.getNumber());
 
                 int newRef = getNewRefForReference(subrNumber, localUniques, localIndexSubr, subsetLocalIndexSubr,
@@ -665,9 +783,8 @@ public class OTFSubSetFile extends OTFFi
                     dataPos -= data.length - newData.length;
                     data = newData;
                 }
-
-                operand.clearNumber();
             } else if (b0 == 29 && hasGlobalSubroutines) {
+                BytesNumber operand = type2Parser.popOperand();
                 int subrNumber = getSubrNumber(globalIndexSubr.getNumObjects(), operand.getNumber());
 
                 int newRef = getNewRefForReference(subrNumber, globalUniques, globalIndexSubr, subsetGlobalIndexSubr,
@@ -679,16 +796,8 @@ public class OTFSubSetFile extends OTFFi
                     dataPos -= (data.length - newData.length);
                     data = newData;
                 }
-
-                operand.clearNumber();
-            } else if ((b0 >= 0 && b0 <= 27) || (b0 >= 29 && b0 <= 31)) {
-                operand.clearNumber();
-                if (b0 == 19) {
-                    dataPos += 1;
-                }
-            } else if (b0 == 28 || (b0 >= 32 && b0 <= 255)) {
-                operand = readNumber(b0, data, dataPos);
-                dataPos += operand.getNumBytes() - 1;
+            } else {
+                dataPos += type2Parser.exec(b0, data, dataPos);
             }
         }
 
@@ -698,18 +807,16 @@ public class OTFSubSetFile extends OTFFi
 
     private int getNewRefForReference(int subrNumber, List<Integer> uniquesArray,
             CFFIndexData indexSubr, List<byte[]> subsetIndexSubr, int subrCount) throws IOException {
-        int newRef = -1;
+        int newRef;
         if (!uniquesArray.contains(subrNumber)) {
             if (subrNumber < indexSubr.getNumObjects()) {
                 byte[] subr = indexSubr.getValue(subrNumber);
                 subr = readCharStringData(subr, subrCount);
-                if (!uniquesArray.contains(subrNumber)) {
-                    uniquesArray.add(subrNumber);
-                    subsetIndexSubr.add(subr);
-                    newRef = subsetIndexSubr.size() - 1;
-                } else {
-                    newRef = uniquesArray.indexOf(subrNumber);
-                }
+                uniquesArray.add(subrNumber);
+                subsetIndexSubr.add(subr);
+                newRef = subsetIndexSubr.size() - 1;
+            } else {
+                throw new IllegalArgumentException("subrNumber out of range");
             }
         } else {
             newRef = uniquesArray.indexOf(subrNumber);
@@ -737,7 +844,7 @@ public class OTFSubSetFile extends OTFFi
         System.arraycopy(currentData, 0, preBytes, 0, startRef);
         int newBias = getBias(fullSubsetIndexSize);
         int newRef = curSubsetIndexSize - newBias;
-        byte[] newRefBytes = createNewRef(newRef, operatorCode, -1);
+        byte[] newRefBytes = createNewRef(newRef, operatorCode, -1, false);
         newData = concatArray(preBytes, newRefBytes);
         byte[] postBytes = new byte[currentData.length - (startRef + length)];
         System.arraycopy(currentData, startRef + length, postBytes, 0,
@@ -745,19 +852,27 @@ public class OTFSubSetFile extends OTFFi
         return concatArray(newData, postBytes);
     }
 
-    public static byte[] createNewRef(int newRef, int[] operatorCode, int forceLength) {
+    public static byte[] createNewRef(int newRef, int[] operatorCode, int forceLength, boolean isDict) {
         byte[] newRefBytes;
         int sizeOfOperator = operatorCode.length;
-        if ((forceLength == -1 && newRef <= 107) || forceLength == 1) {
+        if ((forceLength == -1 && newRef >= -107 && newRef <= 107) || forceLength == 1) {
             newRefBytes = new byte[1 + sizeOfOperator];
             //The index values are 0 indexed
             newRefBytes[0] = (byte)(newRef + 139);
             for (int i = 0; i < operatorCode.length; i++) {
                 newRefBytes[1 + i] = (byte)operatorCode[i];
             }
-        } else if ((forceLength == -1 && newRef <= 1131) || forceLength == 2) {
+        } else if ((forceLength == -1 && newRef >= -1131 && newRef <= 1131) || forceLength == 2) {
             newRefBytes = new byte[2 + sizeOfOperator];
-            if (newRef <= 363) {
+            if (newRef <= -876) {
+                newRefBytes[0] = (byte)254;
+            } else if (newRef <= -620) {
+                newRefBytes[0] = (byte)253;
+            } else if (newRef <= -364) {
+                newRefBytes[0] = (byte)252;
+            } else if (newRef <= -108) {
+                newRefBytes[0] = (byte)251;
+            } else if (newRef <= 363) {
                 newRefBytes[0] = (byte)247;
             } else if (newRef <= 619) {
                 newRefBytes[0] = (byte)248;
@@ -766,11 +881,15 @@ public class OTFSubSetFile extends OTFFi
             } else {
                 newRefBytes[0] = (byte)250;
             }
-            newRefBytes[1] = (byte)(newRef - 108);
+            if (newRef > 0) {
+                newRefBytes[1] = (byte)(newRef - 108);
+            } else {
+                newRefBytes[1] = (byte)(-newRef - 108);
+            }
             for (int i = 0; i < operatorCode.length; i++) {
                 newRefBytes[2 + i] = (byte)operatorCode[i];
             }
-        } else if ((forceLength == -1 && newRef <= 32767) || forceLength == 3) {
+        } else if ((forceLength == -1 && newRef >= -32768 && newRef <= 32767) || forceLength == 3) {
             newRefBytes = new byte[3 + sizeOfOperator];
             newRefBytes[0] = 28;
             newRefBytes[1] = (byte)(newRef >> 8);
@@ -780,7 +899,11 @@ public class OTFSubSetFile extends OTFFi
             }
         } else {
             newRefBytes = new byte[5 + sizeOfOperator];
-            newRefBytes[0] = 29;
+            if (isDict) {
+                newRefBytes[0] = 29;
+            } else {
+                newRefBytes[0] = (byte)255;
+            }
             newRefBytes[1] = (byte)(newRef >> 24);
             newRefBytes[2] = (byte)(newRef >> 16);
             newRefBytes[3] = (byte)(newRef >> 8);
@@ -806,16 +929,18 @@ public class OTFSubSetFile extends OTFFi
         //2 byte number of items
         this.writeCard16(dataArray.size());
         //Offset Size: 1 byte = 256, 2 bytes = 65536 etc.
-        int totLength = 0;
-        for (int i = 0; i < dataArray.size(); i++) {
-            totLength += dataArray.get(i).length;
+        //Offsets in the offset array are relative to the byte that precedes the object data.
+        //Therefore the first element of the offset array is always 1.
+        int totLength = 1;
+        for (byte[] aDataArray1 : dataArray) {
+            totLength += aDataArray1.length;
         }
         int offSize = 1;
-        if (totLength <= (1 << 8)) {
+        if (totLength < (1 << 8)) {
             offSize = 1;
-        } else if (totLength <= (1 << 16)) {
+        } else if (totLength < (1 << 16)) {
             offSize = 2;
-        } else if (totLength <= (1 << 24)) {
+        } else if (totLength < (1 << 24)) {
             offSize = 3;
         } else {
             offSize = 4;
@@ -860,34 +985,12 @@ public class OTFSubSetFile extends OTFFi
                 throw new AssertionError("Offset Size was not an expected value.");
             }
         }
-        for (int i = 0; i < dataArray.size(); i++) {
-            writeBytes(dataArray.get(i));
+        for (byte[] aDataArray : dataArray) {
+            writeBytes(aDataArray);
         }
         return hdrTotal + total;
     }
 
-    private BytesNumber readNumber(int b0, byte[] input, int curPos) throws IOException {
-        if (b0 == 28) {
-            int b1 = input[curPos + 1] & 0xff;
-            int b2 = input[curPos + 2] & 0xff;
-            return new BytesNumber(Integer.valueOf((short) (b1 << 8 | b2)), 3);
-        } else if (b0 >= 32 && b0 <= 246) {
-            return new BytesNumber(Integer.valueOf(b0 - 139), 1);
-        } else if (b0 >= 247 && b0 <= 250) {
-            int b1 = input[curPos + 1] & 0xff;
-            return new BytesNumber(Integer.valueOf((b0 - 247) * 256 + b1 + 108), 2);
-        } else if (b0 >= 251 && b0 <= 254) {
-            int b1 = input[curPos + 1] & 0xff;
-            return new BytesNumber(Integer.valueOf(-(b0 - 251) * 256 - b1 - 108), 2);
-        } else if (b0 == 255) {
-            int b1 = input[curPos + 1] & 0xff;
-            int b2 = input[curPos + 2] & 0xff;
-            return new BytesNumber(Integer.valueOf((short)(b1 << 8 | b2)), 5);
-        } else {
-            throw new IllegalArgumentException();
-        }
-    }
-
     /**
      * A class used to store the last number operand and also it's size in bytes
      */
@@ -980,13 +1083,8 @@ public class OTFSubSetFile extends OTFFi
             DICTEntry subroutines = privateDICT.get("Subrs");
             if (subroutines != null) {
                 int oldLocalSubrOffset = privateDictOffset + subroutines.getOffset();
-                //Value needs to be converted to -139 etc.
-                int encodeValue = 0;
-                if (subroutines.getOperandLength() == 1) {
-                    encodeValue = 139;
-                }
                 output = updateOffset(output, oldLocalSubrOffset, subroutines.getOperandLength(),
-                        (localIndexOffset - privateDictOffset) + encodeValue);
+                        (localIndexOffset - privateDictOffset));
             }
         }
     }
@@ -1033,10 +1131,18 @@ public class OTFSubSetFile extends OTFFi
     protected byte[] updateOffset(byte[] out, int position, int length, int replacement) {
         switch (length) {
         case 1:
-            out[position] = (byte)(replacement & 0xFF);
+            out[position] = (byte)(replacement + 139);
             break;
         case 2:
-            if (replacement <= 363) {
+            if (replacement <= -876) {
+                out[position] = (byte)254;
+            } else if (replacement <= -620) {
+                out[position] = (byte)253;
+            } else if (replacement <= -364) {
+                out[position] = (byte)252;
+            } else if (replacement <= -108) {
+                out[position] = (byte)251;
+            } else if (replacement <= 363) {
                 out[position] = (byte)247;
             } else if (replacement <= 619) {
                 out[position] = (byte)248;
@@ -1045,7 +1151,11 @@ public class OTFSubSetFile extends OTFFi
             } else {
                 out[position] = (byte)250;
             }
-            out[position + 1] = (byte)(replacement - 108);
+            if (replacement > 0) {
+                out[position + 1] = (byte)(replacement - 108);
+            } else {
+                out[position + 1] = (byte)(-replacement - 108);
+            }
             break;
         case 3:
             out[position] = (byte)28;

Modified: xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java?rev=1735284&r1=1735283&r2=1735284&view=diff
==============================================================================
--- xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java (original)
+++ xmlgraphics/fop/branches/maven/fop-core/src/main/java/org/apache/fop/layoutmgr/inline/LineLayoutManager.java Wed Mar 16 19:19:24 2016
@@ -392,22 +392,20 @@ public class LineLayoutManager extends I
                 addedPositions = 0;
             }
 
-            if (log.isWarnEnabled()) {
-                int lack = difference + bestActiveNode.availableShrink;
-                // if this LLM is nested inside a BlockContainerLayoutManager that is constraining
-                // the available width and thus responsible for the overflow then we do not issue
-                // warning event here and instead let the BCLM handle that at a later stage
-                if (lack < 0 && !handleOverflow(-lack)) {
-                    InlineLevelEventProducer eventProducer
-                        = InlineLevelEventProducer.Provider.get(
-                            getFObj().getUserAgent().getEventBroadcaster());
-                    if (curChildLM.getFObj() == null) {
-                        eventProducer.lineOverflows(this, getFObj().getName(), bestActiveNode.line,
-                                -lack, getFObj().getLocator());
-                    } else {
-                        eventProducer.lineOverflows(this, curChildLM.getFObj().getName(), bestActiveNode.line,
-                            -lack, curChildLM.getFObj().getLocator());
-                    }
+            int lack = difference + bestActiveNode.availableShrink;
+            // if this LLM is nested inside a BlockContainerLayoutManager that is constraining
+            // the available width and thus responsible for the overflow then we do not issue
+            // warning event here and instead let the BCLM handle that at a later stage
+            if (lack < 0 && !handleOverflow(-lack)) {
+                InlineLevelEventProducer eventProducer
+                    = InlineLevelEventProducer.Provider.get(
+                        getFObj().getUserAgent().getEventBroadcaster());
+                if (curChildLM.getFObj() == null) {
+                    eventProducer.lineOverflows(this, getFObj().getName(), bestActiveNode.line,
+                            -lack, getFObj().getLocator());
+                } else {
+                    eventProducer.lineOverflows(this, curChildLM.getFObj().getName(), bestActiveNode.line,
+                        -lack, curChildLM.getFObj().getLocator());
                 }
             }
 

Modified: xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java?rev=1735284&r1=1735283&r2=1735284&view=diff
==============================================================================
--- xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java (original)
+++ xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java Wed Mar 16 19:19:24 2016
@@ -23,7 +23,9 @@ import org.junit.runner.RunWith;
 import org.junit.runners.Suite;
 import org.junit.runners.Suite.SuiteClasses;
 
+import org.apache.fop.fonts.cff.CFFDataReaderTestCase;
 import org.apache.fop.fonts.truetype.FontFileReaderTestCase;
+import org.apache.fop.fonts.truetype.OTFSubSetFileTestCase;
 import org.apache.fop.fonts.truetype.TTFFileTestCase;
 import org.apache.fop.fonts.truetype.TTFSubSetFileTestCase;
 import org.apache.fop.fonts.truetype.TTFTableNameTestCase;
@@ -37,6 +39,8 @@ import org.apache.fop.fonts.truetype.TTF
         FontFileReaderTestCase.class,
         TTFFileTestCase.class,
         TTFSubSetFileTestCase.class,
-        TTFTableNameTestCase.class })
+        TTFTableNameTestCase.class,
+        CFFDataReaderTestCase.class,
+        OTFSubSetFileTestCase.class })
 public final class FOPFontsTestSuite {
 }

Modified: xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java?rev=1735284&r1=1735283&r2=1735284&view=diff
==============================================================================
--- xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java (original)
+++ xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java Wed Mar 16 19:19:24 2016
@@ -60,43 +60,43 @@ public class CFFDataReaderTestCase {
         byte[] testDictData = new byte[0];
         //Version
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                392, new int[] { 0 }, -1));
+                392, new int[] { 0 }, -1, true));
         //Notice
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                393, new int[] { 1 }, -1));
+                393, new int[] { 1 }, -1, true));
         //Copyright
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                394, new int[] { 12, 0 }, -1));
+                394, new int[] { 12, 0 }, -1, true));
         //FullName
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                395, new int[] { 2 }, -1));
+                395, new int[] { 2 }, -1, true));
         //FamilyName
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                396, new int[] { 3 }, -1));
+                396, new int[] { 3 }, -1, true));
         //Weight
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                397, new int[] { 4 }, -1));
+                397, new int[] { 4 }, -1, true));
         //isFixedPitch (boolean = false)
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                0, new int[] { 12, 1 }, -1));
+                0, new int[] { 12, 1 }, -1, true));
         //FontBBox
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                -50, new int[0], -1));
+                -50, new int[0], -1, true));
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                -40, new int[0], -1));
+                -40, new int[0], -1, true));
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                100, new int[0], -1));
+                100, new int[0], -1, true));
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                120, new int[] { 5 }, -1));
+                120, new int[] { 5 }, -1, true));
         //charset
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                1234, new int[] { 15 }, -1));
+                1234, new int[] { 15 }, -1, true));
         //CharStrings
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                3654, new int[] { 17 }, -1));
+                3654, new int[] { 17 }, -1, true));
         //Private
         testDictData = OTFSubSetFile.concatArray(testDictData, OTFSubSetFile.createNewRef(
-                11454, new int[] { 18 }, -1));
+                11454, new int[] { 18 }, -1, true));
         return testDictData;
     }
 

Modified: xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java
URL: http://svn.apache.org/viewvc/xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java?rev=1735284&r1=1735283&r2=1735284&view=diff
==============================================================================
--- xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java (original)
+++ xmlgraphics/fop/branches/maven/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java Wed Mar 16 19:19:24 2016
@@ -21,7 +21,6 @@ package org.apache.fop.fonts.truetype;
 
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -44,7 +43,6 @@ public class OTFSubSetFileTestCase exten
     CFFDataReader cffReaderSourceSans;
     private OTFSubSetFile sourceSansSubset;
     private byte[] sourceSansData;
-    CFFDataReader cffReaderHeitiStd;
 
     /**
      * Initialises the test by creating the font subset. A CFFDataReader is
@@ -109,14 +107,84 @@ public class OTFSubSetFileTestCase exten
             byte[] origCharData = origCharStringData.get(origCharStringData.keySet().toArray(
                     new String[0])[i]);
             byte[] charData = charStrings.getValue(i);
-            List<BytesNumber> origOperands = getFullCharString(origCharData, origCFF);
-            List<BytesNumber> subsetOperands = getFullCharString(charData, subsetCFF);
+            List<BytesNumber> origOperands = getFullCharString(new Context(), origCharData, origCFF);
+            List<BytesNumber> subsetOperands = getFullCharString(new Context(), charData, subsetCFF);
             for (int j = 0; j < origOperands.size(); j++) {
-                assertTrue(origOperands.get(j).equals(subsetOperands.get(j)));
+                    assertTrue(origOperands.get(j).equals(subsetOperands.get(j)));
             }
         }
     }
 
+    static class Context {
+        private ArrayList<BytesNumber> operands = new ArrayList<BytesNumber>();
+        private ArrayList<BytesNumber> stack = new ArrayList<BytesNumber>();
+        private int hstemCount;
+        private int vstemCount;
+        private int lastOp = -1;
+        private int maskLength = -1;
+
+        public void pushOperand(BytesNumber v) {
+            operands.add(v);
+            if (v instanceof Operator) {
+                if (v.getNumber() != 11 && v.getNumber() != 12) {
+                    lastOp = v.getNumber();
+                }
+            } else {
+                stack.add(v);
+            }
+        }
+
+        public BytesNumber popOperand() {
+            operands.remove(operands.size() - 1);
+            return stack.remove(stack.size() - 1);
+        }
+
+        public BytesNumber lastOperand() {
+            return operands.get(operands.size() - 1);
+        }
+
+        public void clearStack() {
+            stack.clear();
+        }
+
+        public int getMaskLength() {
+            // The number of data bytes for mask is exactly the number needed, one
+            // bit per hint, to reference the number of stem hints declared
+            // at the beginning of the charstring program.
+            if (maskLength > 0) {
+                return maskLength;
+            }
+            return 1 + (hstemCount + vstemCount  - 1) / 8;
+        }
+
+        public List<BytesNumber> getFullOperandsList() {
+            return operands;
+        }
+
+        public void countHstem() {
+            // hstem(hm) operator
+            hstemCount += stack.size() / 2;
+            clearStack();
+        }
+
+        public void countVstem() {
+            // vstem(hm) operator
+            vstemCount += stack.size() / 2;
+            clearStack();
+        }
+
+        public int calcMaskLength() {
+            if (lastOp == 1 || lastOp == 18) {
+                //If hstem and vstem hints are both declared at the beginning of
+                //a charstring, and this sequence is followed directly by the
+                //hintmask or cntrmask operators, the vstem hint operator need
+                //not be included.
+                vstemCount += stack.size() / 2;
+            }
+            clearStack();
+            return getMaskLength();
+        }
+    }
     /**
      * Recursively reads and constructs the full CharString for comparison
      * @param data The original byte data of the CharString
@@ -124,65 +192,46 @@ public class OTFSubSetFileTestCase exten
      * @return Returns a list of parsed operands and operators
      * @throws IOException
      */
-    private List<BytesNumber> getFullCharString(byte[] data, CFFDataReader cffData) throws IOException {
+    private List<BytesNumber> getFullCharString(Context context, byte[] data, CFFDataReader cffData)
+        throws IOException {
         CFFIndexData localIndexSubr = cffData.getLocalIndexSubr();
         CFFIndexData globalIndexSubr = cffData.getGlobalIndexSubr();
         boolean hasLocalSubroutines = localIndexSubr != null && localIndexSubr.getNumObjects() > 0;
         boolean hasGlobalSubroutines = globalIndexSubr != null && globalIndexSubr.getNumObjects() > 0;
-        ArrayList<BytesNumber> operands = new ArrayList<BytesNumber>();
         for (int dataPos = 0; dataPos < data.length; dataPos++) {
             int b0 = data[dataPos] & 0xff;
             if (b0 == 10 && hasLocalSubroutines) {
                 int subrNumber = getSubrNumber(localIndexSubr.getNumObjects(),
-                        operands.get(operands.size() - 1).getNumber());
+                        context.popOperand().getNumber());
                 byte[] subr = localIndexSubr.getValue(subrNumber);
-                List<BytesNumber> subrOperands = getFullCharString(subr, cffData);
-                operands = mergeOperands(operands, subrOperands);
+                getFullCharString(context, subr, cffData);
             } else if (b0 == 29 && hasGlobalSubroutines) {
                 int subrNumber = getSubrNumber(globalIndexSubr.getNumObjects(),
-                        operands.get(operands.size() - 1).getNumber());
+                        context.popOperand().getNumber());
                 byte[] subr = globalIndexSubr.getValue(subrNumber);
-                ArrayList<BytesNumber> subrOperands = (ArrayList<BytesNumber>)getFullCharString(subr, cffData);
-                operands = mergeOperands(operands, subrOperands);
+                getFullCharString(context, subr, cffData);
             } else if ((b0 >= 0 && b0 <= 27) || (b0 >= 29 && b0 <= 31)) {
                 int size = 1;
                 int b1 = -1;
                 if (b0 == 12) {
                     b1 = data[dataPos++] & 0xff;
                     size = 2;
+                } else if (b0 == 1 || b0 == 18) {
+                    context.countHstem();
+                } else if (b0 == 3 || b0 == 23) {
+                    context.countVstem();
+                } else if (b0 == 19 || b0 == 20) {
+                    int length = context.calcMaskLength();
+                    dataPos += length;
+                    size = length + 1;
                 }
-                if (b0 == 19 || b0 == 20) {
-                    dataPos += 1;
-                    size = 2;
-                }
-                operands.add(new Operator(b0, size, getOperatorName(b0, b1)));
+                context.pushOperand(new Operator(b0, size, getOperatorName(b0, b1)));
             } else if (b0 == 28 || (b0 >= 32 && b0 <= 255)) {
-                operands.add(readNumber(b0, data, dataPos));
-                dataPos += operands.get(operands.size() - 1).getNumBytes() - 1;
+                context.pushOperand(readNumber(b0, data, dataPos));
+                dataPos += context.lastOperand().getNumBytes() - 1;
             }
         }
-        return operands;
-    }
-
-    /**
-     * Merges two lists of operands. This is typically used to merge the CharString
-     * data with that of a parsed and referenced subroutine.
-     * @param charString The parsed CharString data so far
-     * @param subroutine The parsed elements from a subroutine
-     * @return Returns a merged list of both CharString and subroutine elements.
-     */
-    private ArrayList<BytesNumber> mergeOperands(List<BytesNumber> charString,
-            List<BytesNumber> subroutine) {
-        BytesNumber[] charStringOperands = charString.toArray(new BytesNumber[0]);
-        BytesNumber[] subroutineOperands = subroutine.toArray(new BytesNumber[0]);
-        BytesNumber[] mergeData = new BytesNumber[charStringOperands.length - 1
-                                                  + subroutineOperands.length - 1];
-        System.arraycopy(charStringOperands, 0, mergeData, 0, charStringOperands.length - 1);
-        System.arraycopy(subroutineOperands, 0, mergeData, charStringOperands.length - 1,
-                subroutineOperands.length - 1);
-        ArrayList<BytesNumber> hello = new ArrayList<BytesNumber>();
-        hello.addAll(Arrays.asList(mergeData));
-        return hello;
+        return context.getFullOperandsList();
     }
 
     /**
@@ -209,7 +258,9 @@ public class OTFSubSetFileTestCase exten
         } else if (b0 == 255) {
             int b1 = input[curPos + 1] & 0xff;
             int b2 = input[curPos + 2] & 0xff;
-            return new BytesNumber(Integer.valueOf((short)(b1 << 8 | b2)), 5);
+            int b3 = input[curPos + 3] & 0xff;
+            int b4 = input[curPos + 4] & 0xff;
+            return new BytesNumber(Integer.valueOf((b1 << 24  | b2 << 16 | b3 << 8 | b4)), 5);
         } else {
             throw new IllegalArgumentException();
         }
@@ -264,7 +315,7 @@ public class OTFSubSetFileTestCase exten
      * used for debugging purposes. See the Type 2 CharString Format specification
      * document (Technical Note #5177) Appendix A (Command Codes).
      * @param operator The operator code
-     * @param codeb The second byte of the operator
+     * @param operatorB The second byte of the operator
      * @return Returns the operator name.
      */
     private String getOperatorName(int operator, int operatorB) {



---------------------------------------------------------------------
To unsubscribe, e-mail: fop-commits-unsubscribe@xmlgraphics.apache.org
For additional commands, e-mail: fop-commits-help@xmlgraphics.apache.org