diff options
Diffstat (limited to 'test')
3 files changed, 114 insertions, 59 deletions
diff --git a/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java b/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java index 8e1a0040d..205cffb18 100644 --- a/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java +++ b/test/java/org/apache/fop/fonts/FOPFontsTestSuite.java @@ -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.TTFTableNameTestCase; FontFileReaderTestCase.class, TTFFileTestCase.class, TTFSubSetFileTestCase.class, - TTFTableNameTestCase.class }) + TTFTableNameTestCase.class, + CFFDataReaderTestCase.class, + OTFSubSetFileTestCase.class }) public final class FOPFontsTestSuite { } diff --git a/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java b/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java index 97ea5c52b..2e112de7b 100644 --- a/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java +++ b/test/java/org/apache/fop/fonts/cff/CFFDataReaderTestCase.java @@ -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; } diff --git a/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java b/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java index fecb1e9f1..2048bcf46 100644 --- a/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java +++ b/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java @@ -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 extends OTFFileTestCase { 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 extends OTFFileTestCase { 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 extends OTFFileTestCase { * @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 extends OTFFileTestCase { } 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 extends OTFFileTestCase { * 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) { |