⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cfffontsubset.java

📁 iText是一个能够快速产生PDF文件的java类库。iText的java类对于那些要产生包含文本
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/*
 * $Id: CFFFontSubset.java 2671 2007-04-03 16:08:04Z psoares33 $
 * $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.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 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) 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"
	};
	
	/**
	 * 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;
    	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 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)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -