Example #1
0
 /**
 * Function Adds the new private dicts (only for the FDs used) to the list
 * @param Font the font
 * @param fdPrivate OffsetItem array one element for each private
 * @param fdPrivateBase IndexBaseItem array one element for each private
 * @param fdSubrs OffsetItem array one element for each private
 * @throws IOException
 */
 internal void ReconstructPrivateDict(int Font,OffsetItem[] fdPrivate,IndexBaseItem[] fdPrivateBase,
         OffsetItem[] fdSubrs)
 {
     
     // For each fdarray private dict check if that FD is used.
     // if is used build a new one by changing the subrs offset
     // Else do nothing
     for (int i=0;i<fonts[Font].fdprivateOffsets.Length;i++)
     {
         //if (FDArrayUsed.ContainsKey(i))
         //{
             // Mark beginning
             OutputList.Add(new MarkerItem(fdPrivate[i]));
             fdPrivateBase[i] = new IndexBaseItem();
             OutputList.Add(fdPrivateBase[i]);
             // Goto begining of objects
             Seek(fonts[Font].fdprivateOffsets[i]);
             while (GetPosition() < fonts[Font].fdprivateOffsets[i]+fonts[Font].fdprivateLengths[i])
             {
                 int p1 = GetPosition();
                 GetDictItem();
                 int p2 = GetPosition();
                 // If the dictItem is the "Subrs" then, 
                 // use marker for offset and write operator number
                 if (key=="Subrs") {
                     fdSubrs[i] = new DictOffsetItem();
                     OutputList.Add(fdSubrs[i]);
                     OutputList.Add(new UInt8Item((char)19)); // Subrs
                 }
                 // Else copy the entire range
                 else
                     OutputList.Add(new RangeItem(buf,p1,p2-p1));
             }
         //}
     }
 }
Example #2
0
        /**
        * Function subsets the FDArray and builds the new one with new offsets
        * @param Font The font
        * @param fdPrivate OffsetItem Array (one for each FDArray)
        * @throws IOException
        */
        void ReconstructFDArray(int Font,OffsetItem[] fdPrivate)
        {
            // Build the header of the index
            BuildIndexHeader(fonts[Font].FDArrayCount,fonts[Font].FDArrayOffsize,1);

            // For each offset create an Offset Item
            OffsetItem[] fdOffsets = new IndexOffsetItem[fonts[Font].FDArrayOffsets.Length-1];
            for (int i=0;i<fonts[Font].FDArrayOffsets.Length-1;i++)
            {
                fdOffsets[i] = new IndexOffsetItem(fonts[Font].FDArrayOffsize);
                OutputList.Add(fdOffsets[i]);
            }
            
            // Declare beginning of the object array
            IndexBaseItem fdArrayBase = new IndexBaseItem();
            OutputList.Add(fdArrayBase);
            
            // For each object check if that FD is used.
            // if is used build a new one by changing the private object
            // Else do nothing
            // At the end of each object mark its ending (Even if wasn't written)
            for (int k=0; k<fonts[Font].FDArrayOffsets.Length-1; k++) {
                //if (FDArrayUsed.ContainsKey(k))
                //{
                    // Goto begining of objects
                    Seek(fonts[Font].FDArrayOffsets[k]);
                    while (GetPosition() < fonts[Font].FDArrayOffsets[k+1])
                    {
                        int p1 = GetPosition();
                        GetDictItem();
                        int p2 = GetPosition();
                        // If the dictItem is the "Private" then compute and copy length, 
                        // use marker for offset and write operator number
                        if (key=="Private") {
                            // Save the original length of the private dict
                            int NewSize = (int)args[0];
                            // Save the size of the offset to the subrs in that private
                            int OrgSubrsOffsetSize = CalcSubrOffsetSize(fonts[Font].fdprivateOffsets[k],fonts[Font].fdprivateLengths[k]);
                            // Increase the private's length accordingly
                            if (OrgSubrsOffsetSize != 0)
                                NewSize += 5-OrgSubrsOffsetSize;
                            // Insert the new size, OffsetItem and operator key number
                            OutputList.Add(new DictNumberItem(NewSize));
                            fdPrivate[k] = new DictOffsetItem();
                            OutputList.Add(fdPrivate[k]);
                            OutputList.Add(new UInt8Item((char)18)); // Private
                            // Go back to place 
                            Seek(p2);
                        }
                        // Else copy the entire range
                        else  // other than private
                            OutputList.Add(new RangeItem(buf,p1,p2-p1));
                    }
                //}
                // Mark the ending of the object (even if wasn't written)
                OutputList.Add(new IndexMarkerItem(fdOffsets[k],fdArrayBase));
            }
        }
Example #3
0
        /**
        * The function builds the new output stream according to the subset process
        * @param Font the font
        * @return the subseted font stream
        * @throws IOException
        */
        protected byte[] BuildNewFile(int Font)
        {
            // Prepare linked list for new font components
            OutputList = new List<Item>();

            // copy the header of the font
            CopyHeader();
                    
            // create a name index
            BuildIndexHeader(1,1,1);
            OutputList.Add(new UInt8Item((char)( 1+fonts[Font].name.Length)));
            OutputList.Add(new StringItem(fonts[Font].name));
            
            // create the topdict Index
            BuildIndexHeader(1,2,1);
            OffsetItem topdictIndex1Ref = new IndexOffsetItem(2);
            OutputList.Add(topdictIndex1Ref);
            IndexBaseItem topdictBase = new IndexBaseItem();
            OutputList.Add(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.Add(new DictNumberItem(fonts[Font].nstrings));
                OutputList.Add(new DictNumberItem(fonts[Font].nstrings+1));
                OutputList.Add(new DictNumberItem(0));
                OutputList.Add(new UInt8Item((char)12));
                OutputList.Add(new UInt8Item((char)30));
                // create a CIDCount key
                OutputList.Add(new DictNumberItem(fonts[Font].nglyphs));
                OutputList.Add(new UInt8Item((char)12));
                OutputList.Add(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.Add(new IndexMarkerItem(topdictIndex1Ref,topdictBase));
            
            // Copy the string index

            if (fonts[Font].isCID) 
                OutputList.Add(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.Add(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.Add(new MarkerItem(fdselectRef));
                // If an FDSelect exists copy it
                if (fonts[Font].fdselectOffset>=0)
                    OutputList.Add(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.Add(new MarkerItem(charsetRef));
                OutputList.Add(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.Add(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.Add(PrivateBase);
                OutputList.Add(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.Add(new MarkerItem(charstringsRef));

            // Add the subsetted charstring
            OutputList.Add(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
            foreach (Item item in OutputList) {
                item.Increment(currentOffset);
            }
            // Compute the Xref for each of the offset items
            foreach (Item item in OutputList) {
                item.Xref();
            }
            
            int size = currentOffset[0];
            byte[] b = new byte[size];
            
            // Emit all the items into the new byte array
            foreach (Item item in OutputList) {
                item.Emit(b);
            }
            // Return the new stream
            return b;
        }
Example #4
0
 /**
 * Function reconstructs the FDArray, PrivateDict and LSubr for CID fonts
 * @param Font the font
 * @throws IOException
 */
 void Reconstruct(int Font)
 {
     // Init for later use
     OffsetItem[] fdPrivate = new DictOffsetItem[fonts[Font].FDArrayOffsets.Length-1];
     IndexBaseItem[] fdPrivateBase = new IndexBaseItem[fonts[Font].fdprivateOffsets.Length]; 
     OffsetItem[] fdSubrs = new DictOffsetItem[fonts[Font].fdprivateOffsets.Length];
     // Reconstruct each type
     ReconstructFDArray(Font,fdPrivate);
     ReconstructPrivateDict(Font,fdPrivate,fdPrivateBase,fdSubrs);
     ReconstructPrivateSubrs(Font,fdPrivateBase,fdSubrs);
 }
Example #5
0
 /** get a single CID font. The PDF architecture (1.4)
 * supports 16-bit strings only with CID CFF fonts, not
 * in Type-1 CFF fonts, so we convert the font to CID if
 * it is in the Type-1 format.
 * Two other tasks that we need to do are to select
 * only a single font from the CFF package (this again is
 * a PDF restriction) and to subset the CharStrings glyph
 * description.
 */
 
 
 public byte[] GetCID(String fontName)
 //throws java.io.FileNotFoundException
 {
     int j;
     for (j=0; j<fonts.Length; j++)
         if (fontName.Equals(fonts[j].name)) break;
     if (j==fonts.Length) return null;
     
     List<Item> l = new List<Item>();
     
     // copy the header
     
     Seek(0);
     
     int major = GetCard8();
     int minor = GetCard8();
     int hdrSize = GetCard8();
     int offSize = GetCard8();
     nextIndexOffset = hdrSize;
     
     l.Add(new RangeItem(buf,0,hdrSize));
     
     int nglyphs=-1, nstrings=-1;
     if ( ! fonts[j].isCID ) {
         // count the glyphs
         Seek(fonts[j].charstringsOffset);
         nglyphs = GetCard16();
         Seek(stringIndexOffset);
         nstrings = GetCard16()+standardStrings.Length;
         //System.err.Println("number of glyphs = "+nglyphs);
     }
     
     // create a name index
     
     l.Add(new UInt16Item((char)1)); // count
     l.Add(new UInt8Item((char)1)); // offSize
     l.Add(new UInt8Item((char)1)); // first offset
     l.Add(new UInt8Item((char)( 1+fonts[j].name.Length )));
     l.Add(new StringItem(fonts[j].name));
     
     // create the topdict Index
     
     
     l.Add(new UInt16Item((char)1)); // count
     l.Add(new UInt8Item((char)2)); // offSize
     l.Add(new UInt16Item((char)1)); // first offset
     OffsetItem topdictIndex1Ref = new IndexOffsetItem(2);
     l.Add(topdictIndex1Ref);
     IndexBaseItem topdictBase = new IndexBaseItem();
     l.Add(topdictBase);
     
     /*
     int maxTopdictLen = (topdictOffsets[j+1]-topdictOffsets[j])
                         + 9*2 // at most 9 new keys
                         + 8*5 // 8 new integer arguments
                         + 3*2;// 3 new SID arguments
     */
     
     //int    topdictNext = 0;
     //byte[] topdict = new byte[maxTopdictLen];
     
     OffsetItem charsetRef     = new DictOffsetItem();
     OffsetItem charstringsRef = new DictOffsetItem();
     OffsetItem fdarrayRef     = new DictOffsetItem();
     OffsetItem fdselectRef    = new DictOffsetItem();
     
     if ( !fonts[j].isCID ) {
         // create a ROS key
         l.Add(new DictNumberItem(nstrings));
         l.Add(new DictNumberItem(nstrings+1));
         l.Add(new DictNumberItem(0));
         l.Add(new UInt8Item((char)12));
         l.Add(new UInt8Item((char)30));
         // create a CIDCount key
         l.Add(new DictNumberItem(nglyphs));
         l.Add(new UInt8Item((char)12));
         l.Add(new UInt8Item((char)34));
         // 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.
     }
     
     // create an FDArray key
     l.Add(fdarrayRef);
     l.Add(new UInt8Item((char)12));
     l.Add(new UInt8Item((char)36));
     // create an FDSelect key
     l.Add(fdselectRef);
     l.Add(new UInt8Item((char)12));
     l.Add(new UInt8Item((char)37));
     // create an charset key
     l.Add(charsetRef);
     l.Add(new UInt8Item((char)15));
     // create a CharStrings key
     l.Add(charstringsRef);
     l.Add(new UInt8Item((char)17));
     
     Seek(topdictOffsets[j]);
     while (GetPosition() < topdictOffsets[j+1]) {
         int p1 = GetPosition();
         GetDictItem();
         int p2 = GetPosition();
         if (key=="Encoding"
         || key=="Private"
         || key=="FDSelect"
         || key=="FDArray"
         || key=="charset"
         || key=="CharStrings"
         ) {
             // just drop them
         } else {
             l.Add(new RangeItem(buf,p1,p2-p1));
         }
     }
     
     l.Add(new IndexMarkerItem(topdictIndex1Ref,topdictBase));
     
     // Copy the string index and 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
     
     if (fonts[j].isCID) {
         l.Add(GetEntireIndexRange(stringIndexOffset));
     } else {
         String fdFontName = fonts[j].name+"-OneRange";
         if (fdFontName.Length > 127)
             fdFontName = fdFontName.Substring(0,127);
         String extraStrings = "Adobe"+"Identity"+fdFontName;
         
         int origStringsLen = stringOffsets[stringOffsets.Length-1]
         - stringOffsets[0];
         int stringsBaseOffset = stringOffsets[0]-1;
         
         byte stringsIndexOffSize;
         if (origStringsLen+extraStrings.Length <= 0xff) stringsIndexOffSize = 1;
         else if (origStringsLen+extraStrings.Length <= 0xffff) stringsIndexOffSize = 2;
         else if (origStringsLen+extraStrings.Length <= 0xffffff) stringsIndexOffSize = 3;
         else stringsIndexOffSize = 4;
         
         l.Add(new UInt16Item((char)((stringOffsets.Length-1)+3))); // count
         l.Add(new UInt8Item((char)stringsIndexOffSize)); // offSize
         foreach (int stringOffset in stringOffsets)
             l.Add(new IndexOffsetItem(stringsIndexOffSize,
             stringOffset-stringsBaseOffset));
         int currentStringsOffset = stringOffsets[stringOffsets.Length-1]
         - stringsBaseOffset;
         //l.Add(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
         currentStringsOffset += ("Adobe").Length;
         l.Add(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
         currentStringsOffset += ("Identity").Length;
         l.Add(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
         currentStringsOffset += fdFontName.Length;
         l.Add(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
         
         l.Add(new RangeItem(buf,stringOffsets[0],origStringsLen));
         l.Add(new StringItem(extraStrings));
     }
     
     // copy the global subroutine index
     
     l.Add(GetEntireIndexRange(gsubrIndexOffset));
     
     // deal with fdarray, fdselect, and the font descriptors
     
     if (fonts[j].isCID) {
         // copy the FDArray, FDSelect, charset
     } else {
         // create FDSelect
         l.Add(new MarkerItem(fdselectRef));
         l.Add(new UInt8Item((char)3)); // format identifier
         l.Add(new UInt16Item((char)1)); // nRanges
         
         l.Add(new UInt16Item((char)0)); // Range[0].firstGlyph
         l.Add(new UInt8Item((char)0)); // Range[0].fd
         
         l.Add(new UInt16Item((char)nglyphs)); // sentinel
         
         // recreate a new charset
         // This format is suitable only for fonts without subsetting
         
         l.Add(new MarkerItem(charsetRef));
         l.Add(new UInt8Item((char)2)); // format identifier
         
         l.Add(new UInt16Item((char)1)); // first glyph in range (ignore .notdef)
         l.Add(new UInt16Item((char)(nglyphs-1))); // nLeft
         // now all are covered, the data structure is complete.
         
         // create a font dict index (fdarray)
         
         l.Add(new MarkerItem(fdarrayRef));
         l.Add(new UInt16Item((char)1));
         l.Add(new UInt8Item((char)1)); // offSize
         l.Add(new UInt8Item((char)1)); // first offset
         
         OffsetItem privateIndex1Ref = new IndexOffsetItem(1);
         l.Add(privateIndex1Ref);
         IndexBaseItem privateBase = new IndexBaseItem();
         l.Add(privateBase);
         
         // looking at the PS that acrobat generates from a PDF with
         // a CFF opentype font embeded with an identity-H encoding,
         // it seems that it does not need a FontName.
         //l.Add(new DictNumberItem((standardStrings.length+(stringOffsets.length-1)+2)));
         //l.Add(new UInt8Item((char)12));
         //l.Add(new UInt8Item((char)38)); // FontName
         
         l.Add(new DictNumberItem(fonts[j].privateLength));
         OffsetItem privateRef = new DictOffsetItem();
         l.Add(privateRef);
         l.Add(new UInt8Item((char)18)); // Private
         
         l.Add(new IndexMarkerItem(privateIndex1Ref,privateBase));
         
         // copy the private index & local subroutines
         
         l.Add(new MarkerItem(privateRef));
         // copy the private dict and the local subroutines.
         // the length of the private dict seems to NOT include
         // the local subroutines.
         l.Add(new RangeItem(buf,fonts[j].privateOffset,fonts[j].privateLength));
         if (fonts[j].privateSubrs >= 0) {
             //System.err.Println("has subrs="+fonts[j].privateSubrs+" ,len="+fonts[j].privateLength);
             l.Add(GetEntireIndexRange(fonts[j].privateSubrs));
         }
     }
     
     // copy the charstring index
     
     l.Add(new MarkerItem(charstringsRef));
     l.Add(GetEntireIndexRange(fonts[j].charstringsOffset));
     
     // now create the new CFF font
     
     int[] currentOffset = new int[1];
     currentOffset[0] = 0;
     
     foreach (Item item in l) {
         item.Increment(currentOffset);
     }
     
     foreach (Item item in l) {
         item.Xref();
     }
     
     int size = currentOffset[0];
     byte[] b = new byte[size];
     
     foreach (Item item in l) {
         item.Emit(b);
     }
     
     return b;
 }