Package org.jpedal.fonts

Source Code of org.jpedal.fonts.Type1C

/**
* ===========================================
* Java Pdf Extraction Decoding Access Library
* ===========================================
*
* Project Info:  http://www.jpedal.org
* (C) Copyright 1997-2008, IDRsolutions and Contributors.
*
*   This file is part of JPedal
*
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


*
* ---------------
* Type1C.java
* ---------------
*/
package org.jpedal.fonts;

import java.io.*;
import java.util.Map;
import java.awt.*;

import org.jpedal.fonts.glyph.T1Glyphs;
import org.jpedal.fonts.glyph.PdfJavaGlyphs;
import org.jpedal.fonts.objects.FontData;

import org.jpedal.io.PdfObjectReader;
import org.jpedal.io.ObjectStore;

import org.jpedal.utils.LogWriter;
import org.jpedal.objects.raw.PdfObject;
import org.jpedal.objects.raw.PdfDictionary;


/**
* handlestype1 specifics
*/
public class Type1C extends Type1{

  static final boolean  debugFont=false;
 
  static final boolean debugDictionary=false;
 
  int ROS=-1,CIDFontVersion=0,CIDFontRevision=0,CIDFontType=0,CIDcount=0,UIDBase=-1,FDArray=-1,FDSelect=-1;
 
  final static String[] OneByteCCFDict={"version","Notice","FullName","FamilyName","Weight",
      "FontBBox","BlueValues","OtherBlues","FamilyBlues","FamilyOtherBlues",
      "StdHW","StdVW","Escape","UniqueID","XUID",
      "charset","Encoding","CharStrings","Private", "Subrs",
      "defaultWidthX","nominalWidthX","-reserved-","-reserved-","-reserved-",
      "-reserved-","-reserved-","-reserved-","shortint","longint",
      "BCD","-reserved-"};
 
  final static String[] TwoByteCCFDict={"Copyright","isFixedPitch","ItalicAngle","UnderlinePosition","UnderlineThickness",
      "PaintType","CharstringType","FontMatrix","StrokeWidth","BlueScale",
      "BlueShift","BlueFuzz","StemSnapH","StemSnapV","ForceBold",
      "-reserved-","-reserved-","LanguageGroup","ExpansionFactor","initialRandomSeed",
      "SyntheticBase","PostScript","BaseFontName","BaseFontBlend","-reserved-",
      "-reserved-","-reserved-","-reserved-","-reserved-","-reserved-",
      "ROS","CIDFontVersion","CIDFontRevision","CIDFontType","CIDCount",
      "UIDBase","FDArray","FDSelect","FontName"};

  //current location in file
  private int top = 0;

  private int charset = 0;

  private int enc = 0;

  private int charstrings = 0;
 
  private int stringIdx;

  private int stringStart;

  private int stringOffSize;

    private Rectangle BBox=null;
   
 
  private boolean hasFontMatrix=false;// hasFontBBox=false,;

  private int privateDict = -1,privateDictOffset=-1;

    private int defaultWidthX = 0, nominalWidthX = 0;

  /** decoding table for Expert */
  private static final int ExpertSubCharset[] = { // 87
                                            // elements
    0,
      1,
      231,
      232,
      235,
      236,
      237,
      238,
      13,
      14,
      15,
      99,
      239,
      240,
      241,
      242,
      243,
      244,
      245,
      246,
      247,
      248,
      27,
      28,
      249,
      250,
      251,
      253,
      254,
      255,
      256,
      257,
      258,
      259,
      260,
      261,
      262,
      263,
      264,
      265,
      266,
      109,
      110,
      267,
      268,
      269,
      270,
      272,
      300,
      301,
      302,
      305,
      314,
      315,
      158,
      155,
      163,
      320,
      321,
      322,
      323,
      324,
      325,
      326,
      150,
      164,
      169,
      327,
      328,
      329,
      330,
      331,
      332,
      333,
      334,
      335,
      336,
      337,
      338,
      339,
      340,
      341,
      342,
      343,
      344,
      345,
      346 };


  /** lookup table for names for type 1C glyphs */
  public static final String type1CStdStrings[] = { // 391
                                             // elements
    ".notdef",
      "space",
      "exclam",
      "quotedbl",
      "numbersign",
      "dollar",
      "percent",
      "ampersand",
      "quoteright",
      "parenleft",
      "parenright",
      "asterisk",
      "plus",
      "comma",
      "hyphen",
      "period",
      "slash",
      "zero",
      "one",
      "two",
      "three",
      "four",
      "five",
      "six",
      "seven",
      "eight",
      "nine",
      "colon",
      "semicolon",
      "less",
      "equal",
      "greater",
      "question",
      "at",
      "A",
      "B",
      "C",
      "D",
      "E",
      "F",
      "G",
      "H",
      "I",
      "J",
      "K",
      "L",
      "M",
      "N",
      "O",
      "P",
      "Q",
      "R",
      "S",
      "T",
      "U",
      "V",
      "W",
      "X",
      "Y",
      "Z",
      "bracketleft",
      "backslash",
      "bracketright",
      "asciicircum",
      "underscore",
      "quoteleft",
      "a",
      "b",
      "c",
      "d",
      "e",
      "f",
      "g",
      "h",
      "i",
      "j",
      "k",
      "l",
      "m",
      "n",
      "o",
      "p",
      "q",
      "r",
      "s",
      "t",
      "u",
      "v",
      "w",
      "x",
      "y",
      "z",
      "braceleft",
      "bar",
      "braceright",
      "asciitilde",
      "exclamdown",
      "cent",
      "sterling",
      "fraction",
      "yen",
      "florin",
      "section",
      "currency",
      "quotesingle",
      "quotedblleft",
      "guillemotleft",
      "guilsinglleft",
      "guilsinglright",
      "fi",
      "fl",
      "endash",
      "dagger",
      "daggerdbl",
      "periodcentered",
      "paragraph",
      "bullet",
      "quotesinglbase",
      "quotedblbase",
      "quotedblright",
      "guillemotright",
      "ellipsis",
      "perthousand",
      "questiondown",
      "grave",
      "acute",
      "circumflex",
      "tilde",
      "macron",
      "breve",
      "dotaccent",
      "dieresis",
      "ring",
      "cedilla",
      "hungarumlaut",
      "ogonek",
      "caron",
      "emdash",
      "AE",
      "ordfeminine",
      "Lslash",
      "Oslash",
      "OE",
      "ordmasculine",
      "ae",
      "dotlessi",
      "lslash",
      "oslash",
      "oe",
      "germandbls",
      "onesuperior",
      "logicalnot",
      "mu",
      "trademark",
      "Eth",
      "onehalf",
      "plusminus",
      "Thorn",
      "onequarter",
      "divide",
      "brokenbar",
      "degree",
      "thorn",
      "threequarters",
      "twosuperior",
      "registered",
      "minus",
      "eth",
      "multiply",
      "threesuperior",
      "copyright",
      "Aacute",
      "Acircumflex",
      "Adieresis",
      "Agrave",
      "Aring",
      "Atilde",
      "Ccedilla",
      "Eacute",
      "Ecircumflex",
      "Edieresis",
      "Egrave",
      "Iacute",
      "Icircumflex",
      "Idieresis",
      "Igrave",
      "Ntilde",
      "Oacute",
      "Ocircumflex",
      "Odieresis",
      "Ograve",
      "Otilde",
      "Scaron",
      "Uacute",
      "Ucircumflex",
      "Udieresis",
      "Ugrave",
      "Yacute",
      "Ydieresis",
      "Zcaron",
      "aacute",
      "acircumflex",
      "adieresis",
      "agrave",
      "aring",
      "atilde",
      "ccedilla",
      "eacute",
      "ecircumflex",
      "edieresis",
      "egrave",
      "iacute",
      "icircumflex",
      "idieresis",
      "igrave",
      "ntilde",
      "oacute",
      "ocircumflex",
      "odieresis",
      "ograve",
      "otilde",
      "scaron",
      "uacute",
      "ucircumflex",
      "udieresis",
      "ugrave",
      "yacute",
      "ydieresis",
      "zcaron",
      "exclamsmall",
      "Hungarumlautsmall",
      "dollaroldstyle",
      "dollarsuperior",
      "ampersandsmall",
      "Acutesmall",
      "parenleftsuperior",
      "parenrightsuperior",
      "twodotenleader",
      "onedotenleader",
      "zerooldstyle",
      "oneoldstyle",
      "twooldstyle",
      "threeoldstyle",
      "fouroldstyle",
      "fiveoldstyle",
      "sixoldstyle",
      "sevenoldstyle",
      "eightoldstyle",
      "nineoldstyle",
      "commasuperior",
      "threequartersemdash",
      "periodsuperior",
      "questionsmall",
      "asuperior",
      "bsuperior",
      "centsuperior",
      "dsuperior",
      "esuperior",
      "isuperior",
      "lsuperior",
      "msuperior",
      "nsuperior",
      "osuperior",
      "rsuperior",
      "ssuperior",
      "tsuperior",
      "ff",
      "ffi",
      "ffl",
      "parenleftinferior",
      "parenrightinferior",
      "Circumflexsmall",
      "hyphensuperior",
      "Gravesmall",
      "Asmall",
      "Bsmall",
      "Csmall",
      "Dsmall",
      "Esmall",
      "Fsmall",
      "Gsmall",
      "Hsmall",
      "Ismall",
      "Jsmall",
      "Ksmall",
      "Lsmall",
      "Msmall",
      "Nsmall",
      "Osmall",
      "Psmall",
      "Qsmall",
      "Rsmall",
      "Ssmall",
      "Tsmall",
      "Usmall",
      "Vsmall",
      "Wsmall",
      "Xsmall",
      "Ysmall",
      "Zsmall",
      "colonmonetary",
      "onefitted",
      "rupiah",
      "Tildesmall",
      "exclamdownsmall",
      "centoldstyle",
      "Lslashsmall",
      "Scaronsmall",
      "Zcaronsmall",
      "Dieresissmall",
      "Brevesmall",
      "Caronsmall",
      "Dotaccentsmall",
      "Macronsmall",
      "figuredash",
      "hypheninferior",
      "Ogoneksmall",
      "Ringsmall",
      "Cedillasmall",
      "questiondownsmall",
      "oneeighth",
      "threeeighths",
      "fiveeighths",
      "seveneighths",
      "onethird",
      "twothirds",
      "zerosuperior",
      "foursuperior",
      "fivesuperior",
      "sixsuperior",
      "sevensuperior",
      "eightsuperior",
      "ninesuperior",
      "zeroinferior",
      "oneinferior",
      "twoinferior",
      "threeinferior",
      "fourinferior",
      "fiveinferior",
      "sixinferior",
      "seveninferior",
      "eightinferior",
      "nineinferior",
      "centinferior",
      "dollarinferior",
      "periodinferior",
      "commainferior",
      "Agravesmall",
      "Aacutesmall",
      "Acircumflexsmall",
      "Atildesmall",
      "Adieresissmall",
      "Aringsmall",
      "AEsmall",
      "Ccedillasmall",
      "Egravesmall",
      "Eacutesmall",
      "Ecircumflexsmall",
      "Edieresissmall",
      "Igravesmall",
      "Iacutesmall",
      "Icircumflexsmall",
      "Idieresissmall",
      "Ethsmall",
      "Ntildesmall",
      "Ogravesmall",
      "Oacutesmall",
      "Ocircumflexsmall",
      "Otildesmall",
      "Odieresissmall",
      "OEsmall",
      "Oslashsmall",
      "Ugravesmall",
      "Uacutesmall",
      "Ucircumflexsmall",
      "Udieresissmall",
      "Yacutesmall",
      "Thornsmall",
      "Ydieresissmall",
      "001.000",
      "001.001",
      "001.002",
      "001.003",
      "Black",
      "Bold",
      "Book",
      "Light",
      "Medium",
      "Regular",
      "Roman",
      "Semibold" };

  /** Lookup table to map values */
  private static final int ISOAdobeCharset[] = { // 229
                                            // elements
    0,
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
      9,
      10,
      11,
      12,
      13,
      14,
      15,
      16,
      17,
      18,
      19,
      20,
      21,
      22,
      23,
      24,
      25,
      26,
      27,
      28,
      29,
      30,
      31,
      32,
      33,
      34,
      35,
      36,
      37,
      38,
      39,
      40,
      41,
      42,
      43,
      44,
      45,
      46,
      47,
      48,
      49,
      50,
      51,
      52,
      53,
      54,
      55,
      56,
      57,
      58,
      59,
      60,
      61,
      62,
      63,
      64,
      65,
      66,
      67,
      68,
      69,
      70,
      71,
      72,
      73,
      74,
      75,
      76,
      77,
      78,
      79,
      80,
      81,
      82,
      83,
      84,
      85,
      86,
      87,
      88,
      89,
      90,
      91,
      92,
      93,
      94,
      95,
      96,
      97,
      98,
      99,
      100,
      101,
      102,
      103,
      104,
      105,
      106,
      107,
      108,
      109,
      110,
      111,
      112,
      113,
      114,
      115,
      116,
      117,
      118,
      119,
      120,
      121,
      122,
      123,
      124,
      125,
      126,
      127,
      128,
      129,
      130,
      131,
      132,
      133,
      134,
      135,
      136,
      137,
      138,
      139,
      140,
      141,
      142,
      143,
      144,
      145,
      146,
      147,
      148,
      149,
      150,
      151,
      152,
      153,
      154,
      155,
      156,
      157,
      158,
      159,
      160,
      161,
      162,
      163,
      164,
      165,
      166,
      167,
      168,
      169,
      170,
      171,
      172,
      173,
      174,
      175,
      176,
      177,
      178,
      179,
      180,
      181,
      182,
      183,
      184,
      185,
      186,
      187,
      188,
      189,
      190,
      191,
      192,
      193,
      194,
      195,
      196,
      197,
      198,
      199,
      200,
      201,
      202,
      203,
      204,
      205,
      206,
      207,
      208,
      209,
      210,
      211,
      212,
      213,
      214,
      215,
      216,
      217,
      218,
      219,
      220,
      221,
      222,
      223,
      224,
      225,
      226,
      227,
      228 };
  /** lookup data to convert Expert values */
  private static final int ExpertCharset[] = { // 166
                                        // elements
    0,
      1,
      229,
      230,
      231,
      232,
      233,
      234,
      235,
      236,
      237,
      238,
      13,
      14,
      15,
      99,
      239,
      240,
      241,
      242,
      243,
      244,
      245,
      246,
      247,
      248,
      27,
      28,
      249,
      250,
      251,
      252,
      253,
      254,
      255,
      256,
      257,
      258,
      259,
      260,
      261,
      262,
      263,
      264,
      265,
      266,
      109,
      110,
      267,
      268,
      269,
      270,
      271,
      272,
      273,
      274,
      275,
      276,
      277,
      278,
      279,
      280,
      281,
      282,
      283,
      284,
      285,
      286,
      287,
      288,
      289,
      290,
      291,
      292,
      293,
      294,
      295,
      296,
      297,
      298,
      299,
      300,
      301,
      302,
      303,
      304,
      305,
      306,
      307,
      308,
      309,
      310,
      311,
      312,
      313,
      314,
      315,
      316,
      317,
      318,
      158,
      155,
      163,
      319,
      320,
      321,
      322,
      323,
      324,
      325,
      326,
      150,
      164,
      169,
      327,
      328,
      329,
      330,
      331,
      332,
      333,
      334,
      335,
      336,
      337,
      338,
      339,
      340,
      341,
      342,
      343,
      344,
      345,
      346,
      347,
      348,
      349,
      350,
      351,
      352,
      353,
      354,
      355,
      356,
      357,
      358,
      359,
      360,
      361,
      362,
      363,
      364,
      365,
      366,
      367,
      368,
      369,
      370,
      371,
      372,
      373,
      374,
      375,
      376,
      377,
      378 };


    /** needed so CIDFOnt0 can extend */
    public Type1C() {}


       
        /** get handles onto Reader so we can access the file */
    public Type1C(PdfObjectReader current_pdf_file,String substituteFont) {

        glyphs=new T1Glyphs(false);

        init(current_pdf_file);

        this.substituteFont=substituteFont;
    }


        /** read details of any embedded fontFile */
    protected void readEmbeddedFont(PdfObject pdfFontDescriptor) throws Exception {
   
      if(substituteFont!=null){

        byte[] bytes ;

        //read details
        BufferedInputStream from;
        //create streams
        ByteArrayOutputStream to = new ByteArrayOutputStream();

        InputStream jarFile = null;

                try{
                    if(substituteFont.startsWith("jar:")|| substituteFont.startsWith("http:"))
                        jarFile = loader.getResourceAsStream(substituteFont);
                    else
                        jarFile = loader.getResourceAsStream("file:///"+substituteFont);

                }catch(Exception e){
                  if(LogWriter.isOutput())
                    LogWriter.writeLog("3.Unable to open "+substituteFont);
                }catch(Error err){
                  if(LogWriter.isOutput())
                    LogWriter.writeLog("3.Unable to open "+substituteFont);
                }

        if(jarFile==null){
          /**
                  from=new BufferedInputStream(new FileInputStream(substituteFont));

                  //write
                    byte[] buffer = new byte[65535];
                    int bytes_read;
                    while ((bytes_read = from.read(buffer)) != -1)
                        to.write(buffer, 0, bytes_read);

                    to.close();
                    from.close();

                    /**/

          File file=new File(substituteFont);
          InputStream is = new FileInputStream(file);
          long length = file.length();
               
          if (length > Integer.MAX_VALUE) {
            System.out.println("Sorry! Your given file is too large.");
            return;
          }
         
                    bytes = new byte[(int)length];
                    int offset = 0;
                    int numRead  ;
                    while (offset < bytes.length && (numRead=is.read(bytes,
                                offset, bytes.length-offset)) >= 0) {
                        offset += numRead;
                    }
                    if (offset < bytes.length) {
                        throw new IOException("Could not completely read file "
                                            + file.getName());
                    }
                    is.close();
          // new BufferedReader
                      //              (new InputStreamReader(loader.getResourceAsStream("org/jpedal/res/cid/" + encodingName), "Cp1252"));
          /**
                    FileReader from2=null;
                    try {
                        from2 = new FileReader(substituteFont);
                                    //new BufferedReader);
                        //outputStream = new FileWriter("characteroutput.txt");

                        int c;
                        while ((c = from2.read()) != -1) {
                            to.write(c);
                        }
                    } finally {
                        if (from2 != null) {
                            from2.close();
                        }
                        if (to != null) {
                            to.close();
                        }
                    }/**/
        }else{
          from= new BufferedInputStream(jarFile);

          //write
          byte[] buffer = new byte[65535];
          int bytes_read;
          while ((bytes_read = from.read(buffer)) != -1)
            to.write(buffer, 0, bytes_read);

          to.close();
          from.close();

          bytes=to.toByteArray();
        }
        /**load the font*/
        try{
          isFontSubstituted=true;
         
          //if (substituteFont.indexOf(".afm") != -1)
          readType1FontFile(bytes);
          //else
          //  readType1CFontFile(to.toByteArray(),null);

         

        } catch (Exception e) {

          e.printStackTrace();
         
          if(LogWriter.isOutput())
            LogWriter.writeLog("[PDF]Substitute font="+substituteFont+"Type 1 exception=" + e);
        }

        //over-ride font remapping if substituted
        if(isFontSubstituted && glyphs.remapFont)
          glyphs.remapFont=false;

      }else if(pdfFontDescriptor!=null){
   
        PdfObject FontFile=pdfFontDescriptor.getDictionary(PdfDictionary.FontFile);
   
        /** try type 1 first then type 1c/0c */
        if (FontFile != null) {
          try {
            byte[] stream=currentPdfFile.readStream(FontFile,true,true,false, false,false, FontFile.getCacheName(currentPdfFile.getObjectReader()));
            if(stream!=null)
              readType1FontFile(stream);
          } catch (Exception e) {
            e.printStackTrace();
          }
        }else{
   
          PdfObject FontFile3=pdfFontDescriptor.getDictionary(PdfDictionary.FontFile3);
          if(FontFile3!=null){
            byte[] stream=currentPdfFile.readStream(FontFile3,true,true,false, false,false, FontFile3.getCacheName(currentPdfFile.getObjectReader()));
            if(stream!=null){ //if it fails, null returned
              //check for type1c or ottf
              if(stream.length>3 && stream[0]==719 && stream[1]==84 && stream[2]==84 && stream[3]==79){
              }else //assume all standard cff for moment
                readType1CFontFile(stream,null);
            }
          }
        }
      }
    }

        /** read in a font and its details from the pdf file */
    public void createFont(
                PdfObject pdfObject,
                String fontID,
                boolean renderPage,
                ObjectStore objectStore, Map substitutedFonts)
      throws Exception {

            fontTypes = StandardFonts.TYPE1;
     
      //generic setup
      init(fontID, renderPage);
     
      /**
       * get FontDescriptor object - if present contains metrics on glyphs
       */
      PdfObject pdfFontDescriptor=pdfObject.getDictionary(PdfDictionary.FontDescriptor);
     
      //FontBBox and FontMatix
      setBoundsAndMatrix(pdfFontDescriptor);
     
      setName(pdfObject, fontID);
      setEncoding(pdfObject, pdfFontDescriptor);

            try{
            readEmbeddedFont(pdfFontDescriptor);
            }catch(Exception ee){
                ee.printStackTrace();
            }
           
            //setWidths(pdfObject);
            readWidths(pdfObject,true);
     
//            if(embeddedFontName!=null && is1C() && PdfStreamDecoder.runningStoryPad){
//              embeddedFontName= cleanupFontName(embeddedFontName);
//              this.setBaseFontName(embeddedFontName);
//              this.setFontName(embeddedFontName);
//            }

            //make sure a font set
      if (renderPage)
        setFont(getBaseFontName(), 1);
     
    }

    /** Constructor for html fonts */
    public Type1C(byte[] fontDataAsArray,PdfJavaGlyphs glyphs, boolean is1C) throws Exception{

        this.glyphs=glyphs;

        //generate reverse lookup so we can encode CMAP
        this.trackIndices=true;

        //flags we extract all details (used originally by rendering and now by PS2OTF)
        this.renderPage=true;

        if(is1C)
            readType1CFontFile(fontDataAsArray,null);
        else
            readType1FontFile(fontDataAsArray);
    }

    /** Constructor for OTF fonts */
    public Type1C(byte[] fontDataAsArray,FontData fontData, PdfJavaGlyphs glyphs) throws Exception{

        this.glyphs=glyphs;
       
        readType1CFontFile(fontDataAsArray,fontData);

    }


    /** Handle encoding for type1C fonts. Also used for CIDFontType0C */
    final private void readType1CFontFile(byte[] fontDataAsArray,FontData fontDataAsObject) throws Exception{

      if(LogWriter.isOutput())
        LogWriter.writeLog("Embedded Type1C font used");

        glyphs.setis1C(true);

        boolean isByteArray=(fontDataAsArray!=null);

        //debugFont=getBaseFontName().indexOf("LC")!=-1;

        if(debugFont)
            System.err.println(getBaseFontName());


        /**
         try {
            java.io.FileOutputStream fos=new java.io.FileOutputStream(getBaseFontName()+"_"+fontDataAsArray.length+".bfp");
            fos.write(fontDataAsArray);
            fos.close();
         } catch (Exception e1) {
            e1.printStackTrace();
         }/***/

        
        int start; //pointers within table
        int size=2;

        /**
         * read Header
         */
        int major,minor;
        if(isByteArray){
            major = fontDataAsArray[0];
            minor = fontDataAsArray[1];
        }else{
            major = fontDataAsObject.getByte(0);
            minor = fontDataAsObject.getByte(1);
        }

        if ((major != 1 || minor != 0) && LogWriter.isOutput())
            LogWriter.writeLog("1C  format "+ major+ ':' + minor+ " not fully supported");

        if(debugFont)
            System.out.println("major="+major+" minor="+minor);

        // read header size to workout start of names index
        if(isByteArray)
            top = fontDataAsArray[2];
        else
            top = fontDataAsObject.getByte(2);

        /**
         * read names index
         */
        // read name index for the first font
        int count,offsize;
        if(isByteArray){
            count = getWord(fontDataAsArray, top, size);
            offsize = fontDataAsArray[top + size];
        }else{
            count = getWord(fontDataAsObject, top, size);
            offsize = fontDataAsObject.getByte(top + size);
        }

        /**
         * get last offset and use to move to top dict index
         */
        top += (size+1)//move pointer to start of font names
        start = top + (count + 1) * offsize - 1; //move pointer to end of offsets
        if(isByteArray)
            top = start + getWord(fontDataAsArray, top + count * offsize, offsize);
        else
            top = start + getWord(fontDataAsObject, top + count * offsize, offsize);


        /**
         * read the dict index
         */
        if(isByteArray){
            count = getWord(fontDataAsArray, top, size);
            offsize = fontDataAsArray[top + size];
        }else{
            count = getWord(fontDataAsObject, top, size);
            offsize = fontDataAsObject.getByte(top + size);
        }

        top += (size+1); //update pointer
        start = top + (count + 1) * offsize - 1;

        int dicStart,dicEnd;
        if(isByteArray){
            dicStart = start + getWord(fontDataAsArray, top, offsize);
            dicEnd = start + getWord(fontDataAsArray, top + offsize, offsize);
        }else{
            dicStart = start + getWord(fontDataAsObject, top, offsize);
            dicEnd = start + getWord(fontDataAsObject, top + offsize, offsize);
        }

        /**
         * read string index
         */
        String[] strings=readStringIndex(fontDataAsArray, fontDataAsObject, start, offsize, count);

        /**
         * read global subroutines (top set by Strings code)
         */
        readGlobalSubRoutines(fontDataAsArray,fontDataAsObject);

        /**
         * decode the dictionary
         */
        decodeDictionary(fontDataAsArray, fontDataAsObject, dicStart, dicEnd, strings);

        /**
         * allow  for subdictionaries in CID  font
         */
        if(FDSelect!=-1 ){

           

                if(debugDictionary)
                    System.out.println("=============FDSelect===================="+getBaseFontName());

                int nextDic=FDArray;

                if(isByteArray){
                    count = getWord(fontDataAsArray, nextDic, size);
                    offsize = fontDataAsArray[nextDic + size];
                }else{
                    count = getWord(fontDataAsObject, nextDic, size);
                    offsize = fontDataAsObject.getByte(nextDic + size);
                }

                nextDic += (size+1); //update pointer
                start = nextDic + (count + 1) * offsize - 1;

                if(isByteArray){
                    dicStart = start+getWord(fontDataAsArray, nextDic, offsize);
                    dicEnd =start+getWord(fontDataAsArray, nextDic + offsize, offsize);
                }else{
                    dicStart = start+getWord(fontDataAsObject, nextDic, offsize);
                    dicEnd =start+getWord(fontDataAsObject, nextDic + offsize, offsize);
                }

                decodeDictionary(fontDataAsArray, fontDataAsObject, dicStart, dicEnd, strings);

                if(debugDictionary)
                    System.out.println("================================="+getBaseFontName());

        }
       
        /**
         * get number of glyphs from charstrings index
         */
        top = charstrings;

        int nGlyphs;

        if(isByteArray)
            nGlyphs = getWord(fontDataAsArray, top, size); //start of glyph index
        else
            nGlyphs = getWord(fontDataAsObject, top, size); //start of glyph index

        glyphs.setGlyphCount(nGlyphs);

        if(debugFont)
            System.out.println("nGlyphs="+nGlyphs);

        int[] names =readCharset(charset, nGlyphs, charstrings, fontDataAsObject,fontDataAsArray);

        if(debugFont){
            System.out.println("=======charset===============");
            int count2=names.length;
            for(int jj=0;jj<count2;jj++){
                System.out.println(jj+" "+names[jj]);
            }

            System.out.println("=======Encoding===============");
        }

        /**
         * set encoding if not set
         */
        setEncoding(fontDataAsArray, fontDataAsObject,nGlyphs,names);

        /**
         * read glyph index
         */
        top = charstrings;
        readGlyphs(fontDataAsArray, fontDataAsObject, nGlyphs, names);

         /**/
        if(privateDict!=-1){

                decodeDictionary(fontDataAsArray, fontDataAsObject, privateDict, privateDictOffset+privateDict, strings);

                top = privateDict + privateDictOffset;

                int len,nSubrs;

                if(isByteArray)
                    len=fontDataAsArray.length;
                else
                    len=fontDataAsObject.length();

                if(top+2<len){
                    if(isByteArray)
                        nSubrs = getWord(fontDataAsArray, top, size);
                    else
                        nSubrs = getWord(fontDataAsObject, top, size);

                    if(nSubrs>0)
                        readSubrs(fontDataAsArray, fontDataAsObject, nSubrs);
                }else if(debugFont || debugDictionary){
                    System.out.println("Private subroutine out of range");
                }
           
        }
         /**/
        /**
         * set flags to tell software to use these descritpions
         */
        isFontEmbedded = true;

        glyphs.setFontEmbedded(true);

    }

  /**pick up encoding from embedded font*/
  final private void setEncoding(byte[] fontDataAsArray, FontData fontDataAsObject,int nGlyphs,int[] names){

        boolean isByteArray=fontDataAsArray!=null;

    if(debugFont)
      System.out.println("Enc="+enc);
   
    // read encoding (glyph -> code mapping)
    if (enc == 0){
      embeddedEnc=StandardFonts.STD;
      if (fontEnc == -1)
      putFontEncoding(StandardFonts.STD);

      if(isCID){
            //store values for lookup on text
            try{
            String name;
            for (int i = 1; i < nGlyphs; ++i) {

                if(names[i]<391){
                    if(isByteArray)
                        name =getString(fontDataAsArray,names[i],stringIdx,stringStart,stringOffSize);
                    else
                        name =getString(fontDataAsObject,names[i],stringIdx,stringStart,stringOffSize);

                    putMappedChar(names[i],StandardFonts.getUnicodeName(name) );
                }
            }
            }catch(Exception ee){
                ee.printStackTrace();
            }

    }
    }else if (enc == 1){
      embeddedEnc=StandardFonts.MACEXPERT;
      if (fontEnc == -1)
      putFontEncoding(StandardFonts.MACEXPERT);
    }else { //custom mapping

      if(debugFont)
        System.out.println("custom mapping");
     
      top = enc;
            int encFormat,c;

            if(isByteArray)
                encFormat = (fontDataAsArray[top++] & 0xff);
            else
                encFormat = (fontDataAsObject.getByte(top++) & 0xff);

      String name;

      if ((encFormat & 0x7f) == 0) { //format 0

                int nCodes;

                if(isByteArray)
                    nCodes = 1 + (fontDataAsArray[top++] & 0xff);
                else
                    nCodes = 1 + (fontDataAsObject.getByte(top++) & 0xff);

        if (nCodes > nGlyphs)
          nCodes = nGlyphs;
        for (int i = 1; i < nCodes; ++i) {

                    if(isByteArray){
                        c =fontDataAsArray[top++] & 0xff;
                        name =getString(fontDataAsArray,names[i],stringIdx,stringStart,stringOffSize);

                    }else{
                        c =fontDataAsObject.getByte(top++) & 0xff;
                        name =getString(fontDataAsObject,names[i],stringIdx,stringStart,stringOffSize);
                    }

          putChar(c, name);

        }

      } else if ((encFormat & 0x7f) == 1) { //format 1

                int nRanges;
                if(isByteArray)
                    nRanges = (fontDataAsArray[top++] & 0xff);
                else
                    nRanges = (fontDataAsObject.getByte(top++) & 0xff);

        int nCodes = 1;
        for (int i = 0; i < nRanges; ++i) {

                    int nLeft;

                    if(isByteArray){
                        c = (fontDataAsArray[top++] & 0xff);
                        nLeft = (fontDataAsArray[top++] & 0xff);
                    }else{
                        c = (fontDataAsObject.getByte(top++) & 0xff);
                        nLeft = (fontDataAsObject.getByte(top++) & 0xff);
                    }

          for (int j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {

                        if(isByteArray)
                            name =getString(fontDataAsArray,names[nCodes],stringIdx,stringStart,stringOffSize);
                        else
                            name =getString(fontDataAsObject,names[nCodes],stringIdx,stringStart,stringOffSize);

            putChar(c, name);

            nCodes++;
            c++;
          }
        }
      }

      if ((encFormat & 0x80) != 0) { //supplimentary encodings

                int nSups;

                if(isByteArray)
                    nSups = (fontDataAsArray[top++] & 0xff);
                else
                    nSups = (fontDataAsObject.getByte(top++) & 0xff);

        for (int i = 0; i < nSups; ++i) {

                    if(isByteArray)
                        c = (fontDataAsArray[top++] & 0xff);
                    else
                        c = (fontDataAsObject.getByte(top++) & 0xff);

                    int sid;

                    if(isByteArray)
                        sid = getWord(fontDataAsArray, top, 2);
                    else
                        sid = getWord(fontDataAsObject, top, 2);

          top += 2;

                    if(isByteArray)
                        name =getString(fontDataAsArray,sid,stringIdx,stringStart,stringOffSize);
                    else
                        name =getString(fontDataAsObject,sid,stringIdx,stringStart,stringOffSize);

          putChar(c, name);

        }
      }
    }
  }
 
  // LILYPONDTOOL
  private final void readSubrs(byte[] fontDataAsArray, FontData fontDataAsObject, int nSubrs) throws Exception {
   
        boolean isByteArray=fontDataAsArray!=null;

        int subrOffSize;

        if(isByteArray)
            subrOffSize = fontDataAsArray[top+2];
        else
            subrOffSize = fontDataAsObject.getByte(top+2);

    top+=3;
    int subrIdx = top;
    int subrStart = top + (nSubrs + 1) * subrOffSize - 1;

        int nextTablePtr= top+nSubrs*subrOffSize;

        if(isByteArray){
            if(nextTablePtr<fontDataAsArray.length) //allow for table at end of file
                    top = subrStart + getWord(fontDataAsArray,nextTablePtr, subrOffSize);
                else
                    top=fontDataAsArray.length-1;
        }else{
            if(nextTablePtr<fontDataAsArray.length) //allow for table at end of file
                    top = subrStart + getWord(fontDataAsObject, nextTablePtr, subrOffSize);
                else
                    top=fontDataAsObject.length()-1;   
        }

        int[] subrOffset = new int [nSubrs + 2];
    int ii = subrIdx;
    for (int jj = 0; jj<nSubrs+1; jj++) {

            if(isByteArray){
                if((ii+subrOffSize)<fontDataAsArray.length)
                subrOffset[jj] = subrStart + getWord(fontDataAsArray, ii, subrOffSize);
            }else{
                if((ii+subrOffSize)<fontDataAsObject.length())
                subrOffset[jj] = subrStart + getWord(fontDataAsObject, ii, subrOffSize);
            }

            ii += subrOffSize;
    }
    subrOffset[nSubrs + 1] = top;

    glyphs.setLocalBias(calculateSubroutineBias(nSubrs));

        //read the glyphs and store
    int current = subrOffset[0];

        for (int jj = 1; jj < nSubrs+1; jj++) {


            //skip if out of bounds
            if(current==0 || subrOffset[jj]>fontDataAsArray.length || subrOffset[jj]<0 || subrOffset[jj]==0)
            continue;

            ByteArrayOutputStream nextSubr = new ByteArrayOutputStream();
     
      for (int c = current; c < subrOffset[jj]; c++){
                if(!isByteArray && c<fontDataAsObject.length())
                    nextSubr.write(fontDataAsObject.getByte(c));
               
            }

            if(isByteArray){

                int length=subrOffset[jj]-current;
               
                if(length>0){
                  byte[] nextSub=new byte[length];
 
                  System.arraycopy(fontDataAsArray,current,nextSub,0,length);
 
                  glyphs.setCharString("subrs"+(jj-1),nextSub);
                }
            }else{
                nextSubr.close();
     
          glyphs.setCharString("subrs"+(jj-1),nextSubr.toByteArray());
            }
            current = subrOffset[jj];

    }
    }

 
  private final void readGlyphs(byte[] fontDataAsArray, FontData fontDataAsObject,int nGlyphs,int[] names) throws Exception{

        boolean isByteArray=fontDataAsArray!=null;

            int glyphOffSize;

            if(isByteArray)
                glyphOffSize = fontDataAsArray[top + 2];
            else
                glyphOffSize = fontDataAsObject.getByte(top + 2);

    top += 3;
    int glyphIdx = top;
    int glyphStart = top + (nGlyphs + 1) * glyphOffSize - 1;

            if(isByteArray)
                top =glyphStart+ getWord(fontDataAsArray,top + nGlyphs * glyphOffSize,glyphOffSize);
            else
                top =glyphStart+ getWord(fontDataAsObject,top + nGlyphs * glyphOffSize,glyphOffSize);

    int[] glyphoffset = new int[nGlyphs + 2];

    int ii = glyphIdx;

    //read the offsets
    for (int jj = 0; jj < nGlyphs + 1; jj++) {

                if(isByteArray)
                    glyphoffset[jj] = glyphStart+getWord(fontDataAsArray,ii,glyphOffSize);
                else
                    glyphoffset[jj] = glyphStart+getWord(fontDataAsObject,ii,glyphOffSize);
               
      ii = ii + glyphOffSize;

    }

    glyphoffset[nGlyphs + 1] = top;

        //read the glyphs and store
        int current = glyphoffset[0];
        String glyphName;
        byte[] nextGlyph;
        for (int jj = 1; jj < nGlyphs+1; jj++) {

            nextGlyph=new byte[glyphoffset[jj]-current]//read name of glyph

            //get data for the glyph
            for (int c = current; c < glyphoffset[jj]; c++){

                if(isByteArray)
                    nextGlyph[c-current]=fontDataAsArray[c];
                else
                    nextGlyph[c-current]=fontDataAsObject.getByte(c);
            }

            if(isCID){
                glyphName =String.valueOf(names[jj - 1]);
            }else{

                if(isByteArray)
                    glyphName =getString(fontDataAsArray,names[jj-1],stringIdx,stringStart,stringOffSize);
                else
                    glyphName =getString(fontDataAsObject,names[jj-1],stringIdx,stringStart,stringOffSize);
            }
                if(debugFont)
                    System.out.println("glyph= "+ glyphName +" start="+current+" length="+glyphoffset[jj]+" isCID="+isCID);

            glyphs.setCharString(glyphName,nextGlyph);

            current = glyphoffset[jj];

            if(trackIndices){
                glyphs.setIndexForCharString(jj, glyphName);

            }
        }
    }
 
  private static final int calculateSubroutineBias(int subroutineCount) {
    int bias;
    if (subroutineCount < 1240) {
      bias = 107;
    } else if (subroutineCount < 33900) {
      bias = 1131;
    } else {
      bias = 32768;
    }
    return bias;
  }
 
  private final void readGlobalSubRoutines(byte[] fontDataAsArray, FontData fontDataAsObject) throws Exception{

        boolean isByteArray=(fontDataAsArray!=null);

        int subOffSize,count;

        if(isByteArray){
            subOffSize = (fontDataAsArray[top + 2] & 0xff);
        count= getWord(fontDataAsArray, top, 2);
        }else{
            subOffSize = (fontDataAsObject.getByte(top + 2) & 0xff);
            count= getWord(fontDataAsObject, top, 2);
        }

    top += 3;
    if(count>0){

      int idx = top;
      int start = top + (count + 1) * subOffSize - 1;
            if(isByteArray)
                top =start+ getWord(fontDataAsArray,top + count * subOffSize,subOffSize);
            else
                top =start+ getWord(fontDataAsObject,top + count * subOffSize,subOffSize);

      int[] offset = new int[count + 2];

      int ii = idx;

      //read the offsets
      for (int jj = 0; jj < count + 1; jj++) {

                if(isByteArray)
                    offset[jj] = start + getWord(fontDataAsArray,ii,subOffSize);
                else
                    offset[jj] = start + getWord(fontDataAsObject,ii,subOffSize);

        ii = ii + subOffSize;

      }

      offset[count + 1] = top;

      glyphs.setGlobalBias(calculateSubroutineBias(count));
     
      //read the subroutines and store
      int current = offset[0];
      for (int jj = 1; jj < count+1; jj++) {

        ByteArrayOutputStream nextStream = new ByteArrayOutputStream();
        for (int c = current; c < offset[jj]; c++){
                    if(isByteArray)
                        nextStream.write(fontDataAsArray[c]);
                    else
                        nextStream.write(fontDataAsObject.getByte(c));
                }
        nextStream.close();

        //store
        glyphs.setCharString("global"+(jj-1),nextStream.toByteArray());
       
        //setGlobalSubroutine(new Integer(jj-1+bias),nextStream.toByteArray());
        current = offset[jj];

      }
    }
  }

  private void decodeDictionary(byte[] fontDataAsArray, FontData fontDataAsObject, int dicStart, int dicEnd, String[] strings){

        boolean fdReset=false;

    if(debugDictionary)
      System.out.println("=============Read dictionary===================="+getBaseFontName());
   
        boolean isByteArray=fontDataAsArray!=null;

    int p = dicStart, nextVal,key;
    int i=0;
    double[] op = new double[48]; //current operand in dictionary

        while (p < dicEnd) {

            if(isByteArray)
                nextVal = fontDataAsArray[p] & 0xFF;
            else
                nextVal = fontDataAsObject.getByte(p) & 0xFF;

      if (nextVal <= 27 || nextVal == 31) { // operator

        key = nextVal;

        p++;
       
        if(debugDictionary && key!=12)
          System.out.println(key +" (1) "+OneByteCCFDict[key]);
       
        if (key == 0x0c) { //handle escaped keys

                    if(isByteArray)
                        key = fontDataAsArray[p] & 0xFF;
                    else
                        key = fontDataAsObject.getByte(p) & 0xFF;

          if(debugDictionary)
            System.out.println(key +" (2) "+TwoByteCCFDict[key]);
         
          p++;

                    if(key!=36 && key!=37 && key!=7 && FDSelect!=-1){
                        if(debugDictionary){
              System.out.println("Ignored as part of FDArray ");

                            for(int ii=0;ii<6;ii++)
              System.out.println(op[ii]);
                        }
                    }else if (key == 2) { //italic
           
                      italicAngle=(int)op[0];
            if(debugDictionary)
              System.out.println("Italic="+op[0]);
         
                    }else if (key == 7) { //fontMatrix
                      if(!hasFontMatrix)
                        System.arraycopy(op, 0, FontMatrix, 0, 6);
                     
            if(debugDictionary){
              for(int ii=0;ii<6;ii++)
              System.out.println(ii+"="+op[ii]+ ' ' +this);
            }
           
            hasFontMatrix=true;
          }else if (key == 30) { //ROS
            ROS=(int)op[0];
            isCID=true;
            if(debugDictionary)
              System.out.println(op[0]);
          }else if(key==31){ //CIDFontVersion
            CIDFontVersion=(int)op[0];
            if(debugDictionary)
              System.out.println(op[0]);
          }else if(key==32){ //CIDFontRevision
            CIDFontRevision=(int)op[0];
            if(debugDictionary)
              System.out.println(op[0]);   
          }else if(key==33){ //CIDFontType
            CIDFontType=(int)op[0];
            if(debugDictionary)
              System.out.println(op[0]);     
          }else if(key==34){ //CIDcount
            CIDcount=(int)op[0];
            if(debugDictionary)
              System.out.println(op[0]);   
          }else if(key==35){ //UIDBase
            UIDBase=(int)op[0];
            if(debugDictionary)
              System.out.println(op[0])
          }else if(key==36){ //FDArray
            FDArray=(int)op[0];
            if(debugDictionary)
              System.out.println(op[0]);

                    }else if(key==37){ //FDSelect
            FDSelect=(int)op[0];

                        fdReset=true;

                        if(debugDictionary)
              System.out.println(op[0]);
                    }else if(key==0){ //copyright

                        int id=(int)op[0];
                        if(id>390)
                        id=id-390;
                        copyright=strings[id];
                        if(debugDictionary)
                        System.out.println("copyright= "+copyright);
                    }else if(key==21){ //Postscript


                        //postscriptFontName=strings[id];
                        if(debugDictionary)  {
                            int id=(int)op[0];
                            if(id>390)
                            id=id-390;

                            System.out.println("Postscript= "+strings[id]);
                            System.out.println(TwoByteCCFDict[key]+ ' ' +op[0]);
                        }
                    }else if(key==22){ //BaseFontname

                        //baseFontName=strings[id];
                        if(debugDictionary){

                            int id=(int)op[0];
                            if(id>390)
                            id=id-390;

                            System.out.println("BaseFontname= "+embeddedFontName);
                            System.out.println(TwoByteCCFDict[key]+ ' ' +op[0]);
                        }
                    }else if(key==38){ //fullname

                        //fullname=strings[id];
                        if(debugDictionary){

                            int id=(int)op[0];
                            if(id>390)
                            id=id-390;

                            System.out.println("fullname= "+strings[id]);
                            System.out.println(TwoByteCCFDict[key]+ ' ' +op[0]);
                        }

                    }else if(debugDictionary)
            System.out.println(op[0]);

        } else {

                    if(key==2){ //fullname

                        int id=(int)op[0];
                        if(id>390)
                        id=id-390;
                        embeddedFontName=strings[id];
                        if(debugDictionary){
                            System.out.println("name= "+embeddedFontName);
                            System.out.println(OneByteCCFDict[key]+ ' ' +op[0]);
                        }

                    }else if(key==3){ //familyname

                        //embeddedFamilyName=strings[id];
                        if(debugDictionary){
                           
                            int id=(int)op[0];
                            if(id>390)
                            id=id-390;

                            System.out.println("FamilyName= "+embeddedFamilyName);
                            System.out.println(OneByteCCFDict[key]+ ' ' +op[0]);
                        }

                    }else if (key == 5) { //fontBBox
            if(debugDictionary){
              for(int ii=0;ii<4;ii++)
              System.out.println(op[ii]);
            }
            for(int ii=0;ii<4;ii++){
              //System.out.println(" "+ii+" "+op[ii]);
              this.FontBBox[ii]=(float) op[ii];
            }
           
            //hasFontBBox=true;
          }else if (key == 0x0f) { // charset
            charset = (int) op[0];
           
            if(debugDictionary)
              System.out.println(op[0]);
           
          } else if (key == 0x10) { // encoding
            enc = (int) op[0];
           
            if(debugDictionary)
              System.out.println(op[0]);
           
          } else if (key == 0x11) { // charstrings
            charstrings = (int) op[0];
           
            if(debugDictionary)
              System.out.println(op[0]);
           
            //System.out.println("charStrings="+charstrings);
          } else if (key == 18 && glyphs.is1C()) { // readPrivate
            privateDict = (int) op[1];
            privateDictOffset = (int) op[0];
           
            if(debugDictionary)
            System.out.println("privateDict="+op[0]+" Offset="+op[1]);

                    } else if (key == 20) {         //defaultWidthX
                        defaultWidthX = (int)op[0];
                        if (glyphs instanceof T1Glyphs)
                            ((T1Glyphs)glyphs).setWidthValues(defaultWidthX, nominalWidthX);

                        if(debugDictionary)
                System.out.println("defaultWidthX="+op[0]);

                    } else if (key == 21) {         //nominalWidthX
                        nominalWidthX = (int)op[0];
                        if (glyphs instanceof T1Glyphs)
                            ((T1Glyphs)glyphs).setWidthValues(defaultWidthX, nominalWidthX);

                        if(debugDictionary)
                System.out.println("nominalWidthX="+op[0]);

                    } else if(debugDictionary){
           
            // System.out.println(p+" "+key+" "+T1CcharCodes1Byte[key]+" <<<"+op);
            
            System.out.println("Other value "+key);
             /**if(op <type1CStdStrings.length)
             System.out.println(type1CStdStrings[(int)op]);
             else if((op-390) <strings.length)
             System.out.println("interesting key:"+key);*/
          }
          //System.out.println(p+" "+key+" "+raw1ByteValues[key]+" <<<"+op);
        }

        i=0;

      }else{

                if(isByteArray)
                    p=glyphs.getNumber(fontDataAsArray, p,op,i,false);
                else
                    p=glyphs.getNumber(fontDataAsObject, p,op,i,false);

                i++;
      }
    }
   
    if(debugDictionary)
      System.out.println("================================="+getBaseFontName());

        //reset
        if(!fdReset)
        FDSelect=-1;

    }

  private String[] readStringIndex(byte[] fontDataAsArray,FontData fontDataAsObject,int start,int offsize,int count){

        int nStrings;

        boolean isByteArray=(fontDataAsArray!=null);

        if(isByteArray){
            top = start + getWord(fontDataAsArray, top + count * offsize, offsize);
    //start of string index
        nStrings = getWord(fontDataAsArray, top, 2);
        stringOffSize = fontDataAsArray[top + 2];
        }else{
            top = start + getWord(fontDataAsObject, top + count * offsize, offsize);
            //start of string index
            nStrings = getWord(fontDataAsObject, top, 2);
            stringOffSize = fontDataAsObject.getByte(top + 2);
        }

    top += 3;
    stringIdx = top;
    stringStart = top + (nStrings + 1) * stringOffSize - 1;

        if(isByteArray)
            top =stringStart+ getWord(fontDataAsArray,top + nStrings * stringOffSize,stringOffSize);
        else
            top =stringStart+ getWord(fontDataAsObject,top + nStrings * stringOffSize,stringOffSize);

    int[] offsets = new int[nStrings + 2];
    String[] strings = new String[nStrings + 2];

    int ii = stringIdx;
    //read the offsets
    for (int jj = 0; jj < nStrings + 1; jj++) {

            if(isByteArray)
                offsets[jj] = getWord(fontDataAsArray,ii,stringOffSize); //content[ii] & 0xff;
            else
                offsets[jj] = getWord(fontDataAsObject,ii,stringOffSize); //content[ii] & 0xff;
      //getWord(content,ii,stringOffSize);
      ii = ii + stringOffSize;

    }

    offsets[nStrings + 1] = top - stringStart;

    //read the strings
    int current = 0;
        StringBuffer nextString;
    for (int jj = 0; jj < nStrings + 1; jj++) {

      nextString = new StringBuffer(offsets[jj]-current);
      for (int c = current; c < offsets[jj]; c++){
                if(isByteArray)
                    nextString.append((char) fontDataAsArray[stringStart + c]);
                else
                    nextString.append((char) fontDataAsObject.getByte(stringStart + c));
            }

      if(debugFont)
        System.out.println("String "+jj+" ="+nextString);
     
      strings[jj] = nextString.toString();
      current = offsets[jj];

        }
    return strings;
  }

  /** Utility method used during processing of type1C files */
  static final private String getString(FontData fontDataAsObject,int sid,int idx,int start,int offsize) {

    int len;
    String result  ;

    if (sid < 391)
      result = type1CStdStrings[sid];
    else {
      sid -= 391;
      int idx0 =start+ getWord(fontDataAsObject, idx + sid * offsize,offsize);
      int idxPtr1 =start+ getWord(fontDataAsObject, idx + (sid + 1) * offsize,offsize);
      //System.out.println(sid+" "+idx0+" "+idxPtr1);
      if ((len = idxPtr1 - idx0) > 255)
        len = 255;

            result = new String(fontDataAsObject.getBytes(idx0,len));
    }
    return result;
  }

    /** Utility method used during processing of type1C files */
  static final private String getString(byte[] fontDataAsArray,int sid,int idx,int start,int offsize) {

    int len;
    String result  ;

        if (sid < 391)
      result = type1CStdStrings[sid];
    else {
      sid -= 391;
      int idx0 =start+ getWord(fontDataAsArray, idx + sid * offsize,offsize);
      int idxPtr1 =start+ getWord(fontDataAsArray, idx + (sid + 1) * offsize,offsize);
      //System.out.println(sid+" "+idx0+" "+idxPtr1);
      if ((len = idxPtr1 - idx0) > 255)
        len = 255;

            result=new String(fontDataAsArray,idx0,len);
           
    }
    return result;
  }



  /** get standard charset or extract from type 1C font */
  static final private int[] readCharset(int charset,int nGlyphs,int top,FontData fontDataAsObject, byte[] fontDataAsArray) {

        boolean isByteArray=fontDataAsArray!=null;

    int glyphNames[]  ;
    int i, j;
   
    if(debugFont)
      System.out.println("charset="+charset);

    /**
    //handle CIDS first
    if(isCID){
      glyphNames = new int[nGlyphs];
      glyphNames[0] = 0;

      for (i = 1; i < nGlyphs; ++i) {
        glyphNames[i] = i;//getWord(fontData, top, 2);
        //top += 2;
        }


    // read appropriate non-CID charset
    }else */if (charset == 0)
      glyphNames = ISOAdobeCharset;
    else if (charset == 1)
      glyphNames = ExpertCharset;
    else if (charset == 2)
      glyphNames = ExpertSubCharset;
    else {
      glyphNames = new int[nGlyphs+1];
      glyphNames[0] = 0;
      top = charset;

            int charsetFormat;

            if(isByteArray)
                charsetFormat = fontDataAsArray[top++] & 0xff;
            else
                charsetFormat = fontDataAsObject.getByte(top++) & 0xff;

      if(debugFont)
        System.out.println("charsetFormat="+charsetFormat);
     
      if (charsetFormat == 0) {
        for (i = 1; i < nGlyphs; ++i) {
                    if(isByteArray)
                        glyphNames[i] = getWord(fontDataAsArray, top, 2);
                    else
                        glyphNames[i] = getWord(fontDataAsObject, top, 2);

          top += 2;
        }

      } else if (charsetFormat == 1) {
       
        i = 1;

                    int c,nLeft;
        while (i < nGlyphs) {

                        if(isByteArray)
                            c = getWord(fontDataAsArray, top, 2);
                        else
                            c = getWord(fontDataAsObject, top, 2);
          top += 2;
                        if(isByteArray)
                            nLeft = fontDataAsArray[top++] & 0xff;
                        else
                            nLeft = fontDataAsObject.getByte(top++) & 0xff;

          for (j = 0; j <= nLeft; ++j)
            glyphNames[i++] =c++;
         
        }
      } else if (charsetFormat == 2) {
        i = 1;

                int c,nLeft;

        while (i < nGlyphs) {
                    if(isByteArray)
                        c = getWord(fontDataAsArray, top, 2);
                    else
                        c = getWord(fontDataAsObject, top, 2);

          top += 2;

                    if(isByteArray)
                        nLeft = getWord(fontDataAsArray, top, 2);
                    else
                        nLeft = getWord(fontDataAsObject, top, 2);

          top += 2;
          for (j = 0; j <= nLeft; ++j)
            glyphNames[i++] =c++;
        }
      }
    }

    return glyphNames;
  }

  /** Utility method used during processing of type1C files */
  static final private int getWord(FontData fontDataAsObject, int index, int size) {
    int result = 0;
    for (int i = 0; i < size; i++) {
      result = (result << 8) + (fontDataAsObject.getByte(index + i) & 0xff);

    }
    return result;
  }

    /** Utility method used during processing of type1C files */
  static final private int getWord(byte[] fontDataAsArray, int index, int size) {
    int result = 0;
    for (int i = 0; i < size; i++) {
      result = (result << 8) + (fontDataAsArray[index + i] & 0xff);

    }
    return result;
  }

    /**
     * get bounding box to highlight
     * @return
     */
    public Rectangle getBoundingBox() {

        if(BBox==null){
            if(isFontEmbedded)
                BBox=new Rectangle((int)FontBBox[0], (int)FontBBox[1],
                        (int)(FontBBox[2]-FontBBox[0]), (int)(FontBBox[3]-FontBBox[1]))//To change body of created methods use File | Settings | File Templates.
            else
                BBox=super.getBoundingBox();
        }

        return BBox;
    }


}


TOP

Related Classes of org.jpedal.fonts.Type1C

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.