📄 cfffontsubset.java
字号:
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,ENDCHAR_OP); } /** * 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 hashmap-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, Array 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 offset 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 Charstring data storing the used Local and Global subroutines // by the glyphs. Scans the Subrs recursively. 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],RETURN_OP); } } } // 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 Charstring data storing the used Local and Global subroutines // by the glyphs. Scans the Subrs recursively. BuildSubrUsed(Font,-1,fonts[Font].privateSubrs,fonts[Font].SubrsOffsets,hSubrsUsedNonCID,lSubrsUsedNonCID); } // For all fonts subset the Global Subroutines // Scan the Global Subr Hashmap recursively on the Gsubrs BuildGSubrsUsed(Font); if (fonts[Font].privateSubrs>=0) // Builds the New Local Subrs index NewSubrsIndexNonCID = BuildNewIndex(fonts[Font].SubrsOffsets,hSubrsUsedNonCID,RETURN_OP); //Builds the New Global Subrs index NewGSubrsIndex = BuildNewIndex(gsubrOffsets,hGSubrsUsed,RETURN_OP); } /** * 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 beginning 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 lsubr 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 lsubr only) is then scanned recursively 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 recursively 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 beginning 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() { // Find out 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 constitute a short int { int w = getCard8(); args[arg_count] = new Integer((b0-247)*256 + w + 108);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -