aboutsummaryrefslogtreecommitdiffstats
path: root/src/java/org/apache/fop/fonts/cff/CFFDataReader.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/org/apache/fop/fonts/cff/CFFDataReader.java')
-rw-r--r--src/java/org/apache/fop/fonts/cff/CFFDataReader.java929
1 files changed, 0 insertions, 929 deletions
diff --git a/src/java/org/apache/fop/fonts/cff/CFFDataReader.java b/src/java/org/apache/fop/fonts/cff/CFFDataReader.java
deleted file mode 100644
index 3ce63a2a4..000000000
--- a/src/java/org/apache/fop/fonts/cff/CFFDataReader.java
+++ /dev/null
@@ -1,929 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* $Id$ */
-
-package org.apache.fop.fonts.cff;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.fontbox.cff.CFFDataInput;
-import org.apache.fontbox.cff.CFFOperator;
-
-import org.apache.fop.fonts.truetype.FontFileReader;
-import org.apache.fop.fonts.truetype.OTFFile;
-
-/**
- * A class to read the CFF data from an OTF CFF font file.
- */
-public class CFFDataReader {
- private CFFDataInput cffData;
-
- private byte[] header;
- private CFFIndexData nameIndex;
- private CFFIndexData topDICTIndex;
- private CFFIndexData stringIndex;
- private CFFIndexData charStringIndex;
- private CFFIndexData globalIndexSubr;
- private CFFIndexData localIndexSubr;
- private CustomEncoding encoding;
- private FDSelect fdSelect;
- private List<FontDict> fdFonts;
-
- private static final int DOUBLE_BYTE_OPERATOR = 12;
- private static final int NUM_STANDARD_STRINGS = 391;
-
- /** Commonly used parsed dictionaries */
- private LinkedHashMap<String, DICTEntry> topDict;
-
- public CFFDataReader() {
-
- }
-
- /**
- * Constructor for the CFF data reader which accepts the CFF byte data
- * as an argument.
- * @param cffDataArray A byte array which holds the CFF data
- */
- public CFFDataReader(byte[] cffDataArray) throws IOException {
- cffData = new CFFDataInput(cffDataArray);
- readCFFData();
- }
-
- /**
- * Constructor for the CFF data reader which accepts a FontFileReader object
- * which points to the original font file as an argument.
- * @param fontFile The font file as represented by a FontFileReader object
- */
- public CFFDataReader(FontFileReader fontFile) throws IOException {
- cffData = new CFFDataInput(OTFFile.getCFFData(fontFile));
- readCFFData();
- }
-
- private void readCFFData() throws IOException {
- header = readHeader();
- nameIndex = readIndex();
- topDICTIndex = readIndex();
- topDict = parseDictData(topDICTIndex.getData());
- stringIndex = readIndex();
- globalIndexSubr = readIndex();
- charStringIndex = readCharStringIndex();
- encoding = readEncoding();
- fdSelect = readFDSelect();
- localIndexSubr = readLocalIndexSubrs();
- fdFonts = parseCIDData();
- }
-
- public Map<String, DICTEntry> getPrivateDict(DICTEntry privateEntry) throws IOException {
- return parseDictData(getPrivateDictBytes(privateEntry));
- }
-
- public byte[] getPrivateDictBytes(DICTEntry privateEntry) throws IOException {
- int privateLength = privateEntry.getOperands().get(0).intValue();
- int privateOffset = privateEntry.getOperands().get(1).intValue();
- return getCFFOffsetBytes(privateOffset, privateLength);
- }
-
- /**
- * Retrieves a number of bytes from the CFF data stream
- * @param offset The offset of the bytes to retrieve
- * @param length The number of bytes to retrieve
- * @return Returns a byte array of requested bytes
- * @throws IOException Throws an IO Exception if an error occurs
- */
- private byte[] getCFFOffsetBytes(int offset, int length) throws IOException {
- cffData.setPosition(offset);
- return cffData.readBytes(length);
- }
-
- /**
- * Parses the dictionary data and returns a map of objects for each entry
- * @param dictData The data for the dictionary data
- * @return Returns a map of type DICTEntry identified by the operand name
- * @throws IOException Throws an IO Exception if an error occurs
- */
- public LinkedHashMap<String, DICTEntry> parseDictData(byte[] dictData) throws IOException {
- LinkedHashMap<String, DICTEntry> dictEntries = new LinkedHashMap<String, DICTEntry>();
- List<Number> operands = new ArrayList<Number>();
- List<Integer> operandLengths = new ArrayList<Integer>();
- int lastOperandLength = 0;
- for (int i = 0; i < dictData.length; i++) {
- int readByte = dictData[i] & 0xFF;
- if (readByte < 28) {
- int[] operator = new int[(readByte == DOUBLE_BYTE_OPERATOR) ? 2 : 1];
- if (readByte == DOUBLE_BYTE_OPERATOR) {
- operator[0] = dictData[i];
- operator[1] = dictData[i + 1];
- i++;
- } else {
- operator[0] = dictData[i];
- }
- String operatorName = "";
- CFFOperator tempOp = null;
- if (operator.length > 1) {
- tempOp = CFFOperator.getOperator(new CFFOperator.Key(operator[0], operator[1]));
- } else {
- tempOp = CFFOperator.getOperator(new CFFOperator.Key(operator[0]));
- }
- if (tempOp != null) {
- operatorName = tempOp.getName();
- }
- DICTEntry newEntry = new DICTEntry();
- newEntry.setOperator(operator);
- newEntry.setOperands(new ArrayList<Number>(operands));
- newEntry.setOperatorName(operatorName);
- newEntry.setOffset(i - lastOperandLength);
- newEntry.setOperandLength(lastOperandLength);
- newEntry.setOperandLengths(new ArrayList<Integer>(operandLengths));
- byte[] byteData = new byte[lastOperandLength + operator.length];
- System.arraycopy(dictData, i - operator.length - (lastOperandLength - 1),
- byteData, 0, operator.length + lastOperandLength);
- newEntry.setByteData(byteData);
- dictEntries.put(operatorName, newEntry);
- operands.clear();
- operandLengths.clear();
- lastOperandLength = 0;
- } else {
- if (readByte >= 32 && readByte <= 246) {
- operands.add(readByte - 139);
- lastOperandLength += 1;
- operandLengths.add(1);
- } else if (readByte >= 247 && readByte <= 250) {
- operands.add((readByte - 247) * 256 + (dictData[i + 1] & 0xFF) + 108);
- lastOperandLength += 2;
- operandLengths.add(2);
- i++;
- } else if (readByte >= 251 && readByte <= 254) {
- operands.add(-(readByte - 251) * 256 - (dictData[i + 1] & 0xFF) - 108);
- lastOperandLength += 2;
- operandLengths.add(2);
- i++;
- } else if (readByte == 28) {
- operands.add((dictData[i + 1] & 0xFF) << 8 | (dictData[i + 2] & 0xFF));
- lastOperandLength += 3;
- operandLengths.add(3);
- i += 2;
- } else if (readByte == 29) {
- operands.add((dictData[i + 1] & 0xFF) << 24 | (dictData[i + 2] & 0xFF) << 16
- | (dictData[i + 3] & 0xFF) << 8 | (dictData[i + 4] & 0xFF));
- lastOperandLength += 5;
- operandLengths.add(5);
- i += 4;
- } else if (readByte == 30) {
- boolean terminatorFound = false;
- StringBuilder realNumber = new StringBuilder();
- int byteCount = 1;
- do {
- byte nibblesByte = dictData[++i];
- byteCount++;
- terminatorFound = readNibble(realNumber, (nibblesByte >> 4) & 0x0F);
- if (!terminatorFound) {
- terminatorFound = readNibble(realNumber, nibblesByte & 0x0F);
- }
- } while (!terminatorFound);
- operands.add(Double.valueOf(realNumber.toString()));
- lastOperandLength += byteCount;
- operandLengths.add(byteCount);
- }
- }
- }
- return dictEntries;
- }
-
- private boolean readNibble(StringBuilder realNumber, int nibble) {
- if (nibble <= 0x9) {
- realNumber.append(nibble);
- } else {
- switch (nibble) {
- case 0xa: realNumber.append("."); break;
- case 0xb: realNumber.append("E"); break;
- case 0xc: realNumber.append("E-"); break;
- case 0xd: break;
- case 0xe: realNumber.append("-"); break;
- case 0xf: return true;
- default: throw new AssertionError("Unexpected nibble value");
- }
- }
- return false;
- }
-
- /**
- * A class containing data for a dictionary entry
- */
- public static class DICTEntry {
- private int[] operator;
- private List<Number> operands;
- private List<Integer> operandLengths;
- private String operatorName;
- private int offset;
- private int operandLength;
- private byte[] data = new byte[0];
-
- public void setOperator(int[] operator) {
- this.operator = operator;
- }
-
- public int[] getOperator() {
- return this.operator;
- }
-
- public void setOperands(List<Number> operands) {
- this.operands = operands;
- }
-
- public List<Number> getOperands() {
- return this.operands;
- }
-
- public void setOperatorName(String operatorName) {
- this.operatorName = operatorName;
- }
-
- public String getOperatorName() {
- return this.operatorName;
- }
-
- public void setOffset(int offset) {
- this.offset = offset;
- }
-
- public int getOffset() {
- return this.offset;
- }
-
- public void setOperandLength(int operandLength) {
- this.operandLength = operandLength;
- }
-
- public int getOperandLength() {
- return this.operandLength;
- }
-
- public void setByteData(byte[] data) {
- this.data = data.clone();
- }
-
- public byte[] getByteData() {
- return data.clone();
- }
-
- public void setOperandLengths(List<Integer> operandLengths) {
- this.operandLengths = operandLengths;
- }
-
- public List<Integer> getOperandLengths() {
- return operandLengths;
- }
- }
-
- private byte[] readHeader() throws IOException {
- //Read known header
- byte[] fixedHeader = cffData.readBytes(4);
- int hdrSize = (fixedHeader[2] & 0xFF);
- byte[] extra = cffData.readBytes(hdrSize - 4);
- byte[] header = new byte[hdrSize];
- for (int i = 0; i < fixedHeader.length; i++) {
- header[i] = fixedHeader[i];
- }
- for (int i = 4; i < extra.length; i++) {
- header[i] = extra[i - 4];
- }
- return header;
- }
-
- /**
- * Reads a CFF index object are the specified offset position
- * @param offset The position of the index object to read
- * @return Returns an object representing the index
- * @throws IOException Throws an IO Exception if an error occurs
- */
- public CFFIndexData readIndex(int offset) throws IOException {
- cffData.setPosition(offset);
- return readIndex();
- }
-
- private CFFIndexData readIndex() throws IOException {
- return readIndex(cffData);
- }
-
- /**
- * Reads an index from the current position of the CFFDataInput object
- * @param input The object holding the CFF byte data
- * @return Returns an object representing the index
- * @throws IOException Throws an IO Exception if an error occurs
- */
- public CFFIndexData readIndex(CFFDataInput input) throws IOException {
- CFFIndexData nameIndex = new CFFIndexData();
- if (input != null) {
- int origPos = input.getPosition();
- nameIndex.parseIndexHeader(input);
- int tableSize = input.getPosition() - origPos;
- nameIndex.setByteData(input.getPosition() - tableSize, tableSize);
- }
- return nameIndex;
- }
-
- /**
- * Retrieves the SID for the given GID object
- * @param charsetOffset The offset of the charset data
- * @param GID The GID for which to retrieve the SID
- * @return Returns the SID as an integer
- */
- public int getSIDFromGID(int charsetOffset, int gid) throws IOException {
- if (gid == 0) {
- return 0;
- }
- cffData.setPosition(charsetOffset);
- int charsetFormat = cffData.readCard8();
- switch (charsetFormat) {
- case 0: //Adjust for .notdef character
- cffData.setPosition(cffData.getPosition() + (--gid * 2));
- return cffData.readSID();
- case 1: return getSIDFromGIDFormat(gid, 1);
- case 2: return getSIDFromGIDFormat(gid, 2);
- default: return 0;
- }
- }
-
- private int getSIDFromGIDFormat(int gid, int format) throws IOException {
- int glyphCount = 0;
- while (true) {
- int oldGlyphCount = glyphCount;
- int start = cffData.readSID();
- glyphCount += ((format == 1) ? cffData.readCard8() : cffData.readCard16()) + 1;
- if (gid <= glyphCount) {
- return start + (gid - oldGlyphCount) - 1;
- }
- }
- }
-
- public byte[] getHeader() {
- return header.clone();
- }
-
- public CFFIndexData getNameIndex() {
- return nameIndex;
- }
-
- public CFFIndexData getTopDictIndex() {
- return topDICTIndex;
- }
-
- public LinkedHashMap<String, DICTEntry> getTopDictEntries() {
- return topDict;
- }
-
- public CFFIndexData getStringIndex() {
- return stringIndex;
- }
-
- public CFFIndexData getGlobalIndexSubr() {
- return globalIndexSubr;
- }
-
- public CFFIndexData getLocalIndexSubr() {
- return localIndexSubr;
- }
-
- public CFFIndexData getCharStringIndex() {
- return charStringIndex;
- }
-
- public CFFDataInput getCFFData() {
- return cffData;
- }
-
- public CustomEncoding getEncoding() {
- return encoding;
- }
-
- public FDSelect getFDSelect() {
- return fdSelect;
- }
-
- public List<FontDict> getFDFonts() {
- return fdFonts;
- }
-
- public CFFDataInput getLocalSubrsForGlyph(int glyph) throws IOException {
- //Subsets are currently written using a Format0 FDSelect
- FDSelect fontDictionary = getFDSelect();
- if (fontDictionary instanceof Format0FDSelect) {
- Format0FDSelect fdSelect = (Format0FDSelect)fontDictionary;
- int found = fdSelect.getFDIndexes()[glyph];
- FontDict font = getFDFonts().get(found);
- byte[] localSubrData = font.getLocalSubrData().getByteData();
- if (localSubrData != null) {
- return new CFFDataInput(localSubrData);
- } else {
- return null;
- }
- } else if (fontDictionary instanceof Format3FDSelect) {
- Format3FDSelect fdSelect = (Format3FDSelect)fontDictionary;
- int index = 0;
- for (int first : fdSelect.getRanges().keySet()) {
- if (first > glyph) {
- break;
- }
- index++;
- }
- FontDict font = getFDFonts().get(index);
- byte[] localSubrsData = font.getLocalSubrData().getByteData();
- if (localSubrsData != null) {
- return new CFFDataInput(localSubrsData);
- } else {
- return null;
- }
- }
- return null;
- }
-
- /**
- * Parses the char string index from the CFF byte data
- * @param offset The offset to the char string index
- * @return Returns the char string index object
- * @throws IOException Throws an IO Exception if an error occurs
- */
- public CFFIndexData readCharStringIndex() throws IOException {
- int offset = topDict.get("CharStrings").getOperands().get(0).intValue();
- cffData.setPosition(offset);
- return readIndex();
- }
-
- private CustomEncoding readEncoding() throws IOException {
- CustomEncoding foundEncoding = null;
- if (topDict.get("Encoding") != null) {
- int offset = topDict.get("Encoding").getOperands().get(0).intValue();
- if (offset != 0 && offset != 1) {
- //No need to set the offset as we are reading the data sequentially.
- int format = cffData.readCard8();
- int numEntries = cffData.readCard8();
- switch (format) {
- case 0:
- foundEncoding = readFormat0Encoding(format, numEntries);
- break;
- case 1:
- foundEncoding = readFormat1Encoding(format, numEntries);
- break;
- default: break;
- }
- }
- }
- return foundEncoding;
- }
-
- private Format0Encoding readFormat0Encoding(int format, int numEntries)
- throws IOException {
- Format0Encoding newEncoding = new Format0Encoding();
- newEncoding.setFormat(format);
- newEncoding.setNumEntries(numEntries);
- int[] codes = new int[numEntries];
- for (int i = 0; i < numEntries; i++) {
- codes[i] = cffData.readCard8();
- }
- newEncoding.setCodes(codes);
- return newEncoding;
- }
-
- private Format1Encoding readFormat1Encoding(int format, int numEntries)
- throws IOException {
- Format1Encoding newEncoding = new Format1Encoding();
- newEncoding.setFormat(format);
- newEncoding.setNumEntries(numEntries);
- LinkedHashMap<Integer, Integer> ranges = new LinkedHashMap<Integer, Integer>();
- for (int i = 0; i < numEntries; i++) {
- int first = cffData.readCard8();
- int left = cffData.readCard8();
- ranges.put(first, left);
- }
- newEncoding.setRanges(ranges);
- return newEncoding;
- }
-
- private FDSelect readFDSelect() throws IOException {
- FDSelect fdSelect = null;
- DICTEntry fdSelectEntry = topDict.get("FDSelect");
- if (fdSelectEntry != null) {
- int fdOffset = fdSelectEntry.getOperands().get(0).intValue();
- cffData.setPosition(fdOffset);
- int format = cffData.readCard8();
- switch (format) {
- case 0:
- fdSelect = readFormat0FDSelect();
- break;
- case 3:
- fdSelect = readFormat3FDSelect();
- break;
- default:
- }
- }
- return fdSelect;
- }
-
- private Format0FDSelect readFormat0FDSelect() throws IOException {
- Format0FDSelect newFDs = new Format0FDSelect();
- newFDs.setFormat(0);
- int glyphCount = charStringIndex.getNumObjects();
- int[] fds = new int[glyphCount];
- for (int i = 0; i < glyphCount; i++) {
- fds[i] = cffData.readCard8();
- }
- newFDs.setFDIndexes(fds);
- return newFDs;
- }
-
- private Format3FDSelect readFormat3FDSelect() throws IOException {
- Format3FDSelect newFDs = new Format3FDSelect();
- newFDs.setFormat(3);
- int rangeCount = cffData.readCard16();
- newFDs.setRangeCount(rangeCount);
- LinkedHashMap<Integer, Integer> ranges = new LinkedHashMap<Integer, Integer>();
- for (int i = 0; i < rangeCount; i++) {
- int first = cffData.readCard16();
- int fd = cffData.readCard8();
- ranges.put(first, fd);
- }
- newFDs.setRanges(ranges);
- newFDs.setSentinelGID(cffData.readCard16());
- return newFDs;
- }
-
- private List<FontDict> parseCIDData() throws IOException {
- ArrayList<FontDict> fdFonts = new ArrayList<FontDict>();
- if (topDict.get("ROS") != null) {
- DICTEntry fdArray = topDict.get("FDArray");
- if (fdArray != null) {
- int fdIndex = fdArray.getOperands().get(0).intValue();
- CFFIndexData fontDicts = readIndex(fdIndex);
- for (int i = 0; i < fontDicts.getNumObjects(); i++) {
- FontDict newFontDict = new FontDict();
-
- byte[] fdData = fontDicts.getValue(i);
- LinkedHashMap<String, DICTEntry> fdEntries = parseDictData(fdData);
- newFontDict.setByteData(fontDicts.getValuePosition(i), fontDicts.getValueLength(i));
- DICTEntry fontFDEntry = fdEntries.get("FontName");
- if (fontFDEntry != null) {
- newFontDict.setFontName(getString(fontFDEntry.getOperands().get(0).intValue()));
- }
- DICTEntry privateFDEntry = fdEntries.get("Private");
- if (privateFDEntry != null) {
- newFontDict = setFDData(privateFDEntry, newFontDict);
- }
-
- fdFonts.add(newFontDict);
- }
- }
- }
- return fdFonts;
- }
-
- private FontDict setFDData(DICTEntry privateFDEntry, FontDict newFontDict) throws IOException {
- int privateFDLength = privateFDEntry.getOperands().get(0).intValue();
- int privateFDOffset = privateFDEntry.getOperands().get(1).intValue();
- cffData.setPosition(privateFDOffset);
- byte[] privateDict = cffData.readBytes(privateFDLength);
- newFontDict.setPrivateDictData(privateFDOffset, privateFDLength);
- LinkedHashMap<String, DICTEntry> privateEntries = parseDictData(privateDict);
- DICTEntry subroutines = privateEntries.get("Subrs");
- if (subroutines != null) {
- CFFIndexData localSubrs = readIndex(privateFDOffset
- + subroutines.getOperands().get(0).intValue());
- newFontDict.setLocalSubrData(localSubrs);
- } else {
- newFontDict.setLocalSubrData(new CFFIndexData());
- }
- return newFontDict;
- }
-
- private String getString(int sid) throws IOException {
- return new String(stringIndex.getValue(sid - NUM_STANDARD_STRINGS));
- }
-
- private CFFIndexData readLocalIndexSubrs() throws IOException {
- CFFIndexData localSubrs = null;
- DICTEntry privateEntry = topDict.get("Private");
- if (privateEntry != null) {
- int length = privateEntry.getOperands().get(0).intValue();
- int offset = privateEntry.getOperands().get(1).intValue();
- cffData.setPosition(offset);
- byte[] privateData = cffData.readBytes(length);
- LinkedHashMap<String, DICTEntry> privateDict = parseDictData(privateData);
- DICTEntry localSubrsEntry = privateDict.get("Subrs");
- if (localSubrsEntry != null) {
- int localOffset = offset + localSubrsEntry.getOperands().get(0).intValue();
- cffData.setPosition(localOffset);
- localSubrs = readIndex();
- }
- }
- return localSubrs;
- }
-
- /**
- * Parent class which provides the ability to retrieve byte data from
- * a sub-table.
- */
- public class CFFSubTable {
- private DataLocation dataLocation = new DataLocation();
-
- public void setByteData(int position, int length) {
- dataLocation = new DataLocation(position, length);
- }
-
- public byte[] getByteData() throws IOException {
- int oldPos = cffData.getPosition();
- try {
- cffData.setPosition(dataLocation.getDataPosition());
- return cffData.readBytes(dataLocation.getDataLength());
- } finally {
- cffData.setPosition(oldPos);
- }
- }
- }
-
- /**
- * An object used to hold index data from the CFF data
- */
- public class CFFIndexData extends CFFSubTable {
- private int numObjects;
- private int offSize;
- private int[] offsets = new int[0];
- private DataLocation dataLocation = new DataLocation();
-
- public void setNumObjects(int numObjects) {
- this.numObjects = numObjects;
- }
-
- public int getNumObjects() {
- return this.numObjects;
- }
-
- public void setOffSize(int offSize) {
- this.offSize = offSize;
- }
-
- public int getOffSize() {
- return this.offSize;
- }
-
- public void setOffsets(int[] offsets) {
- this.offsets = offsets.clone();
- }
-
- public int[] getOffsets() {
- return offsets.clone();
- }
-
- public void setData(int position, int length) {
- dataLocation = new DataLocation(position, length);
- }
-
- public byte[] getData() throws IOException {
- int origPos = cffData.getPosition();
- try {
- cffData.setPosition(dataLocation.getDataPosition());
- return cffData.readBytes(dataLocation.getDataLength());
- } finally {
- cffData.setPosition(origPos);
- }
- }
-
- /**
- * Parses index data from an index object found within the CFF byte data
- * @param cffData A byte array containing the CFF data
- * @throws IOException Throws an IO Exception if an error occurs
- */
- public void parseIndexHeader(CFFDataInput cffData) throws IOException {
- setNumObjects(cffData.readCard16());
- setOffSize(cffData.readOffSize());
- int[] offsets = new int[getNumObjects() + 1];
- byte[] bytes;
- //Fills the offsets array
- for (int i = 0; i <= getNumObjects(); i++) {
- switch (getOffSize()) {
- case 1:
- offsets[i] = cffData.readCard8();
- break;
- case 2:
- offsets[i] = cffData.readCard16();
- break;
- case 3:
- bytes = cffData.readBytes(3);
- offsets[i] = ((bytes[0] & 0xFF) << 16) + ((bytes[1] & 0xFF) << 8) + (bytes[2] & 0xFF);
- break;
- case 4:
- bytes = cffData.readBytes(4);
- offsets[i] = ((bytes[0] & 0xFF) << 24) + ((bytes[1] & 0xFF) << 16)
- + ((bytes[2] & 0xFF) << 8) + (bytes[3] & 0xFF);
- break;
- default: continue;
- }
- }
- setOffsets(offsets);
- int position = cffData.getPosition();
- int dataSize = offsets[offsets.length - 1] - offsets[0];
-
- cffData.setPosition(cffData.getPosition() + dataSize);
- setData(position, dataSize);
- }
-
- /**
- * Retrieves data from the index data
- * @param index The index position of the data to retrieve
- * @return Returns the byte data for the given index
- * @throws IOException Throws an IO Exception if an error occurs
- */
- public byte[] getValue(int index) throws IOException {
- int oldPos = cffData.getPosition();
- try {
- cffData.setPosition(dataLocation.getDataPosition() + (offsets[index] - 1));
- return cffData.readBytes(offsets[index + 1] - offsets[index]);
- } finally {
- cffData.setPosition(oldPos);
- }
- }
-
- public int getValuePosition(int index) {
- return dataLocation.getDataPosition() + (offsets[index] - 1);
- }
-
- public int getValueLength(int index) {
- return offsets[index + 1] - offsets[index];
- }
- }
-
- public abstract class CustomEncoding {
- private int format;
- private int numEntries;
-
- public void setFormat(int format) {
- this.format = format;
- }
-
- public int getFormat() {
- return format;
- }
-
- public void setNumEntries(int numEntries) {
- this.numEntries = numEntries;
- }
-
- public int getNumEntries() {
- return numEntries;
- }
- }
-
- public class Format0Encoding extends CustomEncoding {
- private int[] codes = new int[0];
-
- public void setCodes(int[] codes) {
- this.codes = codes.clone();
- }
-
- public int[] getCodes() {
- return codes.clone();
- }
- }
-
- public class Format1Encoding extends CustomEncoding {
- private LinkedHashMap<Integer, Integer> ranges;
-
- public void setRanges(LinkedHashMap<Integer, Integer> ranges) {
- this.ranges = ranges;
- }
-
- public LinkedHashMap<Integer, Integer> getRanges() {
- return ranges;
- }
- }
-
- public class FDSelect {
- private int format;
-
- public void setFormat(int format) {
- this.format = format;
- }
-
- public int getFormat() {
- return format;
- }
- }
-
- public class Format0FDSelect extends FDSelect {
- private int[] fds = new int[0];
-
- public void setFDIndexes(int[] fds) {
- this.fds = fds.clone();
- }
-
- public int[] getFDIndexes() {
- return fds.clone();
- }
- }
-
- public class Format3FDSelect extends FDSelect {
- private int rangeCount;
- private LinkedHashMap<Integer, Integer> ranges;
- private int sentinelGID;
-
- public void setRangeCount(int rangeCount) {
- this.rangeCount = rangeCount;
- }
-
- public int getRangeCount() {
- return rangeCount;
- }
-
- public void setRanges(LinkedHashMap<Integer, Integer> ranges) {
- this.ranges = ranges;
- }
-
- public LinkedHashMap<Integer, Integer> getRanges() {
- return ranges;
- }
-
- public void setSentinelGID(int sentinelGID) {
- this.sentinelGID = sentinelGID;
- }
-
- public int getSentinelGID() {
- return sentinelGID;
- }
- }
-
- public class FontDict extends CFFSubTable {
- private String fontName;
- private DataLocation dataLocation = new DataLocation();
- private CFFIndexData localSubrData;
-
- public void setFontName(String groupName) {
- this.fontName = groupName;
- }
-
- public String getFontName() {
- return fontName;
- }
-
- public void setPrivateDictData(int position, int length) {
- dataLocation = new DataLocation(position, length);
- }
-
- public byte[] getPrivateDictData() throws IOException {
- int origPos = cffData.getPosition();
- try {
- cffData.setPosition(dataLocation.getDataPosition());
- return cffData.readBytes(dataLocation.getDataLength());
- } finally {
- cffData.setPosition(origPos);
- }
- }
-
- public void setLocalSubrData(CFFIndexData localSubrData) {
- this.localSubrData = localSubrData;
- }
-
- public CFFIndexData getLocalSubrData() {
- return localSubrData;
- }
- }
-
- private static class DataLocation {
- private int dataPosition;
- private int dataLength;
-
- public DataLocation() {
- dataPosition = 0;
- dataLength = 0;
- }
-
- public DataLocation(int position, int length) {
- this.dataPosition = position;
- this.dataLength = length;
- }
-
- public int getDataPosition() {
- return dataPosition;
- }
-
- public int getDataLength() {
- return dataLength;
- }
- }
-}