From: Simon Steiner Date: Tue, 17 Jan 2017 15:00:19 +0000 (+0000) Subject: FOP-2680: OTF font needs format 3 FDSelect due to offset size X-Git-Tag: fop-2_2~22 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=a9223cdc46a0d61e8f4ce9c4d7da267f6c4f933f;p=xmlgraphics-fop.git FOP-2680: OTF font needs format 3 FDSelect due to offset size git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1779202 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/fop-core/src/main/java/org/apache/fop/fonts/cff/CFFDataReader.java b/fop-core/src/main/java/org/apache/fop/fonts/cff/CFFDataReader.java index 3ce63a2a4..83ebd6053 100644 --- a/fop-core/src/main/java/org/apache/fop/fonts/cff/CFFDataReader.java +++ b/fop-core/src/main/java/org/apache/fop/fonts/cff/CFFDataReader.java @@ -814,7 +814,7 @@ public class CFFDataReader { } } - public class FDSelect { + public abstract class FDSelect { private int format; public void setFormat(int format) { 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 c28bca5fe..5ee54eaa8 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 @@ -415,11 +415,10 @@ public class OTFSubSetFile extends OTFFile { int gid = subsetGlyph.getKey(); int group = subsetGroups.get(gid); localIndexSubr = cffReader.getFDFonts().get(group).getLocalSubrData(); - localUniques = foundLocalUniques.get(uniqueGroups.indexOf(subsetGroups.get(gid))); + localUniques = foundLocalUniques.get(uniqueGroups.indexOf(group)); type2Parser = new Type2Parser(); - FDIndexReference newFDReference = new FDIndexReference( - uniqueGroups.indexOf(subsetGroups.get(gid)), subsetGroups.get(gid)); + FDIndexReference newFDReference = new FDIndexReference(uniqueGroups.indexOf(group), group); subsetFDSelect.put(subsetGlyph.getValue(), newFDReference); byte[] data = charStringsIndex.getValue(gid); preScanForSubsetIndexSize(data); @@ -460,10 +459,40 @@ public class OTFSubSetFile extends OTFFile { } protected void writeFDSelect() { - writeByte(0); //Format + if (cffReader.getTopDictEntries().get("CharStrings").getOperandLength() == 2) { + Map indexs = getFormat3Index(); + writeByte(3); //Format + writeCard16(indexs.size()); + int count = 0; + for (Entry x : indexs.entrySet()) { + writeCard16(count); + writeByte(x.getKey()); + count += x.getValue(); + } + writeCard16(subsetFDSelect.size()); + } else { + writeByte(0); //Format + for (FDIndexReference e : subsetFDSelect.values()) { + writeByte(e.getNewFDIndex()); + } + } + } + + private Map getFormat3Index() { + Map indexs = new LinkedHashMap(); + int last = -1; + int count = 0; for (FDIndexReference e : subsetFDSelect.values()) { - writeByte(e.getNewFDIndex()); + int i = e.getNewFDIndex(); + count++; + if (i != last) { + indexs.put(i, count); + count = 1; + } + last = i; } + indexs.put(last, count); + return indexs; } protected List getUsedFDFonts() { @@ -534,7 +563,7 @@ public class OTFSubSetFile extends OTFFile { return offset; } - private class FDIndexReference { + private static class FDIndexReference { private int newFDIndex; private int oldFDIndex; 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 cce22531c..d87d19be5 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 @@ -21,15 +21,20 @@ package org.apache.fop.fonts.truetype; import java.io.IOException; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.junit.Assert; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import org.apache.fontbox.cff.CFFFont; @@ -40,9 +45,8 @@ import org.apache.fop.fonts.truetype.OTFSubSetFile.BytesNumber; public class OTFSubSetFileTestCase extends OTFFileTestCase { - CFFDataReader cffReaderSourceSans; + private CFFDataReader cffReaderSourceSans; private OTFSubSetFile sourceSansSubset; - private byte[] sourceSansData; /** * Initialises the test by creating the font subset. A CFFDataReader is @@ -61,7 +65,7 @@ public class OTFSubSetFileTestCase extends OTFFileTestCase { sourceSansSubset = new OTFSubSetFile(); String sourceSansHeader = OFFontLoader.readHeader(sourceSansReader); sourceSansSubset.readFont(sourceSansReader, "SourceSansProBold", sourceSansHeader, glyphs); - sourceSansData = sourceSansSubset.getFontSubset(); + byte[] sourceSansData = sourceSansSubset.getFontSubset(); cffReaderSourceSans = new CFFDataReader(sourceSansData); } @@ -428,4 +432,40 @@ public class OTFSubSetFileTestCase extends OTFFileTestCase { cffReaderSourceSans.getTopDictIndex().getData()); assertEquals(10, topDictEntries.size()); } + + @Test + public void testFDSelect() throws IOException { + Assert.assertEquals(getSubset(1).length, 39); + Assert.assertEquals(getSubset(2).length, 46); + } + + private byte[] getSubset(final int opLen) throws IOException { + FontFileReader reader = sourceSansReader; + String header = OFFontLoader.readHeader(reader); + + OTFSubSetFile otfSubSetFile = new OTFSubSetFile() { + protected void createCFF() throws IOException { + cffReader = mock(CFFDataReader.class); + when(cffReader.getHeader()).thenReturn(new byte[0]); + when(cffReader.getTopDictIndex()).thenReturn(new CFFDataReader().new CFFIndexData() { + public byte[] getByteData() throws IOException { + return new byte[3]; + } + }); + + LinkedHashMap map = new LinkedHashMap(); + DICTEntry dict = new DICTEntry(); + dict.setOperands(Collections.singletonList(1)); + map.put("charset", dict); + map.put("CharStrings", dict); + when((cffReader.getTopDictEntries())).thenReturn(map); + when(cffReader.getFDSelect()).thenReturn(new CFFDataReader().new Format3FDSelect()); + cffReader.getTopDictEntries().get("CharStrings").setOperandLength(opLen); + super.createCFF(); + } + }; + + otfSubSetFile.readFont(reader, "StandardOpenType", header, new HashMap()); + return otfSubSetFile.getFontSubset(); + } }