aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/com/lowagie/text/pdf/CFFFontSubset.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/lowagie/text/pdf/CFFFontSubset.java')
-rw-r--r--src/main/java/com/lowagie/text/pdf/CFFFontSubset.java1633
1 files changed, 0 insertions, 1633 deletions
diff --git a/src/main/java/com/lowagie/text/pdf/CFFFontSubset.java b/src/main/java/com/lowagie/text/pdf/CFFFontSubset.java
deleted file mode 100644
index 111f899..0000000
--- a/src/main/java/com/lowagie/text/pdf/CFFFontSubset.java
+++ /dev/null
@@ -1,1633 +0,0 @@
-/*
- * $Id: CFFFontSubset.java,v 1.3 2005/02/17 09:20:54 blowagie Exp $
- * $Name: $
- *
- * Copyright 2004 Oren Manor and Ygal Blum
- *
- * 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.
- *
- * The Original Code is 'iText, a free JAVA-PDF library'.
- *
- * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
- * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
- * All Rights Reserved.
- * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
- * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
- *
- * 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.
- *
- * If you didn't download this code from the following link, you should check if
- * you aren't using an obsolete version:
- * http://www.lowagie.com/iText/
- */
-package com.lowagie.text.pdf;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.ArrayList;
-import java.io.*;
-
-/**
- * This Class subsets a CFF Type Font. The subset is preformed for CID fonts and NON CID fonts.
- * The Charstring is subseted for both types. For CID fonts only the FDArray which are used are embedded.
- * The Lsubroutines of the FDArrays used are subsetted as well. The Subroutine subset supports both Type1 and Type2
- * formatting altough only tested on Type2 Format.
- * For Non CID the Lsubroutines are subsetted. On both types the Gsubroutines is subsetted.
- * A font which was not of CID type is transformed into CID as a part of the subset process.
- * The CID synthetic creation was written by Sivan Toledo <sivan@math.tau.ac.il>
- * @author Oren Manor <manorore@post.tau.ac.il> & Ygal Blum <blumygal@post.tau.ac.il>
- */
-public class CFFFontSubset extends CFFFont {
-
- /**
- * The Strings in this array represent Type1/Type2 operator names
- */
- static final String SubrsFunctions[] = {
- "RESERVED_0","hstem","RESERVED_2","vstem","vmoveto","rlineto","hlineto","vlineto",
- "rrcurveto","RESERVED_9","callsubr","return","escape","RESERVED_13",
- "endchar","RESERVED_15","RESERVED_16","RESERVED_17","hstemhm","hintmask",
- "cntrmask","rmoveto","hmoveto","vstemhm","rcurveline","rlinecurve","vvcurveto",
- "hhcurveto","shortint","callgsubr","vhcurveto","hvcurveto"
- };
- /**
- * The Strings in this array represent Type1/Type2 escape operator names
- */
- static final String SubrsEscapeFuncs[] = {
- "RESERVED_0","RESERVED_1","RESERVED_2","and","or","not","RESERVED_6",
- "RESERVED_7","RESERVED_8","abs","add","sub","div","RESERVED_13","neg",
- "eq","RESERVED_16","RESERVED_17","drop","RESERVED_19","put","get","ifelse",
- "random","mul","RESERVED_25","sqrt","dup","exch","index","roll","RESERVED_31",
- "RESERVED_32","RESERVED_33","hflex","flex","hflex1","flex1","RESERVED_REST"
- };
-
- /**
- * A HashMap containing the glyphs used in the text after being converted
- * to glyph number by the CMap
- */
- HashMap GlyphsUsed;
- /**
- * The GlyphsUsed keys as an ArrayList
- */
- ArrayList glyphsInList;
- /**
- * A HashMap for keeping the FDArrays being used by the font
- */
- HashMap FDArrayUsed = new HashMap();
- /**
- * A HashMaps array for keeping the subroutines used in each FontDict
- */
- HashMap[] hSubrsUsed;
- /**
- * The SubroutinesUsed HashMaps as ArrayLists
- */
- ArrayList[] lSubrsUsed;
- /**
- * A HashMap for keeping the Global subroutines used in the font
- */
- HashMap hGSubrsUsed = new HashMap();
- /**
- * The Global SubroutinesUsed HashMaps as ArrayLists
- */
- ArrayList lGSubrsUsed = new ArrayList();
- /**
- * A HashMap for keeping the subroutines used in a non-cid font
- */
- HashMap hSubrsUsedNonCID = new HashMap();
- /**
- * The SubroutinesUsed HashMap as ArrayList
- */
- ArrayList lSubrsUsedNonCID = new ArrayList();
- /**
- * An array of the new Indexs for the local Subr. One index for each FontDict
- */
- byte[][] NewLSubrsIndex;
- /**
- * The new subroutines index for a non-cid font
- */
- byte[] NewSubrsIndexNonCID;
- /**
- * The new global subroutines index of the font
- */
- byte[] NewGSubrsIndex;
- /**
- * The new CharString of the font
- */
- byte[] NewCharStringsIndex;
-
- /**
- * The bias for the global subroutines
- */
- int GBias = 0;
-
- /**
- * The linked list for generating the new font stream
- */
- LinkedList OutputList;
-
- /**
- * Number of arguments to the stem operators in a subroutine calculated recursivly
- */
- int NumOfHints=0;
-
-
- /**
- * C'tor for CFFFontSubset
- * @param rf - The font file
- * @param GlyphsUsed - a HashMap that contains the glyph used in the subset
- */
- public CFFFontSubset(RandomAccessFileOrArray rf,HashMap GlyphsUsed){
- // Use CFFFont c'tor in order to parse the font file.
- super(rf);
- this.GlyphsUsed = GlyphsUsed;
- //Put the glyphs into a list
- glyphsInList = new ArrayList(GlyphsUsed.keySet());
-
-
- for (int i=0;i<fonts.length;++i)
- {
- // Read the number of glyphs in the font
- seek(fonts[i].charstringsOffset);
- fonts[i].nglyphs = getCard16();
-
- // Jump to the count field of the String Index
- seek(stringIndexOffset);
- fonts[i].nstrings = getCard16()+standardStrings.length;
-
- // For each font save the offset array of the charstring
- fonts[i].charstringsOffsets = getIndex(fonts[i].charstringsOffset);
-
- // Proces the FDSelect if exist
- if (fonts[i].fdselectOffset>=0)
- {
- // Proces the FDSelect
- readFDSelect(i);
- // Build the FDArrayUsed hashmap
- BuildFDArrayUsed(i);
- }
- if (fonts[i].isCID)
- // Build the FD Array used Hash Map
- ReadFDArray(i);
- // compute the charset length
- fonts[i].CharsetLength = CountCharset(fonts[i].charsetOffset,fonts[i].nglyphs);
- }
- }
-
- /**
- * Calculates the length of the charset according to its format
- * @param Offset The Charset Offset
- * @param NumofGlyphs Number of glyphs in the font
- * @return the length of the Charset
- */
- int CountCharset(int Offset,int NumofGlyphs){
- int format;
- int Length=0;
- seek(Offset);
- // Read the format
- format = getCard8();
- // Calc according to format
- switch (format){
- case 0:
- Length = 1+2*NumofGlyphs;
- break;
- case 1:
- Length = 1+3*CountRange(NumofGlyphs,1);
- break;
- case 2:
- Length = 1+4*CountRange(NumofGlyphs,2);
- break;
- default:
- break;
- }
- return Length;
- }
-
- /**
- * Function calculates the number of ranges in the Charset
- * @param NumofGlyphs The number of glyphs in the font
- * @param Type The format of the Charset
- * @return The number of ranges in the Charset data structure
- */
- int CountRange(int NumofGlyphs,int Type){
- int num=0;
- char Sid;
- int i=1,nLeft,Places;
- while (i<NumofGlyphs){
- num++;
- Sid = getCard16();
- if (Type==1)
- nLeft = getCard8();
- else
- nLeft = getCard16();
- i += nLeft+1;
- }
- return num;
- }
-
-
- /**
- * Read the FDSelect of the font and compute the array and its length
- * @param Font The index of the font being processed
- * @return The Processed FDSelect of the font
- */
- protected void readFDSelect(int Font)
- {
- // Restore the number of glyphs
- int NumOfGlyphs = fonts[Font].nglyphs;
- int[] FDSelect = new int[NumOfGlyphs];
- // Go to the beginning of the FDSelect
- seek(fonts[Font].fdselectOffset);
- // Read the FDSelect's format
- fonts[Font].FDSelectFormat = getCard8();
-
- switch(fonts[Font].FDSelectFormat){
- // Format==0 means each glyph has an entry that indicated
- // its FD.
- case 0:
- for (int i=0;i<NumOfGlyphs;i++)
- {
- FDSelect[i] = getCard8();
- }
- // The FDSelect's Length is one for each glyph + the format
- // for later use
- fonts[Font].FDSelectLength = fonts[Font].nglyphs+1;
- break;
- case 3:
- // Format==3 means the ranges version
- // The number of ranges
- int nRanges = getCard16();
- int l=0;
- // Read the first in the first range
- int first = getCard16();
- for (int i=0;i<nRanges;i++)
- {
- // Read the FD index
- int fd = getCard8();
- // Read the first of the next range
- int last = getCard16();
- // Calc the steps and write to the array
- int steps = last-first;
- for (int k=0;k<steps;k++)
- {
- FDSelect[l] = fd;
- l++;
- }
- // The last from this iteration is the first of the next
- first = last;
- }
- // Store the length for later use
- fonts[Font].FDSelectLength = 1+2+nRanges*3+2;
- break;
- default:
- break;
- }
- // Save the FDSelect of the font
- fonts[Font].FDSelect = FDSelect;
- }
-
- /**
- * Function reads the FDSelect and builds the FDArrayUsed HashMap According to the glyphs used
- * @param Font the Number of font being processed
- */
- protected void BuildFDArrayUsed(int Font)
- {
- int[] FDSelect = fonts[Font].FDSelect;
- // For each glyph used
- for (int i=0;i<glyphsInList.size();i++)
- {
- // Pop the glyphs index
- int glyph = ((Integer)glyphsInList.get(i)).intValue();
- // Pop the glyph's FD
- int FD = FDSelect[glyph];
- // Put the FD index into the FDArrayUsed HashMap
- FDArrayUsed.put(new Integer(FD),null);
- }
- }
-
- /**
- * Read the FDArray count, offsize and Offset array
- * @param Font
- */
- protected void ReadFDArray(int Font)
- {
- seek(fonts[Font].fdarrayOffset);
- fonts[Font].FDArrayCount = getCard16();
- fonts[Font].FDArrayOffsize = getCard8();
- // Since we will change values inside the FDArray objects
- // We increase its offsize to prevent errors
- if (fonts[Font].FDArrayOffsize < 4)
- fonts[Font].FDArrayOffsize++;
- fonts[Font].FDArrayOffsets = getIndex(fonts[Font].fdarrayOffset);
- }
-
-
- /**
- * The Process function extracts one font out of the CFF file and returns a
- * subset version of the original.
- * @param fontName - The name of the font to be taken out of the CFF
- * @return The new font stream
- * @throws IOException
- */
- public byte[] Process(String fontName)throws IOException{
- try
- {
- // Verify that the file is open
- buf.reOpen();
- // Find the Font that we will be dealing with
- int j;
- for (j=0; j<fonts.length; j++)
- if (fontName.equals(fonts[j].name)) break;
- if (j==fonts.length) return null;
-
- // Calc the bias for the global subrs
- if (gsubrIndexOffset >= 0)
- GBias = CalcBias(gsubrIndexOffset,j);
-
- // Prepare the new CharStrings Index
- BuildNewCharString(j);
- // Prepare the new Global and Local Subrs Indices
- BuildNewLGSubrs(j);
- // Build the new file
- byte[] Ret = BuildNewFile(j);
- return Ret;
- }
- finally {
- try {
- buf.close();
- }
- catch (Exception e) {
- // empty on purpose
- }
- }
- }
-
- /**
- * Function calcs bias according to the CharString type and the count
- * of the subrs
- * @param Offset The offset to the relevent subrs index
- * @param Font the font
- * @return The calculated Bias
- */
- protected int CalcBias(int Offset,int Font)
- {
- seek(Offset);
- int nSubrs = getCard16();
- // If type==1 -> bias=0
- if (fonts[Font].CharstringType == 1)
- return 0;
- // else calc according to the count
- else if (nSubrs < 1240)
- return 107;
- else if (nSubrs < 33900)
- return 1131;
- else
- return 32768;
- }
-
- /**
- *Function uses BuildNewIndex to create the new index of the subset charstrings
- * @param FontIndex the font
- * @throws IOException
- */
- protected void BuildNewCharString(int FontIndex) throws IOException
- {
- NewCharStringsIndex = BuildNewIndex(fonts[FontIndex].charstringsOffsets,GlyphsUsed);
- }
-
- /**
- * Function builds the new local & global subsrs indices. IF CID then All of
- * the FD Array lsubrs will be subsetted.
- * @param Font the font
- * @throws IOException
- */
- protected void BuildNewLGSubrs(int Font)throws IOException
- {
- // If the font is CID then the lsubrs are divided into FontDicts.
- // for each FD array the lsubrs will be subsetted.
- if(fonts[Font].isCID)
- {
- // Init the hasmap-array and the arraylist-array to hold the subrs used
- // in each private dict.
- hSubrsUsed = new HashMap[fonts[Font].fdprivateOffsets.length];
- lSubrsUsed = new ArrayList[fonts[Font].fdprivateOffsets.length];
- // A [][] which will store the byte array for each new FD Array lsubs index
- NewLSubrsIndex = new byte[fonts[Font].fdprivateOffsets.length][];
- // An array to hold the offset for each Lsubr index
- fonts[Font].PrivateSubrsOffset = new int[fonts[Font].fdprivateOffsets.length];
- // A [][] which will store the offset array for each lsubr index
- fonts[Font].PrivateSubrsOffsetsArray = new int[fonts[Font].fdprivateOffsets.length][];
-
- // Put the FDarrayUsed into a list
- ArrayList FDInList = new ArrayList(FDArrayUsed.keySet());
- // For each FD array which is used subset the lsubr
- for (int j=0;j<FDInList.size();j++)
- {
- // The FDArray index, Hash Map, Arrat List to work on
- int FD = ((Integer)FDInList.get(j)).intValue();
- hSubrsUsed[FD] = new HashMap();
- lSubrsUsed[FD] = new ArrayList();
- //Reads the private dicts looking for the subr operator and
- // store both the offest for the index and its offset array
- BuildFDSubrsOffsets(Font,FD);
- // Verify that FDPrivate has a LSubrs index
- if(fonts[Font].PrivateSubrsOffset[FD]>=0)
- {
- //Scans the Charsting data storing the used Local and Global subroutines
- // by the glyphs. Scans the Subrs recursivley.
- BuildSubrUsed(Font,FD,fonts[Font].PrivateSubrsOffset[FD],fonts[Font].PrivateSubrsOffsetsArray[FD],hSubrsUsed[FD],lSubrsUsed[FD]);
- // Builds the New Local Subrs index
- NewLSubrsIndex[FD] = BuildNewIndex(fonts[Font].PrivateSubrsOffsetsArray[FD],hSubrsUsed[FD]);
- }
- }
- }
- // If the font is not CID && the Private Subr exists then subset:
- else if (fonts[Font].privateSubrs>=0)
- {
- // Build the subrs offsets;
- fonts[Font].SubrsOffsets = getIndex(fonts[Font].privateSubrs);
- //Scans the Charsting data storing the used Local and Global subroutines
- // by the glyphs. Scans the Subrs recursivley.
- BuildSubrUsed(Font,-1,fonts[Font].privateSubrs,fonts[Font].SubrsOffsets,hSubrsUsedNonCID,lSubrsUsedNonCID);
- }
- // For all fonts susbset the Global Subroutines
- // Scan the Global Subr Hashmap recursivly on the Gsubrs
- BuildGSubrsUsed(Font);
- if (fonts[Font].privateSubrs>=0)
- // Builds the New Local Subrs index
- NewSubrsIndexNonCID = BuildNewIndex(fonts[Font].SubrsOffsets,hSubrsUsedNonCID);
- //Builds the New Global Subrs index
- NewGSubrsIndex = BuildNewIndex(gsubrOffsets,hGSubrsUsed);
- }
-
- /**
- * The function finds for the FD array processed the local subr offset and its
- * offset array.
- * @param Font the font
- * @param FD The FDARRAY processed
- */
- protected void BuildFDSubrsOffsets(int Font,int FD)
- {
- // Initiate to -1 to indicate lsubr operator present
- fonts[Font].PrivateSubrsOffset[FD] = -1;
- // Goto begining of objects
- seek(fonts[Font].fdprivateOffsets[FD]);
- // While in the same object:
- while (getPosition() < fonts[Font].fdprivateOffsets[FD]+fonts[Font].fdprivateLengths[FD])
- {
- getDictItem();
- // If the dictItem is the "Subrs" then find and store offset,
- if (key=="Subrs")
- fonts[Font].PrivateSubrsOffset[FD] = ((Integer)args[0]).intValue()+fonts[Font].fdprivateOffsets[FD];
- }
- //Read the lsub index if the lsubr was found
- if (fonts[Font].PrivateSubrsOffset[FD] >= 0)
- fonts[Font].PrivateSubrsOffsetsArray[FD] = getIndex(fonts[Font].PrivateSubrsOffset[FD]);
- }
-
- /**
- * Function uses ReadAsubr on the glyph used to build the LSubr & Gsubr HashMap.
- * The HashMap (of the lsub only) is then scaned recursivly for Lsubr & Gsubrs
- * calls.
- * @param Font the font
- * @param FD FD array processed. 0 indicates function was called by non CID font
- * @param SubrOffset the offset to the subr index to calc the bias
- * @param SubrsOffsets the offset array of the subr index
- * @param hSubr HashMap of the subrs used
- * @param lSubr ArrayList of the subrs used
- */
- protected void BuildSubrUsed(int Font,int FD,int SubrOffset,int[] SubrsOffsets,HashMap hSubr,ArrayList lSubr)
- {
-
- // Calc the Bias for the subr index
- int LBias = CalcBias(SubrOffset,Font);
-
- // For each glyph used find its GID, start & end pos
- for (int i=0;i<glyphsInList.size();i++)
- {
- int glyph = ((Integer)glyphsInList.get(i)).intValue();
- int Start = fonts[Font].charstringsOffsets[glyph];
- int End = fonts[Font].charstringsOffsets[glyph+1];
-
- // IF CID:
- if (FD >= 0)
- {
- EmptyStack();
- NumOfHints=0;
- // Using FDSELECT find the FD Array the glyph belongs to.
- int GlyphFD = fonts[Font].FDSelect[glyph];
- // If the Glyph is part of the FD being processed
- if (GlyphFD == FD)
- // Find the Subrs called by the glyph and insert to hash:
- ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
- }
- else
- // If the font is not CID
- //Find the Subrs called by the glyph and insert to hash:
- ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
- }
- // For all Lsubrs used, check recusrivly for Lsubr & Gsubr used
- for (int i=0;i<lSubr.size();i++)
- {
- // Pop the subr value from the hash
- int Subr = ((Integer)lSubr.get(i)).intValue();
- // Ensure the Lsubr call is valid
- if (Subr < SubrsOffsets.length-1 && Subr>=0)
- {
- // Read and process the subr
- int Start = SubrsOffsets[Subr];
- int End = SubrsOffsets[Subr+1];
- ReadASubr(Start,End,GBias,LBias,hSubr,lSubr,SubrsOffsets);
- }
- }
- }
-
- /**
- * Function scans the Glsubr used ArrayList to find recursive calls
- * to Gsubrs and adds to Hashmap & ArrayList
- * @param Font the font
- */
- protected void BuildGSubrsUsed(int Font)
- {
- int LBias = 0;
- int SizeOfNonCIDSubrsUsed = 0;
- if (fonts[Font].privateSubrs>=0)
- {
- LBias = CalcBias(fonts[Font].privateSubrs,Font);
- SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
- }
-
- // For each global subr used
- for (int i=0;i<lGSubrsUsed.size();i++)
- {
- //Pop the value + check valid
- int Subr = ((Integer)lGSubrsUsed.get(i)).intValue();
- if (Subr < gsubrOffsets.length-1 && Subr>=0)
- {
- // Read the subr and process
- int Start = gsubrOffsets[Subr];
- int End = gsubrOffsets[Subr+1];
-
- if (fonts[Font].isCID)
- ReadASubr(Start,End,GBias,0,hGSubrsUsed,lGSubrsUsed,null);
- else
- {
- ReadASubr(Start,End,GBias,LBias,hSubrsUsedNonCID,lSubrsUsedNonCID,fonts[Font].SubrsOffsets);
- if (SizeOfNonCIDSubrsUsed < lSubrsUsedNonCID.size())
- {
- for (int j=SizeOfNonCIDSubrsUsed;j<lSubrsUsedNonCID.size();j++)
- {
- //Pop the value + check valid
- int LSubr = ((Integer)lSubrsUsedNonCID.get(j)).intValue();
- if (LSubr < fonts[Font].SubrsOffsets.length-1 && LSubr>=0)
- {
- // Read the subr and process
- int LStart = fonts[Font].SubrsOffsets[LSubr];
- int LEnd = fonts[Font].SubrsOffsets[LSubr+1];
- ReadASubr(LStart,LEnd,GBias,LBias,hSubrsUsedNonCID,lSubrsUsedNonCID,fonts[Font].SubrsOffsets);
- }
- }
- SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
- }
- }
- }
- }
- }
-
- /**
- * The function reads a subrs (glyph info) between begin and end.
- * Adds calls to a Lsubr to the hSubr and lSubrs.
- * Adds calls to a Gsubr to the hGSubr and lGSubrs.
- * @param begin the start point of the subr
- * @param end the end point of the subr
- * @param GBias the bias of the Global Subrs
- * @param LBias the bias of the Local Subrs
- * @param hSubr the HashMap for the lSubrs
- * @param lSubr the ArrayList for the lSubrs
- */
- protected void ReadASubr(int begin,int end,int GBias,int LBias,HashMap hSubr,ArrayList lSubr,int[] LSubrsOffsets)
- {
- // Clear the stack for the subrs
- EmptyStack();
- NumOfHints = 0;
- // Goto begining of the subr
- seek(begin);
- while (getPosition() < end)
- {
- // Read the next command
- ReadCommand();
- int pos = getPosition();
- Object TopElement=null;
- if (arg_count > 0)
- TopElement = args[arg_count-1];
- int NumOfArgs = arg_count;
- // Check the modification needed on the Argument Stack according to key;
- HandelStack();
- // a call to a Lsubr
- if (key=="callsubr")
- {
- // Verify that arguments are passed
- if (NumOfArgs > 0)
- {
- // Calc the index of the Subrs
- int Subr = ((Integer)TopElement).intValue() + LBias;
- // If the subr isn't in the HashMap -> Put in
- if (!hSubr.containsKey(new Integer (Subr)))
- {
- hSubr.put(new Integer(Subr),null);
- lSubr.add(new Integer(Subr));
- }
- CalcHints(LSubrsOffsets[Subr],LSubrsOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
- seek(pos);
- }
- }
- // a call to a Gsubr
- else if (key=="callgsubr")
- {
- // Verify that arguments are passed
- if (NumOfArgs > 0)
- {
- // Calc the index of the Subrs
- int Subr = ((Integer)TopElement).intValue() + GBias;
- // If the subr isn't in the HashMap -> Put in
- if (!hGSubrsUsed.containsKey(new Integer (Subr)))
- {
- hGSubrsUsed.put(new Integer(Subr),null);
- lGSubrsUsed.add(new Integer(Subr));
- }
- CalcHints(gsubrOffsets[Subr],gsubrOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
- seek(pos);
- }
- }
- // A call to "stem"
- else if (key == "hstem" || key == "vstem" || key == "hstemhm" || key == "vstemhm")
- // Increment the NumOfHints by the number couples of of arguments
- NumOfHints += NumOfArgs/2;
- // A call to "mask"
- else if (key == "hintmask" || key == "cntrmask")
- {
- // Compute the size of the mask
- int SizeOfMask = NumOfHints/8;
- if (NumOfHints%8 != 0 || SizeOfMask == 0)
- SizeOfMask++;
- // Continue the pointer in SizeOfMask steps
- for (int i=0;i<SizeOfMask;i++)
- getCard8();
- }
- }
- }
-
- /**
- * Function Checks how the current operator effects the run time stack after being run
- * An operator may increase or decrease the stack size
- */
- protected void HandelStack()
- {
- // Findout what the operator does to the stack
- int StackHandel = StackOpp();
- if (StackHandel < 2)
- {
- // The operators that enlarge the stack by one
- if (StackHandel==1)
- PushStack();
- // The operators that pop the stack
- else
- {
- // Abs value for the for loop
- StackHandel *= -1;
- for (int i=0;i<StackHandel;i++)
- PopStack();
- }
-
- }
- // All other flush the stack
- else
- EmptyStack();
- }
-
- /**
- * Function checks the key and return the change to the stack after the operator
- * @return The change in the stack. 2-> flush the stack
- */
- protected int StackOpp()
- {
- if (key == "ifelse")
- return -3;
- if (key == "roll" || key == "put")
- return -2;
- if (key == "callsubr" || key == "callgsubr" || key == "add" || key == "sub" ||
- key == "div" || key == "mul" || key == "drop" || key == "and" ||
- key == "or" || key == "eq")
- return -1;
- if (key == "abs" || key == "neg" || key == "sqrt" || key == "exch" ||
- key == "index" || key == "get" || key == "not" || key == "return")
- return 0;
- if (key == "random" || key == "dup")
- return 1;
- return 2;
- }
-
- /**
- * Empty the Type2 Stack
- *
- */
- protected void EmptyStack()
- {
- // Null the arguments
- for (int i=0; i<arg_count; i++) args[i]=null;
- arg_count = 0;
- }
-
- /**
- * Pop one element from the stack
- *
- */
- protected void PopStack()
- {
- if (arg_count>0)
- {
- args[arg_count-1]=null;
- arg_count--;
- }
- }
-
- /**
- * Add an item to the stack
- *
- */
- protected void PushStack()
- {
- arg_count++;
- }
-
- /**
- * The function reads the next command after the file pointer is set
- */
- protected void ReadCommand()
- {
- key = null;
- boolean gotKey = false;
- // Until a key is found
- while (!gotKey) {
- // Read the first Char
- char b0 = getCard8();
- // decode according to the type1/type2 format
- if (b0 == 28) // the two next bytes represent a short int;
- {
- int first = getCard8();
- int second = getCard8();
- args[arg_count] = new Integer(first<<8 | second);
- arg_count++;
- continue;
- }
- if (b0 >= 32 && b0 <= 246) // The byte read is the byte;
- {
- args[arg_count] = new Integer(b0 - 139);
- arg_count++;
- continue;
- }
- if (b0 >= 247 && b0 <= 250) // The byte read and the next byte constetute a short int
- {
- int w = getCard8();
- args[arg_count] = new Integer((b0-247)*256 + w + 108);
- arg_count++;
- continue;
- }
- if (b0 >= 251 && b0 <= 254)// Same as above except negative
- {
- int w = getCard8();
- args[arg_count] = new Integer(-(b0-251)*256 - w - 108);
- arg_count++;
- continue;
- }
- if (b0 == 255)// The next for bytes represent a double.
- {
- int first = getCard8();
- int second = getCard8();
- int third = getCard8();
- int fourth = getCard8();
- args[arg_count] = new Integer(first<<24 | second<<16 | third<<8 | fourth);
- arg_count++;
- continue;
- }
- if (b0<=31 && b0 != 28) // An operator was found.. Set Key.
- {
- gotKey=true;
- // 12 is an escape command therefor the next byte is a part
- // of this command
- if (b0 == 12)
- {
- int b1 = getCard8();
- if (b1>SubrsEscapeFuncs.length-1)
- b1 = SubrsEscapeFuncs.length-1;
- key = SubrsEscapeFuncs[b1];
- }
- else
- key = SubrsFunctions[b0];
- continue;
- }
- }
- }
-
- /**
- * The function reads the subroutine and returns the number of the hint in it.
- * If a call to another subroutine is found the function calls recursively.
- * @param begin the start point of the subr
- * @param end the end point of the subr
- * @param LBias the bias of the Local Subrs
- * @param GBias the bias of the Global Subrs
- * @param LSubrsOffsets The Offsets array of the subroutines
- * @return The number of hints in the subroutine read.
- */
- protected int CalcHints(int begin,int end,int LBias,int GBias,int[] LSubrsOffsets)
- {
- // Goto begining of the subr
- seek(begin);
- while (getPosition() < end)
- {
- // Read the next command
- ReadCommand();
- int pos = getPosition();
- Object TopElement = null;
- if (arg_count>0)
- TopElement = args[arg_count-1];
- int NumOfArgs = arg_count;
- //Check the modification needed on the Argument Stack according to key;
- HandelStack();
- // a call to a Lsubr
- if (key=="callsubr")
- {
- if (NumOfArgs>0)
- {
- int Subr = ((Integer)TopElement).intValue() + LBias;
- CalcHints(LSubrsOffsets[Subr],LSubrsOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
- seek(pos);
- }
- }
- // a call to a Gsubr
- else if (key=="callgsubr")
- {
- if (NumOfArgs>0)
- {
- int Subr = ((Integer)TopElement).intValue() + GBias;
- CalcHints(gsubrOffsets[Subr],gsubrOffsets[Subr+1],LBias,GBias,LSubrsOffsets);
- seek(pos);
- }
- }
- // A call to "stem"
- else if (key == "hstem" || key == "vstem" || key == "hstemhm" || key == "vstemhm")
- // Increment the NumOfHints by the number couples of of arguments
- NumOfHints += NumOfArgs/2;
- // A call to "mask"
- else if (key == "hintmask" || key == "cntrmask")
- {
- // Compute the size of the mask
- int SizeOfMask = NumOfHints/8;
- if (NumOfHints%8 != 0 || SizeOfMask == 0)
- SizeOfMask++;
- // Continue the pointer in SizeOfMask steps
- for (int i=0;i<SizeOfMask;i++)
- getCard8();
- }
- }
- return NumOfHints;
- }
-
-
- /**
- * Function builds the new offset array, object array and assembles the index.
- * used for creating the glyph and subrs subsetted index
- * @param Offsets the offset array of the original index
- * @param Used the hashmap of the used objects
- * @return the new index subset version
- * @throws IOException
- */
- protected byte[] BuildNewIndex(int[] Offsets,HashMap Used) throws IOException
- {
- int Offset=0;
- int[] NewOffsets = new int[Offsets.length];
- // Build the Offsets Array for the Subset
- for (int i=0;i<Offsets.length;++i)
- {
- NewOffsets[i] = Offset;
- // If the object in the offset is also present in the used
- // HashMap then increment the offset var by its size
- if (Used.containsKey(new Integer(i)))
- Offset += Offsets[i+1] - Offsets[i];
- // Else the same offset is kept in i+1.
- }
- // Offset var determines the size of the object array
- byte[] NewObjects = new byte[Offset];
- // Build the new Object array
- for (int i=0;i<Offsets.length-1;++i)
- {
- int start = NewOffsets[i];
- int end = NewOffsets[i+1];
- // If start != End then the Object is used
- // So, we will copy the object data from the font file
- if (start != end)
- {
- // All offsets are Global Offsets relative to the begining of the font file.
- // Jump the file pointer to the start address to read from.
- buf.seek(Offsets[i]);
- // Read from the buffer and write into the array at start.
- buf.readFully(NewObjects, start, end-start);
- }
- }
- // Use AssembleIndex to build the index from the offset & object arrays
- return AssembleIndex(NewOffsets,NewObjects);
- }
-
- /**
- * Function creates the new index, inserting the count,offsetsize,offset array
- * and object array.
- * @param NewOffsets the subsetted offset array
- * @param NewObjects the subsetted object array
- * @return the new index created
- */
- protected byte[] AssembleIndex(int[] NewOffsets,byte[] NewObjects)
- {
- // Calc the index' count field
- char Count = (char)(NewOffsets.length-1);
- // Calc the size of the object array
- int Size = NewOffsets[NewOffsets.length-1];
- // Calc the Offsize
- byte Offsize;
- if (Size <= 0xff) Offsize = 1;
- else if (Size <= 0xffff) Offsize = 2;
- else if (Size <= 0xffffff) Offsize = 3;
- else Offsize = 4;
- // The byte array for the new index. The size is calc by
- // Count=2, Offsize=1, OffsetArray = Offsize*(Count+1), The object array
- byte[] NewIndex = new byte[2+1+Offsize*(Count+1)+NewObjects.length];
- // The counter for writing
- int Place = 0;
- // Write the count field
- NewIndex[Place++] = (byte) ((Count >>> 8) & 0xff);
- NewIndex[Place++] = (byte) ((Count >>> 0) & 0xff);
- // Write the offsize field
- NewIndex[Place++] = Offsize;
- // Write the offset array according to the offsize
- for (int i=0;i<NewOffsets.length;i++)
- {
- // The value to be written
- int Num = NewOffsets[i]-NewOffsets[0]+1;
- // Write in bytes according to the offsize
- switch (Offsize) {
- case 4:
- NewIndex[Place++] = (byte) ((Num >>> 24) & 0xff);
- case 3:
- NewIndex[Place++] = (byte) ((Num >>> 16) & 0xff);
- case 2:
- NewIndex[Place++] = (byte) ((Num >>> 8) & 0xff);
- case 1:
- NewIndex[Place++] = (byte) ((Num >>> 0) & 0xff);
- }
- }
- // Write the new object array one by one
- for (int i=0;i<NewObjects.length;i++)
- {
- NewIndex[Place++] = NewObjects[i];
- }
- // Return the new index
- return NewIndex;
- }
-
- /**
- * The function builds the new output stream according to the subset process
- * @param Font the font
- * @return the subseted font stream
- * @throws IOException
- */
- protected byte[] BuildNewFile(int Font)throws IOException
- {
- // Prepare linked list for new font components
- OutputList = new LinkedList();
-
- // copy the header of the font
- CopyHeader();
-
- // create a name index
- BuildIndexHeader(1,1,1);
- OutputList.addLast(new UInt8Item((char)( 1+fonts[Font].name.length() )));
- OutputList.addLast(new StringItem(fonts[Font].name));
-
- // create the topdict Index
- BuildIndexHeader(1,2,1);
- OffsetItem topdictIndex1Ref = new IndexOffsetItem(2);
- OutputList.addLast(topdictIndex1Ref);
- IndexBaseItem topdictBase = new IndexBaseItem();
- OutputList.addLast(topdictBase);
-
- // Initialise the Dict Items for later use
- OffsetItem charsetRef = new DictOffsetItem();
- OffsetItem charstringsRef = new DictOffsetItem();
- OffsetItem fdarrayRef = new DictOffsetItem();
- OffsetItem fdselectRef = new DictOffsetItem();
- OffsetItem privateRef = new DictOffsetItem();
-
- // If the font is not CID create the following keys
- if ( !fonts[Font].isCID ) {
- // create a ROS key
- OutputList.addLast(new DictNumberItem(fonts[Font].nstrings));
- OutputList.addLast(new DictNumberItem(fonts[Font].nstrings+1));
- OutputList.addLast(new DictNumberItem(0));
- OutputList.addLast(new UInt8Item((char)12));
- OutputList.addLast(new UInt8Item((char)30));
- // create a CIDCount key
- OutputList.addLast(new DictNumberItem(fonts[Font].nglyphs));
- OutputList.addLast(new UInt8Item((char)12));
- OutputList.addLast(new UInt8Item((char)34));
- // Sivan's comments
- // 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.
- }
- // Go to the TopDict of the font being processed
- seek(topdictOffsets[Font]);
- // Run untill the end of the TopDict
- while (getPosition() < topdictOffsets[Font+1]) {
- int p1 = getPosition();
- getDictItem();
- int p2 = getPosition();
- // The encoding key is disregarded since CID has no encoding
- if (key=="Encoding"
- // These keys will be added manualy by the process.
- || key=="Private"
- || key=="FDSelect"
- || key=="FDArray"
- || key=="charset"
- || key=="CharStrings"
- ) {
- }else {
- //OtherWise copy key "as is" to the output list
- OutputList.add(new RangeItem(buf,p1,p2-p1));
- }
- }
- // Create the FDArray, FDSelect, Charset and CharStrings Keys
- CreateKeys(fdarrayRef,fdselectRef,charsetRef,charstringsRef);
-
- // Mark the end of the top dict area
- OutputList.addLast(new IndexMarkerItem(topdictIndex1Ref,topdictBase));
-
- // Copy the string index
-
- if (fonts[Font].isCID)
- OutputList.addLast(getEntireIndexRange(stringIndexOffset));
- // If the font is not CID we need to 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
- else
- CreateNewStringIndex(Font);
-
- // copy the new subsetted global subroutine index
- OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewGSubrsIndex),0,NewGSubrsIndex.length));
-
- // deal with fdarray, fdselect, and the font descriptors
- // If the font is CID:
- if (fonts[Font].isCID) {
- // copy the FDArray, FDSelect, charset
-
- // Copy FDSelect
- // Mark the beginning
- OutputList.addLast(new MarkerItem(fdselectRef));
- // If an FDSelect exists copy it
- if (fonts[Font].fdselectOffset>=0)
- OutputList.addLast(new RangeItem(buf,fonts[Font].fdselectOffset,fonts[Font].FDSelectLength));
- // Else create a new one
- else
- CreateFDSelect(fdselectRef,fonts[Font].nglyphs);
-
- // Copy the Charset
- // Mark the beginning and copy entirly
- OutputList.addLast(new MarkerItem(charsetRef));
- OutputList.addLast(new RangeItem(buf,fonts[Font].charsetOffset,fonts[Font].CharsetLength));
-
- // Copy the FDArray
- // If an FDArray exists
- if (fonts[Font].fdarrayOffset>=0)
- {
- // Mark the beginning
- OutputList.addLast(new MarkerItem(fdarrayRef));
- // Build a new FDArray with its private dicts and their LSubrs
- Reconstruct(Font);
- }
- else
- // Else create a new one
- CreateFDArray(fdarrayRef,privateRef,Font);
-
- }
- // If the font is not CID
- else
- {
- // create FDSelect
- CreateFDSelect(fdselectRef,fonts[Font].nglyphs);
- // recreate a new charset
- CreateCharset(charsetRef,fonts[Font].nglyphs);
- // create a font dict index (fdarray)
- CreateFDArray(fdarrayRef,privateRef,Font);
- }
-
- // if a private dict exists insert its subsetted version
- if (fonts[Font].privateOffset>=0)
- {
- // Mark the beginning of the private dict
- IndexBaseItem PrivateBase = new IndexBaseItem();
- OutputList.addLast(PrivateBase);
- OutputList.addLast(new MarkerItem(privateRef));
-
- OffsetItem Subr = new DictOffsetItem();
- // Build and copy the new private dict
- CreateNonCIDPrivate(Font,Subr);
- // Copy the new LSubrs index
- CreateNonCIDSubrs(Font,PrivateBase,Subr);
- }
-
- // copy the charstring index
- OutputList.addLast(new MarkerItem(charstringsRef));
-
- // Add the subsetted charstring
- OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewCharStringsIndex),0,NewCharStringsIndex.length));
-
- // now create the new CFF font
- int[] currentOffset = new int[1];
- currentOffset[0] = 0;
- // Count and save the offset for each item
- Iterator listIter = OutputList.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.increment(currentOffset);
- }
- // Compute the Xref for each of the offset items
- listIter = OutputList.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.xref();
- }
-
- int size = currentOffset[0];
- byte[] b = new byte[size];
-
- // Emit all the items into the new byte array
- listIter = OutputList.iterator();
- while ( listIter.hasNext() ) {
- Item item = (Item) listIter.next();
- item.emit(b);
- }
- // Return the new stream
- return b;
- }
-
- /**
- * Function Copies the header from the original fileto the output list
- */
- protected void CopyHeader()
- {
- seek(0);
- int major = getCard8();
- int minor = getCard8();
- int hdrSize = getCard8();
- int offSize = getCard8();
- nextIndexOffset = hdrSize;
- OutputList.addLast(new RangeItem(buf,0,hdrSize));
- }
-
- /**
- * Function Build the header of an index
- * @param Count the count field of the index
- * @param Offsize the offsize field of the index
- * @param First the first offset of the index
- */
- protected void BuildIndexHeader(int Count,int Offsize,int First)
- {
- // Add the count field
- OutputList.addLast(new UInt16Item((char)Count)); // count
- // Add the offsize field
- OutputList.addLast(new UInt8Item((char)Offsize)); // offSize
- // Add the first offset according to the offsize
- switch(Offsize){
- case 1:
- OutputList.addLast(new UInt8Item((char)First)); // first offset
- break;
- case 2:
- OutputList.addLast(new UInt16Item((char)First)); // first offset
- break;
- case 3:
- OutputList.addLast(new UInt24Item((char)First)); // first offset
- break;
- case 4:
- OutputList.addLast(new UInt32Item((char)First)); // first offset
- break;
- default:
- break;
- }
- }
-
- /**
- * Function adds the keys into the TopDict
- * @param fdarrayRef OffsetItem for the FDArray
- * @param fdselectRef OffsetItem for the FDSelect
- * @param charsetRef OffsetItem for the CharSet
- * @param charstringsRef OffsetItem for the CharString
- */
- protected void CreateKeys(OffsetItem fdarrayRef,OffsetItem fdselectRef,OffsetItem charsetRef,OffsetItem charstringsRef)
- {
- // create an FDArray key
- OutputList.addLast(fdarrayRef);
- OutputList.addLast(new UInt8Item((char)12));
- OutputList.addLast(new UInt8Item((char)36));
- // create an FDSelect key
- OutputList.addLast(fdselectRef);
- OutputList.addLast(new UInt8Item((char)12));
- OutputList.addLast(new UInt8Item((char)37));
- // create an charset key
- OutputList.addLast(charsetRef);
- OutputList.addLast(new UInt8Item((char)15));
- // create a CharStrings key
- OutputList.addLast(charstringsRef);
- OutputList.addLast(new UInt8Item((char)17));
- }
-
- /**
- * Function takes the original string item and adds the new strings
- * to accomodate the CID rules
- * @param Font the font
- */
- protected void CreateNewStringIndex(int Font)
- {
- String fdFontName = fonts[Font].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;
-
- OutputList.addLast(new UInt16Item((char)((stringOffsets.length-1)+3))); // count
- OutputList.addLast(new UInt8Item((char)stringsIndexOffSize)); // offSize
- for (int i=0; i<stringOffsets.length; i++)
- OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,
- stringOffsets[i]-stringsBaseOffset));
- int currentStringsOffset = stringOffsets[stringOffsets.length-1]
- - stringsBaseOffset;
- //l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
- currentStringsOffset += ("Adobe").length();
- OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
- currentStringsOffset += ("Identity").length();
- OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
- currentStringsOffset += fdFontName.length();
- OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
-
- OutputList.addLast(new RangeItem(buf,stringOffsets[0],origStringsLen));
- OutputList.addLast(new StringItem(extraStrings));
- }
-
- /**
- * Function creates new FDSelect for non-CID fonts.
- * The FDSelect built uses a single range for all glyphs
- * @param fdselectRef OffsetItem for the FDSelect
- * @param nglyphs the number of glyphs in the font
- */
- protected void CreateFDSelect(OffsetItem fdselectRef,int nglyphs)
- {
- OutputList.addLast(new MarkerItem(fdselectRef));
- OutputList.addLast(new UInt8Item((char)3)); // format identifier
- OutputList.addLast(new UInt16Item((char)1)); // nRanges
-
- OutputList.addLast(new UInt16Item((char)0)); // Range[0].firstGlyph
- OutputList.addLast(new UInt8Item((char)0)); // Range[0].fd
-
- OutputList.addLast(new UInt16Item((char)nglyphs)); // sentinel
- }
-
- /**
- * Function creates new CharSet for non-CID fonts.
- * The CharSet built uses a single range for all glyphs
- * @param charsetRef OffsetItem for the CharSet
- * @param nglyphs the number of glyphs in the font
- */
- protected void CreateCharset(OffsetItem charsetRef,int nglyphs)
- {
- OutputList.addLast(new MarkerItem(charsetRef));
- OutputList.addLast(new UInt8Item((char)2)); // format identifier
- OutputList.addLast(new UInt16Item((char)1)); // first glyph in range (ignore .notdef)
- OutputList.addLast(new UInt16Item((char)(nglyphs-1))); // nLeft
- }
-
- /**
- * Function creates new FDArray for non-CID fonts.
- * The FDArray built has only the "Private" operator that points to the font's
- * original private dict
- * @param fdarrayRef OffsetItem for the FDArray
- * @param privateRef OffsetItem for the Private Dict
- * @param Font the font
- */
- protected void CreateFDArray(OffsetItem fdarrayRef,OffsetItem privateRef,int Font)
- {
- OutputList.addLast(new MarkerItem(fdarrayRef));
- // Build the header (count=offsize=first=1)
- BuildIndexHeader(1,1,1);
-
- // Mark
- OffsetItem privateIndex1Ref = new IndexOffsetItem(1);
- OutputList.addLast(privateIndex1Ref);
- IndexBaseItem privateBase = new IndexBaseItem();
- // Insert the private operands and operator
- OutputList.addLast(privateBase);
- // Calc the new size of the private after subsetting
- // Origianl size
- int NewSize = fonts[Font].privateLength;
- // Calc the original size of the Subr offset in the private
- int OrgSubrsOffsetSize = CalcSubrOffsetSize(fonts[Font].privateOffset,fonts[Font].privateLength);
- // Increase the ptivate's size
- if (OrgSubrsOffsetSize != 0)
- NewSize += 5-OrgSubrsOffsetSize;
- OutputList.addLast(new DictNumberItem(NewSize));
- OutputList.addLast(privateRef);
- OutputList.addLast(new UInt8Item((char)18)); // Private
-
- OutputList.addLast(new IndexMarkerItem(privateIndex1Ref,privateBase));
- }
-
- /**
- * Function reconstructs the FDArray, PrivateDict and LSubr for CID fonts
- * @param Font the font
- * @throws IOException
- */
- void Reconstruct(int Font)throws IOException
- {
- // Init for later use
- OffsetItem[] fdPrivate = new DictOffsetItem[fonts[Font].FDArrayOffsets.length-1];
- IndexBaseItem[] fdPrivateBase = new IndexBaseItem[fonts[Font].fdprivateOffsets.length];
- OffsetItem[] fdSubrs = new DictOffsetItem[fonts[Font].fdprivateOffsets.length];
- // Reconstruct each type
- ReconstructFDArray(Font,fdPrivate);
- ReconstructPrivateDict(Font,fdPrivate,fdPrivateBase,fdSubrs);
- ReconstructPrivateSubrs(Font,fdPrivateBase,fdSubrs);
- }
-
- /**
- * Function subsets the FDArray and builds the new one with new offsets
- * @param Font The font
- * @param fdPrivate OffsetItem Array (one for each FDArray)
- * @throws IOException
- */
- void ReconstructFDArray(int Font,OffsetItem[] fdPrivate)throws IOException
- {
- // Build the header of the index
- BuildIndexHeader(fonts[Font].FDArrayCount,fonts[Font].FDArrayOffsize,1);
-
- // For each offset create an Offset Item
- OffsetItem[] fdOffsets = new IndexOffsetItem[fonts[Font].FDArrayOffsets.length-1];
- for (int i=0;i<fonts[Font].FDArrayOffsets.length-1;i++)
- {
- fdOffsets[i] = new IndexOffsetItem(fonts[Font].FDArrayOffsize);
- OutputList.addLast(fdOffsets[i]);
- }
-
- // Declare beginning of the object array
- IndexBaseItem fdArrayBase = new IndexBaseItem();
- OutputList.addLast(fdArrayBase);
-
- // For each object check if that FD is used.
- // if is used build a new one by changing the private object
- // Else do nothing
- // At the end of each object mark its ending (Even if wasn't written)
- for (int k=0; k<fonts[Font].FDArrayOffsets.length-1; k++) {
- if (FDArrayUsed.containsKey(new Integer (k)))
- {
- // Goto begining of objects
- seek(fonts[Font].FDArrayOffsets[k]);
- while (getPosition() < fonts[Font].FDArrayOffsets[k+1])
- {
- int p1 = getPosition();
- getDictItem();
- int p2 = getPosition();
- // If the dictItem is the "Private" then compute and copy length,
- // use marker for offset and write operator number
- if (key=="Private") {
- // Save the original length of the private dict
- int NewSize = ((Integer)args[0]).intValue();
- // Save the size of the offset to the subrs in that private
- int OrgSubrsOffsetSize = CalcSubrOffsetSize(fonts[Font].fdprivateOffsets[k],fonts[Font].fdprivateLengths[k]);
- // Increase the private's length accordingly
- if (OrgSubrsOffsetSize != 0)
- NewSize += 5-OrgSubrsOffsetSize;
- // Insert the new size, OffsetItem and operator key number
- OutputList.addLast(new DictNumberItem(NewSize));
- fdPrivate[k] = new DictOffsetItem();
- OutputList.addLast(fdPrivate[k]);
- OutputList.addLast(new UInt8Item((char)18)); // Private
- // Go back to place
- seek(p2);
- }
- // Else copy the entire range
- else // other than private
- OutputList.addLast(new RangeItem(buf,p1,p2-p1));
- }
- }
- // Mark the ending of the object (even if wasn't written)
- OutputList.addLast(new IndexMarkerItem(fdOffsets[k],fdArrayBase));
- }
- }
- /**
- * Function Adds the new private dicts (only for the FDs used) to the list
- * @param Font the font
- * @param fdPrivate OffsetItem array one element for each private
- * @param fdPrivateBase IndexBaseItem array one element for each private
- * @param fdSubrs OffsetItem array one element for each private
- * @throws IOException
- */
- void ReconstructPrivateDict(int Font,OffsetItem[] fdPrivate,IndexBaseItem[] fdPrivateBase,
- OffsetItem[] fdSubrs)throws IOException
- {
-
- // For each fdarray private dict check if that FD is used.
- // if is used build a new one by changing the subrs offset
- // Else do nothing
- for (int i=0;i<fonts[Font].fdprivateOffsets.length;i++)
- {
- if (FDArrayUsed.containsKey(new Integer (i)))
- {
- // Mark beginning
- OutputList.addLast(new MarkerItem(fdPrivate[i]));
- fdPrivateBase[i] = new IndexBaseItem();
- OutputList.addLast(fdPrivateBase[i]);
- // Goto begining of objects
- seek(fonts[Font].fdprivateOffsets[i]);
- while (getPosition() < fonts[Font].fdprivateOffsets[i]+fonts[Font].fdprivateLengths[i])
- {
- int p1 = getPosition();
- getDictItem();
- int p2 = getPosition();
- // If the dictItem is the "Subrs" then,
- // use marker for offset and write operator number
- if (key=="Subrs") {
- fdSubrs[i] = new DictOffsetItem();
- OutputList.addLast(fdSubrs[i]);
- OutputList.addLast(new UInt8Item((char)19)); // Subrs
- }
- // Else copy the entire range
- else
- OutputList.addLast(new RangeItem(buf,p1,p2-p1));
- }
- }
- }
- }
-
- /**
- * Function Adds the new LSubrs dicts (only for the FDs used) to the list
- * @param Font The index of the font
- * @param fdPrivateBase The IndexBaseItem array for the linked list
- * @param fdSubrs OffsetItem array for the linked list
- * @throws IOException
- */
-
- void ReconstructPrivateSubrs(int Font,IndexBaseItem[] fdPrivateBase,
- OffsetItem[] fdSubrs)throws IOException
- {
- // For each private dict
- for (int i=0;i<fonts[Font].fdprivateLengths.length;i++)
- {
- // If that private dict's Subrs are used insert the new LSubrs
- // computed earlier
- if (fdSubrs[i]!= null && fonts[Font].PrivateSubrsOffset[i] >= 0)
- {
- OutputList.addLast(new SubrMarkerItem(fdSubrs[i],fdPrivateBase[i]));
- OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewLSubrsIndex[i]),0,NewLSubrsIndex[i].length));
- }
- }
- }
-
- /**
- * Calculates how many byte it took to write the offset for the subrs in a specific
- * private dict.
- * @param Offset The Offset for the private dict
- * @param Size The size of the private dict
- * @return The size of the offset of the subrs in the private dict
- */
- int CalcSubrOffsetSize(int Offset,int Size)
- {
- // Set the size to 0
- int OffsetSize = 0;
- // Go to the beginning of the private dict
- seek(Offset);
- // Go until the end of the private dict
- while (getPosition() < Offset+Size)
- {
- int p1 = getPosition();
- getDictItem();
- int p2 = getPosition();
- // When reached to the subrs offset
- if (key=="Subrs") {
- // The Offsize (minus the subrs key)
- OffsetSize = p2-p1-1;
- }
- // All other keys are ignored
- }
- // return the size
- return OffsetSize;
- }
-
- /**
- * Function computes the size of an index
- * @param indexOffset The offset for the computed index
- * @return The size of the index
- */
- protected int countEntireIndexRange(int indexOffset)
- {
- // Go to the beginning of the index
- seek(indexOffset);
- // Read the count field
- int count = getCard16();
- // If count==0 -> size=2
- if (count==0)
- return 2;
- else
- {
- // Read the offsize field
- int indexOffSize = getCard8();
- // Go to the last element of the offset array
- seek(indexOffset+2+1+count*indexOffSize);
- // The size of the object array is the value of the last element-1
- int size = getOffset(indexOffSize)-1;
- // Return the size of the entire index
- return 2+1+(count+1)*indexOffSize+size;
- }
- }
-
- /**
- * The function creates a private dict for a font that was not CID
- * All the keys are copied as is except for the subrs key
- * @param Font the font
- * @param Subr The OffsetItem for the subrs of the private
- */
- void CreateNonCIDPrivate(int Font,OffsetItem Subr)
- {
- // Go to the beginning of the private dict and read untill the end
- seek(fonts[Font].privateOffset);
- while (getPosition() < fonts[Font].privateOffset+fonts[Font].privateLength)
- {
- int p1 = getPosition();
- getDictItem();
- int p2 = getPosition();
- // If the dictItem is the "Subrs" then,
- // use marker for offset and write operator number
- if (key=="Subrs") {
- OutputList.addLast(Subr);
- OutputList.addLast(new UInt8Item((char)19)); // Subrs
- }
- // Else copy the entire range
- else
- OutputList.addLast(new RangeItem(buf,p1,p2-p1));
- }
- }
-
- /**
- * the function marks the beginning of the subrs index and adds the subsetted subrs
- * index to the output list.
- * @param Font the font
- * @param PrivateBase IndexBaseItem for the private that's referencing to the subrs
- * @param Subrs OffsetItem for the subrs
- * @throws IOException
- */
- void CreateNonCIDSubrs(int Font,IndexBaseItem PrivateBase,OffsetItem Subrs)throws IOException
- {
- // Mark the beginning of the Subrs index
- OutputList.addLast(new SubrMarkerItem(Subrs,PrivateBase));
- // Put the subsetted new subrs index
- OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(NewSubrsIndexNonCID),0,NewSubrsIndexNonCID.length));
- }
-} \ No newline at end of file