Browse Source

FOP-2978: Include composite glyphs in otf subset

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@1882485 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-2_6
Simon Steiner 3 years ago
parent
commit
c1a6088b2a

+ 35
- 7
fop-core/src/main/java/org/apache/fop/fonts/truetype/OTFSubSetFile.java View File

@@ -37,6 +37,9 @@ import org.apache.commons.logging.Log;
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;
@@ -46,6 +49,7 @@ import org.apache.fop.fonts.cff.CFFDataReader.FDSelect;
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
@@ -105,6 +109,9 @@ public class OTFSubSetFile extends OTFSubSetWriter {
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;

@@ -129,20 +136,41 @@ public class OTFSubSetFile extends OTFSubSetWriter {
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>>() {

+ 9
- 0
fop-core/src/main/java/org/apache/fop/fonts/type1/AdobeStandardEncoding.java View File

@@ -416,4 +416,13 @@ public enum AdobeStandardEncoding {
}
return "";
}

public static char getUnicodeFromCodePoint(int codePoint) {
for (AdobeStandardEncoding encoding : CACHE.values()) {
if (encoding.getAdobeCodePoint() == codePoint) {
return (char) encoding.getUnicodeIndex();
}
}
return (char) -1;
}
}

+ 31
- 0
fop-core/src/test/java/org/apache/fop/fonts/truetype/OTFSubSetFileTestCase.java View File

@@ -21,6 +21,7 @@ package org.apache.fop.fonts.truetype;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -42,6 +43,9 @@ import static org.mockito.Mockito.when;

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;
@@ -699,4 +703,31 @@ public class OTFSubSetFileTestCase extends OTFFileTestCase {
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}");
}
}

Loading…
Cancel
Save