]> source.dussan.org Git - xmlgraphics-fop.git/commitdiff
FOP-2680: OTF font needs format 3 FDSelect due to offset size
authorSimon Steiner <ssteiner@apache.org>
Tue, 17 Jan 2017 15:00:19 +0000 (15:00 +0000)
committerSimon Steiner <ssteiner@apache.org>
Tue, 17 Jan 2017 15:00:19 +0000 (15:00 +0000)
git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1779202 13f79535-47bb-0310-9956-ffa450edef68

fop-core/src/main/java/org/apache/fop/fonts/cff/CFFDataReader.java
fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java
fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java

index 3ce63a2a4d4bb409e5a911bc766a8992bbc4d30d..83ebd6053af6c682458ccf9742e5f68591ea71fa 100644 (file)
@@ -814,7 +814,7 @@ public class CFFDataReader {
         }
     }
 
-    public class FDSelect {
+    public abstract class FDSelect {
         private int format;
 
         public void setFormat(int format) {
index c28bca5fe8bf68fc33d8402a543a9df2c697a516..5ee54eaa88e28f8f1fdbb7c40d416a204b10f7db 100644 (file)
@@ -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<Integer, Integer> indexs = getFormat3Index();
+            writeByte(3); //Format
+            writeCard16(indexs.size());
+            int count = 0;
+            for (Entry<Integer, Integer> 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<Integer, Integer> getFormat3Index() {
+        Map<Integer, Integer> indexs = new LinkedHashMap<Integer, Integer>();
+        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<Integer> 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;
 
index cce22531c6a6327823744d92b9911b1f94f31f63..d87d19be5c2972b2358bc71ac99c7e6cf73fb72f 100644 (file)
@@ -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<String, DICTEntry> map = new LinkedHashMap<String, DICTEntry>();
+                DICTEntry dict = new DICTEntry();
+                dict.setOperands(Collections.<Number>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<Integer, Integer>());
+        return otfSubSetFile.getFontSubset();
+    }
 }