Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2022 iText Group NV
Authors: Bruno Lowagie, Paulo Soares, et al.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License version 3
as published by the Free Software Foundation with the addition of the
following permission added to Section 15 as permitted in Section 7(a):
FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY
ITEXT GROUP. ITEXT GROUP DISCLAIMS THE WARRANTY OF NON INFRINGEMENT
OF THIRD PARTY RIGHTS
This program 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program; if not, see http://www.gnu.org/licenses or write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA, 02110-1301 USA, or download the license from the following URL:
http://itextpdf.com/terms-of-use/
The interactive user interfaces in modified source and object code versions
of this program must display Appropriate Legal Notices, as required under
Section 5 of the GNU Affero General Public License.
In accordance with Section 7(b) of the GNU Affero General Public License,
a covered work must retain the producer line in every PDF that is created
or manipulated using iText.
You can be released from the requirements of the license by purchasing
a commercial license. Buying such a license is mandatory as soon as you
develop commercial activities involving the iText software without
disclosing the source code of your own applications.
These activities include: offering paid services to customers as an ASP,
serving PDFs on the fly in a web application, shipping iText with a closed
source product.
For more information, please contact iText Software Corp. at this
address: [email protected]
*/
package com.itextpdf.io.font;
import com.itextpdf.io.exceptions.IOException;
import com.itextpdf.io.source.RandomAccessFileOrArray;
import com.itextpdf.io.source.RandomAccessSourceFactory;
import java.util.LinkedList;
public class CFFFont {
static final String[] operatorNames = {
"version", "Notice", "FullName", "FamilyName",
"Weight", "FontBBox", "BlueValues", "OtherBlues",
"FamilyBlues", "FamilyOtherBlues", "StdHW", "StdVW",
"UNKNOWN_12", "UniqueID", "XUID", "charset",
"Encoding", "CharStrings", "Private", "Subrs",
"defaultWidthX", "nominalWidthX", "UNKNOWN_22", "UNKNOWN_23",
"UNKNOWN_24", "UNKNOWN_25", "UNKNOWN_26", "UNKNOWN_27",
"UNKNOWN_28", "UNKNOWN_29", "UNKNOWN_30", "UNKNOWN_31",
"Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition",
"UnderlineThickness", "PaintType", "CharstringType", "FontMatrix",
"StrokeWidth", "BlueScale", "BlueShift", "BlueFuzz",
"StemSnapH", "StemSnapV", "ForceBold", "UNKNOWN_12_15",
"UNKNOWN_12_16", "LanguageGroup", "ExpansionFactor", "initialRandomSeed",
"SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend",
"UNKNOWN_12_24", "UNKNOWN_12_25", "UNKNOWN_12_26", "UNKNOWN_12_27",
"UNKNOWN_12_28", "UNKNOWN_12_29", "ROS", "CIDFontVersion",
"CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase",
"FDArray", "FDSelect", "FontName"
};
static final String[] standardStrings = {
// Automatically generated from Appendix A of the CFF specification; do
// not edit. Size should be 391.
".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"
};
//private String[] strings;
public String getString(char sid) {
if (sid < standardStrings.length) return standardStrings[sid];
if (sid >= standardStrings.length+stringOffsets.length-1) return null;
int j = sid - standardStrings.length;
//java.lang.System.err.println("going for "+j);
int p = getPosition();
seek(stringOffsets[j]);
StringBuffer s = new StringBuffer();
for (int k=stringOffsets[j]; k count in the index header. 1->offset size in index header
+ 2+1
//offset array size * offset size
+ (count+1)*indexOffSize
//???zero <-> one base
- 1
// read object offset relative to object array base
+ getOffset(indexOffSize);
}
//nextIndexOffset = offsets[count];
return offsets;
}
protected String key;
protected Object[] args = new Object[48];
protected int arg_count = 0;
protected void getDictItem() {
for (int i=0; i= 32 && b0 <= 246) {
args[arg_count] = b0-139;
arg_count++;
//System.err.println(item+" ");
continue;
}
if (b0 >= 247 && b0 <= 250) {
char b1 = getCard8();
short item = (short) ((b0-247)*256+b1+108);
args[arg_count] = (int) item;
arg_count++;
//System.err.println(item+" ");
continue;
}
if (b0 >= 251 && b0 <= 254) {
char b1 = getCard8();
short item = (short) (-(b0-251)*256-b1-108);
args[arg_count] = (int) item;
arg_count++;
//System.err.println(item+" ");
continue;
}
if (b0 == 30) {
StringBuilder item = new StringBuilder("");
boolean done = false;
char buffer = (char) 0;
byte avail = 0;
int nibble = 0;
while (!done) {
// get a nibble
if (avail==0) { buffer = getCard8(); avail=2; }
if (avail==1) { nibble = buffer / 16; avail--; }
if (avail==2) { nibble = buffer % 16; avail--; }
switch (nibble) {
case 0xa: item.append(".") ; break;
case 0xb: item.append("E") ; break;
case 0xc: item.append("E-"); break;
case 0xe: item.append("-") ; break;
case 0xf: done=true ; break;
default:
if (nibble >= 0 && nibble <= 9)
item.append(nibble);
else {
item.append("');
done = true;
}
break;
}
}
args[arg_count] = item.toString();
arg_count++;
//System.err.println(" real=["+item+"]");
continue;
}
if (b0 <= 21) {
gotKey=true;
if (b0 != 12) key = operatorNames[b0];
else key = operatorNames[32 + getCard8()];
//for (int i=0; i= 1 && size <= 4) {
for (int i = 0; i < size; i++) {
buffer[myOffset + i] = (byte) (value >>> ((size - 1 - i) << 3) & 0xFF);
}
}
}
}
protected static final class IndexBaseItem extends Item {
public IndexBaseItem() {}
}
protected static final class IndexMarkerItem extends Item {
private OffsetItem offItem;
private IndexBaseItem indexBase;
public IndexMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
this.offItem = offItem;
this.indexBase = indexBase;
}
@Override
public void xref() {
//System.err.println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
offItem.set(this.myOffset-indexBase.myOffset+1);
}
}
protected static final class SubrMarkerItem extends Item {
private OffsetItem offItem;
private IndexBaseItem indexBase;
public SubrMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
this.offItem = offItem;
this.indexBase = indexBase;
}
@Override
public void xref() {
//System.err.println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
offItem.set(this.myOffset-indexBase.myOffset);
}
}
/** an unknown offset in a dictionary for the list.
* We will fix up the offset later; for now, assume it's large.
*/
protected static final class DictOffsetItem extends OffsetItem {
public final int size;
public DictOffsetItem() {this.size=5; }
@Override
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += size;
}
// this is incomplete!
@Override
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);
}
}
}
/** Card24 item.
*/
protected static final class UInt24Item extends Item {
public int value;
public UInt24Item(int value) {this.value=value;}
@Override
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += 3;
}
// this is incomplete!
@Override
public void emit(byte[] buffer) {
buffer[myOffset+0] = (byte) (value >>> 16 & 0xff);
buffer[myOffset+1] = (byte) (value >>> 8 & 0xff);
buffer[myOffset+2] = (byte) (value >>> 0 & 0xff);
}
}
/** Card32 item.
*/
protected static final class UInt32Item extends Item {
public int value;
public UInt32Item(int value) {this.value=value;}
@Override
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += 4;
}
// this is incomplete!
@Override
public void emit(byte[] buffer) {
buffer[myOffset+0] = (byte) (value >>> 24 & 0xff);
buffer[myOffset+1] = (byte) (value >>> 16 & 0xff);
buffer[myOffset+2] = (byte) (value >>> 8 & 0xff);
buffer[myOffset+3] = (byte) (value >>> 0 & 0xff);
}
}
/** A SID or Card16 item.
*/
protected static final class UInt16Item extends Item {
public char value;
public UInt16Item(char value) {this.value = value;}
@Override
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += 2;
}
// this is incomplete!
@Override
public void emit(byte[] buffer) {
// Simplify from: there is no sense in >>> for unsigned char.
// buffer[myOffset+0] = (byte) (value >>> 8 & 0xff);
// buffer[myOffset+1] = (byte) (value >>> 0 & 0xff);
buffer[myOffset+0] = (byte) (value >> 8 & 0xff);
buffer[myOffset+1] = (byte) (value >> 0 & 0xff);
}
}
/** A Card8 item.
*/
protected static final class UInt8Item extends Item {
public char value;
public UInt8Item(char value) {this.value=value;}
@Override
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += 1;
}
// this is incomplete!
@Override
public void emit(byte[] buffer) {
//buffer[myOffset+0] = (byte) (value >>> 0 & 0xff);
buffer[myOffset+0] = (byte) (value & 0xff);
}
}
protected static final class StringItem extends Item {
public String s;
public StringItem(String s) {this.s=s;}
@Override
public void increment(int[] currentOffset) {
super.increment(currentOffset);
currentOffset[0] += s.length();
}
@Override
public void emit(byte[] buffer) {
for (int i=0; i>> 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.
*/
protected static final class MarkerItem extends Item {
OffsetItem p;
public MarkerItem(OffsetItem pointerToMarker) {p=pointerToMarker;}
@Override
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.
*
* @param fontName name of the font
* @return byte array represents the CID font
*/
public byte[] getCID(String fontName)
//throws java.io.FileNotFoundException
{
int j;
for (j=0; j 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
// count
l.addLast(new UInt16Item((char)1));
// offSize
l.addLast(new UInt8Item((char)1));
// first offset
l.addLast(new UInt8Item((char)1));
l.addLast(new UInt8Item((char)( 1+fonts[j].name.length() )));
l.addLast(new StringItem(fonts[j].name));
// create the topdict Index
// count
l.addLast(new UInt16Item((char)1));
// offSize
l.addLast(new UInt8Item((char)2));
// first offset
l.addLast(new UInt16Item((char)1));
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 ("Encoding".equals(key)
|| "Private".equals(key)
|| "FDSelect".equals(key)
|| "FDArray".equals(key)
|| "charset".equals(key)
|| "CharStrings".equals(key)
) {
// just drop them
} else {
l.addLast(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;
// count
l.addLast(new UInt16Item((char)(stringOffsets.length-1+3)));
// offSize
l.addLast(new UInt8Item((char)stringsIndexOffSize));
for (int stringOffset : stringOffsets)
l.addLast(new IndexOffsetItem(stringsIndexOffSize,
stringOffset-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));
// format identifier
l.addLast(new UInt8Item((char)3));
// nRanges
l.addLast(new UInt16Item((char)1));
// Range[0].firstGlyph
l.addLast(new UInt16Item((char)0));
// Range[0].fd
l.addLast(new UInt8Item((char)0));
// sentinel
l.addLast(new UInt16Item((char)nglyphs));
// recreate a new charset
// This format is suitable only for fonts without subsetting
l.addLast(new MarkerItem(charsetRef));
// format identifier
l.addLast(new UInt8Item((char)2));
// first glyph in range (ignore .notdef)
l.addLast(new UInt16Item((char)1));
// nLeft
l.addLast(new UInt16Item((char)(nglyphs-1)));
// 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));
// offSize
l.addLast(new UInt8Item((char)1));
// first offset
l.addLast(new UInt8Item((char)1));
OffsetItem privateIndex1Ref = new IndexOffsetItem(1);
l.addLast(privateIndex1Ref);
IndexBaseItem privateBase = new IndexBaseItem();
l.addLast(privateBase);
// looking at the PS that acrobat generates from a PDF with
// a CFF opentype font embedded with an identity-H encoding,
// it seems that it does not need a FontName.
//l.addLast(new DictNumberItem((standardStrings.length+(stringOffsets.length-1)+2)));
//l.addLast(new UInt8Item((char)12));
//l.addLast(new UInt8Item((char)38)); // FontName
l.addLast(new DictNumberItem(fonts[j].privateLength));
OffsetItem privateRef = new DictOffsetItem();
l.addLast(privateRef);
// Private
l.addLast(new UInt8Item((char)18));
l.addLast(new IndexMarkerItem(privateIndex1Ref,privateBase));
// copy the private index & local subroutines
l.addLast(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.addLast(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.addLast(getEntireIndexRange(fonts[j].privateSubrs));
}
}
// copy the charstring index
l.addLast(new MarkerItem(charstringsRef));
l.addLast(getEntireIndexRange(fonts[j].charstringsOffset));
// now create the new CFF font
int[] currentOffset = new int[1];
currentOffset[0] = 0;
for (Item item : l) {
item.increment(currentOffset);
}
for (Item item : l) {
item.xref();
}
int size = currentOffset[0];
byte[] b = new byte[size];
for (Item item : l) {
item.emit(b);
}
return b;
}
public boolean isCID() {
return isCID(getNames()[0]);
}
public boolean isCID(String fontName) {
int j;
for (j=0; j");
}
// string index
//strings = new String[stringOffsets.length-1];
/*
System.err.println("std strings = "+standardStrings.length);
System.err.println("fnt strings = "+(stringOffsets.length-1));
for (char j=0; j");
}
*/
// top dict
for (int j=0; j 0) {
// fonts[j].encodingOffset = encOffset;
// ReadEncoding(fonts[j].encodingOffset);
// }
// }
else if (key=="CharStrings") {
fonts[j].charstringsOffset = (int) ((Integer)args[0]).intValue();
//System.err.println("charstrings "+fonts[j].charstringsOffset);
// Added by Oren & Ygal
int p = getPosition();
fonts[j].charstringsOffsets = getIndex(fonts[j].charstringsOffset);
seek(p);
} else if (key=="FDArray")
fonts[j].fdarrayOffset = (int) ((Integer)args[0]).intValue();
else if (key=="FDSelect")
fonts[j].fdselectOffset = (int) ((Integer)args[0]).intValue();
else if (key=="CharstringType")
fonts[j].CharstringType = (int) ((Integer)args[0]).intValue();
}
// private dict
if (fonts[j].privateOffset >= 0) {
//System.err.println("PRIVATE::");
seek(fonts[j].privateOffset);
while (getPosition() < fonts[j].privateOffset+fonts[j].privateLength) {
getDictItem();
if (key=="Subrs")
//Add the private offset to the lsubrs since the offset is
// relative to the beginning of the PrivateDict
fonts[j].privateSubrs = (int) ((Integer)args[0]).intValue()+fonts[j].privateOffset;
}
}
// fdarray index
if (fonts[j].fdarrayOffset >= 0) {
int[] fdarrayOffsets = getIndex(fonts[j].fdarrayOffset);
fonts[j].fdprivateOffsets = new int[fdarrayOffsets.length-1];
fonts[j].fdprivateLengths = new int[fdarrayOffsets.length-1];
//System.err.println("FD Font::");
for (int k=0; k