📄 cfffont.java
字号:
static protected final class UInt8Item extends Item {
public char value;
public UInt8Item(char value) {this.value=value;}
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += 1;
}
// this is incomplete!
public void emit(byte[] buffer) {
buffer[myOffset+0] = (byte) ((value >>> 0) & 0xff);
}
}
static protected final class StringItem extends Item {
public String s;
public StringItem(String s) {this.s=s;}
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += s.length();
}
public void emit(byte[] buffer) {
for (int i=0; i<s.length(); i++)
buffer[myOffset+i] = (byte) (s.charAt(i) & 0xff);
}
}
/** A dictionary number on the list.
* This implementation is inefficient: it doesn't use the variable-length
* representation.
*/
static protected final class DictNumberItem extends Item {
public final int value;
public int size = 5;
public DictNumberItem(int value) {this.value=value;}
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += size;
}
// this is imcomplete!
public void emit(byte[] buffer) {
if (size==5) {
buffer[myOffset] = 29;
buffer[myOffset+1] = (byte) ((value >>> 24) & 0xff);
buffer[myOffset+2] = (byte) ((value >>> 16) & 0xff);
buffer[myOffset+3] = (byte) ((value >>> 8) & 0xff);
buffer[myOffset+4] = (byte) ((value >>> 0) & 0xff);
}
}
}
/** An offset-marker item for the list.
* It is used to mark an offset and to set the offset list item.
*/
static protected final class MarkerItem extends Item {
OffsetItem p;
public MarkerItem(OffsetItem pointerToMarker) {p=pointerToMarker;}
public void xref() {
p.set(this.myOffset);
}
}
/** a utility that creates a range item for an entire index
*
* @param indexOffset where the index is
* @return a range item representing the entire index
*/
protected RangeItem getEntireIndexRange(int indexOffset) {
seek(indexOffset);
int count = getCard16();
if (count==0) {
return new RangeItem(buf,indexOffset,2);
} else {
int indexOffSize = getCard8();
seek(indexOffset+2+1+count*indexOffSize);
int size = getOffset(indexOffSize)-1;
return new RangeItem(buf,indexOffset,
2+1+(count+1)*indexOffSize+size);
}
}
/** get a single CID font. The PDF architecture (1.4)
* supports 16-bit strings only with CID CFF fonts, not
* in Type-1 CFF fonts, so we convert the font to CID if
* it is in the Type-1 format.
* Two other tasks that we need to do are to select
* only a single font from the CFF package (this again is
* a PDF restriction) and to subset the CharStrings glyph
* description.
*/
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;
LinkedList l = new LinkedList();
// copy the header
seek(0);
int major = getCard8();
int minor = getCard8();
int hdrSize = getCard8();
int offSize = getCard8();
nextIndexOffset = hdrSize;
l.addLast(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.addLast(new UInt16Item((char)1)); // count
l.addLast(new UInt8Item((char)1)); // offSize
l.addLast(new UInt8Item((char)1)); // first offset
l.addLast(new UInt8Item((char)( 1+fonts[j].name.length() )));
l.addLast(new StringItem(fonts[j].name));
// create the topdict Index
l.addLast(new UInt16Item((char)1)); // count
l.addLast(new UInt8Item((char)2)); // offSize
l.addLast(new UInt16Item((char)1)); // first offset
OffsetItem topdictIndex1Ref = new IndexOffsetItem(2);
l.addLast(topdictIndex1Ref);
IndexBaseItem topdictBase = new IndexBaseItem();
l.addLast(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.addLast(new DictNumberItem(nstrings));
l.addLast(new DictNumberItem(nstrings+1));
l.addLast(new DictNumberItem(0));
l.addLast(new UInt8Item((char)12));
l.addLast(new UInt8Item((char)30));
// create a CIDCount key
l.addLast(new DictNumberItem(nglyphs));
l.addLast(new UInt8Item((char)12));
l.addLast(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.addLast(fdarrayRef);
l.addLast(new UInt8Item((char)12));
l.addLast(new UInt8Item((char)36));
// create an FDSelect key
l.addLast(fdselectRef);
l.addLast(new UInt8Item((char)12));
l.addLast(new UInt8Item((char)37));
// create an charset key
l.addLast(charsetRef);
l.addLast(new UInt8Item((char)15));
// create a CharStrings key
l.addLast(charstringsRef);
l.addLast(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.addLast(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.addLast(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.addLast(new UInt16Item((char)((stringOffsets.length-1)+3))); // count
l.addLast(new UInt8Item((char)stringsIndexOffSize)); // offSize
for (int i=0; i<stringOffsets.length; i++)
l.addLast(new IndexOffsetItem(stringsIndexOffSize,
stringOffsets[i]-stringsBaseOffset));
int currentStringsOffset = stringOffsets[stringOffsets.length-1]
- stringsBaseOffset;
//l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
currentStringsOffset += ("Adobe").length();
l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
currentStringsOffset += ("Identity").length();
l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
currentStringsOffset += fdFontName.length();
l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
l.addLast(new RangeItem(buf,stringOffsets[0],origStringsLen));
l.addLast(new StringItem(extraStrings));
}
// copy the global subroutine index
l.addLast(getEntireIndexRange(gsubrIndexOffset));
// deal with fdarray, fdselect, and the font descriptors
if (fonts[j].isCID) {
// copy the FDArray, FDSelect, charset
} else {
// create FDSelect
l.addLast(new MarkerItem(fdselectRef));
l.addLast(new UInt8Item((char)3)); // format identifier
l.addLast(new UInt16Item((char)1)); // nRanges
l.addLast(new UInt16Item((char)0)); // Range[0].firstGlyph
l.addLast(new UInt8Item((char)0)); // Range[0].fd
l.addLast(new UInt16Item((char)nglyphs)); // sentinel
// recreate a new charset
// This format is suitable only for fonts without subsetting
l.addLast(new MarkerItem(charsetRef));
l.addLast(new UInt8Item((char)2)); // format identifier
l.addLast(new UInt16Item((char)1)); // first glyph in range (ignore .notdef)
l.addLast(new UInt16Item((char)(nglyphs-1))); // nLeft
// now all are covered, the data structure is complete.
// create a font dict index (fdarray)
l.addLast(new MarkerItem(fdarrayRef));
l.addLast(new UInt16Item((char)1));
l.addLast(new UInt8Item((char)1)); // offSize
l.addLast(new UInt8Item((char)1)); // first offset
OffsetItem privateIndex1Ref = new IndexOffsetItem(1);
l.addLast(privateIndex1Ref);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -