📄 cfffontsubset.java
字号:
/* * $Id: CFFFontSubset.java 3573 2008-07-21 15:08:04Z blowagie $ * * 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.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.LinkedList;/** * This Class subsets a CFF Type Font. The subset is preformed for CID fonts and NON CID fonts. * The Charstring is subsetted 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 although 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) and 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" }; /** * Operator codes for unused CharStrings and unused local and global Subrs */ static final byte ENDCHAR_OP = 14; static final byte RETURN_OP = 11; /** * 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 Indexes 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 recursively */ 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); // Process the FDSelect if exist if (fonts[i].fdselectOffset>=0) { // Process 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; 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 */ 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 relevant 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -