import org.apache.commons.logging.LogFactory;
import org.apache.fontbox.cff.CFFStandardString;
+import org.apache.fontbox.cff.CFFType1Font;
+import org.apache.fontbox.cff.CharStringCommand;
+import org.apache.fontbox.cff.Type2CharString;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.cff.CFFDataReader;
import org.apache.fop.fonts.cff.CFFDataReader.FontDict;
import org.apache.fop.fonts.cff.CFFDataReader.Format0FDSelect;
import org.apache.fop.fonts.cff.CFFDataReader.Format3FDSelect;
+import org.apache.fop.fonts.type1.AdobeStandardEncoding;
/**
* Reads an OpenType CFF file and generates a subset
private static final int LOCAL_SUBROUTINE = 10;
/** The operator used to identify a global subroutine reference */
private static final int GLOBAL_SUBROUTINE = 29;
+
+ private static final String ACCENT_CMD = "seac";
+
/** The parser used to parse type2 charstring */
private Type2Parser type2Parser;
Map<Integer, Integer> usedGlyphs) throws IOException {
this.mbFont = mbFont;
fontFile = in;
-
this.embeddedName = embeddedName;
-
- //Sort by the new GID and store in a LinkedHashMap
- subsetGlyphs = sortByValue(usedGlyphs);
-
initializeFont(in);
-
cffReader = new CFFDataReader(fontFile);
-
+ mapChars(usedGlyphs);
+ //Sort by the new GID and store in a LinkedHashMap
+ subsetGlyphs = sortByValue(usedGlyphs);
//Create the CIDFontType0C data
createCFF();
}
+ private void mapChars(Map<Integer, Integer> usedGlyphs) throws IOException {
+ if (fileFont instanceof CFFType1Font) {
+ CFFType1Font cffType1Font = (CFFType1Font) fileFont;
+ subsetGlyphs = sortByValue(usedGlyphs);
+ for (int gid : subsetGlyphs.keySet()) {
+ Type2CharString type2CharString = cffType1Font.getType2CharString(gid);
+ List<Number> stack = new ArrayList<Number>();
+ for (Object obj : type2CharString.getType1Sequence()) {
+ if (obj instanceof CharStringCommand) {
+ String name = CharStringCommand.TYPE1_VOCABULARY.get(((CharStringCommand) obj).getKey());
+ if (ACCENT_CMD.equals(name)) {
+ int first = stack.get(3).intValue();
+ int second = stack.get(4).intValue();
+ mbFont.mapChar(AdobeStandardEncoding.getUnicodeFromCodePoint(first));
+ mbFont.mapChar(AdobeStandardEncoding.getUnicodeFromCodePoint(second));
+ }
+ stack.clear();
+ } else {
+ stack.add((Number) obj);
+ }
+ }
+ }
+ }
+ }
+
private Map<Integer, Integer> sortByValue(Map<Integer, Integer> map) {
List<Entry<Integer, Integer>> list = new ArrayList<Entry<Integer, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Entry<Integer, Integer>>() {
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
+import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import org.apache.fontbox.cff.CFFFont;
import org.apache.fontbox.cff.CFFParser;
+import org.apache.fontbox.cff.CFFType1Font;
+import org.apache.fontbox.cff.CharStringCommand;
+import org.apache.fontbox.cff.Type2CharString;
import org.apache.fop.fonts.MultiByteFont;
import org.apache.fop.fonts.cff.CFFDataReader;
Assert.assertEquals(fontSubset.read(), 248);
Assert.assertEquals(fontSubset.read(), (byte)(390 - 108));
}
+
+ @Test
+ public void testCompositeGlyphMapping() throws IOException {
+ glyphs.clear();
+ glyphs.put(0, 0);
+ OTFSubSetFile sourceSansSubset = new OTFSubSetFile() {
+ protected void initializeFont(FontFileReader in) {
+ fileFont = new CFFType1Font() {
+ List<Object> sequence = Arrays.asList(0, 0, 0, (int)'a', (int)'b', new CharStringCommand(12, 6));
+ public Type2CharString getType2CharString(int gid) {
+ return new Type2CharString(null, null, null, 0, sequence, 0, 0);
+ }
+ };
+ }
+ };
+ MultiByteFont multiByteFont = new MultiByteFont(null, null) {
+ public void setEmbedResourceName(String name) {
+ super.setEmbedResourceName(name);
+ addPrivateUseMapping('a', 'a');
+ addPrivateUseMapping('b', 'b');
+ }
+ };
+ multiByteFont.setEmbedURI(new File(".").toURI());
+ multiByteFont.setEmbedResourceName("");
+ sourceSansSubset.readFont(sourceSansReader, "SourceSansProBold", multiByteFont, glyphs);
+ Assert.assertEquals(multiByteFont.getUsedGlyphs().toString(), "{0=0, 97=1, 98=2}");
+ }
}