1112 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			1112 lines
		
	
	
		
			47 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Text;
 | |
| using System.Collections;
 | |
| /*
 | |
|  *
 | |
|  * Copyright 2003 Sivan Toledo
 | |
|  *
 | |
|  * The contents of this file are subject to the Mozilla Public License Version 1.1
 | |
|  * (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.mozilla.org/MPL/
 | |
|  *
 | |
|  * Software distributed under the License is distributed on an "AS IS" basis,
 | |
|  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 | |
|  * for the specific language governing rights and limitations under the License.
 | |
|  *
 | |
|  * Contributor(s): all the names of the contributors are added in the source code
 | |
|  * where applicable.
 | |
|  *
 | |
|  * Alternatively, the contents of this file may be used under the terms of the
 | |
|  * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
 | |
|  * provisions of LGPL are applicable instead of those above.  If you wish to
 | |
|  * allow use of your version of this file only under the terms of the LGPL
 | |
|  * License and not to allow others to use your version of this file under
 | |
|  * the MPL, indicate your decision by deleting the provisions above and
 | |
|  * replace them with the notice and other provisions required by the LGPL.
 | |
|  * If you do not delete the provisions above, a recipient may use your version
 | |
|  * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
 | |
|  *
 | |
|  * This library is free software; you can redistribute it and/or modify it
 | |
|  * under the terms of the MPL as stated above or under the terms of the GNU
 | |
|  * Library General Public License as published by the Free Software Foundation;
 | |
|  * either version 2 of the License, or 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 Library general Public License for more
 | |
|  * details.
 | |
|  *
 | |
|  */
 | |
| 
 | |
| namespace iTextSharp.text.pdf {
 | |
|     public class CFFFont {
 | |
|         
 | |
|         internal static 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"
 | |
|         };
 | |
|         
 | |
|         internal static 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;
 | |
|             int p = GetPosition();
 | |
|             Seek(stringOffsets[j]);
 | |
|             StringBuilder s = new StringBuilder();
 | |
|             for (int k=stringOffsets[j]; k<stringOffsets[j+1]; k++) {
 | |
|                 s.Append(GetCard8());
 | |
|             }
 | |
|             Seek(p);
 | |
|             return s.ToString();
 | |
|         }
 | |
|         
 | |
|         internal char GetCard8() {
 | |
|             byte i = buf.ReadByte();
 | |
|             return (char)(i & 0xff);
 | |
|         }
 | |
|         
 | |
|         internal char GetCard16() {
 | |
|             return buf.ReadChar();
 | |
|         }
 | |
|         
 | |
|         internal int GetOffset(int offSize) {
 | |
|             int offset = 0;
 | |
|             for (int i=0; i<offSize; i++) {
 | |
|                 offset *= 256;
 | |
|                 offset += GetCard8();
 | |
|             }
 | |
|             return offset;
 | |
|         }
 | |
|         
 | |
|         internal void Seek(int offset) {
 | |
|             buf.Seek(offset);
 | |
|         }
 | |
|         
 | |
|         internal short GetShort() {
 | |
|             return buf.ReadShort();
 | |
|         }
 | |
|         
 | |
|         internal int GetInt() {
 | |
|             return buf.ReadInt();
 | |
|         }
 | |
|         
 | |
|         internal int GetPosition() {
 | |
|             return buf.FilePointer;
 | |
|         }
 | |
| 
 | |
|         internal int nextIndexOffset;
 | |
|         // read the offsets in the next index
 | |
|         // data structure, convert to global
 | |
|         // offsets, and return them.
 | |
|         // Sets the nextIndexOffset.
 | |
|         internal int[] GetIndex(int nextIndexOffset) {
 | |
|             int count, indexOffSize;
 | |
|             
 | |
|             Seek(nextIndexOffset);
 | |
|             count = GetCard16();
 | |
|             int[] offsets = new int[count+1];
 | |
|             
 | |
|             if (count==0) {
 | |
|                 offsets[0] = -1;
 | |
|                 nextIndexOffset += 2;
 | |
|                 return offsets;
 | |
|             }
 | |
|             
 | |
|             indexOffSize = GetCard8();
 | |
|             
 | |
|             for (int j=0; j<=count; j++) {
 | |
|                 //nextIndexOffset = ofset to relative segment
 | |
|                 offsets[j] = nextIndexOffset
 | |
|                 //2-> 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<arg_count; i++) args[i]=null;
 | |
|             arg_count = 0;
 | |
|             key = null;
 | |
|             bool gotKey = false;
 | |
|             
 | |
|             while (!gotKey) {
 | |
|                 char b0 = GetCard8();
 | |
|                 if (b0 == 29) {
 | |
|                     int item = GetInt();
 | |
|                     args[arg_count] = item;
 | |
|                     arg_count++;
 | |
|                     //System.err.Println(item+" ");
 | |
|                     continue;
 | |
|                 }
 | |
|                 if (b0 == 28) {
 | |
|                     short item = GetShort();
 | |
|                     args[arg_count] = (int)item;
 | |
|                     arg_count++;
 | |
|                     //System.err.Println(item+" ");
 | |
|                     continue;
 | |
|                 }
 | |
|                 if (b0 >= 32 && b0 <= 246) {
 | |
|                     sbyte item = (sbyte) ((int)b0-139);
 | |
|                     args[arg_count] = (int)item;
 | |
|                     arg_count++;
 | |
|                     //System.err.Println(item+" ");
 | |
|                     continue;
 | |
|                 }
 | |
|                 if (b0 >= 247 && b0 <= 250) {
 | |
|                     char b1 = GetCard8();
 | |
|                     short item = (short) (((int)b0-247)*256+(int)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) (-((int)b0-251)*256-(int)b1-108);
 | |
|                     args[arg_count] = (int)item;
 | |
|                     arg_count++;
 | |
|                     //System.err.Println(item+" ");
 | |
|                     continue;
 | |
|                 }
 | |
|                 if (b0 == 30) {
 | |
|                     String item = "";
 | |
|                     bool 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 += "." ; break;
 | |
|                             case 0xb: item += "E" ; break;
 | |
|                             case 0xc: item += "E-"; break;
 | |
|                             case 0xe: item += "-" ; break;
 | |
|                             case 0xf: done=true   ; break;
 | |
|                             default:
 | |
|                                 if (nibble >= 0 && nibble <= 9)
 | |
|                                     item += nibble.ToString();
 | |
|                                 else {
 | |
|                                     item += "<NIBBLE ERROR: "+nibble.ToString()+">";
 | |
|                                     done = true;
 | |
|                                 }
 | |
|                                 break;
 | |
|                         }
 | |
|                     }
 | |
|                     args[arg_count] = item;
 | |
|                     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<arg_count; i++)
 | |
|                     //  System.err.Print(args[i].ToString()+" ");
 | |
|                     //System.err.Println(key+" ;");
 | |
|                     continue;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         /** List items for the linked list that builds the new CID font.
 | |
|         */
 | |
|         
 | |
|         protected internal abstract class Item {
 | |
|             protected internal int myOffset = -1;
 | |
|             /** remember the current offset and increment by item's size in bytes. */
 | |
|             public virtual void Increment(int[] currentOffset) {
 | |
|                 myOffset = currentOffset[0];
 | |
|             }
 | |
|             /** Emit the byte stream for this item. */
 | |
|             public virtual void Emit(byte[] buffer) {}
 | |
|             /** Fix up cross references to this item (applies only to markers). */
 | |
|             public virtual void Xref() {}
 | |
|         }
 | |
|         
 | |
|         protected internal abstract class OffsetItem : Item {
 | |
|             public int value;
 | |
|             /** set the value of an offset item that was initially unknown.
 | |
|             * It will be fixed up latex by a call to xref on some marker.
 | |
|             */
 | |
|             public void Set(int offset) { this.value = offset; }
 | |
|         }
 | |
|         
 | |
|         
 | |
|         /** A range item.
 | |
|         */
 | |
|         
 | |
|         protected internal class RangeItem : Item {
 | |
|             public int offset, length;
 | |
|             private RandomAccessFileOrArray buf;
 | |
|             public RangeItem(RandomAccessFileOrArray buf, int offset, int length) {
 | |
|                 this.offset = offset;
 | |
|                 this.length = length;
 | |
|                 this.buf = buf;
 | |
|             }
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += length;
 | |
|             }
 | |
|             public override void Emit(byte[] buffer) {
 | |
|                 //System.err.Println("range emit offset "+offset+" size="+length);
 | |
|                 buf.Seek(offset);
 | |
|                 for (int i=myOffset; i<myOffset+length; i++)
 | |
|                     buffer[i] = buf.ReadByte();
 | |
|                 //System.err.Println("finished range emit");
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         /** An index-offset item for the list.
 | |
|         * The size denotes the required size in the CFF. A positive
 | |
|         * value means that we need a specific size in bytes (for offset arrays)
 | |
|         * and a negative value means that this is a dict item that uses a
 | |
|         * variable-size representation.
 | |
|         */
 | |
|         protected internal class IndexOffsetItem : OffsetItem {
 | |
|             public int size;
 | |
|             public IndexOffsetItem(int size, int value) {this.size=size; this.value=value;}
 | |
|             public IndexOffsetItem(int size) {this.size=size; }
 | |
|             
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += size;
 | |
|             }
 | |
|             public override void Emit(byte[] buffer) {
 | |
|                 int i=0;
 | |
|                 switch (size) {
 | |
|                     case 4:
 | |
|                         buffer[myOffset+i] = (byte) ((value >> 24) & 0xff);
 | |
|                         i++;
 | |
|                         goto case 3;
 | |
|                     case 3:
 | |
|                         buffer[myOffset+i] = (byte) ((value >> 16) & 0xff);
 | |
|                         i++;
 | |
|                         goto case 2;
 | |
|                     case 2:
 | |
|                         buffer[myOffset+i] = (byte) ((value >>  8) & 0xff);
 | |
|                         i++;
 | |
|                         goto case 1;
 | |
|                     case 1:
 | |
|                         buffer[myOffset+i] = (byte) ((value >>  0) & 0xff);
 | |
|                         i++;
 | |
|                         break;
 | |
|                 }
 | |
|                 /*
 | |
|                 int mask = 0xff;
 | |
|                 for (int i=size-1; i>=0; i--) {
 | |
|                     buffer[myOffset+i] = (byte) (value & mask);
 | |
|                     mask <<= 8;
 | |
|                 }
 | |
|                 */
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         protected internal class IndexBaseItem : Item {
 | |
|             public IndexBaseItem() {}
 | |
|         }
 | |
|         
 | |
|         protected internal class IndexMarkerItem : Item {
 | |
|             private OffsetItem offItem;
 | |
|             private IndexBaseItem indexBase;
 | |
|             public IndexMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
 | |
|                 this.offItem   = offItem;
 | |
|                 this.indexBase = indexBase;
 | |
|             }
 | |
|             public override void Xref() {
 | |
|                 //System.err.Println("index marker item, base="+indexBase.myOffset+" my="+this.myOffset);
 | |
|                 offItem.Set(this.myOffset-indexBase.myOffset+1);
 | |
|             }
 | |
|         }
 | |
|         /**
 | |
|         * 
 | |
|         * @author orly manor
 | |
|         *
 | |
|         * TODO To change the template for this generated type comment go to
 | |
|         * Window - Preferences - Java - Code Generation - Code and Comments
 | |
|         */
 | |
|         protected internal class SubrMarkerItem : Item {
 | |
|             private OffsetItem offItem;
 | |
|             private IndexBaseItem indexBase;
 | |
|             public SubrMarkerItem(OffsetItem offItem, IndexBaseItem indexBase) {
 | |
|                 this.offItem   = offItem;
 | |
|                 this.indexBase = indexBase;
 | |
|             }
 | |
|             public override 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 internal class DictOffsetItem : OffsetItem {
 | |
|             public int size;
 | |
|             public DictOffsetItem() {this.size=5; }
 | |
|             
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += size;
 | |
|             }
 | |
|             // this is incomplete!
 | |
|             public override 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 internal class UInt24Item : Item {
 | |
|             public int value;
 | |
|             public UInt24Item(int value) {this.value=value;}
 | |
|             
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += 3;
 | |
|             }
 | |
|             // this is incomplete!
 | |
|             public override 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 internal class UInt32Item : Item {
 | |
|             public int value;
 | |
|             public UInt32Item(int value) {this.value=value;}
 | |
|             
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += 4;
 | |
|             }
 | |
|             // this is incomplete!
 | |
|             public override 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 internal class UInt16Item : Item {
 | |
|             public char value;
 | |
|             public UInt16Item(char value) {this.value=value;}
 | |
|             
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += 2;
 | |
|             }
 | |
|             // this is incomplete!
 | |
|             public override void Emit(byte[] buffer) {
 | |
|                 buffer[myOffset+0] = (byte) ((value >> 8) & 0xff);
 | |
|                 buffer[myOffset+1] = (byte) ((value >> 0) & 0xff);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         /** A Card8 item.
 | |
|         */
 | |
|         
 | |
|         protected internal class UInt8Item : Item {
 | |
|             public char value;
 | |
|             public UInt8Item(char value) {this.value=value;}
 | |
|             
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += 1;
 | |
|             }
 | |
|             // this is incomplete!
 | |
|             public override void Emit(byte[] buffer) {
 | |
|                 buffer[myOffset+0] = (byte) ((value >> 0) & 0xff);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         protected internal class StringItem : Item {
 | |
|             public String s;
 | |
|             public StringItem(String s) {this.s=s;}
 | |
|             
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += s.Length;
 | |
|             }
 | |
|             public override void Emit(byte[] buffer) {
 | |
|                 for (int i=0; i<s.Length; i++)
 | |
|                     buffer[myOffset+i] = (byte) (s[i] & 0xff);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         
 | |
|         /** A dictionary number on the list.
 | |
|         * This implementation is inefficient: it doesn't use the variable-length
 | |
|         * representation.
 | |
|         */
 | |
|         
 | |
|         protected internal class DictNumberItem : Item {
 | |
|             public int value;
 | |
|             public int size = 5;
 | |
|             public DictNumberItem(int value) {this.value=value;}
 | |
|             public override void Increment(int[] currentOffset) {
 | |
|                 base.Increment(currentOffset);
 | |
|                 currentOffset[0] += size;
 | |
|             }
 | |
|             // this is imcomplete!
 | |
|             public override 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.
 | |
|         */
 | |
|         
 | |
|         protected internal class MarkerItem : Item {
 | |
|             OffsetItem p;
 | |
|             public MarkerItem(OffsetItem pointerToMarker) {p=pointerToMarker;}
 | |
|             public override 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 virtual 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;
 | |
|             
 | |
|             ArrayList l = new ArrayList();
 | |
|             
 | |
|             // 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
 | |
|                 for (int i=0; i<stringOffsets.Length; i++)
 | |
|                     l.Add(new IndexOffsetItem(stringsIndexOffSize,
 | |
|                     stringOffsets[i]-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;
 | |
|         }
 | |
|         
 | |
|         
 | |
|         public bool IsCID(String fontName) {
 | |
|             int j;
 | |
|             for (j=0; j<fonts.Length; j++)
 | |
|                 if (fontName.Equals(fonts[j].name)) return fonts[j].isCID;
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         public bool Exists(String fontName) {
 | |
|             int j;
 | |
|             for (j=0; j<fonts.Length; j++)
 | |
|                 if (fontName.Equals(fonts[j].name)) return true;
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         
 | |
|         public String[] GetNames() {
 | |
|             String[] names = new String[ fonts.Length ];
 | |
|             for (int i=0; i<fonts.Length; i++)
 | |
|                 names[i] = fonts[i].name;
 | |
|             return names;
 | |
|         }
 | |
|         /**
 | |
|         * A random Access File or an array
 | |
|         * (contributed by orly manor)
 | |
|         */
 | |
|         protected RandomAccessFileOrArray buf;
 | |
|         private int offSize;
 | |
|         
 | |
|         protected int nameIndexOffset;
 | |
|         protected int topdictIndexOffset;
 | |
|         protected int stringIndexOffset;
 | |
|         protected int gsubrIndexOffset;
 | |
|         protected int[] nameOffsets;
 | |
|         protected int[] topdictOffsets;
 | |
|         protected int[] stringOffsets;
 | |
|         protected int[] gsubrOffsets;
 | |
|         
 | |
|         /**
 | |
|         * @author orly manor
 | |
|         * TODO Changed from private to protected by Ygal&Oren
 | |
|         */
 | |
|         protected internal class Font {
 | |
|             public String    name;
 | |
|             public String    fullName;
 | |
|             public bool   isCID = false;
 | |
|             public int       privateOffset     = -1; // only if not CID
 | |
|             public int       privateLength     = -1; // only if not CID
 | |
|             public int       privateSubrs      = -1;
 | |
|             public int       charstringsOffset = -1;
 | |
|             public int       encodingOffset    = -1;
 | |
|             public int       charsetOffset     = -1;
 | |
|             public int       fdarrayOffset     = -1; // only if CID
 | |
|             public int       fdselectOffset    = -1; // only if CID
 | |
|             public int[]     fdprivateOffsets;
 | |
|             public int[]     fdprivateLengths;
 | |
|             public int[]     fdprivateSubrs;
 | |
|             
 | |
|             // Added by Oren & Ygal
 | |
|             public int nglyphs;
 | |
|             public int nstrings;
 | |
|             public int CharsetLength;
 | |
|             public int[]    charstringsOffsets;
 | |
|             public int[]    charset;
 | |
|             public int[]     FDSelect;
 | |
|             public int FDSelectLength;
 | |
|             public int FDSelectFormat;
 | |
|             public int         CharstringType = 2;
 | |
|             public int FDArrayCount;
 | |
|             public int FDArrayOffsize;
 | |
|             public int[] FDArrayOffsets;
 | |
|             public int[] PrivateSubrsOffset;
 | |
|             public int[][] PrivateSubrsOffsetsArray;
 | |
|             public int[]       SubrsOffsets;
 | |
|         }
 | |
|         // Changed from private to protected by Ygal&Oren
 | |
|         protected Font[] fonts;
 | |
|         
 | |
|         public CFFFont(RandomAccessFileOrArray inputbuffer) {
 | |
|             
 | |
|             //System.err.Println("CFF: nStdString = "+standardStrings.length);
 | |
|             buf = inputbuffer;
 | |
|             Seek(0);
 | |
|             
 | |
|             int major, minor;
 | |
|             major = GetCard8();
 | |
|             minor = GetCard8();
 | |
|             
 | |
|             //System.err.Println("CFF Major-Minor = "+major+"-"+minor);
 | |
|             
 | |
|             int hdrSize = GetCard8();
 | |
|             
 | |
|             offSize = GetCard8();
 | |
|             
 | |
|             //System.err.Println("offSize = "+offSize);
 | |
|             
 | |
|             //int count, indexOffSize, indexOffset, nextOffset;
 | |
|             
 | |
|             nameIndexOffset    = hdrSize;
 | |
|             nameOffsets        = GetIndex(nameIndexOffset);
 | |
|             topdictIndexOffset = nameOffsets[nameOffsets.Length-1];
 | |
|             topdictOffsets     = GetIndex(topdictIndexOffset);
 | |
|             stringIndexOffset  = topdictOffsets[topdictOffsets.Length-1];
 | |
|             stringOffsets      = GetIndex(stringIndexOffset);
 | |
|             gsubrIndexOffset   = stringOffsets[stringOffsets.Length-1];
 | |
|             gsubrOffsets       = GetIndex(gsubrIndexOffset);
 | |
|             
 | |
|             fonts = new Font[nameOffsets.Length-1];
 | |
|             
 | |
|             // now get the name index
 | |
|             
 | |
|             /*
 | |
|             names             = new String[nfonts];
 | |
|             privateOffset     = new int[nfonts];
 | |
|             charsetOffset     = new int[nfonts];
 | |
|             encodingOffset    = new int[nfonts];
 | |
|             charstringsOffset = new int[nfonts];
 | |
|             fdarrayOffset     = new int[nfonts];
 | |
|             fdselectOffset    = new int[nfonts];
 | |
|             */
 | |
|             
 | |
|             for (int j=0; j<nameOffsets.Length-1; j++) {
 | |
|                 fonts[j] = new Font();
 | |
|                 Seek(nameOffsets[j]);
 | |
|                 fonts[j].name = "";
 | |
|                 for (int k=nameOffsets[j]; k<nameOffsets[j+1]; k++) {
 | |
|                     fonts[j].name += (char)GetCard8();
 | |
|                 }
 | |
|                 //System.err.Println("name["+j+"]=<"+fonts[j].name+">");
 | |
|             }
 | |
|             
 | |
|             // 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<standardStrings.length+(stringOffsets.length-1); j++) {
 | |
|                 //Seek(stringOffsets[j]);
 | |
|                 //strings[j] = "";
 | |
|                 //for (int k=stringOffsets[j]; k<stringOffsets[j+1]; k++) {
 | |
|                 //    strings[j] += (char)getCard8();
 | |
|                 //}
 | |
|                 System.err.Println("j="+(int)j+" <? "+(standardStrings.length+(stringOffsets.length-1)));
 | |
|                 System.err.Println("strings["+(int)j+"]=<"+getString(j)+">");
 | |
|             }
 | |
|             */
 | |
|             
 | |
|             // top dict
 | |
|             
 | |
|             for (int j=0; j<topdictOffsets.Length-1; j++) {
 | |
|                 Seek(topdictOffsets[j]);
 | |
|                 while (GetPosition() < topdictOffsets[j+1]) {                
 | |
|                     GetDictItem();
 | |
|                     if (key=="FullName") {
 | |
|                         //System.err.Println("getting fullname sid = "+((Integer)args[0]).IntValue);
 | |
|                         fonts[j].fullName = GetString((char)((int)args[0]));
 | |
|                         //System.err.Println("got it");
 | |
|                     } else if (key=="ROS")
 | |
|                         fonts[j].isCID = true;
 | |
|                     else if (key=="Private") {
 | |
|                         fonts[j].privateLength  = (int)args[0];
 | |
|                         fonts[j].privateOffset  = (int)args[1];
 | |
|                     }
 | |
|                     else if (key=="charset"){
 | |
|                         fonts[j].charsetOffset = (int)args[0];
 | |
|                         
 | |
|                     }
 | |
|                     else if (key=="Encoding"){
 | |
|                         fonts[j].encodingOffset = (int)args[0];
 | |
|                         ReadEncoding(fonts[j].encodingOffset);
 | |
|                     }
 | |
|                     else if (key=="CharStrings") {
 | |
|                         fonts[j].charstringsOffset = (int)args[0];
 | |
|                         //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)args[0];
 | |
|                     else if (key=="FDSelect")
 | |
|                         fonts[j].fdselectOffset = (int)args[0];
 | |
|                     else if (key=="CharstringType")
 | |
|                         fonts[j].CharstringType = (int)args[0];
 | |
|                 }
 | |
|                 
 | |
|                 // 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 begining of the PrivateDict
 | |
|                             fonts[j].privateSubrs = (int)args[0]+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<fdarrayOffsets.Length-1; k++) {
 | |
|                         Seek(fdarrayOffsets[k]);
 | |
|                         while (GetPosition() < fdarrayOffsets[k+1])
 | |
|                             GetDictItem();
 | |
|                         if (key=="Private") {
 | |
|                             fonts[j].fdprivateLengths[k]  = (int)args[0];
 | |
|                             fonts[j].fdprivateOffsets[k]  = (int)args[1];
 | |
|                         }
 | |
|                         
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             //System.err.Println("CFF: done");
 | |
|         }
 | |
|         
 | |
|         // ADDED BY Oren & Ygal
 | |
|         
 | |
|         internal void ReadEncoding(int nextIndexOffset){
 | |
|             int format;
 | |
|             Seek(nextIndexOffset);
 | |
|             format = GetCard8();
 | |
|         }    
 | |
|     }
 | |
| }
 |