Browse Source

Add t1 merging

git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/branches/Temp_FontMerging@1604113 13f79535-47bb-0310-9956-ffa450edef68
tags/fop-2_0
Simon Steiner 10 years ago
parent
commit
507202d1e7

+ 1
- 1
src/java/org/apache/fop/fonts/truetype/OpenFont.java View File

protected List<UnicodeMapping> unicodeMappings; protected List<UnicodeMapping> unicodeMappings;


private int upem; // unitsPerEm from "head" table private int upem; // unitsPerEm from "head" table
private int nhmtx; // Number of horizontal metrics
protected int nhmtx; // Number of horizontal metrics
private PostScriptVersion postScriptVersion; private PostScriptVersion postScriptVersion;
protected int locaFormat; protected int locaFormat;
/** /**

+ 1
- 1
src/java/org/apache/fop/fonts/type1/PostscriptParser.java View File

import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;


class PostscriptParser {
public class PostscriptParser {


protected static final Log LOG = LogFactory.getLog(PostscriptParser.class); protected static final Log LOG = LogFactory.getLog(PostscriptParser.class);
/* Patterns used to identify Postscript elements */ /* Patterns used to identify Postscript elements */

+ 45
- 61
src/java/org/apache/fop/fonts/type1/Type1SubsetFile.java View File



protected static final Log LOG = LogFactory.getLog(Type1SubsetFile.class); protected static final Log LOG = LogFactory.getLog(Type1SubsetFile.class);
/* The subset list of char strings */ /* The subset list of char strings */
private HashMap<String, byte[]> subsetCharStrings;
protected HashMap<String, byte[]> subsetCharStrings;
/* The list of character names in the subset font */ /* The list of character names in the subset font */
private List<String> charNames = null;
protected List<String> charNames = null;
/* A list of unique subroutines references */ /* A list of unique subroutines references */
private LinkedHashMap<Integer, byte[]> uniqueSubs;
protected LinkedHashMap<Integer, byte[]> uniqueSubs;
private SingleByteFont sbfont = null; private SingleByteFont sbfont = null;
/* New line character */ /* New line character */
private String eol = "\n";
protected String eol = "\n";
/* An option to determine whether the subroutines are subset */ /* An option to determine whether the subroutines are subset */
private boolean subsetSubroutines = true;
protected boolean subsetSubroutines = true;
private byte[] fullFont; private byte[] fullFont;
//List of parsed Postscript elements //List of parsed Postscript elements
private List<PSElement> headerSection;
private List<PSElement> mainSection;
protected List<PSElement> headerSection;
protected List<PSElement> mainSection;
//Determines whether the current font uses standard encoding //Determines whether the current font uses standard encoding
private boolean standardEncoding = false;
protected boolean standardEncoding = false;


//Type 1 operators //Type 1 operators
private static final int OP_SEAC = 6; private static final int OP_SEAC = 6;
private static final int OP_CALLSUBR = 10; private static final int OP_CALLSUBR = 10;
private static final int OP_CALLOTHERSUBR = 16; private static final int OP_CALLOTHERSUBR = 16;


public byte[] createSubset(InputStream in, SingleByteFont sbfont,
String fontPrefix) throws IOException {
public byte[] createSubset(InputStream in, SingleByteFont sbfont) throws IOException {
fullFont = IOUtils.toByteArray(in); fullFont = IOUtils.toByteArray(in);
byte[] subsetFont = createSubset(sbfont, fontPrefix, true);
byte[] subsetFont = createSubset(sbfont, true);
//This should never happen but ensure that subset is shorter than original font //This should never happen but ensure that subset is shorter than original font
return (subsetFont.length == 0 || subsetFont.length > fullFont.length) return (subsetFont.length == 0 || subsetFont.length > fullFont.length)
? fullFont : subsetFont; ? fullFont : subsetFont;


/** /**
* Creates a new subset from the given type 1 font input stream * Creates a new subset from the given type 1 font input stream
* @param in The type 1 font to subset
* @param sbfont The font object containing information such as the * @param sbfont The font object containing information such as the
* characters from which to create the subset * characters from which to create the subset
* @param fontPrefix The prefix used in identifying the subset font
* @param allSubroutines This option will force the subset to include all
* @param subsetSubroutines This option will force the subset to include all
* subroutines. * subroutines.
* @return Returns the subset as a byte array * @return Returns the subset as a byte array
* @throws IOException * @throws IOException
*/ */
private byte[] createSubset(SingleByteFont sbfont,
String fontPrefix, boolean subsetSubroutines) throws IOException {
private byte[] createSubset(SingleByteFont sbfont, boolean subsetSubroutines) throws IOException {
this.subsetSubroutines = subsetSubroutines; this.subsetSubroutines = subsetSubroutines;
InputStream in = new ByteArrayInputStream(fullFont); InputStream in = new ByteArrayInputStream(fullFont);
//Initialise resources used for the font creation //Initialise resources used for the font creation


//Process and write the main section //Process and write the main section
PSElement charStrings = getElement("/CharStrings", mainSection); PSElement charStrings = getElement("/CharStrings", mainSection);
int result = readMainSection(mainSection, decoded, subsetEncodingEntries, charStrings);
if (result == 0) {
boolean result = readMainSection(mainSection, decoded, subsetEncodingEntries, charStrings);
if (!result) {
/* This check handles the case where a font uses a postscript method to return a /* This check handles the case where a font uses a postscript method to return a
* subroutine index. As there is currently no java postscript interpreter and writing * subroutine index. As there is currently no java postscript interpreter and writing
* one would be very difficult it prevents us from handling this eventuality. The way * one would be very difficult it prevents us from handling this eventuality. The way
uniqueSubs.clear(); uniqueSubs.clear();
subsetCharStrings.clear(); subsetCharStrings.clear();
charNames.clear(); charNames.clear();
return createSubset(sbfont, fontPrefix, false);
return createSubset(sbfont, false);
} }


//Write header section //Write header section
ByteArrayOutputStream boasHeader = writeHeader(pfbData, encoding, subsetEncodingEntries);
ByteArrayOutputStream boasHeader = writeHeader(pfbData, encoding);


ByteArrayOutputStream boasMain = writeMainSection(decoded, mainSection, charStrings); ByteArrayOutputStream boasMain = writeMainSection(decoded, mainSection, charStrings);
byte[] mainSectionBytes = boasMain.toByteArray(); byte[] mainSectionBytes = boasMain.toByteArray();
mainSectionBytes = BinaryCoder.encodeBytes(mainSectionBytes, 55665, 4); mainSectionBytes = BinaryCoder.encodeBytes(mainSectionBytes, 55665, 4);
boasMain = new ByteArrayOutputStream();
boasMain.reset();
boasMain.write(mainSectionBytes); boasMain.write(mainSectionBytes);


ByteArrayOutputStream baosTrailer = new ByteArrayOutputStream(); ByteArrayOutputStream baosTrailer = new ByteArrayOutputStream();
return stitchFont(boasHeader, boasMain, baosTrailer); return stitchFont(boasHeader, boasMain, baosTrailer);
} }


byte[] stitchFont(ByteArrayOutputStream boasHeader, ByteArrayOutputStream boasMain,
ByteArrayOutputStream boasTrailer) throws IOException {
protected byte[] stitchFont(ByteArrayOutputStream boasHeader, ByteArrayOutputStream boasMain,
ByteArrayOutputStream boasTrailer) throws IOException {
int headerLength = boasHeader.size(); int headerLength = boasHeader.size();
int mainLength = boasMain.size(); int mainLength = boasMain.size();


/* If no matches are found, create a new entry for the character so /* If no matches are found, create a new entry for the character so
* that it can be added even if it's not in the current encoding. */ * that it can be added even if it's not in the current encoding. */
if (matches.size() == 0) { if (matches.size() == 0) {
matches = new ArrayList<String>();
matches.clear();
if (glyph == 0) { if (glyph == 0) {
matches.add("dup 0 /.notdef put"); matches.add("dup 0 /.notdef put");
} else { } else {
return subsetEncodingEntries; return subsetEncodingEntries;
} }


private List<String> searchEntries(HashMap<Integer, String> encodingEntries, int glyph) {
protected List<String> searchEntries(HashMap<Integer, String> encodingEntries, int glyph) {
List<String> matches = new ArrayList<String>(); List<String> matches = new ArrayList<String>();
for (Entry<Integer, String> entry : encodingEntries.entrySet()) { for (Entry<Integer, String> entry : encodingEntries.entrySet()) {
String tag = getEntryPart(entry.getValue(), 3); String tag = getEntryPart(entry.getValue(), 3);
return matches; return matches;
} }


private ByteArrayOutputStream writeHeader(PFBData pfbData, PSElement encoding,
List<String> subsetEncodingEntries) throws UnsupportedEncodingException,
IOException {
protected ByteArrayOutputStream writeHeader(PFBData pfbData, PSElement encoding) throws IOException {
ByteArrayOutputStream boasHeader = new ByteArrayOutputStream(); ByteArrayOutputStream boasHeader = new ByteArrayOutputStream();
boasHeader.write(pfbData.getHeaderSegment(), 0, encoding.getStartPoint() - 1); boasHeader.write(pfbData.getHeaderSegment(), 0, encoding.getStartPoint() - 1);


if (!standardEncoding) { if (!standardEncoding) {
//Write out the new encoding table for the subset font //Write out the new encoding table for the subset font
String encodingArray = eol + String.format("/Encoding %d array", 256) + eol
String encodingArray = eol + "/Encoding 256 array" + eol
+ "0 1 255 {1 index exch /.notdef put } for" + eol; + "0 1 255 {1 index exch /.notdef put } for" + eol;
byte[] encodingDefinition = encodingArray.getBytes("ASCII"); byte[] encodingDefinition = encodingArray.getBytes("ASCII");
boasHeader.write(encodingDefinition, 0, encodingDefinition.length); boasHeader.write(encodingDefinition, 0, encodingDefinition.length);
return boas; return boas;
} }


private int readMainSection(List<PSElement> mainSection, byte[] decoded,
private boolean readMainSection(List<PSElement> mainSection, byte[] decoded,
List<String> subsetEncodingEntries, PSElement charStrings) { List<String> subsetEncodingEntries, PSElement charStrings) {
subsetEncodingEntries.add(0, "dup 0 /.notdef put"); subsetEncodingEntries.add(0, "dup 0 /.notdef put");
/* Reads and parses the charStrings section to subset the charString /* Reads and parses the charStrings section to subset the charString
/* Recursively scan the charString array for subroutines and if found, copy the /* Recursively scan the charString array for subroutines and if found, copy the
* entry to our subset entries and update any references. */ * entry to our subset entries and update any references. */
charStringEntry = createSubsetCharStrings(decoded, charStringEntry, subroutines, charStringEntry = createSubsetCharStrings(decoded, charStringEntry, subroutines,
subsetEncodingEntries, tag);
subsetEncodingEntries);
} }
if (charStringEntry.length == 0) { if (charStringEntry.length == 0) {
return 0;
return false;
} }
charStringEntry = BinaryCoder.encodeBytes(charStringEntry, 4330, skipBytes); charStringEntry = BinaryCoder.encodeBytes(charStringEntry, 4330, skipBytes);
subsetCharStrings.put(tag, charStringEntry); subsetCharStrings.put(tag, charStringEntry);
} }
return 1;
return true;
} }


private byte[] createSubsetCharStrings(byte[] decoded, byte[] data, PSFixedArray subroutines, private byte[] createSubsetCharStrings(byte[] decoded, byte[] data, PSFixedArray subroutines,
List<String> subsetEncodingEntries, String glyphName) {
List<String> subsetEncodingEntries) {
List<BytesNumber> operands = new ArrayList<BytesNumber>(); List<BytesNumber> operands = new ArrayList<BytesNumber>();
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
int cur = data[i] & 0xFF; int cur = data[i] & 0xFF;
if (uniqueSubs.get(operands.get(operands.size() - 1).getNumber()) == null) { if (uniqueSubs.get(operands.get(operands.size() - 1).getNumber()) == null) {
uniqueSubs.put(operands.get(operands.size() - 1).getNumber(), new byte[0]); uniqueSubs.put(operands.get(operands.size() - 1).getNumber(), new byte[0]);
data = addSubroutine(subroutines, operands, decoded, subsetEncodingEntries, data = addSubroutine(subroutines, operands, decoded, subsetEncodingEntries,
glyphName, data, i, 1, -1, operands.get(
data, i, 1, -1, operands.get(
operands.size() - 1).getNumber()); operands.size() - 1).getNumber());
} else { } else {
data = addSubroutine(subroutines, operands, decoded, subsetEncodingEntries, data = addSubroutine(subroutines, operands, decoded, subsetEncodingEntries,
glyphName, data, i, 1, getSubrIndex(operands.get(
data, i, 1, getSubrIndex(operands.get(
operands.size() - 1).getNumber()), operands.get( operands.size() - 1).getNumber()), operands.get(
operands.size() - 1).getNumber()); operands.size() - 1).getNumber());
} }
return new byte[0]; return new byte[0];
} }
data = addSubroutine(subroutines, operands, decoded, subsetEncodingEntries, data = addSubroutine(subroutines, operands, decoded, subsetEncodingEntries,
glyphName, data, i, 2, -1, operands.get(0).getNumber());
data, i, 2, -1, operands.get(0).getNumber());
} }
} }
if (data.length == 0) { if (data.length == 0) {
} }


private byte[] addSubroutine(PSFixedArray subroutines, List<BytesNumber> operands, byte[] decoded, private byte[] addSubroutine(PSFixedArray subroutines, List<BytesNumber> operands, byte[] decoded,
List<String> subsetEncodingEntries, String glyphName, byte[] data, int i, int opLength,
List<String> subsetEncodingEntries, byte[] data, int i, int opLength,
int existingSubrRef, int subrID) { int existingSubrRef, int subrID) {
if (existingSubrRef == -1) { if (existingSubrRef == -1) {
int[] subrData = subroutines.getBinaryEntryByIndex(subrID); int[] subrData = subroutines.getBinaryEntryByIndex(subrID);
byte[] subroutine = getBinaryEntry(subrData, decoded); byte[] subroutine = getBinaryEntry(subrData, decoded);
subroutine = BinaryCoder.decodeBytes(subroutine, 4330, 4); subroutine = BinaryCoder.decodeBytes(subroutine, 4330, 4);
subroutine = createSubsetCharStrings(decoded, subroutine, subroutines, subroutine = createSubsetCharStrings(decoded, subroutine, subroutines,
subsetEncodingEntries, glyphName);
subsetEncodingEntries);
if (subroutine.length == 0) { if (subroutine.length == 0) {
return new byte[0]; return new byte[0];
} }
return data; return data;
} }


private ByteArrayOutputStream writeMainSection(byte[] decoded, List<PSElement> mainSection,
PSElement charStrings) throws IOException {
protected ByteArrayOutputStream writeMainSection(byte[] decoded, List<PSElement> mainSection,
PSElement charStrings) throws IOException {
ByteArrayOutputStream main = new ByteArrayOutputStream(); ByteArrayOutputStream main = new ByteArrayOutputStream();
PSElement subrs = getElement("/Subrs", mainSection); PSElement subrs = getElement("/Subrs", mainSection);


writeString(eol + String.format("/Subrs %d array", uniqueSubs.size()), main); writeString(eol + String.format("/Subrs %d array", uniqueSubs.size()), main);
int count = 0; int count = 0;
for (Entry<Integer, byte[]> entry : uniqueSubs.entrySet()) { for (Entry<Integer, byte[]> entry : uniqueSubs.entrySet()) {
byte[] newSubrBytes = (eol + String.format("dup %d %d %s ", count++,
entry.getValue().length, rd)).getBytes("ASCII");
newSubrBytes = concatArray(newSubrBytes, entry.getValue());
newSubrBytes = concatArray(newSubrBytes, String.format(" %s", np).getBytes("ASCII"));
main.write(newSubrBytes);
writeString(eol + String.format("dup %d %d %s ", count++, entry.getValue().length, rd), main);
main.write(entry.getValue());
writeString(" " + np, main);
} }
writeString(eol + nd, main); writeString(eol + nd, main);
} else { } else {
return main; return main;
} }


private String findVariable(byte[] decoded, List<PSElement> elements, String[] matches,
String fallback) throws UnsupportedEncodingException {
protected String findVariable(byte[] decoded, List<PSElement> elements, String[] matches,
String fallback) throws UnsupportedEncodingException {
for (PSElement element : elements) { for (PSElement element : elements) {
if (element instanceof PSSubroutine) { if (element instanceof PSSubroutine) {
byte[] var = new byte[element.getEndPoint() - element.getStartPoint()]; byte[] var = new byte[element.getEndPoint() - element.getStartPoint()];
sbfont.mapUsedGlyphName(charIndex, charName); sbfont.mapUsedGlyphName(charIndex, charName);
} }


private void writeString(String entry, ByteArrayOutputStream boas)
throws UnsupportedEncodingException, IOException {
protected void writeString(String entry, ByteArrayOutputStream boas)
throws IOException {
byte[] byteEntry = entry.getBytes("ASCII"); byte[] byteEntry = entry.getBytes("ASCII");
boas.write(byteEntry); boas.write(byteEntry);
} }
* @param decoded The array from which to copy a section of data * @param decoded The array from which to copy a section of data
* @return Returns the copy of the data section * @return Returns the copy of the data section
*/ */
byte[] getBinaryEntry(int[] position, byte[] decoded) {
protected byte[] getBinaryEntry(int[] position, byte[] decoded) {
int start = position[0]; int start = position[0];
int finish = position[1]; int finish = position[1];
byte[] line = new byte[finish - start]; byte[] line = new byte[finish - start];
return line; return line;
} }


private String getEntryPart(String entry, int part) {
protected String getEntryPart(String entry, int part) {
Scanner s = new Scanner(entry).useDelimiter(" "); Scanner s = new Scanner(entry).useDelimiter(" ");
for (int i = 1; i < part; i++) { for (int i = 1; i < part; i++) {
s.next(); s.next();
return s.next(); return s.next();
} }


private PSElement getElement(String elementID, List<PSElement> elements) {
protected PSElement getElement(String elementID, List<PSElement> elements) {
for (PSElement element : elements) { for (PSElement element : elements) {
if (element.getOperator().equals(elementID)) { if (element.getOperator().equals(elementID)) {
return element; return element;
return null; return null;
} }


/**
* Gets the list of subset character names
* @return Returns the subset character names
*/
public List<String> getCharNames() {
return charNames;
}

/** /**
* A class to encode and decode sections of a type 1 font file. See Adobe * A class to encode and decode sections of a type 1 font file. See Adobe
* Type 1 Font Format Section 7.2 for more details. * Type 1 Font Format Section 7.2 for more details.

+ 1
- 1
src/java/org/apache/fop/pdf/PDFFactory.java View File

assert font instanceof SingleByteFont; assert font instanceof SingleByteFont;
SingleByteFont sbfont = (SingleByteFont)font; SingleByteFont sbfont = (SingleByteFont)font;
Type1SubsetFile pfbFile = new Type1SubsetFile(); Type1SubsetFile pfbFile = new Type1SubsetFile();
byte[] subsetData = pfbFile.createSubset(in, sbfont, fontPrefix);
byte[] subsetData = pfbFile.createSubset(in, sbfont);
InputStream subsetStream = new ByteArrayInputStream(subsetData); InputStream subsetStream = new ByteArrayInputStream(subsetData);
PFBParser parser = new PFBParser(); PFBParser parser = new PFBParser();
PFBData pfb = parser.parsePFB(subsetStream); PFBData pfb = parser.parsePFB(subsetStream);

+ 1
- 1
src/java/org/apache/fop/render/ps/PSFontUtils.java View File

boolean embed = true; boolean embed = true;
if (font.getEmbeddingMode() == EmbeddingMode.SUBSET) { if (font.getEmbeddingMode() == EmbeddingMode.SUBSET) {
Type1SubsetFile subset = new Type1SubsetFile(); Type1SubsetFile subset = new Type1SubsetFile();
byte[] byteSubset = subset.createSubset(fontStream, font, "");
byte[] byteSubset = subset.createSubset(fontStream, font);
fontStream = new ByteArrayInputStream(byteSubset); fontStream = new ByteArrayInputStream(byteSubset);
} }
embedType1Font(gen, fontStream); embedType1Font(gen, fontStream);

+ 4
- 15
test/java/org/apache/fop/fonts/type1/Type1SubsetFileTestCase.java View File

@Test @Test
public void test() throws IOException { public void test() throws IOException {
InputStream in = new FileInputStream(TEST_FONT_A); InputStream in = new FileInputStream(TEST_FONT_A);
compareCharStringData(in, TEST_FONT_A, createFontASubset(in, TEST_FONT_A));
compareCharStringData(TEST_FONT_A, createFontASubset(in, TEST_FONT_A));
} }


@Test @Test
assertEquals(segment[3], 65); assertEquals(segment[3], 65);
} }


private void compareCharStringData(InputStream in, String font, byte[] subsetFont)
private void compareCharStringData(String font, byte[] subsetFont)
throws IOException { throws IOException {
decodedSections = new ArrayList<byte[]>(); decodedSections = new ArrayList<byte[]>();


//Reinitialise the input stream as reset only supports 1000 bytes. //Reinitialise the input stream as reset only supports 1000 bytes.
in = new FileInputStream(font);
InputStream in = new FileInputStream(font);
List<PSElement> origElements = parseElements(in); List<PSElement> origElements = parseElements(in);
List<PSElement> subsetElements = parseElements(new ByteArrayInputStream(subsetFont)); List<PSElement> subsetElements = parseElements(new ByteArrayInputStream(subsetFont));


SingleByteFont sbfont = mock(SingleByteFont.class); SingleByteFont sbfont = mock(SingleByteFont.class);
//Glyph index & selector //Glyph index & selector
Map<Integer, Integer> glyphs = new HashMap<Integer, Integer>(); Map<Integer, Integer> glyphs = new HashMap<Integer, Integer>();
//Selector & unicode
Map<Integer, Character> usedCharsIndex = new HashMap<Integer, Character>();
Map<Integer, String> usedCharNames = new HashMap<Integer, String>(); Map<Integer, String> usedCharNames = new HashMap<Integer, String>();
int count = 0; int count = 0;
for (int i = 32; i < 127; i++) { for (int i = 32; i < 127; i++) {
} }
for (int i = 161; i < 204; i++) { for (int i = 161; i < 204; i++) {
glyphs.put(i, count++); glyphs.put(i, count++);
usedCharsIndex.put(count, (char)i);
when(sbfont.getUnicodeFromSelector(count)).thenReturn((char)i); when(sbfont.getUnicodeFromSelector(count)).thenReturn((char)i);
usedCharNames.put(i, String.format("/%s", Glyphs.charToGlyphName((char)i))); usedCharNames.put(i, String.format("/%s", Glyphs.charToGlyphName((char)i)));
when(sbfont.getGlyphName(i)).thenReturn(AdobeStandardEncoding.getCharFromCodePoint(i)); when(sbfont.getGlyphName(i)).thenReturn(AdobeStandardEncoding.getCharFromCodePoint(i));
}; };
for (int i = 0; i < randomGlyphs.length; i++) { for (int i = 0; i < randomGlyphs.length; i++) {
glyphs.put(randomGlyphs[i], count++); glyphs.put(randomGlyphs[i], count++);
usedCharsIndex.put(count, (char)randomGlyphs[i]);
when(sbfont.getUnicodeFromSelector(count)).thenReturn((char)randomGlyphs[i]); when(sbfont.getUnicodeFromSelector(count)).thenReturn((char)randomGlyphs[i]);
usedCharNames.put(i, String.format("/%s", Glyphs.charToGlyphName((char)i))); usedCharNames.put(i, String.format("/%s", Glyphs.charToGlyphName((char)i)));
when(sbfont.getGlyphName(i)).thenReturn(AdobeStandardEncoding.getCharFromCodePoint(i)); when(sbfont.getGlyphName(i)).thenReturn(AdobeStandardEncoding.getCharFromCodePoint(i));
} }
for (int i = 256; i < 335; i++) { for (int i = 256; i < 335; i++) {
glyphs.put(i, count++); glyphs.put(i, count++);
usedCharsIndex.put(count, (char)i);
when(sbfont.getUnicodeFromSelector(count)).thenReturn((char)i); when(sbfont.getUnicodeFromSelector(count)).thenReturn((char)i);
usedCharNames.put(i, String.format("/%s", Glyphs.charToGlyphName((char)i))); usedCharNames.put(i, String.format("/%s", Glyphs.charToGlyphName((char)i)));
when(sbfont.getGlyphName(i)).thenReturn(AdobeStandardEncoding.getCharFromCodePoint(i)); when(sbfont.getGlyphName(i)).thenReturn(AdobeStandardEncoding.getCharFromCodePoint(i));
when(sbfont.getUsedGlyphs()).thenReturn(glyphs); when(sbfont.getUsedGlyphs()).thenReturn(glyphs);
when(sbfont.getEmbedFileURI()).thenReturn(URI.create(font)); when(sbfont.getEmbedFileURI()).thenReturn(URI.create(font));
Type1SubsetFile subset = new Type1SubsetFile(); Type1SubsetFile subset = new Type1SubsetFile();
return subset.createSubset(in, sbfont, "AAAAAA");
return subset.createSubset(in, sbfont);
} }


private List<PSElement> parseElements(InputStream in) private List<PSElement> parseElements(InputStream in)


private byte[] readFullCharString(byte[] decoded, byte[] data, PSFixedArray subroutines) { private byte[] readFullCharString(byte[] decoded, byte[] data, PSFixedArray subroutines) {
List<BytesNumber> operands = new ArrayList<BytesNumber>(); List<BytesNumber> operands = new ArrayList<BytesNumber>();
List<BytesNumber> fullList = new ArrayList<BytesNumber>();
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {
int cur = data[i] & 0xFF; int cur = data[i] & 0xFF;
if (cur >= 0 && cur <= 31) { if (cur >= 0 && cur <= 31) {
} }
BytesNumber operand = new BytesNumber(cur, i); BytesNumber operand = new BytesNumber(cur, i);
operand.setName(getName(cur, next)); operand.setName(getName(cur, next));
fullList.add(operand);
} }
operands.clear(); operands.clear();
} }
if (cur >= 32 && cur <= 246) { if (cur >= 32 && cur <= 246) {
operands.add(new BytesNumber(cur - 139, 1)); operands.add(new BytesNumber(cur - 139, 1));
fullList.add(operands.get(operands.size() - 1));
} else if (cur >= 247 && cur <= 250) { } else if (cur >= 247 && cur <= 250) {
operands.add(new BytesNumber((cur - 247) * 256 + (data[i + 1] & 0xFF) + 108, 2)); operands.add(new BytesNumber((cur - 247) * 256 + (data[i + 1] & 0xFF) + 108, 2));
fullList.add(operands.get(operands.size() - 1));
i++; i++;
} else if (cur >= 251 && cur <= 254) { } else if (cur >= 251 && cur <= 254) {
operands.add(new BytesNumber(-(cur - 251) * 256 - (data[i + 1] & 0xFF) - 108, 2)); operands.add(new BytesNumber(-(cur - 251) * 256 - (data[i + 1] & 0xFF) - 108, 2));
fullList.add(operands.get(operands.size() - 1));
i++; i++;
} else if (cur == 255) { } else if (cur == 255) {
int b1 = data[i + 1] & 0xFF; int b1 = data[i + 1] & 0xFF;
int b4 = data[i + 4] & 0xFF; int b4 = data[i + 4] & 0xFF;
int value = b1 << 24 | b2 << 16 | b3 << 8 | b4; int value = b1 << 24 | b2 << 16 | b3 << 8 | b4;
operands.add(new BytesNumber(value, 5)); operands.add(new BytesNumber(value, 5));
fullList.add(operands.get(operands.size() - 1));
i += 4; i += 4;
} }
} }

Loading…
Cancel
Save