diff options
author | Simon Steiner <ssteiner@apache.org> | 2017-10-11 07:49:03 +0000 |
---|---|---|
committer | Simon Steiner <ssteiner@apache.org> | 2017-10-11 07:49:03 +0000 |
commit | c803867f451abf384fdc1bd5f524bfe3c2e47851 (patch) | |
tree | dfb22ecbe70f4eabbf2d026fbb6fd60400161360 | |
parent | ade0e4ebd6ce8f92e9a19878e838a5a75226801d (diff) | |
download | xmlgraphics-fop-c803867f451abf384fdc1bd5f524bfe3c2e47851.tar.gz xmlgraphics-fop-c803867f451abf384fdc1bd5f524bfe3c2e47851.zip |
FOP-2750: Use streams for OTF subsetting
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1811797 13f79535-47bb-0310-9956-ffa450edef68
3 files changed, 58 insertions, 64 deletions
diff --git a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java index 0487c6127..fd3a9988e 100644 --- a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java +++ b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java @@ -19,8 +19,10 @@ package org.apache.fop.fonts.truetype; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -128,16 +130,11 @@ public class OTFSubSetFile extends OTFSubSetWriter { this.mbFont = mbFont; fontFile = in; - currentPos = 0; - realSize = 0; - this.embeddedName = embeddedName; //Sort by the new GID and store in a LinkedHashMap subsetGlyphs = sortByValue(usedGlyphs); - output = new byte[in.getFileSize()]; - initializeFont(in); cffReader = new CFFDataReader(fontFile); @@ -710,7 +707,13 @@ public class OTFSubSetFile extends OTFSubSetWriter { return 1 + (hstemCount + vstemCount - 1) / 8; } - public int exec(int b0, byte[] data, int dataPos) { + private int exec(int b0, byte[] input, int curPos) throws IOException { + ByteArrayInputStream bis = new ByteArrayInputStream(input); + bis.skip(curPos + 1); + return exec(b0, bis); + } + + public int exec(int b0, InputStream data) throws IOException { int posDelta = 0; if ((b0 >= 0 && b0 <= 27) || (b0 >= 29 && b0 <= 31)) { if (b0 == 12) { @@ -739,7 +742,7 @@ public class OTFSubSetFile extends OTFSubSetWriter { lastOp = b0; } } else if (b0 == 28 || (b0 >= 32 && b0 <= 255)) { - BytesNumber operand = readNumber(b0, data, dataPos); + BytesNumber operand = readNumber(b0, data); pushOperand(operand); posDelta = operand.getNumBytes() - 1; } else { @@ -748,24 +751,24 @@ public class OTFSubSetFile extends OTFSubSetWriter { return posDelta; } - private BytesNumber readNumber(int b0, byte[] input, int curPos) { + private BytesNumber readNumber(int b0, InputStream input) throws IOException { if (b0 == 28) { - int b1 = input[curPos + 1] & 0xff; - int b2 = input[curPos + 2] & 0xff; + int b1 = input.read(); + int b2 = input.read(); 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; + int b1 = input.read(); return new BytesNumber((b0 - 247) * 256 + b1 + 108, 2); } else if (b0 >= 251 && b0 <= 254) { - int b1 = input[curPos + 1] & 0xff; + int b1 = input.read(); 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; + int b1 = input.read(); + int b2 = input.read(); + int b3 = input.read(); + int b4 = input.read(); return new BytesNumber((b1 << 24 | b2 << 16 | b3 << 8 | b4), 5); } else { throw new IllegalArgumentException(); @@ -778,33 +781,28 @@ public class OTFSubSetFile extends OTFSubSetWriter { for (int dataPos = 0; dataPos < data.length; dataPos++) { int b0 = data[dataPos] & 0xff; if (b0 == LOCAL_SUBROUTINE && hasLocalSubroutines) { - 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"); - } + preScanForSubsetIndexSize(localIndexSubr, localUniques); } else if (b0 == GLOBAL_SUBROUTINE && hasGlobalSubroutines) { - 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"); - } + preScanForSubsetIndexSize(globalIndexSubr, globalUniques); } else { dataPos += type2Parser.exec(b0, data, dataPos); } } } + private void preScanForSubsetIndexSize(CFFIndexData indexSubr, List<Integer> uniques) throws IOException { + int subrNumber = getSubrNumber(indexSubr.getNumObjects(), type2Parser.popOperand().getNumber()); + if (!uniques.contains(subrNumber) && subrNumber < indexSubr.getNumObjects()) { + uniques.add(subrNumber); + } + if (subrNumber < indexSubr.getNumObjects()) { + byte[] subr = indexSubr.getValue(subrNumber); + preScanForSubsetIndexSize(subr); + } else { + throw new IllegalArgumentException("callgsubr out of range"); + } + } + private int getSubrNumber(int numSubroutines, int operand) { int bias = getBias(numSubroutines); return bias + operand; @@ -1111,57 +1109,64 @@ public class OTFSubSetFile extends OTFSubSetWriter { if (privateDICT != null) { //Private index offset in the top dict int oldPrivateOffset = offsets.topDictData + privateEntry.getOffset(); - updateOffset(output, oldPrivateOffset + privateEntry.getOperandLengths().get(0), + updateOffset(oldPrivateOffset + privateEntry.getOperandLengths().get(0), privateEntry.getOperandLengths().get(1), offsets.privateDict); //Update the local subroutine index offset in the private dict DICTEntry subroutines = privateDICT.get("Subrs"); if (subroutines != null) { int oldLocalSubrOffset = offsets.privateDict + subroutines.getOffset(); - updateOffset(output, oldLocalSubrOffset, subroutines.getOperandLength(), + updateOffset(oldLocalSubrOffset, subroutines.getOperandLength(), (offsets.localIndex - offsets.privateDict)); } } } - protected void updateFixedOffsets(Map<String, DICTEntry> topDICT, Offsets offsets) { + protected void updateFixedOffsets(Map<String, DICTEntry> topDICT, Offsets offsets) throws IOException { //Charset offset in the top dict DICTEntry charset = topDICT.get("charset"); int oldCharsetOffset = offsets.topDictData + charset.getOffset(); - updateOffset(output, oldCharsetOffset, charset.getOperandLength(), offsets.charset); + updateOffset(oldCharsetOffset, charset.getOperandLength(), offsets.charset); //Char string index offset in the private dict DICTEntry charString = topDICT.get("CharStrings"); int oldCharStringOffset = offsets.topDictData + charString.getOffset(); - updateOffset(output, oldCharStringOffset, charString.getOperandLength(), offsets.charString); + updateOffset(oldCharStringOffset, charString.getOperandLength(), offsets.charString); DICTEntry encodingEntry = topDICT.get("Encoding"); if (encodingEntry != null && encodingEntry.getOperands().get(0).intValue() != 0 && encodingEntry.getOperands().get(0).intValue() != 1) { int oldEncodingOffset = offsets.topDictData + encodingEntry.getOffset(); - updateOffset(output, oldEncodingOffset, encodingEntry.getOperandLength(), offsets.encoding); + updateOffset(oldEncodingOffset, encodingEntry.getOperandLength(), offsets.encoding); } } - protected void updateCIDOffsets(Offsets offsets) { + protected void updateCIDOffsets(Offsets offsets) throws IOException { Map<String, DICTEntry> topDict = cffReader.getTopDictEntries(); DICTEntry fdArrayEntry = topDict.get("FDArray"); if (fdArrayEntry != null) { - updateOffset(output, offsets.topDictData + fdArrayEntry.getOffset() - 1, + updateOffset(offsets.topDictData + fdArrayEntry.getOffset() - 1, fdArrayEntry.getOperandLength(), offsets.fdArray); } DICTEntry fdSelect = topDict.get("FDSelect"); if (fdSelect != null) { - updateOffset(output, offsets.topDictData + fdSelect.getOffset() - 1, + updateOffset(offsets.topDictData + fdSelect.getOffset() - 1, fdSelect.getOperandLength(), offsets.fdSelect); } updateFixedOffsets(topDict, offsets); } - protected void updateOffset(byte[] out, int position, int length, int replacement) { + private void updateOffset(int position, int length, int replacement) throws IOException { + byte[] outBytes = output.toByteArray(); + updateOffset(outBytes, position, length, replacement); + output.reset(); + output.write(outBytes); + } + + private void updateOffset(byte[] out, int position, int length, int replacement) { switch (length) { case 1: out[position] = (byte)(replacement + 139); diff --git a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetWriter.java b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetWriter.java index 9cac010b2..92e6f2651 100644 --- a/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetWriter.java +++ b/fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetWriter.java @@ -18,12 +18,12 @@ /* $Id$ */ package org.apache.fop.fonts.truetype; +import java.io.ByteArrayOutputStream; import java.io.IOException; public class OTFSubSetWriter extends OTFFile { protected int currentPos; - protected int realSize; - protected byte[] output; + protected ByteArrayOutputStream output = new ByteArrayOutputStream(); public OTFSubSetWriter() throws IOException { super(); @@ -43,8 +43,8 @@ public class OTFSubSetWriter extends OTFFile { * updates currentPost but not realSize */ protected void writeByte(int b) { - output[currentPos++] = (byte)b; - realSize++; + output.write(b); + currentPos++; } /** @@ -89,21 +89,12 @@ public class OTFSubSetWriter extends OTFFile { } } - protected void writeBytes(byte[] out, int offset, int length) { - for (int i = offset; i < offset + length; i++) { - output[currentPos++] = out[i]; - realSize++; - } - } - /** * Returns a subset of the fonts (readFont() MUST be called first in order to create the * subset). * @return byte array */ public byte[] getFontSubset() { - byte[] ret = new byte[realSize]; - System.arraycopy(output, 0, ret, 0, realSize); - return ret; + return output.toByteArray(); } } diff --git a/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java b/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java index 8f15edde0..c872c731e 100644 --- a/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java +++ b/fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java @@ -508,7 +508,7 @@ public class OTFSubSetFileTestCase extends OTFFileTestCase { super.createCFF(); } - protected void updateFixedOffsets(Map<String, DICTEntry> topDICT, Offsets offsets) { + protected void updateFixedOffsets(Map<String, DICTEntry> topDICT, Offsets offsets) throws IOException { this.charsetOffset = offsets.charset; super.updateFixedOffsets(topDICT, offsets); } @@ -621,7 +621,7 @@ public class OTFSubSetFileTestCase extends OTFFileTestCase { super.createCFF(); } - protected void updateCIDOffsets(Offsets offsets) { + protected void updateCIDOffsets(Offsets offsets) throws IOException { super.updateCIDOffsets(offsets); this.offsets = offsets; } @@ -658,7 +658,6 @@ public class OTFSubSetFileTestCase extends OTFFileTestCase { public void testWriteCIDDictsAndSubrs() throws IOException { OTFSubSetFile subSetFile = new OTFSubSetFile() { public void readFont(FontFileReader in, String embeddedName, MultiByteFont mbFont) throws IOException { - output = new byte[128]; cffReader = makeCFFDataReader(); fdSubrs = new ArrayList<List<byte[]>>(); fdSubrs.add(new ArrayList<byte[]>()); @@ -682,7 +681,6 @@ public class OTFSubSetFileTestCase extends OTFFileTestCase { OTFSubSetFile otfSubSetFile = new OTFSubSetFile() { void readFont(FontFileReader in, String embeddedName, MultiByteFont mbFont, Map<Integer, Integer> usedGlyphs) throws IOException { - output = new byte[7]; cffReader = makeCFFDataReader(); LinkedHashMap<String, DICTEntry> topDict = new LinkedHashMap<String, DICTEntry>(); DICTEntry entry = new DICTEntry(); |