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

📄 cfffontsubset.java

📁 iText是一个能够快速产生PDF文件的java类库。iText的java类对于那些要产生包含文本
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
            {
            	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
	 */
	protected byte[] BuildNewFile(int Font)
    {
		// 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

⌨️ 快捷键说明

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