From 3dc1ca2cb1d36104467d11a7e98024ea12a37c27 Mon Sep 17 00:00:00 2001 From: Simon Steiner Date: Wed, 13 Sep 2017 08:32:17 +0000 Subject: [PATCH] FOP-2736: Change font table order depending on offset size git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1808210 13f79535-47bb-0310-9956-ffa450edef68 --- .../fop/fonts/truetype/OTFSubSetFile.java | 45 ++++++++++---- .../fonts/truetype/OTFSubSetFileTestCase.java | 60 +++++++++++++++++++ 2 files changed, 93 insertions(+), 12 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 70ac3cb62..ee534ba2e 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 @@ -174,17 +174,19 @@ public class OTFSubSetFile extends OTFSubSetWriter { //Top DICT Index and Data int topDictDataOffset = topDictOffset + writeTopDICT(); + boolean hasFDSelect = cffReader.getFDSelect() != null; + //Create the char string index data and related local / global subroutines - if (cffReader.getFDSelect() == null) { - createCharStringData(); - } else { + if (hasFDSelect) { createCharStringDataCID(); + } else { + createCharStringData(); } //If it is a CID-Keyed font, store each FD font and add each SID List fontNameSIDs = null; List subsetFDFonts = null; - if (cffReader.getFDSelect() != null) { + if (hasFDSelect) { subsetFDFonts = getUsedFDFonts(); fontNameSIDs = storeFDStrings(subsetFDFonts); } @@ -200,19 +202,29 @@ public class OTFSubSetFile extends OTFSubSetWriter { //Charset table int charsetOffset = currentPos; - writeCharsetTable(cffReader.getFDSelect() != null); + writeCharsetTable(hasFDSelect); //FDSelect table int fdSelectOffset = currentPos; - if (cffReader.getFDSelect() != null) { + if (hasFDSelect) { writeFDSelect(); } + int fdArrayOffset = -1; + if (hasFDSelect && !isCharStringBeforeFD()) { + fdArrayOffset = writeFDArray(subsetFDFonts, fontNameSIDs); + } //Char Strings Index int charStringOffset = currentPos; writeIndex(subsetCharStringsIndex); + if (hasFDSelect && isCharStringBeforeFD()) { + fdArrayOffset = writeFDArray(subsetFDFonts, fontNameSIDs); + } - if (cffReader.getFDSelect() == null) { + if (hasFDSelect) { + updateCIDOffsets(topDictDataOffset, fdArrayOffset, fdSelectOffset, charsetOffset, + charStringOffset, encodingOffset); + } else { //Keep offset to modify later with the local subroutine index offset int privateDictOffset = currentPos; writePrivateDict(); @@ -224,13 +236,22 @@ public class OTFSubSetFile extends OTFSubSetWriter { //Update the offsets updateOffsets(topDictOffset, charsetOffset, charStringOffset, privateDictOffset, localIndexOffset, encodingOffset); - } else { - List privateDictOffsets = writeCIDDictsAndSubrs(subsetFDFonts); - int fdArrayOffset = writeFDArray(subsetFDFonts, privateDictOffsets, fontNameSIDs); + } + } - updateCIDOffsets(topDictDataOffset, fdArrayOffset, fdSelectOffset, charsetOffset, - charStringOffset, encodingOffset); + private int writeFDArray(List subsetFDFonts, List fontNameSIDs) throws IOException { + List privateDictOffsets = writeCIDDictsAndSubrs(subsetFDFonts); + return writeFDArray(subsetFDFonts, privateDictOffsets, fontNameSIDs); + } + + private boolean isCharStringBeforeFD() { + LinkedHashMap entries = cffReader.getTopDictEntries(); + int len = entries.get("CharStrings").getOperandLength(); + if (entries.containsKey("FDArray")) { + int len2 = entries.get("FDArray").getOperandLength(); + return len < len2; } + return true; } protected List storeFDStrings(List uniqueNewRefs) throws IOException { 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 8804dd1bc..b2d12ec90 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 @@ -583,4 +583,64 @@ public class OTFSubSetFileTestCase extends OTFFileTestCase { return offset; } } + + @Test + public void testOrderOfEntries() throws IOException { + OTFSubSetFileEntryOrder otfSubSetFile = getFont(3, 2); + assertTrue(otfSubSetFile.fdArrayOffset < otfSubSetFile.charStringOffset); + + otfSubSetFile = getFont(2, 3); + assertTrue(otfSubSetFile.fdArrayOffset > otfSubSetFile.charStringOffset); + } + + private OTFSubSetFileEntryOrder getFont(int csLen, int fdLen) throws IOException { + glyphs.clear(); + OTFSubSetFileEntryOrder otfSubSetFile = new OTFSubSetFileEntryOrder(csLen, fdLen); + otfSubSetFile.readFont(sourceSansReader, "StandardOpenType", null, glyphs); + return otfSubSetFile; + } + + static class OTFSubSetFileEntryOrder extends OTFSubSetFile { + int fdArrayOffset; + int charStringOffset; + int csLen; + int fdLen; + + public OTFSubSetFileEntryOrder(int csLen, int fdLen) throws IOException { + super(); + this.csLen = csLen; + this.fdLen = fdLen; + } + + protected void createCFF() throws IOException { + cffReader = mock(CFFDataReader.class); + when(cffReader.getHeader()).thenReturn(new byte[0]); + when(cffReader.getTopDictIndex()).thenReturn(cffReader.new CFFIndexData() { + public byte[] getByteData() throws IOException { + return new byte[]{0, 0, 1}; + } + }); + when(cffReader.getFDSelect()).thenReturn(cffReader.new Format3FDSelect()); + + LinkedHashMap topDict = new LinkedHashMap(); + DICTEntry entry = new DICTEntry(); + entry.setOperands(Arrays.asList(0)); + topDict.put("charset", entry); + entry.setOperandLength(csLen); + topDict.put("CharStrings", entry); + entry = new DICTEntry(); + entry.setOperandLength(fdLen); + topDict.put("FDArray", entry); + when(cffReader.getTopDictEntries()).thenReturn(topDict); + super.createCFF(); + } + + protected void updateCIDOffsets(int topDictDataOffset, int fdArrayOffset, int fdSelectOffset, + int charsetOffset, int charStringOffset, int encodingOffset) { + super.updateCIDOffsets( + topDictDataOffset, fdArrayOffset, fdSelectOffset, charsetOffset, charStringOffset, encodingOffset); + this.fdArrayOffset = fdArrayOffset; + this.charStringOffset = charStringOffset; + } + } } -- 2.39.5