public byte[] GetCID(String fontName)
//throws java.io.FileNotFoundException
{
int j;
for (j=0; j<fonts.Length; j++)
if (fontName.Equals(fonts[j].name)) break;
if (j==fonts.Length) return null;
List<Item> l = new List<Item>();
// copy the header
Seek(0);
int major = GetCard8();
int minor = GetCard8();
int hdrSize = GetCard8();
int offSize = GetCard8();
nextIndexOffset = hdrSize;
l.Add(new RangeItem(buf,0,hdrSize));
int nglyphs=-1, nstrings=-1;
if ( ! fonts[j].isCID ) {
// count the glyphs
Seek(fonts[j].charstringsOffset);
nglyphs = GetCard16();
Seek(stringIndexOffset);
nstrings = GetCard16()+standardStrings.Length;
//System.err.Println("number of glyphs = "+nglyphs);
}
// create a name index
l.Add(new UInt16Item((char)1)); // count
l.Add(new UInt8Item((char)1)); // offSize
l.Add(new UInt8Item((char)1)); // first offset
l.Add(new UInt8Item((char)( 1+fonts[j].name.Length )));
l.Add(new StringItem(fonts[j].name));
// create the topdict Index
l.Add(new UInt16Item((char)1)); // count
l.Add(new UInt8Item((char)2)); // offSize
l.Add(new UInt16Item((char)1)); // first offset
OffsetItem topdictIndex1Ref = new IndexOffsetItem(2);
l.Add(topdictIndex1Ref);
IndexBaseItem topdictBase = new IndexBaseItem();
l.Add(topdictBase);
/*
int maxTopdictLen = (topdictOffsets[j+1]-topdictOffsets[j])
+ 9*2 // at most 9 new keys
+ 8*5 // 8 new integer arguments
+ 3*2;// 3 new SID arguments
*/
//int topdictNext = 0;
//byte[] topdict = new byte[maxTopdictLen];
OffsetItem charsetRef = new DictOffsetItem();
OffsetItem charstringsRef = new DictOffsetItem();
OffsetItem fdarrayRef = new DictOffsetItem();
OffsetItem fdselectRef = new DictOffsetItem();
if ( !fonts[j].isCID ) {
// create a ROS key
l.Add(new DictNumberItem(nstrings));
l.Add(new DictNumberItem(nstrings+1));
l.Add(new DictNumberItem(0));
l.Add(new UInt8Item((char)12));
l.Add(new UInt8Item((char)30));
// create a CIDCount key
l.Add(new DictNumberItem(nglyphs));
l.Add(new UInt8Item((char)12));
l.Add(new UInt8Item((char)34));
// What about UIDBase (12,35)? Don't know what is it.
// I don't think we need FontName; the font I looked at didn't have it.
}
// create an FDArray key
l.Add(fdarrayRef);
l.Add(new UInt8Item((char)12));
l.Add(new UInt8Item((char)36));
// create an FDSelect key
l.Add(fdselectRef);
l.Add(new UInt8Item((char)12));
l.Add(new UInt8Item((char)37));
// create an charset key
l.Add(charsetRef);
l.Add(new UInt8Item((char)15));
// create a CharStrings key
l.Add(charstringsRef);
l.Add(new UInt8Item((char)17));
Seek(topdictOffsets[j]);
while (GetPosition() < topdictOffsets[j+1]) {
int p1 = GetPosition();
GetDictItem();
int p2 = GetPosition();
if (key=="Encoding"
|| key=="Private"
|| key=="FDSelect"
|| key=="FDArray"
|| key=="charset"
|| key=="CharStrings"
) {
// just drop them
} else {
l.Add(new RangeItem(buf,p1,p2-p1));
}
}
l.Add(new IndexMarkerItem(topdictIndex1Ref,topdictBase));
// Copy the string index and append new strings.
// We need 3 more strings: Registry, Ordering, and a FontName for one FD.
// The total length is at most "Adobe"+"Identity"+63 = 76
if (fonts[j].isCID) {
l.Add(GetEntireIndexRange(stringIndexOffset));
} else {
String fdFontName = fonts[j].name+"-OneRange";
if (fdFontName.Length > 127)
fdFontName = fdFontName.Substring(0,127);
String extraStrings = "Adobe"+"Identity"+fdFontName;
int origStringsLen = stringOffsets[stringOffsets.Length-1]
- stringOffsets[0];
int stringsBaseOffset = stringOffsets[0]-1;
byte stringsIndexOffSize;
if (origStringsLen+extraStrings.Length <= 0xff) stringsIndexOffSize = 1;
else if (origStringsLen+extraStrings.Length <= 0xffff) stringsIndexOffSize = 2;
else if (origStringsLen+extraStrings.Length <= 0xffffff) stringsIndexOffSize = 3;
else stringsIndexOffSize = 4;
l.Add(new UInt16Item((char)((stringOffsets.Length-1)+3))); // count
l.Add(new UInt8Item((char)stringsIndexOffSize)); // offSize
foreach (int stringOffset in stringOffsets)
l.Add(new IndexOffsetItem(stringsIndexOffSize,
stringOffset-stringsBaseOffset));
int currentStringsOffset = stringOffsets[stringOffsets.Length-1]
- stringsBaseOffset;
//l.Add(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
currentStringsOffset += ("Adobe").Length;
l.Add(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
currentStringsOffset += ("Identity").Length;
l.Add(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
currentStringsOffset += fdFontName.Length;
l.Add(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
l.Add(new RangeItem(buf,stringOffsets[0],origStringsLen));
l.Add(new StringItem(extraStrings));
}
// copy the global subroutine index
l.Add(GetEntireIndexRange(gsubrIndexOffset));
// deal with fdarray, fdselect, and the font descriptors
if (fonts[j].isCID) {
// copy the FDArray, FDSelect, charset
} else {
// create FDSelect
l.Add(new MarkerItem(fdselectRef));
l.Add(new UInt8Item((char)3)); // format identifier
l.Add(new UInt16Item((char)1)); // nRanges
l.Add(new UInt16Item((char)0)); // Range[0].firstGlyph
l.Add(new UInt8Item((char)0)); // Range[0].fd
l.Add(new UInt16Item((char)nglyphs)); // sentinel
// recreate a new charset
// This format is suitable only for fonts without subsetting
l.Add(new MarkerItem(charsetRef));
l.Add(new UInt8Item((char)2)); // format identifier
l.Add(new UInt16Item((char)1)); // first glyph in range (ignore .notdef)
l.Add(new UInt16Item((char)(nglyphs-1))); // nLeft
// now all are covered, the data structure is complete.
// create a font dict index (fdarray)
l.Add(new MarkerItem(fdarrayRef));
l.Add(new UInt16Item((char)1));
l.Add(new UInt8Item((char)1)); // offSize
l.Add(new UInt8Item((char)1)); // first offset
OffsetItem privateIndex1Ref = new IndexOffsetItem(1);
l.Add(privateIndex1Ref);
IndexBaseItem privateBase = new IndexBaseItem();
l.Add(privateBase);
// looking at the PS that acrobat generates from a PDF with
// a CFF opentype font embeded with an identity-H encoding,
// it seems that it does not need a FontName.
//l.Add(new DictNumberItem((standardStrings.length+(stringOffsets.length-1)+2)));
//l.Add(new UInt8Item((char)12));
//l.Add(new UInt8Item((char)38)); // FontName
l.Add(new DictNumberItem(fonts[j].privateLength));
OffsetItem privateRef = new DictOffsetItem();
l.Add(privateRef);
l.Add(new UInt8Item((char)18)); // Private
l.Add(new IndexMarkerItem(privateIndex1Ref,privateBase));
// copy the private index & local subroutines
l.Add(new MarkerItem(privateRef));
// copy the private dict and the local subroutines.
// the length of the private dict seems to NOT include
// the local subroutines.
l.Add(new RangeItem(buf,fonts[j].privateOffset,fonts[j].privateLength));
if (fonts[j].privateSubrs >= 0) {
//System.err.Println("has subrs="+fonts[j].privateSubrs+" ,len="+fonts[j].privateLength);
l.Add(GetEntireIndexRange(fonts[j].privateSubrs));
}
}
// copy the charstring index
l.Add(new MarkerItem(charstringsRef));
l.Add(GetEntireIndexRange(fonts[j].charstringsOffset));
// now create the new CFF font
int[] currentOffset = new int[1];
currentOffset[0] = 0;
foreach (Item item in l) {
item.Increment(currentOffset);
}
foreach (Item item in l) {
item.Xref();
}
int size = currentOffset[0];
byte[] b = new byte[size];
foreach (Item item in l) {
item.Emit(b);
}
return b;
}