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

📄 cfffontsubset.java

📁 源码包含生成 PDF 和 HTML 的类库
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
            	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 therefore 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 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")         	{        		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	 * @param OperatorForUnusedEntries the operator inserted into the data stream for unused entries	 * @return the new index subset version 	 * @throws IOException	 */	protected byte[] BuildNewIndex(int[] Offsets,HashMap Used,byte OperatorForUnusedEntries) throws IOException 	{		int unusedCount = 0;		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 {				// Else the same offset is kept in i+1.				unusedCount++;			}		}		// Offset var determines the size of the object array		byte[] NewObjects = new byte[Offset+unusedCount];		// Build the new Object array		int unusedOffset = 0;		for (int i=0;i<Offsets.length-1;++i)		{			int start = NewOffsets[i];			int end = NewOffsets[i+1];			NewOffsets[i] = start+unusedOffset;			// 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 beginning 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+unusedOffset, end-start);			} else {				NewObjects[start+unusedOffset] = OperatorForUnusedEntries;				unusedOffset++;			}		}		NewOffsets[Offsets.length-1] += unusedOffset;		// 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 subsetted 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);                        // Initialize 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 until 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 manually 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 entirely             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));	}

⌨️ 快捷键说明

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