/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info: http://www.jpedal.org
* (C) Copyright 1997-2008, IDRsolutions and Contributors.
*
* This file is part of JPedal
*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* ---------------
* Type1C.java
* ---------------
*/
package org.jpedal.fonts;
import java.io.*;
import java.util.Map;
import java.awt.*;
import org.jpedal.fonts.glyph.T1Glyphs;
import org.jpedal.fonts.glyph.PdfJavaGlyphs;
import org.jpedal.fonts.objects.FontData;
import org.jpedal.io.PdfObjectReader;
import org.jpedal.io.ObjectStore;
import org.jpedal.utils.LogWriter;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.objects.raw.PdfDictionary;
/**
* handlestype1 specifics
*/
public class Type1C extends Type1{
static final boolean debugFont=false;
static final boolean debugDictionary=false;
int ROS=-1,CIDFontVersion=0,CIDFontRevision=0,CIDFontType=0,CIDcount=0,UIDBase=-1,FDArray=-1,FDSelect=-1;
final static String[] OneByteCCFDict={"version","Notice","FullName","FamilyName","Weight",
"FontBBox","BlueValues","OtherBlues","FamilyBlues","FamilyOtherBlues",
"StdHW","StdVW","Escape","UniqueID","XUID",
"charset","Encoding","CharStrings","Private", "Subrs",
"defaultWidthX","nominalWidthX","-reserved-","-reserved-","-reserved-",
"-reserved-","-reserved-","-reserved-","shortint","longint",
"BCD","-reserved-"};
final static String[] TwoByteCCFDict={"Copyright","isFixedPitch","ItalicAngle","UnderlinePosition","UnderlineThickness",
"PaintType","CharstringType","FontMatrix","StrokeWidth","BlueScale",
"BlueShift","BlueFuzz","StemSnapH","StemSnapV","ForceBold",
"-reserved-","-reserved-","LanguageGroup","ExpansionFactor","initialRandomSeed",
"SyntheticBase","PostScript","BaseFontName","BaseFontBlend","-reserved-",
"-reserved-","-reserved-","-reserved-","-reserved-","-reserved-",
"ROS","CIDFontVersion","CIDFontRevision","CIDFontType","CIDCount",
"UIDBase","FDArray","FDSelect","FontName"};
//current location in file
private int top = 0;
private int charset = 0;
private int enc = 0;
private int charstrings = 0;
private int stringIdx;
private int stringStart;
private int stringOffSize;
private Rectangle BBox=null;
private boolean hasFontMatrix=false;// hasFontBBox=false,;
private int privateDict = -1,privateDictOffset=-1;
private int defaultWidthX = 0, nominalWidthX = 0;
/** decoding table for Expert */
private static final int ExpertSubCharset[] = { // 87
// elements
0,
1,
231,
232,
235,
236,
237,
238,
13,
14,
15,
99,
239,
240,
241,
242,
243,
244,
245,
246,
247,
248,
27,
28,
249,
250,
251,
253,
254,
255,
256,
257,
258,
259,
260,
261,
262,
263,
264,
265,
266,
109,
110,
267,
268,
269,
270,
272,
300,
301,
302,
305,
314,
315,
158,
155,
163,
320,
321,
322,
323,
324,
325,
326,
150,
164,
169,
327,
328,
329,
330,
331,
332,
333,
334,
335,
336,
337,
338,
339,
340,
341,
342,
343,
344,
345,
346 };
/** lookup table for names for type 1C glyphs */
public static final String type1CStdStrings[] = { // 391
// elements
".notdef",
"space",
"exclam",
"quotedbl",
"numbersign",
"dollar",
"percent",
"ampersand",
"quoteright",
"parenleft",
"parenright",
"asterisk",
"plus",
"comma",
"hyphen",
"period",
"slash",
"zero",
"one",
"two",
"three",
"four",
"five",
"six",
"seven",
"eight",
"nine",
"colon",
"semicolon",
"less",
"equal",
"greater",
"question",
"at",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"bracketleft",
"backslash",
"bracketright",
"asciicircum",
"underscore",
"quoteleft",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"braceleft",
"bar",
"braceright",
"asciitilde",
"exclamdown",
"cent",
"sterling",
"fraction",
"yen",
"florin",
"section",
"currency",
"quotesingle",
"quotedblleft",
"guillemotleft",
"guilsinglleft",
"guilsinglright",
"fi",
"fl",
"endash",
"dagger",
"daggerdbl",
"periodcentered",
"paragraph",
"bullet",
"quotesinglbase",
"quotedblbase",
"quotedblright",
"guillemotright",
"ellipsis",
"perthousand",
"questiondown",
"grave",
"acute",
"circumflex",
"tilde",
"macron",
"breve",
"dotaccent",
"dieresis",
"ring",
"cedilla",
"hungarumlaut",
"ogonek",
"caron",
"emdash",
"AE",
"ordfeminine",
"Lslash",
"Oslash",
"OE",
"ordmasculine",
"ae",
"dotlessi",
"lslash",
"oslash",
"oe",
"germandbls",
"onesuperior",
"logicalnot",
"mu",
"trademark",
"Eth",
"onehalf",
"plusminus",
"Thorn",
"onequarter",
"divide",
"brokenbar",
"degree",
"thorn",
"threequarters",
"twosuperior",
"registered",
"minus",
"eth",
"multiply",
"threesuperior",
"copyright",
"Aacute",
"Acircumflex",
"Adieresis",
"Agrave",
"Aring",
"Atilde",
"Ccedilla",
"Eacute",
"Ecircumflex",
"Edieresis",
"Egrave",
"Iacute",
"Icircumflex",
"Idieresis",
"Igrave",
"Ntilde",
"Oacute",
"Ocircumflex",
"Odieresis",
"Ograve",
"Otilde",
"Scaron",
"Uacute",
"Ucircumflex",
"Udieresis",
"Ugrave",
"Yacute",
"Ydieresis",
"Zcaron",
"aacute",
"acircumflex",
"adieresis",
"agrave",
"aring",
"atilde",
"ccedilla",
"eacute",
"ecircumflex",
"edieresis",
"egrave",
"iacute",
"icircumflex",
"idieresis",
"igrave",
"ntilde",
"oacute",
"ocircumflex",
"odieresis",
"ograve",
"otilde",
"scaron",
"uacute",
"ucircumflex",
"udieresis",
"ugrave",
"yacute",
"ydieresis",
"zcaron",
"exclamsmall",
"Hungarumlautsmall",
"dollaroldstyle",
"dollarsuperior",
"ampersandsmall",
"Acutesmall",
"parenleftsuperior",
"parenrightsuperior",
"twodotenleader",
"onedotenleader",
"zerooldstyle",
"oneoldstyle",
"twooldstyle",
"threeoldstyle",
"fouroldstyle",
"fiveoldstyle",
"sixoldstyle",
"sevenoldstyle",
"eightoldstyle",
"nineoldstyle",
"commasuperior",
"threequartersemdash",
"periodsuperior",
"questionsmall",
"asuperior",
"bsuperior",
"centsuperior",
"dsuperior",
"esuperior",
"isuperior",
"lsuperior",
"msuperior",
"nsuperior",
"osuperior",
"rsuperior",
"ssuperior",
"tsuperior",
"ff",
"ffi",
"ffl",
"parenleftinferior",
"parenrightinferior",
"Circumflexsmall",
"hyphensuperior",
"Gravesmall",
"Asmall",
"Bsmall",
"Csmall",
"Dsmall",
"Esmall",
"Fsmall",
"Gsmall",
"Hsmall",
"Ismall",
"Jsmall",
"Ksmall",
"Lsmall",
"Msmall",
"Nsmall",
"Osmall",
"Psmall",
"Qsmall",
"Rsmall",
"Ssmall",
"Tsmall",
"Usmall",
"Vsmall",
"Wsmall",
"Xsmall",
"Ysmall",
"Zsmall",
"colonmonetary",
"onefitted",
"rupiah",
"Tildesmall",
"exclamdownsmall",
"centoldstyle",
"Lslashsmall",
"Scaronsmall",
"Zcaronsmall",
"Dieresissmall",
"Brevesmall",
"Caronsmall",
"Dotaccentsmall",
"Macronsmall",
"figuredash",
"hypheninferior",
"Ogoneksmall",
"Ringsmall",
"Cedillasmall",
"questiondownsmall",
"oneeighth",
"threeeighths",
"fiveeighths",
"seveneighths",
"onethird",
"twothirds",
"zerosuperior",
"foursuperior",
"fivesuperior",
"sixsuperior",
"sevensuperior",
"eightsuperior",
"ninesuperior",
"zeroinferior",
"oneinferior",
"twoinferior",
"threeinferior",
"fourinferior",
"fiveinferior",
"sixinferior",
"seveninferior",
"eightinferior",
"nineinferior",
"centinferior",
"dollarinferior",
"periodinferior",
"commainferior",
"Agravesmall",
"Aacutesmall",
"Acircumflexsmall",
"Atildesmall",
"Adieresissmall",
"Aringsmall",
"AEsmall",
"Ccedillasmall",
"Egravesmall",
"Eacutesmall",
"Ecircumflexsmall",
"Edieresissmall",
"Igravesmall",
"Iacutesmall",
"Icircumflexsmall",
"Idieresissmall",
"Ethsmall",
"Ntildesmall",
"Ogravesmall",
"Oacutesmall",
"Ocircumflexsmall",
"Otildesmall",
"Odieresissmall",
"OEsmall",
"Oslashsmall",
"Ugravesmall",
"Uacutesmall",
"Ucircumflexsmall",
"Udieresissmall",
"Yacutesmall",
"Thornsmall",
"Ydieresissmall",
"001.000",
"001.001",
"001.002",
"001.003",
"Black",
"Bold",
"Book",
"Light",
"Medium",
"Regular",
"Roman",
"Semibold" };
/** Lookup table to map values */
private static final int ISOAdobeCharset[] = { // 229
// elements
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40,
41,
42,
43,
44,
45,
46,
47,
48,
49,
50,
51,
52,
53,
54,
55,
56,
57,
58,
59,
60,
61,
62,
63,
64,
65,
66,
67,
68,
69,
70,
71,
72,
73,
74,
75,
76,
77,
78,
79,
80,
81,
82,
83,
84,
85,
86,
87,
88,
89,
90,
91,
92,
93,
94,
95,
96,
97,
98,
99,
100,
101,
102,
103,
104,
105,
106,
107,
108,
109,
110,
111,
112,
113,
114,
115,
116,
117,
118,
119,
120,
121,
122,
123,
124,
125,
126,
127,
128,
129,
130,
131,
132,
133,
134,
135,
136,
137,
138,
139,
140,
141,
142,
143,
144,
145,
146,
147,
148,
149,
150,
151,
152,
153,
154,
155,
156,
157,
158,
159,
160,
161,
162,
163,
164,
165,
166,
167,
168,
169,
170,
171,
172,
173,
174,
175,
176,
177,
178,
179,
180,
181,
182,
183,
184,
185,
186,
187,
188,
189,
190,
191,
192,
193,
194,
195,
196,
197,
198,
199,
200,
201,
202,
203,
204,
205,
206,
207,
208,
209,
210,
211,
212,
213,
214,
215,
216,
217,
218,
219,
220,
221,
222,
223,
224,
225,
226,
227,
228 };
/** lookup data to convert Expert values */
private static final int ExpertCharset[] = { // 166
// elements
0,
1,
229,
230,
231,
232,
233,
234,
235,
236,
237,
238,
13,
14,
15,
99,
239,
240,
241,
242,
243,
244,
245,
246,
247,
248,
27,
28,
249,
250,
251,
252,
253,
254,
255,
256,
257,
258,
259,
260,
261,
262,
263,
264,
265,
266,
109,
110,
267,
268,
269,
270,
271,
272,
273,
274,
275,
276,
277,
278,
279,
280,
281,
282,
283,
284,
285,
286,
287,
288,
289,
290,
291,
292,
293,
294,
295,
296,
297,
298,
299,
300,
301,
302,
303,
304,
305,
306,
307,
308,
309,
310,
311,
312,
313,
314,
315,
316,
317,
318,
158,
155,
163,
319,
320,
321,
322,
323,
324,
325,
326,
150,
164,
169,
327,
328,
329,
330,
331,
332,
333,
334,
335,
336,
337,
338,
339,
340,
341,
342,
343,
344,
345,
346,
347,
348,
349,
350,
351,
352,
353,
354,
355,
356,
357,
358,
359,
360,
361,
362,
363,
364,
365,
366,
367,
368,
369,
370,
371,
372,
373,
374,
375,
376,
377,
378 };
/** needed so CIDFOnt0 can extend */
public Type1C() {}
/** get handles onto Reader so we can access the file */
public Type1C(PdfObjectReader current_pdf_file,String substituteFont) {
glyphs=new T1Glyphs(false);
init(current_pdf_file);
this.substituteFont=substituteFont;
}
/** read details of any embedded fontFile */
protected void readEmbeddedFont(PdfObject pdfFontDescriptor) throws Exception {
if(substituteFont!=null){
byte[] bytes ;
//read details
BufferedInputStream from;
//create streams
ByteArrayOutputStream to = new ByteArrayOutputStream();
InputStream jarFile = null;
try{
if(substituteFont.startsWith("jar:")|| substituteFont.startsWith("http:"))
jarFile = loader.getResourceAsStream(substituteFont);
else
jarFile = loader.getResourceAsStream("file:///"+substituteFont);
}catch(Exception e){
if(LogWriter.isOutput())
LogWriter.writeLog("3.Unable to open "+substituteFont);
}catch(Error err){
if(LogWriter.isOutput())
LogWriter.writeLog("3.Unable to open "+substituteFont);
}
if(jarFile==null){
/**
from=new BufferedInputStream(new FileInputStream(substituteFont));
//write
byte[] buffer = new byte[65535];
int bytes_read;
while ((bytes_read = from.read(buffer)) != -1)
to.write(buffer, 0, bytes_read);
to.close();
from.close();
/**/
File file=new File(substituteFont);
InputStream is = new FileInputStream(file);
long length = file.length();
if (length > Integer.MAX_VALUE) {
System.out.println("Sorry! Your given file is too large.");
return;
}
bytes = new byte[(int)length];
int offset = 0;
int numRead ;
while (offset < bytes.length && (numRead=is.read(bytes,
offset, bytes.length-offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file "
+ file.getName());
}
is.close();
// new BufferedReader
// (new InputStreamReader(loader.getResourceAsStream("org/jpedal/res/cid/" + encodingName), "Cp1252"));
/**
FileReader from2=null;
try {
from2 = new FileReader(substituteFont);
//new BufferedReader);
//outputStream = new FileWriter("characteroutput.txt");
int c;
while ((c = from2.read()) != -1) {
to.write(c);
}
} finally {
if (from2 != null) {
from2.close();
}
if (to != null) {
to.close();
}
}/**/
}else{
from= new BufferedInputStream(jarFile);
//write
byte[] buffer = new byte[65535];
int bytes_read;
while ((bytes_read = from.read(buffer)) != -1)
to.write(buffer, 0, bytes_read);
to.close();
from.close();
bytes=to.toByteArray();
}
/**load the font*/
try{
isFontSubstituted=true;
//if (substituteFont.indexOf(".afm") != -1)
readType1FontFile(bytes);
//else
// readType1CFontFile(to.toByteArray(),null);
} catch (Exception e) {
e.printStackTrace();
if(LogWriter.isOutput())
LogWriter.writeLog("[PDF]Substitute font="+substituteFont+"Type 1 exception=" + e);
}
//over-ride font remapping if substituted
if(isFontSubstituted && glyphs.remapFont)
glyphs.remapFont=false;
}else if(pdfFontDescriptor!=null){
PdfObject FontFile=pdfFontDescriptor.getDictionary(PdfDictionary.FontFile);
/** try type 1 first then type 1c/0c */
if (FontFile != null) {
try {
byte[] stream=currentPdfFile.readStream(FontFile,true,true,false, false,false, FontFile.getCacheName(currentPdfFile.getObjectReader()));
if(stream!=null)
readType1FontFile(stream);
} catch (Exception e) {
e.printStackTrace();
}
}else{
PdfObject FontFile3=pdfFontDescriptor.getDictionary(PdfDictionary.FontFile3);
if(FontFile3!=null){
byte[] stream=currentPdfFile.readStream(FontFile3,true,true,false, false,false, FontFile3.getCacheName(currentPdfFile.getObjectReader()));
if(stream!=null){ //if it fails, null returned
//check for type1c or ottf
if(stream.length>3 && stream[0]==719 && stream[1]==84 && stream[2]==84 && stream[3]==79){
}else //assume all standard cff for moment
readType1CFontFile(stream,null);
}
}
}
}
}
/** read in a font and its details from the pdf file */
public void createFont(
PdfObject pdfObject,
String fontID,
boolean renderPage,
ObjectStore objectStore, Map substitutedFonts)
throws Exception {
fontTypes = StandardFonts.TYPE1;
//generic setup
init(fontID, renderPage);
/**
* get FontDescriptor object - if present contains metrics on glyphs
*/
PdfObject pdfFontDescriptor=pdfObject.getDictionary(PdfDictionary.FontDescriptor);
//FontBBox and FontMatix
setBoundsAndMatrix(pdfFontDescriptor);
setName(pdfObject, fontID);
setEncoding(pdfObject, pdfFontDescriptor);
try{
readEmbeddedFont(pdfFontDescriptor);
}catch(Exception ee){
ee.printStackTrace();
}
//setWidths(pdfObject);
readWidths(pdfObject,true);
// if(embeddedFontName!=null && is1C() && PdfStreamDecoder.runningStoryPad){
// embeddedFontName= cleanupFontName(embeddedFontName);
// this.setBaseFontName(embeddedFontName);
// this.setFontName(embeddedFontName);
// }
//make sure a font set
if (renderPage)
setFont(getBaseFontName(), 1);
}
/** Constructor for html fonts */
public Type1C(byte[] fontDataAsArray,PdfJavaGlyphs glyphs, boolean is1C) throws Exception{
this.glyphs=glyphs;
//generate reverse lookup so we can encode CMAP
this.trackIndices=true;
//flags we extract all details (used originally by rendering and now by PS2OTF)
this.renderPage=true;
if(is1C)
readType1CFontFile(fontDataAsArray,null);
else
readType1FontFile(fontDataAsArray);
}
/** Constructor for OTF fonts */
public Type1C(byte[] fontDataAsArray,FontData fontData, PdfJavaGlyphs glyphs) throws Exception{
this.glyphs=glyphs;
readType1CFontFile(fontDataAsArray,fontData);
}
/** Handle encoding for type1C fonts. Also used for CIDFontType0C */
final private void readType1CFontFile(byte[] fontDataAsArray,FontData fontDataAsObject) throws Exception{
if(LogWriter.isOutput())
LogWriter.writeLog("Embedded Type1C font used");
glyphs.setis1C(true);
boolean isByteArray=(fontDataAsArray!=null);
//debugFont=getBaseFontName().indexOf("LC")!=-1;
if(debugFont)
System.err.println(getBaseFontName());
/**
try {
java.io.FileOutputStream fos=new java.io.FileOutputStream(getBaseFontName()+"_"+fontDataAsArray.length+".bfp");
fos.write(fontDataAsArray);
fos.close();
} catch (Exception e1) {
e1.printStackTrace();
}/***/
int start; //pointers within table
int size=2;
/**
* read Header
*/
int major,minor;
if(isByteArray){
major = fontDataAsArray[0];
minor = fontDataAsArray[1];
}else{
major = fontDataAsObject.getByte(0);
minor = fontDataAsObject.getByte(1);
}
if ((major != 1 || minor != 0) && LogWriter.isOutput())
LogWriter.writeLog("1C format "+ major+ ':' + minor+ " not fully supported");
if(debugFont)
System.out.println("major="+major+" minor="+minor);
// read header size to workout start of names index
if(isByteArray)
top = fontDataAsArray[2];
else
top = fontDataAsObject.getByte(2);
/**
* read names index
*/
// read name index for the first font
int count,offsize;
if(isByteArray){
count = getWord(fontDataAsArray, top, size);
offsize = fontDataAsArray[top + size];
}else{
count = getWord(fontDataAsObject, top, size);
offsize = fontDataAsObject.getByte(top + size);
}
/**
* get last offset and use to move to top dict index
*/
top += (size+1); //move pointer to start of font names
start = top + (count + 1) * offsize - 1; //move pointer to end of offsets
if(isByteArray)
top = start + getWord(fontDataAsArray, top + count * offsize, offsize);
else
top = start + getWord(fontDataAsObject, top + count * offsize, offsize);
/**
* read the dict index
*/
if(isByteArray){
count = getWord(fontDataAsArray, top, size);
offsize = fontDataAsArray[top + size];
}else{
count = getWord(fontDataAsObject, top, size);
offsize = fontDataAsObject.getByte(top + size);
}
top += (size+1); //update pointer
start = top + (count + 1) * offsize - 1;
int dicStart,dicEnd;
if(isByteArray){
dicStart = start + getWord(fontDataAsArray, top, offsize);
dicEnd = start + getWord(fontDataAsArray, top + offsize, offsize);
}else{
dicStart = start + getWord(fontDataAsObject, top, offsize);
dicEnd = start + getWord(fontDataAsObject, top + offsize, offsize);
}
/**
* read string index
*/
String[] strings=readStringIndex(fontDataAsArray, fontDataAsObject, start, offsize, count);
/**
* read global subroutines (top set by Strings code)
*/
readGlobalSubRoutines(fontDataAsArray,fontDataAsObject);
/**
* decode the dictionary
*/
decodeDictionary(fontDataAsArray, fontDataAsObject, dicStart, dicEnd, strings);
/**
* allow for subdictionaries in CID font
*/
if(FDSelect!=-1 ){
if(debugDictionary)
System.out.println("=============FDSelect===================="+getBaseFontName());
int nextDic=FDArray;
if(isByteArray){
count = getWord(fontDataAsArray, nextDic, size);
offsize = fontDataAsArray[nextDic + size];
}else{
count = getWord(fontDataAsObject, nextDic, size);
offsize = fontDataAsObject.getByte(nextDic + size);
}
nextDic += (size+1); //update pointer
start = nextDic + (count + 1) * offsize - 1;
if(isByteArray){
dicStart = start+getWord(fontDataAsArray, nextDic, offsize);
dicEnd =start+getWord(fontDataAsArray, nextDic + offsize, offsize);
}else{
dicStart = start+getWord(fontDataAsObject, nextDic, offsize);
dicEnd =start+getWord(fontDataAsObject, nextDic + offsize, offsize);
}
decodeDictionary(fontDataAsArray, fontDataAsObject, dicStart, dicEnd, strings);
if(debugDictionary)
System.out.println("================================="+getBaseFontName());
}
/**
* get number of glyphs from charstrings index
*/
top = charstrings;
int nGlyphs;
if(isByteArray)
nGlyphs = getWord(fontDataAsArray, top, size); //start of glyph index
else
nGlyphs = getWord(fontDataAsObject, top, size); //start of glyph index
glyphs.setGlyphCount(nGlyphs);
if(debugFont)
System.out.println("nGlyphs="+nGlyphs);
int[] names =readCharset(charset, nGlyphs, charstrings, fontDataAsObject,fontDataAsArray);
if(debugFont){
System.out.println("=======charset===============");
int count2=names.length;
for(int jj=0;jj<count2;jj++){
System.out.println(jj+" "+names[jj]);
}
System.out.println("=======Encoding===============");
}
/**
* set encoding if not set
*/
setEncoding(fontDataAsArray, fontDataAsObject,nGlyphs,names);
/**
* read glyph index
*/
top = charstrings;
readGlyphs(fontDataAsArray, fontDataAsObject, nGlyphs, names);
/**/
if(privateDict!=-1){
decodeDictionary(fontDataAsArray, fontDataAsObject, privateDict, privateDictOffset+privateDict, strings);
top = privateDict + privateDictOffset;
int len,nSubrs;
if(isByteArray)
len=fontDataAsArray.length;
else
len=fontDataAsObject.length();
if(top+2<len){
if(isByteArray)
nSubrs = getWord(fontDataAsArray, top, size);
else
nSubrs = getWord(fontDataAsObject, top, size);
if(nSubrs>0)
readSubrs(fontDataAsArray, fontDataAsObject, nSubrs);
}else if(debugFont || debugDictionary){
System.out.println("Private subroutine out of range");
}
}
/**/
/**
* set flags to tell software to use these descritpions
*/
isFontEmbedded = true;
glyphs.setFontEmbedded(true);
}
/**pick up encoding from embedded font*/
final private void setEncoding(byte[] fontDataAsArray, FontData fontDataAsObject,int nGlyphs,int[] names){
boolean isByteArray=fontDataAsArray!=null;
if(debugFont)
System.out.println("Enc="+enc);
// read encoding (glyph -> code mapping)
if (enc == 0){
embeddedEnc=StandardFonts.STD;
if (fontEnc == -1)
putFontEncoding(StandardFonts.STD);
if(isCID){
//store values for lookup on text
try{
String name;
for (int i = 1; i < nGlyphs; ++i) {
if(names[i]<391){
if(isByteArray)
name =getString(fontDataAsArray,names[i],stringIdx,stringStart,stringOffSize);
else
name =getString(fontDataAsObject,names[i],stringIdx,stringStart,stringOffSize);
putMappedChar(names[i],StandardFonts.getUnicodeName(name) );
}
}
}catch(Exception ee){
ee.printStackTrace();
}
}
}else if (enc == 1){
embeddedEnc=StandardFonts.MACEXPERT;
if (fontEnc == -1)
putFontEncoding(StandardFonts.MACEXPERT);
}else { //custom mapping
if(debugFont)
System.out.println("custom mapping");
top = enc;
int encFormat,c;
if(isByteArray)
encFormat = (fontDataAsArray[top++] & 0xff);
else
encFormat = (fontDataAsObject.getByte(top++) & 0xff);
String name;
if ((encFormat & 0x7f) == 0) { //format 0
int nCodes;
if(isByteArray)
nCodes = 1 + (fontDataAsArray[top++] & 0xff);
else
nCodes = 1 + (fontDataAsObject.getByte(top++) & 0xff);
if (nCodes > nGlyphs)
nCodes = nGlyphs;
for (int i = 1; i < nCodes; ++i) {
if(isByteArray){
c =fontDataAsArray[top++] & 0xff;
name =getString(fontDataAsArray,names[i],stringIdx,stringStart,stringOffSize);
}else{
c =fontDataAsObject.getByte(top++) & 0xff;
name =getString(fontDataAsObject,names[i],stringIdx,stringStart,stringOffSize);
}
putChar(c, name);
}
} else if ((encFormat & 0x7f) == 1) { //format 1
int nRanges;
if(isByteArray)
nRanges = (fontDataAsArray[top++] & 0xff);
else
nRanges = (fontDataAsObject.getByte(top++) & 0xff);
int nCodes = 1;
for (int i = 0; i < nRanges; ++i) {
int nLeft;
if(isByteArray){
c = (fontDataAsArray[top++] & 0xff);
nLeft = (fontDataAsArray[top++] & 0xff);
}else{
c = (fontDataAsObject.getByte(top++) & 0xff);
nLeft = (fontDataAsObject.getByte(top++) & 0xff);
}
for (int j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
if(isByteArray)
name =getString(fontDataAsArray,names[nCodes],stringIdx,stringStart,stringOffSize);
else
name =getString(fontDataAsObject,names[nCodes],stringIdx,stringStart,stringOffSize);
putChar(c, name);
nCodes++;
c++;
}
}
}
if ((encFormat & 0x80) != 0) { //supplimentary encodings
int nSups;
if(isByteArray)
nSups = (fontDataAsArray[top++] & 0xff);
else
nSups = (fontDataAsObject.getByte(top++) & 0xff);
for (int i = 0; i < nSups; ++i) {
if(isByteArray)
c = (fontDataAsArray[top++] & 0xff);
else
c = (fontDataAsObject.getByte(top++) & 0xff);
int sid;
if(isByteArray)
sid = getWord(fontDataAsArray, top, 2);
else
sid = getWord(fontDataAsObject, top, 2);
top += 2;
if(isByteArray)
name =getString(fontDataAsArray,sid,stringIdx,stringStart,stringOffSize);
else
name =getString(fontDataAsObject,sid,stringIdx,stringStart,stringOffSize);
putChar(c, name);
}
}
}
}
// LILYPONDTOOL
private final void readSubrs(byte[] fontDataAsArray, FontData fontDataAsObject, int nSubrs) throws Exception {
boolean isByteArray=fontDataAsArray!=null;
int subrOffSize;
if(isByteArray)
subrOffSize = fontDataAsArray[top+2];
else
subrOffSize = fontDataAsObject.getByte(top+2);
top+=3;
int subrIdx = top;
int subrStart = top + (nSubrs + 1) * subrOffSize - 1;
int nextTablePtr= top+nSubrs*subrOffSize;
if(isByteArray){
if(nextTablePtr<fontDataAsArray.length) //allow for table at end of file
top = subrStart + getWord(fontDataAsArray,nextTablePtr, subrOffSize);
else
top=fontDataAsArray.length-1;
}else{
if(nextTablePtr<fontDataAsArray.length) //allow for table at end of file
top = subrStart + getWord(fontDataAsObject, nextTablePtr, subrOffSize);
else
top=fontDataAsObject.length()-1;
}
int[] subrOffset = new int [nSubrs + 2];
int ii = subrIdx;
for (int jj = 0; jj<nSubrs+1; jj++) {
if(isByteArray){
if((ii+subrOffSize)<fontDataAsArray.length)
subrOffset[jj] = subrStart + getWord(fontDataAsArray, ii, subrOffSize);
}else{
if((ii+subrOffSize)<fontDataAsObject.length())
subrOffset[jj] = subrStart + getWord(fontDataAsObject, ii, subrOffSize);
}
ii += subrOffSize;
}
subrOffset[nSubrs + 1] = top;
glyphs.setLocalBias(calculateSubroutineBias(nSubrs));
//read the glyphs and store
int current = subrOffset[0];
for (int jj = 1; jj < nSubrs+1; jj++) {
//skip if out of bounds
if(current==0 || subrOffset[jj]>fontDataAsArray.length || subrOffset[jj]<0 || subrOffset[jj]==0)
continue;
ByteArrayOutputStream nextSubr = new ByteArrayOutputStream();
for (int c = current; c < subrOffset[jj]; c++){
if(!isByteArray && c<fontDataAsObject.length())
nextSubr.write(fontDataAsObject.getByte(c));
}
if(isByteArray){
int length=subrOffset[jj]-current;
if(length>0){
byte[] nextSub=new byte[length];
System.arraycopy(fontDataAsArray,current,nextSub,0,length);
glyphs.setCharString("subrs"+(jj-1),nextSub);
}
}else{
nextSubr.close();
glyphs.setCharString("subrs"+(jj-1),nextSubr.toByteArray());
}
current = subrOffset[jj];
}
}
private final void readGlyphs(byte[] fontDataAsArray, FontData fontDataAsObject,int nGlyphs,int[] names) throws Exception{
boolean isByteArray=fontDataAsArray!=null;
int glyphOffSize;
if(isByteArray)
glyphOffSize = fontDataAsArray[top + 2];
else
glyphOffSize = fontDataAsObject.getByte(top + 2);
top += 3;
int glyphIdx = top;
int glyphStart = top + (nGlyphs + 1) * glyphOffSize - 1;
if(isByteArray)
top =glyphStart+ getWord(fontDataAsArray,top + nGlyphs * glyphOffSize,glyphOffSize);
else
top =glyphStart+ getWord(fontDataAsObject,top + nGlyphs * glyphOffSize,glyphOffSize);
int[] glyphoffset = new int[nGlyphs + 2];
int ii = glyphIdx;
//read the offsets
for (int jj = 0; jj < nGlyphs + 1; jj++) {
if(isByteArray)
glyphoffset[jj] = glyphStart+getWord(fontDataAsArray,ii,glyphOffSize);
else
glyphoffset[jj] = glyphStart+getWord(fontDataAsObject,ii,glyphOffSize);
ii = ii + glyphOffSize;
}
glyphoffset[nGlyphs + 1] = top;
//read the glyphs and store
int current = glyphoffset[0];
String glyphName;
byte[] nextGlyph;
for (int jj = 1; jj < nGlyphs+1; jj++) {
nextGlyph=new byte[glyphoffset[jj]-current]; //read name of glyph
//get data for the glyph
for (int c = current; c < glyphoffset[jj]; c++){
if(isByteArray)
nextGlyph[c-current]=fontDataAsArray[c];
else
nextGlyph[c-current]=fontDataAsObject.getByte(c);
}
if(isCID){
glyphName =String.valueOf(names[jj - 1]);
}else{
if(isByteArray)
glyphName =getString(fontDataAsArray,names[jj-1],stringIdx,stringStart,stringOffSize);
else
glyphName =getString(fontDataAsObject,names[jj-1],stringIdx,stringStart,stringOffSize);
}
if(debugFont)
System.out.println("glyph= "+ glyphName +" start="+current+" length="+glyphoffset[jj]+" isCID="+isCID);
glyphs.setCharString(glyphName,nextGlyph);
current = glyphoffset[jj];
if(trackIndices){
glyphs.setIndexForCharString(jj, glyphName);
}
}
}
private static final int calculateSubroutineBias(int subroutineCount) {
int bias;
if (subroutineCount < 1240) {
bias = 107;
} else if (subroutineCount < 33900) {
bias = 1131;
} else {
bias = 32768;
}
return bias;
}
private final void readGlobalSubRoutines(byte[] fontDataAsArray, FontData fontDataAsObject) throws Exception{
boolean isByteArray=(fontDataAsArray!=null);
int subOffSize,count;
if(isByteArray){
subOffSize = (fontDataAsArray[top + 2] & 0xff);
count= getWord(fontDataAsArray, top, 2);
}else{
subOffSize = (fontDataAsObject.getByte(top + 2) & 0xff);
count= getWord(fontDataAsObject, top, 2);
}
top += 3;
if(count>0){
int idx = top;
int start = top + (count + 1) * subOffSize - 1;
if(isByteArray)
top =start+ getWord(fontDataAsArray,top + count * subOffSize,subOffSize);
else
top =start+ getWord(fontDataAsObject,top + count * subOffSize,subOffSize);
int[] offset = new int[count + 2];
int ii = idx;
//read the offsets
for (int jj = 0; jj < count + 1; jj++) {
if(isByteArray)
offset[jj] = start + getWord(fontDataAsArray,ii,subOffSize);
else
offset[jj] = start + getWord(fontDataAsObject,ii,subOffSize);
ii = ii + subOffSize;
}
offset[count + 1] = top;
glyphs.setGlobalBias(calculateSubroutineBias(count));
//read the subroutines and store
int current = offset[0];
for (int jj = 1; jj < count+1; jj++) {
ByteArrayOutputStream nextStream = new ByteArrayOutputStream();
for (int c = current; c < offset[jj]; c++){
if(isByteArray)
nextStream.write(fontDataAsArray[c]);
else
nextStream.write(fontDataAsObject.getByte(c));
}
nextStream.close();
//store
glyphs.setCharString("global"+(jj-1),nextStream.toByteArray());
//setGlobalSubroutine(new Integer(jj-1+bias),nextStream.toByteArray());
current = offset[jj];
}
}
}
private void decodeDictionary(byte[] fontDataAsArray, FontData fontDataAsObject, int dicStart, int dicEnd, String[] strings){
boolean fdReset=false;
if(debugDictionary)
System.out.println("=============Read dictionary===================="+getBaseFontName());
boolean isByteArray=fontDataAsArray!=null;
int p = dicStart, nextVal,key;
int i=0;
double[] op = new double[48]; //current operand in dictionary
while (p < dicEnd) {
if(isByteArray)
nextVal = fontDataAsArray[p] & 0xFF;
else
nextVal = fontDataAsObject.getByte(p) & 0xFF;
if (nextVal <= 27 || nextVal == 31) { // operator
key = nextVal;
p++;
if(debugDictionary && key!=12)
System.out.println(key +" (1) "+OneByteCCFDict[key]);
if (key == 0x0c) { //handle escaped keys
if(isByteArray)
key = fontDataAsArray[p] & 0xFF;
else
key = fontDataAsObject.getByte(p) & 0xFF;
if(debugDictionary)
System.out.println(key +" (2) "+TwoByteCCFDict[key]);
p++;
if(key!=36 && key!=37 && key!=7 && FDSelect!=-1){
if(debugDictionary){
System.out.println("Ignored as part of FDArray ");
for(int ii=0;ii<6;ii++)
System.out.println(op[ii]);
}
}else if (key == 2) { //italic
italicAngle=(int)op[0];
if(debugDictionary)
System.out.println("Italic="+op[0]);
}else if (key == 7) { //fontMatrix
if(!hasFontMatrix)
System.arraycopy(op, 0, FontMatrix, 0, 6);
if(debugDictionary){
for(int ii=0;ii<6;ii++)
System.out.println(ii+"="+op[ii]+ ' ' +this);
}
hasFontMatrix=true;
}else if (key == 30) { //ROS
ROS=(int)op[0];
isCID=true;
if(debugDictionary)
System.out.println(op[0]);
}else if(key==31){ //CIDFontVersion
CIDFontVersion=(int)op[0];
if(debugDictionary)
System.out.println(op[0]);
}else if(key==32){ //CIDFontRevision
CIDFontRevision=(int)op[0];
if(debugDictionary)
System.out.println(op[0]);
}else if(key==33){ //CIDFontType
CIDFontType=(int)op[0];
if(debugDictionary)
System.out.println(op[0]);
}else if(key==34){ //CIDcount
CIDcount=(int)op[0];
if(debugDictionary)
System.out.println(op[0]);
}else if(key==35){ //UIDBase
UIDBase=(int)op[0];
if(debugDictionary)
System.out.println(op[0]);
}else if(key==36){ //FDArray
FDArray=(int)op[0];
if(debugDictionary)
System.out.println(op[0]);
}else if(key==37){ //FDSelect
FDSelect=(int)op[0];
fdReset=true;
if(debugDictionary)
System.out.println(op[0]);
}else if(key==0){ //copyright
int id=(int)op[0];
if(id>390)
id=id-390;
copyright=strings[id];
if(debugDictionary)
System.out.println("copyright= "+copyright);
}else if(key==21){ //Postscript
//postscriptFontName=strings[id];
if(debugDictionary) {
int id=(int)op[0];
if(id>390)
id=id-390;
System.out.println("Postscript= "+strings[id]);
System.out.println(TwoByteCCFDict[key]+ ' ' +op[0]);
}
}else if(key==22){ //BaseFontname
//baseFontName=strings[id];
if(debugDictionary){
int id=(int)op[0];
if(id>390)
id=id-390;
System.out.println("BaseFontname= "+embeddedFontName);
System.out.println(TwoByteCCFDict[key]+ ' ' +op[0]);
}
}else if(key==38){ //fullname
//fullname=strings[id];
if(debugDictionary){
int id=(int)op[0];
if(id>390)
id=id-390;
System.out.println("fullname= "+strings[id]);
System.out.println(TwoByteCCFDict[key]+ ' ' +op[0]);
}
}else if(debugDictionary)
System.out.println(op[0]);
} else {
if(key==2){ //fullname
int id=(int)op[0];
if(id>390)
id=id-390;
embeddedFontName=strings[id];
if(debugDictionary){
System.out.println("name= "+embeddedFontName);
System.out.println(OneByteCCFDict[key]+ ' ' +op[0]);
}
}else if(key==3){ //familyname
//embeddedFamilyName=strings[id];
if(debugDictionary){
int id=(int)op[0];
if(id>390)
id=id-390;
System.out.println("FamilyName= "+embeddedFamilyName);
System.out.println(OneByteCCFDict[key]+ ' ' +op[0]);
}
}else if (key == 5) { //fontBBox
if(debugDictionary){
for(int ii=0;ii<4;ii++)
System.out.println(op[ii]);
}
for(int ii=0;ii<4;ii++){
//System.out.println(" "+ii+" "+op[ii]);
this.FontBBox[ii]=(float) op[ii];
}
//hasFontBBox=true;
}else if (key == 0x0f) { // charset
charset = (int) op[0];
if(debugDictionary)
System.out.println(op[0]);
} else if (key == 0x10) { // encoding
enc = (int) op[0];
if(debugDictionary)
System.out.println(op[0]);
} else if (key == 0x11) { // charstrings
charstrings = (int) op[0];
if(debugDictionary)
System.out.println(op[0]);
//System.out.println("charStrings="+charstrings);
} else if (key == 18 && glyphs.is1C()) { // readPrivate
privateDict = (int) op[1];
privateDictOffset = (int) op[0];
if(debugDictionary)
System.out.println("privateDict="+op[0]+" Offset="+op[1]);
} else if (key == 20) { //defaultWidthX
defaultWidthX = (int)op[0];
if (glyphs instanceof T1Glyphs)
((T1Glyphs)glyphs).setWidthValues(defaultWidthX, nominalWidthX);
if(debugDictionary)
System.out.println("defaultWidthX="+op[0]);
} else if (key == 21) { //nominalWidthX
nominalWidthX = (int)op[0];
if (glyphs instanceof T1Glyphs)
((T1Glyphs)glyphs).setWidthValues(defaultWidthX, nominalWidthX);
if(debugDictionary)
System.out.println("nominalWidthX="+op[0]);
} else if(debugDictionary){
// System.out.println(p+" "+key+" "+T1CcharCodes1Byte[key]+" <<<"+op);
System.out.println("Other value "+key);
/**if(op <type1CStdStrings.length)
System.out.println(type1CStdStrings[(int)op]);
else if((op-390) <strings.length)
System.out.println("interesting key:"+key);*/
}
//System.out.println(p+" "+key+" "+raw1ByteValues[key]+" <<<"+op);
}
i=0;
}else{
if(isByteArray)
p=glyphs.getNumber(fontDataAsArray, p,op,i,false);
else
p=glyphs.getNumber(fontDataAsObject, p,op,i,false);
i++;
}
}
if(debugDictionary)
System.out.println("================================="+getBaseFontName());
//reset
if(!fdReset)
FDSelect=-1;
}
private String[] readStringIndex(byte[] fontDataAsArray,FontData fontDataAsObject,int start,int offsize,int count){
int nStrings;
boolean isByteArray=(fontDataAsArray!=null);
if(isByteArray){
top = start + getWord(fontDataAsArray, top + count * offsize, offsize);
//start of string index
nStrings = getWord(fontDataAsArray, top, 2);
stringOffSize = fontDataAsArray[top + 2];
}else{
top = start + getWord(fontDataAsObject, top + count * offsize, offsize);
//start of string index
nStrings = getWord(fontDataAsObject, top, 2);
stringOffSize = fontDataAsObject.getByte(top + 2);
}
top += 3;
stringIdx = top;
stringStart = top + (nStrings + 1) * stringOffSize - 1;
if(isByteArray)
top =stringStart+ getWord(fontDataAsArray,top + nStrings * stringOffSize,stringOffSize);
else
top =stringStart+ getWord(fontDataAsObject,top + nStrings * stringOffSize,stringOffSize);
int[] offsets = new int[nStrings + 2];
String[] strings = new String[nStrings + 2];
int ii = stringIdx;
//read the offsets
for (int jj = 0; jj < nStrings + 1; jj++) {
if(isByteArray)
offsets[jj] = getWord(fontDataAsArray,ii,stringOffSize); //content[ii] & 0xff;
else
offsets[jj] = getWord(fontDataAsObject,ii,stringOffSize); //content[ii] & 0xff;
//getWord(content,ii,stringOffSize);
ii = ii + stringOffSize;
}
offsets[nStrings + 1] = top - stringStart;
//read the strings
int current = 0;
StringBuffer nextString;
for (int jj = 0; jj < nStrings + 1; jj++) {
nextString = new StringBuffer(offsets[jj]-current);
for (int c = current; c < offsets[jj]; c++){
if(isByteArray)
nextString.append((char) fontDataAsArray[stringStart + c]);
else
nextString.append((char) fontDataAsObject.getByte(stringStart + c));
}
if(debugFont)
System.out.println("String "+jj+" ="+nextString);
strings[jj] = nextString.toString();
current = offsets[jj];
}
return strings;
}
/** Utility method used during processing of type1C files */
static final private String getString(FontData fontDataAsObject,int sid,int idx,int start,int offsize) {
int len;
String result ;
if (sid < 391)
result = type1CStdStrings[sid];
else {
sid -= 391;
int idx0 =start+ getWord(fontDataAsObject, idx + sid * offsize,offsize);
int idxPtr1 =start+ getWord(fontDataAsObject, idx + (sid + 1) * offsize,offsize);
//System.out.println(sid+" "+idx0+" "+idxPtr1);
if ((len = idxPtr1 - idx0) > 255)
len = 255;
result = new String(fontDataAsObject.getBytes(idx0,len));
}
return result;
}
/** Utility method used during processing of type1C files */
static final private String getString(byte[] fontDataAsArray,int sid,int idx,int start,int offsize) {
int len;
String result ;
if (sid < 391)
result = type1CStdStrings[sid];
else {
sid -= 391;
int idx0 =start+ getWord(fontDataAsArray, idx + sid * offsize,offsize);
int idxPtr1 =start+ getWord(fontDataAsArray, idx + (sid + 1) * offsize,offsize);
//System.out.println(sid+" "+idx0+" "+idxPtr1);
if ((len = idxPtr1 - idx0) > 255)
len = 255;
result=new String(fontDataAsArray,idx0,len);
}
return result;
}
/** get standard charset or extract from type 1C font */
static final private int[] readCharset(int charset,int nGlyphs,int top,FontData fontDataAsObject, byte[] fontDataAsArray) {
boolean isByteArray=fontDataAsArray!=null;
int glyphNames[] ;
int i, j;
if(debugFont)
System.out.println("charset="+charset);
/**
//handle CIDS first
if(isCID){
glyphNames = new int[nGlyphs];
glyphNames[0] = 0;
for (i = 1; i < nGlyphs; ++i) {
glyphNames[i] = i;//getWord(fontData, top, 2);
//top += 2;
}
// read appropriate non-CID charset
}else */if (charset == 0)
glyphNames = ISOAdobeCharset;
else if (charset == 1)
glyphNames = ExpertCharset;
else if (charset == 2)
glyphNames = ExpertSubCharset;
else {
glyphNames = new int[nGlyphs+1];
glyphNames[0] = 0;
top = charset;
int charsetFormat;
if(isByteArray)
charsetFormat = fontDataAsArray[top++] & 0xff;
else
charsetFormat = fontDataAsObject.getByte(top++) & 0xff;
if(debugFont)
System.out.println("charsetFormat="+charsetFormat);
if (charsetFormat == 0) {
for (i = 1; i < nGlyphs; ++i) {
if(isByteArray)
glyphNames[i] = getWord(fontDataAsArray, top, 2);
else
glyphNames[i] = getWord(fontDataAsObject, top, 2);
top += 2;
}
} else if (charsetFormat == 1) {
i = 1;
int c,nLeft;
while (i < nGlyphs) {
if(isByteArray)
c = getWord(fontDataAsArray, top, 2);
else
c = getWord(fontDataAsObject, top, 2);
top += 2;
if(isByteArray)
nLeft = fontDataAsArray[top++] & 0xff;
else
nLeft = fontDataAsObject.getByte(top++) & 0xff;
for (j = 0; j <= nLeft; ++j)
glyphNames[i++] =c++;
}
} else if (charsetFormat == 2) {
i = 1;
int c,nLeft;
while (i < nGlyphs) {
if(isByteArray)
c = getWord(fontDataAsArray, top, 2);
else
c = getWord(fontDataAsObject, top, 2);
top += 2;
if(isByteArray)
nLeft = getWord(fontDataAsArray, top, 2);
else
nLeft = getWord(fontDataAsObject, top, 2);
top += 2;
for (j = 0; j <= nLeft; ++j)
glyphNames[i++] =c++;
}
}
}
return glyphNames;
}
/** Utility method used during processing of type1C files */
static final private int getWord(FontData fontDataAsObject, int index, int size) {
int result = 0;
for (int i = 0; i < size; i++) {
result = (result << 8) + (fontDataAsObject.getByte(index + i) & 0xff);
}
return result;
}
/** Utility method used during processing of type1C files */
static final private int getWord(byte[] fontDataAsArray, int index, int size) {
int result = 0;
for (int i = 0; i < size; i++) {
result = (result << 8) + (fontDataAsArray[index + i] & 0xff);
}
return result;
}
/**
* get bounding box to highlight
* @return
*/
public Rectangle getBoundingBox() {
if(BBox==null){
if(isFontEmbedded)
BBox=new Rectangle((int)FontBBox[0], (int)FontBBox[1],
(int)(FontBBox[2]-FontBBox[0]), (int)(FontBBox[3]-FontBBox[1])); //To change body of created methods use File | Settings | File Templates.
else
BBox=super.getBoundingBox();
}
return BBox;
}
}