Source Code Cross Referenced for CFFFontSubset.java in  » PDF » pdf-itext » com » lowagie » text » pdf » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » PDF » pdf itext » com.lowagie.text.pdf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Id: CFFFontSubset.java 2671 2007-04-03 16:08:04Z psoares33 $
0003:         * $Name$
0004:         *
0005:         * Copyright 2004 Oren Manor and Ygal Blum
0006:         *
0007:         * The contents of this file are subject to the Mozilla Public License Version 1.1
0008:         * (the "License"); you may not use this file except in compliance with the License.
0009:         * You may obtain a copy of the License at http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the License.
0014:         *
0015:         * The Original Code is 'iText, a free JAVA-PDF library'.
0016:         *
0017:         * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
0018:         * the Initial Developer are Copyright (C) 1999-2005 by Bruno Lowagie.
0019:         * All Rights Reserved.
0020:         * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
0021:         * are Copyright (C) 2000-2005 by Paulo Soares. All Rights Reserved.
0022:         *
0023:         * Contributor(s): all the names of the contributors are added in the source code
0024:         * where applicable.
0025:         *
0026:         * Alternatively, the contents of this file may be used under the terms of the
0027:         * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
0028:         * provisions of LGPL are applicable instead of those above.  If you wish to
0029:         * allow use of your version of this file only under the terms of the LGPL
0030:         * License and not to allow others to use your version of this file under
0031:         * the MPL, indicate your decision by deleting the provisions above and
0032:         * replace them with the notice and other provisions required by the LGPL.
0033:         * If you do not delete the provisions above, a recipient may use your version
0034:         * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
0035:         *
0036:         * This library is free software; you can redistribute it and/or modify it
0037:         * under the terms of the MPL as stated above or under the terms of the GNU
0038:         * Library General Public License as published by the Free Software Foundation;
0039:         * either version 2 of the License, or any later version.
0040:         *
0041:         * This library is distributed in the hope that it will be useful, but WITHOUT
0042:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
0043:         * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
0044:         * details.
0045:         *
0046:         * If you didn't download this code from the following link, you should check if
0047:         * you aren't using an obsolete version:
0048:         * http://www.lowagie.com/iText/
0049:         */
0050:        package com.lowagie.text.pdf;
0051:
0052:        import java.io.IOException;
0053:        import java.util.ArrayList;
0054:        import java.util.HashMap;
0055:        import java.util.Iterator;
0056:        import java.util.LinkedList;
0057:
0058:        /**
0059:         * This Class subsets a CFF Type Font. The subset is preformed for CID fonts and NON CID fonts.
0060:         * The Charstring is subseted for both types. For CID fonts only the FDArray which are used are embedded. 
0061:         * The Lsubroutines of the FDArrays used are subsetted as well. The Subroutine subset supports both Type1 and Type2
0062:         * formatting altough only tested on Type2 Format.
0063:         * For Non CID the Lsubroutines are subsetted. On both types the Gsubroutines is subsetted. 
0064:         * A font which was not of CID type is transformed into CID as a part of the subset process. 
0065:         * The CID synthetic creation was written by Sivan Toledo (sivan@math.tau.ac.il) 
0066:         * @author Oren Manor (manorore@post.tau.ac.il) and Ygal Blum (blumygal@post.tau.ac.il)
0067:         */
0068:        public class CFFFontSubset extends CFFFont {
0069:
0070:            /**
0071:             *  The Strings in this array represent Type1/Type2 operator names
0072:             */
0073:            static final String SubrsFunctions[] = { "RESERVED_0", "hstem",
0074:                    "RESERVED_2", "vstem", "vmoveto", "rlineto", "hlineto",
0075:                    "vlineto", "rrcurveto", "RESERVED_9", "callsubr", "return",
0076:                    "escape", "RESERVED_13", "endchar", "RESERVED_15",
0077:                    "RESERVED_16", "RESERVED_17", "hstemhm", "hintmask",
0078:                    "cntrmask", "rmoveto", "hmoveto", "vstemhm", "rcurveline",
0079:                    "rlinecurve", "vvcurveto", "hhcurveto", "shortint",
0080:                    "callgsubr", "vhcurveto", "hvcurveto" };
0081:            /**
0082:             * The Strings in this array represent Type1/Type2 escape operator names
0083:             */
0084:            static final String SubrsEscapeFuncs[] = { "RESERVED_0",
0085:                    "RESERVED_1", "RESERVED_2", "and", "or", "not",
0086:                    "RESERVED_6", "RESERVED_7", "RESERVED_8", "abs", "add",
0087:                    "sub", "div", "RESERVED_13", "neg", "eq", "RESERVED_16",
0088:                    "RESERVED_17", "drop", "RESERVED_19", "put", "get",
0089:                    "ifelse", "random", "mul", "RESERVED_25", "sqrt", "dup",
0090:                    "exch", "index", "roll", "RESERVED_31", "RESERVED_32",
0091:                    "RESERVED_33", "hflex", "flex", "hflex1", "flex1",
0092:                    "RESERVED_REST" };
0093:
0094:            /**
0095:             * A HashMap containing the glyphs used in the text after being converted
0096:             * to glyph number by the CMap 
0097:             */
0098:            HashMap GlyphsUsed;
0099:            /**
0100:             * The GlyphsUsed keys as an ArrayList
0101:             */
0102:            ArrayList glyphsInList;
0103:            /**
0104:             * A HashMap for keeping the FDArrays being used by the font
0105:             */
0106:            HashMap FDArrayUsed = new HashMap();
0107:            /**
0108:             * A HashMaps array for keeping the subroutines used in each FontDict
0109:             */
0110:            HashMap[] hSubrsUsed;
0111:            /**
0112:             * The SubroutinesUsed HashMaps as ArrayLists
0113:             */
0114:            ArrayList[] lSubrsUsed;
0115:            /**
0116:             * A HashMap for keeping the Global subroutines used in the font
0117:             */
0118:            HashMap hGSubrsUsed = new HashMap();
0119:            /**
0120:             * The Global SubroutinesUsed HashMaps as ArrayLists
0121:             */
0122:            ArrayList lGSubrsUsed = new ArrayList();
0123:            /**
0124:             * A HashMap for keeping the subroutines used in a non-cid font
0125:             */
0126:            HashMap hSubrsUsedNonCID = new HashMap();
0127:            /**
0128:             * The SubroutinesUsed HashMap as ArrayList
0129:             */
0130:            ArrayList lSubrsUsedNonCID = new ArrayList();
0131:            /**
0132:             * An array of the new Indexs for the local Subr. One index for each FontDict
0133:             */
0134:            byte[][] NewLSubrsIndex;
0135:            /**
0136:             * The new subroutines index for a non-cid font
0137:             */
0138:            byte[] NewSubrsIndexNonCID;
0139:            /**
0140:             * The new global subroutines index of the font
0141:             */
0142:            byte[] NewGSubrsIndex;
0143:            /**
0144:             * The new CharString of the font
0145:             */
0146:            byte[] NewCharStringsIndex;
0147:
0148:            /**
0149:             * The bias for the global subroutines
0150:             */
0151:            int GBias = 0;
0152:
0153:            /**
0154:             * The linked list for generating the new font stream
0155:             */
0156:            LinkedList OutputList;
0157:
0158:            /**
0159:             * Number of arguments to the stem operators in a subroutine calculated recursivly
0160:             */
0161:            int NumOfHints = 0;
0162:
0163:            /**	 
0164:             * C'tor for CFFFontSubset
0165:             * @param rf - The font file
0166:             * @param GlyphsUsed - a HashMap that contains the glyph used in the subset 
0167:             */
0168:            public CFFFontSubset(RandomAccessFileOrArray rf, HashMap GlyphsUsed) {
0169:                // Use CFFFont c'tor in order to parse the font file.
0170:                super (rf);
0171:                this .GlyphsUsed = GlyphsUsed;
0172:                //Put the glyphs into a list
0173:                glyphsInList = new ArrayList(GlyphsUsed.keySet());
0174:
0175:                for (int i = 0; i < fonts.length; ++i) {
0176:                    // Read the number of glyphs in the font
0177:                    seek(fonts[i].charstringsOffset);
0178:                    fonts[i].nglyphs = getCard16();
0179:
0180:                    // Jump to the count field of the String Index
0181:                    seek(stringIndexOffset);
0182:                    fonts[i].nstrings = getCard16() + standardStrings.length;
0183:
0184:                    // For each font save the offset array of the charstring
0185:                    fonts[i].charstringsOffsets = getIndex(fonts[i].charstringsOffset);
0186:
0187:                    // Proces the FDSelect if exist 
0188:                    if (fonts[i].fdselectOffset >= 0) {
0189:                        // Proces the FDSelect
0190:                        readFDSelect(i);
0191:                        // Build the FDArrayUsed hashmap
0192:                        BuildFDArrayUsed(i);
0193:                    }
0194:                    if (fonts[i].isCID)
0195:                        // Build the FD Array used Hash Map
0196:                        ReadFDArray(i);
0197:                    // compute the charset length 
0198:                    fonts[i].CharsetLength = CountCharset(
0199:                            fonts[i].charsetOffset, fonts[i].nglyphs);
0200:                }
0201:            }
0202:
0203:            /**
0204:             * Calculates the length of the charset according to its format
0205:             * @param Offset The Charset Offset
0206:             * @param NumofGlyphs Number of glyphs in the font
0207:             * @return the length of the Charset
0208:             */
0209:            int CountCharset(int Offset, int NumofGlyphs) {
0210:                int format;
0211:                int Length = 0;
0212:                seek(Offset);
0213:                // Read the format
0214:                format = getCard8();
0215:                // Calc according to format
0216:                switch (format) {
0217:                case 0:
0218:                    Length = 1 + 2 * NumofGlyphs;
0219:                    break;
0220:                case 1:
0221:                    Length = 1 + 3 * CountRange(NumofGlyphs, 1);
0222:                    break;
0223:                case 2:
0224:                    Length = 1 + 4 * CountRange(NumofGlyphs, 2);
0225:                    break;
0226:                default:
0227:                    break;
0228:                }
0229:                return Length;
0230:            }
0231:
0232:            /**
0233:             * Function calculates the number of ranges in the Charset
0234:             * @param NumofGlyphs The number of glyphs in the font
0235:             * @param Type The format of the Charset
0236:             * @return The number of ranges in the Charset data structure
0237:             */
0238:            int CountRange(int NumofGlyphs, int Type) {
0239:                int num = 0;
0240:                char Sid;
0241:                int i = 1, nLeft;
0242:                while (i < NumofGlyphs) {
0243:                    num++;
0244:                    Sid = getCard16();
0245:                    if (Type == 1)
0246:                        nLeft = getCard8();
0247:                    else
0248:                        nLeft = getCard16();
0249:                    i += nLeft + 1;
0250:                }
0251:                return num;
0252:            }
0253:
0254:            /**
0255:             * Read the FDSelect of the font and compute the array and its length
0256:             * @param Font The index of the font being processed
0257:             */
0258:            protected void readFDSelect(int Font) {
0259:                // Restore the number of glyphs
0260:                int NumOfGlyphs = fonts[Font].nglyphs;
0261:                int[] FDSelect = new int[NumOfGlyphs];
0262:                // Go to the beginning of the FDSelect
0263:                seek(fonts[Font].fdselectOffset);
0264:                // Read the FDSelect's format
0265:                fonts[Font].FDSelectFormat = getCard8();
0266:
0267:                switch (fonts[Font].FDSelectFormat) {
0268:                // Format==0 means each glyph has an entry that indicated
0269:                // its FD.
0270:                case 0:
0271:                    for (int i = 0; i < NumOfGlyphs; i++) {
0272:                        FDSelect[i] = getCard8();
0273:                    }
0274:                    // The FDSelect's Length is one for each glyph + the format
0275:                    // for later use
0276:                    fonts[Font].FDSelectLength = fonts[Font].nglyphs + 1;
0277:                    break;
0278:                case 3:
0279:                    // Format==3 means the ranges version
0280:                    // The number of ranges
0281:                    int nRanges = getCard16();
0282:                    int l = 0;
0283:                    // Read the first in the first range
0284:                    int first = getCard16();
0285:                    for (int i = 0; i < nRanges; i++) {
0286:                        // Read the FD index
0287:                        int fd = getCard8();
0288:                        // Read the first of the next range
0289:                        int last = getCard16();
0290:                        // Calc the steps and write to the array
0291:                        int steps = last - first;
0292:                        for (int k = 0; k < steps; k++) {
0293:                            FDSelect[l] = fd;
0294:                            l++;
0295:                        }
0296:                        // The last from this iteration is the first of the next
0297:                        first = last;
0298:                    }
0299:                    // Store the length for later use
0300:                    fonts[Font].FDSelectLength = 1 + 2 + nRanges * 3 + 2;
0301:                    break;
0302:                default:
0303:                    break;
0304:                }
0305:                // Save the FDSelect of the font 
0306:                fonts[Font].FDSelect = FDSelect;
0307:            }
0308:
0309:            /**
0310:             * Function reads the FDSelect and builds the FDArrayUsed HashMap According to the glyphs used
0311:             * @param Font the Number of font being processed
0312:             */
0313:            protected void BuildFDArrayUsed(int Font) {
0314:                int[] FDSelect = fonts[Font].FDSelect;
0315:                // For each glyph used
0316:                for (int i = 0; i < glyphsInList.size(); i++) {
0317:                    // Pop the glyphs index
0318:                    int glyph = ((Integer) glyphsInList.get(i)).intValue();
0319:                    // Pop the glyph's FD
0320:                    int FD = FDSelect[glyph];
0321:                    // Put the FD index into the FDArrayUsed HashMap
0322:                    FDArrayUsed.put(new Integer(FD), null);
0323:                }
0324:            }
0325:
0326:            /**
0327:             * Read the FDArray count, offsize and Offset array
0328:             * @param Font
0329:             */
0330:            protected void ReadFDArray(int Font) {
0331:                seek(fonts[Font].fdarrayOffset);
0332:                fonts[Font].FDArrayCount = getCard16();
0333:                fonts[Font].FDArrayOffsize = getCard8();
0334:                // Since we will change values inside the FDArray objects
0335:                // We increase its offsize to prevent errors 
0336:                if (fonts[Font].FDArrayOffsize < 4)
0337:                    fonts[Font].FDArrayOffsize++;
0338:                fonts[Font].FDArrayOffsets = getIndex(fonts[Font].fdarrayOffset);
0339:            }
0340:
0341:            /**
0342:             * The Process function extracts one font out of the CFF file and returns a
0343:             * subset version of the original.
0344:             * @param fontName - The name of the font to be taken out of the CFF
0345:             * @return The new font stream
0346:             * @throws IOException
0347:             */
0348:            public byte[] Process(String fontName) throws IOException {
0349:                try {
0350:                    // Verify that the file is open
0351:                    buf.reOpen();
0352:                    // Find the Font that we will be dealing with
0353:                    int j;
0354:                    for (j = 0; j < fonts.length; j++)
0355:                        if (fontName.equals(fonts[j].name))
0356:                            break;
0357:                    if (j == fonts.length)
0358:                        return null;
0359:
0360:                    // Calc the bias for the global subrs
0361:                    if (gsubrIndexOffset >= 0)
0362:                        GBias = CalcBias(gsubrIndexOffset, j);
0363:
0364:                    // Prepare the new CharStrings Index
0365:                    BuildNewCharString(j);
0366:                    // Prepare the new Global and Local Subrs Indices
0367:                    BuildNewLGSubrs(j);
0368:                    // Build the new file 
0369:                    byte[] Ret = BuildNewFile(j);
0370:                    return Ret;
0371:                } finally {
0372:                    try {
0373:                        buf.close();
0374:                    } catch (Exception e) {
0375:                        // empty on purpose
0376:                    }
0377:                }
0378:            }
0379:
0380:            /**
0381:             * Function calcs bias according to the CharString type and the count
0382:             * of the subrs
0383:             * @param Offset The offset to the relevent subrs index
0384:             * @param Font the font
0385:             * @return The calculated Bias
0386:             */
0387:            protected int CalcBias(int Offset, int Font) {
0388:                seek(Offset);
0389:                int nSubrs = getCard16();
0390:                // If type==1 -> bias=0 
0391:                if (fonts[Font].CharstringType == 1)
0392:                    return 0;
0393:                // else calc according to the count
0394:                else if (nSubrs < 1240)
0395:                    return 107;
0396:                else if (nSubrs < 33900)
0397:                    return 1131;
0398:                else
0399:                    return 32768;
0400:            }
0401:
0402:            /**
0403:             *Function uses BuildNewIndex to create the new index of the subset charstrings
0404:             * @param FontIndex the font
0405:             * @throws IOException
0406:             */
0407:            protected void BuildNewCharString(int FontIndex) throws IOException {
0408:                NewCharStringsIndex = BuildNewIndex(
0409:                        fonts[FontIndex].charstringsOffsets, GlyphsUsed);
0410:            }
0411:
0412:            /**
0413:             * Function builds the new local & global subsrs indices. IF CID then All of 
0414:             * the FD Array lsubrs will be subsetted. 
0415:             * @param Font the font
0416:             * @throws IOException
0417:             */
0418:            protected void BuildNewLGSubrs(int Font) throws IOException {
0419:                // If the font is CID then the lsubrs are divided into FontDicts.
0420:                // for each FD array the lsubrs will be subsetted.
0421:                if (fonts[Font].isCID) {
0422:                    // Init the hasmap-array and the arraylist-array to hold the subrs used
0423:                    // in each private dict.
0424:                    hSubrsUsed = new HashMap[fonts[Font].fdprivateOffsets.length];
0425:                    lSubrsUsed = new ArrayList[fonts[Font].fdprivateOffsets.length];
0426:                    // A [][] which will store the byte array for each new FD Array lsubs index
0427:                    NewLSubrsIndex = new byte[fonts[Font].fdprivateOffsets.length][];
0428:                    // An array to hold the offset for each Lsubr index 
0429:                    fonts[Font].PrivateSubrsOffset = new int[fonts[Font].fdprivateOffsets.length];
0430:                    // A [][] which will store the offset array for each lsubr index			
0431:                    fonts[Font].PrivateSubrsOffsetsArray = new int[fonts[Font].fdprivateOffsets.length][];
0432:
0433:                    // Put the FDarrayUsed into a list
0434:                    ArrayList FDInList = new ArrayList(FDArrayUsed.keySet());
0435:                    // For each FD array which is used subset the lsubr 
0436:                    for (int j = 0; j < FDInList.size(); j++) {
0437:                        // The FDArray index, Hash Map, Arrat List to work on
0438:                        int FD = ((Integer) FDInList.get(j)).intValue();
0439:                        hSubrsUsed[FD] = new HashMap();
0440:                        lSubrsUsed[FD] = new ArrayList();
0441:                        //Reads the private dicts looking for the subr operator and 
0442:                        // store both the offest for the index and its offset array
0443:                        BuildFDSubrsOffsets(Font, FD);
0444:                        // Verify that FDPrivate has a LSubrs index
0445:                        if (fonts[Font].PrivateSubrsOffset[FD] >= 0) {
0446:                            //Scans the Charsting data storing the used Local and Global subroutines 
0447:                            // by the glyphs. Scans the Subrs recursivley. 
0448:                            BuildSubrUsed(Font, FD,
0449:                                    fonts[Font].PrivateSubrsOffset[FD],
0450:                                    fonts[Font].PrivateSubrsOffsetsArray[FD],
0451:                                    hSubrsUsed[FD], lSubrsUsed[FD]);
0452:                            // Builds the New Local Subrs index
0453:                            NewLSubrsIndex[FD] = BuildNewIndex(
0454:                                    fonts[Font].PrivateSubrsOffsetsArray[FD],
0455:                                    hSubrsUsed[FD]);
0456:                        }
0457:                    }
0458:                }
0459:                // If the font is not CID && the Private Subr exists then subset:
0460:                else if (fonts[Font].privateSubrs >= 0) {
0461:                    // Build the subrs offsets;
0462:                    fonts[Font].SubrsOffsets = getIndex(fonts[Font].privateSubrs);
0463:                    //Scans the Charsting data storing the used Local and Global subroutines 
0464:                    // by the glyphs. Scans the Subrs recursivley.
0465:                    BuildSubrUsed(Font, -1, fonts[Font].privateSubrs,
0466:                            fonts[Font].SubrsOffsets, hSubrsUsedNonCID,
0467:                            lSubrsUsedNonCID);
0468:                }
0469:                // For all fonts susbset the Global Subroutines
0470:                // Scan the Global Subr Hashmap recursivly on the Gsubrs
0471:                BuildGSubrsUsed(Font);
0472:                if (fonts[Font].privateSubrs >= 0)
0473:                    // Builds the New Local Subrs index
0474:                    NewSubrsIndexNonCID = BuildNewIndex(
0475:                            fonts[Font].SubrsOffsets, hSubrsUsedNonCID);
0476:                //Builds the New Global Subrs index
0477:                NewGSubrsIndex = BuildNewIndex(gsubrOffsets, hGSubrsUsed);
0478:            }
0479:
0480:            /**
0481:             * The function finds for the FD array processed the local subr offset and its 
0482:             * offset array.  
0483:             * @param Font the font
0484:             * @param FD The FDARRAY processed
0485:             */
0486:            protected void BuildFDSubrsOffsets(int Font, int FD) {
0487:                // Initiate to -1 to indicate lsubr operator present
0488:                fonts[Font].PrivateSubrsOffset[FD] = -1;
0489:                // Goto begining of objects
0490:                seek(fonts[Font].fdprivateOffsets[FD]);
0491:                // While in the same object:
0492:                while (getPosition() < fonts[Font].fdprivateOffsets[FD]
0493:                        + fonts[Font].fdprivateLengths[FD]) {
0494:                    getDictItem();
0495:                    // If the dictItem is the "Subrs" then find and store offset, 
0496:                    if (key == "Subrs")
0497:                        fonts[Font].PrivateSubrsOffset[FD] = ((Integer) args[0])
0498:                                .intValue()
0499:                                + fonts[Font].fdprivateOffsets[FD];
0500:                }
0501:                //Read the lsub index if the lsubr was found
0502:                if (fonts[Font].PrivateSubrsOffset[FD] >= 0)
0503:                    fonts[Font].PrivateSubrsOffsetsArray[FD] = getIndex(fonts[Font].PrivateSubrsOffset[FD]);
0504:            }
0505:
0506:            /**
0507:             * Function uses ReadAsubr on the glyph used to build the LSubr & Gsubr HashMap.
0508:             * The HashMap (of the lsub only) is then scaned recursivly for Lsubr & Gsubrs
0509:             * calls.  
0510:             * @param Font the font
0511:             * @param FD FD array processed. 0 indicates function was called by non CID font
0512:             * @param SubrOffset the offset to the subr index to calc the bias
0513:             * @param SubrsOffsets the offset array of the subr index
0514:             * @param hSubr HashMap of the subrs used
0515:             * @param lSubr ArrayList of the subrs used
0516:             */
0517:            protected void BuildSubrUsed(int Font, int FD, int SubrOffset,
0518:                    int[] SubrsOffsets, HashMap hSubr, ArrayList lSubr) {
0519:
0520:                // Calc the Bias for the subr index
0521:                int LBias = CalcBias(SubrOffset, Font);
0522:
0523:                // For each glyph used find its GID, start & end pos
0524:                for (int i = 0; i < glyphsInList.size(); i++) {
0525:                    int glyph = ((Integer) glyphsInList.get(i)).intValue();
0526:                    int Start = fonts[Font].charstringsOffsets[glyph];
0527:                    int End = fonts[Font].charstringsOffsets[glyph + 1];
0528:
0529:                    // IF CID:
0530:                    if (FD >= 0) {
0531:                        EmptyStack();
0532:                        NumOfHints = 0;
0533:                        // Using FDSELECT find the FD Array the glyph belongs to.
0534:                        int GlyphFD = fonts[Font].FDSelect[glyph];
0535:                        // If the Glyph is part of the FD being processed 
0536:                        if (GlyphFD == FD)
0537:                            // Find the Subrs called by the glyph and insert to hash:
0538:                            ReadASubr(Start, End, GBias, LBias, hSubr, lSubr,
0539:                                    SubrsOffsets);
0540:                    } else
0541:                        // If the font is not CID 
0542:                        //Find the Subrs called by the glyph and insert to hash:
0543:                        ReadASubr(Start, End, GBias, LBias, hSubr, lSubr,
0544:                                SubrsOffsets);
0545:                }
0546:                // For all Lsubrs used, check recusrivly for Lsubr & Gsubr used
0547:                for (int i = 0; i < lSubr.size(); i++) {
0548:                    // Pop the subr value from the hash
0549:                    int Subr = ((Integer) lSubr.get(i)).intValue();
0550:                    // Ensure the Lsubr call is valid
0551:                    if (Subr < SubrsOffsets.length - 1 && Subr >= 0) {
0552:                        // Read and process the subr
0553:                        int Start = SubrsOffsets[Subr];
0554:                        int End = SubrsOffsets[Subr + 1];
0555:                        ReadASubr(Start, End, GBias, LBias, hSubr, lSubr,
0556:                                SubrsOffsets);
0557:                    }
0558:                }
0559:            }
0560:
0561:            /**
0562:             * Function scans the Glsubr used ArrayList to find recursive calls 
0563:             * to Gsubrs and adds to Hashmap & ArrayList
0564:             * @param Font the font
0565:             */
0566:            protected void BuildGSubrsUsed(int Font) {
0567:                int LBias = 0;
0568:                int SizeOfNonCIDSubrsUsed = 0;
0569:                if (fonts[Font].privateSubrs >= 0) {
0570:                    LBias = CalcBias(fonts[Font].privateSubrs, Font);
0571:                    SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
0572:                }
0573:
0574:                // For each global subr used 
0575:                for (int i = 0; i < lGSubrsUsed.size(); i++) {
0576:                    //Pop the value + check valid 
0577:                    int Subr = ((Integer) lGSubrsUsed.get(i)).intValue();
0578:                    if (Subr < gsubrOffsets.length - 1 && Subr >= 0) {
0579:                        // Read the subr and process
0580:                        int Start = gsubrOffsets[Subr];
0581:                        int End = gsubrOffsets[Subr + 1];
0582:
0583:                        if (fonts[Font].isCID)
0584:                            ReadASubr(Start, End, GBias, 0, hGSubrsUsed,
0585:                                    lGSubrsUsed, null);
0586:                        else {
0587:                            ReadASubr(Start, End, GBias, LBias,
0588:                                    hSubrsUsedNonCID, lSubrsUsedNonCID,
0589:                                    fonts[Font].SubrsOffsets);
0590:                            if (SizeOfNonCIDSubrsUsed < lSubrsUsedNonCID.size()) {
0591:                                for (int j = SizeOfNonCIDSubrsUsed; j < lSubrsUsedNonCID
0592:                                        .size(); j++) {
0593:                                    //Pop the value + check valid 
0594:                                    int LSubr = ((Integer) lSubrsUsedNonCID
0595:                                            .get(j)).intValue();
0596:                                    if (LSubr < fonts[Font].SubrsOffsets.length - 1
0597:                                            && LSubr >= 0) {
0598:                                        // Read the subr and process
0599:                                        int LStart = fonts[Font].SubrsOffsets[LSubr];
0600:                                        int LEnd = fonts[Font].SubrsOffsets[LSubr + 1];
0601:                                        ReadASubr(LStart, LEnd, GBias, LBias,
0602:                                                hSubrsUsedNonCID,
0603:                                                lSubrsUsedNonCID,
0604:                                                fonts[Font].SubrsOffsets);
0605:                                    }
0606:                                }
0607:                                SizeOfNonCIDSubrsUsed = lSubrsUsedNonCID.size();
0608:                            }
0609:                        }
0610:                    }
0611:                }
0612:            }
0613:
0614:            /**
0615:             * The function reads a subrs (glyph info) between begin and end.
0616:             * Adds calls to a Lsubr to the hSubr and lSubrs.
0617:             * Adds calls to a Gsubr to the hGSubr and lGSubrs.
0618:             * @param begin the start point of the subr
0619:             * @param end the end point of the subr
0620:             * @param GBias the bias of the Global Subrs
0621:             * @param LBias the bias of the Local Subrs
0622:             * @param hSubr the HashMap for the lSubrs
0623:             * @param lSubr the ArrayList for the lSubrs
0624:             */
0625:            protected void ReadASubr(int begin, int end, int GBias, int LBias,
0626:                    HashMap hSubr, ArrayList lSubr, int[] LSubrsOffsets) {
0627:                // Clear the stack for the subrs
0628:                EmptyStack();
0629:                NumOfHints = 0;
0630:                // Goto begining of the subr
0631:                seek(begin);
0632:                while (getPosition() < end) {
0633:                    // Read the next command
0634:                    ReadCommand();
0635:                    int pos = getPosition();
0636:                    Object TopElement = null;
0637:                    if (arg_count > 0)
0638:                        TopElement = args[arg_count - 1];
0639:                    int NumOfArgs = arg_count;
0640:                    // Check the modification needed on the Argument Stack according to key;
0641:                    HandelStack();
0642:                    // a call to a Lsubr
0643:                    if (key == "callsubr") {
0644:                        // Verify that arguments are passed 
0645:                        if (NumOfArgs > 0) {
0646:                            // Calc the index of the Subrs
0647:                            int Subr = ((Integer) TopElement).intValue()
0648:                                    + LBias;
0649:                            // If the subr isn't in the HashMap -> Put in
0650:                            if (!hSubr.containsKey(new Integer(Subr))) {
0651:                                hSubr.put(new Integer(Subr), null);
0652:                                lSubr.add(new Integer(Subr));
0653:                            }
0654:                            CalcHints(LSubrsOffsets[Subr],
0655:                                    LSubrsOffsets[Subr + 1], LBias, GBias,
0656:                                    LSubrsOffsets);
0657:                            seek(pos);
0658:                        }
0659:                    }
0660:                    // a call to a Gsubr
0661:                    else if (key == "callgsubr") {
0662:                        // Verify that arguments are passed 
0663:                        if (NumOfArgs > 0) {
0664:                            // Calc the index of the Subrs
0665:                            int Subr = ((Integer) TopElement).intValue()
0666:                                    + GBias;
0667:                            // If the subr isn't in the HashMap -> Put in
0668:                            if (!hGSubrsUsed.containsKey(new Integer(Subr))) {
0669:                                hGSubrsUsed.put(new Integer(Subr), null);
0670:                                lGSubrsUsed.add(new Integer(Subr));
0671:                            }
0672:                            CalcHints(gsubrOffsets[Subr],
0673:                                    gsubrOffsets[Subr + 1], LBias, GBias,
0674:                                    LSubrsOffsets);
0675:                            seek(pos);
0676:                        }
0677:                    }
0678:                    // A call to "stem"
0679:                    else if (key == "hstem" || key == "vstem"
0680:                            || key == "hstemhm" || key == "vstemhm")
0681:                        // Increment the NumOfHints by the number couples of of arguments
0682:                        NumOfHints += NumOfArgs / 2;
0683:                    // A call to "mask"
0684:                    else if (key == "hintmask" || key == "cntrmask") {
0685:                        // Compute the size of the mask
0686:                        int SizeOfMask = NumOfHints / 8;
0687:                        if (NumOfHints % 8 != 0 || SizeOfMask == 0)
0688:                            SizeOfMask++;
0689:                        // Continue the pointer in SizeOfMask steps
0690:                        for (int i = 0; i < SizeOfMask; i++)
0691:                            getCard8();
0692:                    }
0693:                }
0694:            }
0695:
0696:            /**
0697:             * Function Checks how the current operator effects the run time stack after being run 
0698:             * An operator may increase or decrease the stack size
0699:             */
0700:            protected void HandelStack() {
0701:                // Findout what the operator does to the stack
0702:                int StackHandel = StackOpp();
0703:                if (StackHandel < 2) {
0704:                    // The operators that enlarge the stack by one
0705:                    if (StackHandel == 1)
0706:                        PushStack();
0707:                    // The operators that pop the stack
0708:                    else {
0709:                        // Abs value for the for loop
0710:                        StackHandel *= -1;
0711:                        for (int i = 0; i < StackHandel; i++)
0712:                            PopStack();
0713:                    }
0714:
0715:                }
0716:                // All other flush the stack
0717:                else
0718:                    EmptyStack();
0719:            }
0720:
0721:            /**
0722:             * Function checks the key and return the change to the stack after the operator
0723:             * @return The change in the stack. 2-> flush the stack
0724:             */
0725:            protected int StackOpp() {
0726:                if (key == "ifelse")
0727:                    return -3;
0728:                if (key == "roll" || key == "put")
0729:                    return -2;
0730:                if (key == "callsubr" || key == "callgsubr" || key == "add"
0731:                        || key == "sub" || key == "div" || key == "mul"
0732:                        || key == "drop" || key == "and" || key == "or"
0733:                        || key == "eq")
0734:                    return -1;
0735:                if (key == "abs" || key == "neg" || key == "sqrt"
0736:                        || key == "exch" || key == "index" || key == "get"
0737:                        || key == "not" || key == "return")
0738:                    return 0;
0739:                if (key == "random" || key == "dup")
0740:                    return 1;
0741:                return 2;
0742:            }
0743:
0744:            /**
0745:             * Empty the Type2 Stack
0746:             *
0747:             */
0748:            protected void EmptyStack() {
0749:                // Null the arguments
0750:                for (int i = 0; i < arg_count; i++)
0751:                    args[i] = null;
0752:                arg_count = 0;
0753:            }
0754:
0755:            /**
0756:             * Pop one element from the stack 
0757:             *
0758:             */
0759:            protected void PopStack() {
0760:                if (arg_count > 0) {
0761:                    args[arg_count - 1] = null;
0762:                    arg_count--;
0763:                }
0764:            }
0765:
0766:            /**
0767:             * Add an item to the stack
0768:             *
0769:             */
0770:            protected void PushStack() {
0771:                arg_count++;
0772:            }
0773:
0774:            /**
0775:             * The function reads the next command after the file pointer is set
0776:             */
0777:            protected void ReadCommand() {
0778:                key = null;
0779:                boolean gotKey = false;
0780:                // Until a key is found
0781:                while (!gotKey) {
0782:                    // Read the first Char
0783:                    char b0 = getCard8();
0784:                    // decode according to the type1/type2 format
0785:                    if (b0 == 28) // the two next bytes represent a short int;
0786:                    {
0787:                        int first = getCard8();
0788:                        int second = getCard8();
0789:                        args[arg_count] = new Integer(first << 8 | second);
0790:                        arg_count++;
0791:                        continue;
0792:                    }
0793:                    if (b0 >= 32 && b0 <= 246) // The byte read is the byte;
0794:                    {
0795:                        args[arg_count] = new Integer(b0 - 139);
0796:                        arg_count++;
0797:                        continue;
0798:                    }
0799:                    if (b0 >= 247 && b0 <= 250) // The byte read and the next byte constetute a short int
0800:                    {
0801:                        int w = getCard8();
0802:                        args[arg_count] = new Integer((b0 - 247) * 256 + w
0803:                                + 108);
0804:                        arg_count++;
0805:                        continue;
0806:                    }
0807:                    if (b0 >= 251 && b0 <= 254)// Same as above except negative
0808:                    {
0809:                        int w = getCard8();
0810:                        args[arg_count] = new Integer(-(b0 - 251) * 256 - w
0811:                                - 108);
0812:                        arg_count++;
0813:                        continue;
0814:                    }
0815:                    if (b0 == 255)// The next for bytes represent a double.
0816:                    {
0817:                        int first = getCard8();
0818:                        int second = getCard8();
0819:                        int third = getCard8();
0820:                        int fourth = getCard8();
0821:                        args[arg_count] = new Integer(first << 24
0822:                                | second << 16 | third << 8 | fourth);
0823:                        arg_count++;
0824:                        continue;
0825:                    }
0826:                    if (b0 <= 31 && b0 != 28) // An operator was found.. Set Key.
0827:                    {
0828:                        gotKey = true;
0829:                        // 12 is an escape command therefor the next byte is a part
0830:                        // of this command
0831:                        if (b0 == 12) {
0832:                            int b1 = getCard8();
0833:                            if (b1 > SubrsEscapeFuncs.length - 1)
0834:                                b1 = SubrsEscapeFuncs.length - 1;
0835:                            key = SubrsEscapeFuncs[b1];
0836:                        } else
0837:                            key = SubrsFunctions[b0];
0838:                        continue;
0839:                    }
0840:                }
0841:            }
0842:
0843:            /**
0844:             * The function reads the subroutine and returns the number of the hint in it.
0845:             * If a call to another subroutine is found the function calls recursively.
0846:             * @param begin the start point of the subr
0847:             * @param end the end point of the subr
0848:             * @param LBias the bias of the Local Subrs
0849:             * @param GBias the bias of the Global Subrs
0850:             * @param LSubrsOffsets The Offsets array of the subroutines
0851:             * @return The number of hints in the subroutine read.
0852:             */
0853:            protected int CalcHints(int begin, int end, int LBias, int GBias,
0854:                    int[] LSubrsOffsets) {
0855:                // Goto begining of the subr
0856:                seek(begin);
0857:                while (getPosition() < end) {
0858:                    // Read the next command
0859:                    ReadCommand();
0860:                    int pos = getPosition();
0861:                    Object TopElement = null;
0862:                    if (arg_count > 0)
0863:                        TopElement = args[arg_count - 1];
0864:                    int NumOfArgs = arg_count;
0865:                    //Check the modification needed on the Argument Stack according to key;
0866:                    HandelStack();
0867:                    // a call to a Lsubr
0868:                    if (key == "callsubr") {
0869:                        if (NumOfArgs > 0) {
0870:                            int Subr = ((Integer) TopElement).intValue()
0871:                                    + LBias;
0872:                            CalcHints(LSubrsOffsets[Subr],
0873:                                    LSubrsOffsets[Subr + 1], LBias, GBias,
0874:                                    LSubrsOffsets);
0875:                            seek(pos);
0876:                        }
0877:                    }
0878:                    // a call to a Gsubr
0879:                    else if (key == "callgsubr") {
0880:                        if (NumOfArgs > 0) {
0881:                            int Subr = ((Integer) TopElement).intValue()
0882:                                    + GBias;
0883:                            CalcHints(gsubrOffsets[Subr],
0884:                                    gsubrOffsets[Subr + 1], LBias, GBias,
0885:                                    LSubrsOffsets);
0886:                            seek(pos);
0887:                        }
0888:                    }
0889:                    // A call to "stem"
0890:                    else if (key == "hstem" || key == "vstem"
0891:                            || key == "hstemhm" || key == "vstemhm")
0892:                        // Increment the NumOfHints by the number couples of of arguments
0893:                        NumOfHints += NumOfArgs / 2;
0894:                    // A call to "mask"
0895:                    else if (key == "hintmask" || key == "cntrmask") {
0896:                        // Compute the size of the mask
0897:                        int SizeOfMask = NumOfHints / 8;
0898:                        if (NumOfHints % 8 != 0 || SizeOfMask == 0)
0899:                            SizeOfMask++;
0900:                        // Continue the pointer in SizeOfMask steps
0901:                        for (int i = 0; i < SizeOfMask; i++)
0902:                            getCard8();
0903:                    }
0904:                }
0905:                return NumOfHints;
0906:            }
0907:
0908:            /**
0909:             * Function builds the new offset array, object array and assembles the index.
0910:             * used for creating the glyph and subrs subsetted index 
0911:             * @param Offsets the offset array of the original index  
0912:             * @param Used the hashmap of the used objects
0913:             * @return the new index subset version 
0914:             * @throws IOException
0915:             */
0916:            protected byte[] BuildNewIndex(int[] Offsets, HashMap Used)
0917:                    throws IOException {
0918:                int Offset = 0;
0919:                int[] NewOffsets = new int[Offsets.length];
0920:                // Build the Offsets Array for the Subset
0921:                for (int i = 0; i < Offsets.length; ++i) {
0922:                    NewOffsets[i] = Offset;
0923:                    // If the object in the offset is also present in the used
0924:                    // HashMap then increment the offset var by its size
0925:                    if (Used.containsKey(new Integer(i)))
0926:                        Offset += Offsets[i + 1] - Offsets[i];
0927:                    // Else the same offset is kept in i+1.
0928:                }
0929:                // Offset var determines the size of the object array
0930:                byte[] NewObjects = new byte[Offset];
0931:                // Build the new Object array
0932:                for (int i = 0; i < Offsets.length - 1; ++i) {
0933:                    int start = NewOffsets[i];
0934:                    int end = NewOffsets[i + 1];
0935:                    // If start != End then the Object is used
0936:                    // So, we will copy the object data from the font file
0937:                    if (start != end) {
0938:                        // All offsets are Global Offsets relative to the begining of the font file.
0939:                        // Jump the file pointer to the start address to read from.
0940:                        buf.seek(Offsets[i]);
0941:                        // Read from the buffer and write into the array at start.  
0942:                        buf.readFully(NewObjects, start, end - start);
0943:                    }
0944:                }
0945:                // Use AssembleIndex to build the index from the offset & object arrays
0946:                return AssembleIndex(NewOffsets, NewObjects);
0947:            }
0948:
0949:            /**
0950:             * Function creates the new index, inserting the count,offsetsize,offset array
0951:             * and object array.
0952:             * @param NewOffsets the subsetted offset array
0953:             * @param NewObjects the subsetted object array
0954:             * @return the new index created
0955:             */
0956:            protected byte[] AssembleIndex(int[] NewOffsets, byte[] NewObjects) {
0957:                // Calc the index' count field
0958:                char Count = (char) (NewOffsets.length - 1);
0959:                // Calc the size of the object array
0960:                int Size = NewOffsets[NewOffsets.length - 1];
0961:                // Calc the Offsize
0962:                byte Offsize;
0963:                if (Size <= 0xff)
0964:                    Offsize = 1;
0965:                else if (Size <= 0xffff)
0966:                    Offsize = 2;
0967:                else if (Size <= 0xffffff)
0968:                    Offsize = 3;
0969:                else
0970:                    Offsize = 4;
0971:                // The byte array for the new index. The size is calc by
0972:                // Count=2, Offsize=1, OffsetArray = Offsize*(Count+1), The object array
0973:                byte[] NewIndex = new byte[2 + 1 + Offsize * (Count + 1)
0974:                        + NewObjects.length];
0975:                // The counter for writing
0976:                int Place = 0;
0977:                // Write the count field
0978:                NewIndex[Place++] = (byte) ((Count >>> 8) & 0xff);
0979:                NewIndex[Place++] = (byte) ((Count >>> 0) & 0xff);
0980:                // Write the offsize field
0981:                NewIndex[Place++] = Offsize;
0982:                // Write the offset array according to the offsize
0983:                for (int i = 0; i < NewOffsets.length; i++) {
0984:                    // The value to be written
0985:                    int Num = NewOffsets[i] - NewOffsets[0] + 1;
0986:                    // Write in bytes according to the offsize
0987:                    switch (Offsize) {
0988:                    case 4:
0989:                        NewIndex[Place++] = (byte) ((Num >>> 24) & 0xff);
0990:                    case 3:
0991:                        NewIndex[Place++] = (byte) ((Num >>> 16) & 0xff);
0992:                    case 2:
0993:                        NewIndex[Place++] = (byte) ((Num >>> 8) & 0xff);
0994:                    case 1:
0995:                        NewIndex[Place++] = (byte) ((Num >>> 0) & 0xff);
0996:                    }
0997:                }
0998:                // Write the new object array one by one
0999:                for (int i = 0; i < NewObjects.length; i++) {
1000:                    NewIndex[Place++] = NewObjects[i];
1001:                }
1002:                // Return the new index
1003:                return NewIndex;
1004:            }
1005:
1006:            /**
1007:             * The function builds the new output stream according to the subset process
1008:             * @param Font the font
1009:             * @return the subseted font stream
1010:             */
1011:            protected byte[] BuildNewFile(int Font) {
1012:                // Prepare linked list for new font components
1013:                OutputList = new LinkedList();
1014:
1015:                // copy the header of the font
1016:                CopyHeader();
1017:
1018:                // create a name index
1019:                BuildIndexHeader(1, 1, 1);
1020:                OutputList.addLast(new UInt8Item((char) (1 + fonts[Font].name
1021:                        .length())));
1022:                OutputList.addLast(new StringItem(fonts[Font].name));
1023:
1024:                // create the topdict Index
1025:                BuildIndexHeader(1, 2, 1);
1026:                OffsetItem topdictIndex1Ref = new IndexOffsetItem(2);
1027:                OutputList.addLast(topdictIndex1Ref);
1028:                IndexBaseItem topdictBase = new IndexBaseItem();
1029:                OutputList.addLast(topdictBase);
1030:
1031:                // Initialise the Dict Items for later use
1032:                OffsetItem charsetRef = new DictOffsetItem();
1033:                OffsetItem charstringsRef = new DictOffsetItem();
1034:                OffsetItem fdarrayRef = new DictOffsetItem();
1035:                OffsetItem fdselectRef = new DictOffsetItem();
1036:                OffsetItem privateRef = new DictOffsetItem();
1037:
1038:                // If the font is not CID create the following keys
1039:                if (!fonts[Font].isCID) {
1040:                    // create a ROS key
1041:                    OutputList
1042:                            .addLast(new DictNumberItem(fonts[Font].nstrings));
1043:                    OutputList.addLast(new DictNumberItem(
1044:                            fonts[Font].nstrings + 1));
1045:                    OutputList.addLast(new DictNumberItem(0));
1046:                    OutputList.addLast(new UInt8Item((char) 12));
1047:                    OutputList.addLast(new UInt8Item((char) 30));
1048:                    // create a CIDCount key
1049:                    OutputList.addLast(new DictNumberItem(fonts[Font].nglyphs));
1050:                    OutputList.addLast(new UInt8Item((char) 12));
1051:                    OutputList.addLast(new UInt8Item((char) 34));
1052:                    // Sivan's comments
1053:                    // What about UIDBase (12,35)? Don't know what is it.
1054:                    // I don't think we need FontName; the font I looked at didn't have it.
1055:                }
1056:                // Go to the TopDict of the font being processed
1057:                seek(topdictOffsets[Font]);
1058:                // Run untill the end of the TopDict
1059:                while (getPosition() < topdictOffsets[Font + 1]) {
1060:                    int p1 = getPosition();
1061:                    getDictItem();
1062:                    int p2 = getPosition();
1063:                    // The encoding key is disregarded since CID has no encoding
1064:                    if (key == "Encoding"
1065:                            // These keys will be added manualy by the process.
1066:                            || key == "Private" || key == "FDSelect"
1067:                            || key == "FDArray" || key == "charset"
1068:                            || key == "CharStrings") {
1069:                    } else {
1070:                        //OtherWise copy key "as is" to the output list
1071:                        OutputList.add(new RangeItem(buf, p1, p2 - p1));
1072:                    }
1073:                }
1074:                // Create the FDArray, FDSelect, Charset and CharStrings Keys
1075:                CreateKeys(fdarrayRef, fdselectRef, charsetRef, charstringsRef);
1076:
1077:                // Mark the end of the top dict area
1078:                OutputList.addLast(new IndexMarkerItem(topdictIndex1Ref,
1079:                        topdictBase));
1080:
1081:                // Copy the string index
1082:
1083:                if (fonts[Font].isCID)
1084:                    OutputList.addLast(getEntireIndexRange(stringIndexOffset));
1085:                // If the font is not CID we need to append new strings.
1086:                // We need 3 more strings: Registry, Ordering, and a FontName for one FD.
1087:                // The total length is at most "Adobe"+"Identity"+63 = 76
1088:                else
1089:                    CreateNewStringIndex(Font);
1090:
1091:                // copy the new subsetted global subroutine index       
1092:                OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(
1093:                        NewGSubrsIndex), 0, NewGSubrsIndex.length));
1094:
1095:                // deal with fdarray, fdselect, and the font descriptors
1096:                // If the font is CID:
1097:                if (fonts[Font].isCID) {
1098:                    // copy the FDArray, FDSelect, charset
1099:
1100:                    // Copy FDSelect
1101:                    // Mark the beginning
1102:                    OutputList.addLast(new MarkerItem(fdselectRef));
1103:                    // If an FDSelect exists copy it
1104:                    if (fonts[Font].fdselectOffset >= 0)
1105:                        OutputList.addLast(new RangeItem(buf,
1106:                                fonts[Font].fdselectOffset,
1107:                                fonts[Font].FDSelectLength));
1108:                    // Else create a new one
1109:                    else
1110:                        CreateFDSelect(fdselectRef, fonts[Font].nglyphs);
1111:
1112:                    // Copy the Charset
1113:                    // Mark the beginning and copy entirly 
1114:                    OutputList.addLast(new MarkerItem(charsetRef));
1115:                    OutputList.addLast(new RangeItem(buf,
1116:                            fonts[Font].charsetOffset,
1117:                            fonts[Font].CharsetLength));
1118:
1119:                    // Copy the FDArray
1120:                    // If an FDArray exists
1121:                    if (fonts[Font].fdarrayOffset >= 0) {
1122:                        // Mark the beginning
1123:                        OutputList.addLast(new MarkerItem(fdarrayRef));
1124:                        // Build a new FDArray with its private dicts and their LSubrs
1125:                        Reconstruct(Font);
1126:                    } else
1127:                        // Else create a new one
1128:                        CreateFDArray(fdarrayRef, privateRef, Font);
1129:
1130:                }
1131:                // If the font is not CID
1132:                else {
1133:                    // create FDSelect
1134:                    CreateFDSelect(fdselectRef, fonts[Font].nglyphs);
1135:                    // recreate a new charset
1136:                    CreateCharset(charsetRef, fonts[Font].nglyphs);
1137:                    // create a font dict index (fdarray)
1138:                    CreateFDArray(fdarrayRef, privateRef, Font);
1139:                }
1140:
1141:                // if a private dict exists insert its subsetted version
1142:                if (fonts[Font].privateOffset >= 0) {
1143:                    // Mark the beginning of the private dict
1144:                    IndexBaseItem PrivateBase = new IndexBaseItem();
1145:                    OutputList.addLast(PrivateBase);
1146:                    OutputList.addLast(new MarkerItem(privateRef));
1147:
1148:                    OffsetItem Subr = new DictOffsetItem();
1149:                    // Build and copy the new private dict
1150:                    CreateNonCIDPrivate(Font, Subr);
1151:                    // Copy the new LSubrs index
1152:                    CreateNonCIDSubrs(Font, PrivateBase, Subr);
1153:                }
1154:
1155:                // copy the charstring index
1156:                OutputList.addLast(new MarkerItem(charstringsRef));
1157:
1158:                // Add the subsetted charstring
1159:                OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(
1160:                        NewCharStringsIndex), 0, NewCharStringsIndex.length));
1161:
1162:                // now create the new CFF font        
1163:                int[] currentOffset = new int[1];
1164:                currentOffset[0] = 0;
1165:                // Count and save the offset for each item
1166:                Iterator listIter = OutputList.iterator();
1167:                while (listIter.hasNext()) {
1168:                    Item item = (Item) listIter.next();
1169:                    item.increment(currentOffset);
1170:                }
1171:                // Compute the Xref for each of the offset items
1172:                listIter = OutputList.iterator();
1173:                while (listIter.hasNext()) {
1174:                    Item item = (Item) listIter.next();
1175:                    item.xref();
1176:                }
1177:
1178:                int size = currentOffset[0];
1179:                byte[] b = new byte[size];
1180:
1181:                // Emit all the items into the new byte array
1182:                listIter = OutputList.iterator();
1183:                while (listIter.hasNext()) {
1184:                    Item item = (Item) listIter.next();
1185:                    item.emit(b);
1186:                }
1187:                // Return the new stream
1188:                return b;
1189:            }
1190:
1191:            /**
1192:             * Function Copies the header from the original fileto the output list
1193:             */
1194:            protected void CopyHeader() {
1195:                seek(0);
1196:                int major = getCard8();
1197:                int minor = getCard8();
1198:                int hdrSize = getCard8();
1199:                int offSize = getCard8();
1200:                nextIndexOffset = hdrSize;
1201:                OutputList.addLast(new RangeItem(buf, 0, hdrSize));
1202:            }
1203:
1204:            /**
1205:             * Function Build the header of an index
1206:             * @param Count the count field of the index
1207:             * @param Offsize the offsize field of the index
1208:             * @param First the first offset of the index
1209:             */
1210:            protected void BuildIndexHeader(int Count, int Offsize, int First) {
1211:                // Add the count field
1212:                OutputList.addLast(new UInt16Item((char) Count)); // count
1213:                // Add the offsize field
1214:                OutputList.addLast(new UInt8Item((char) Offsize)); // offSize
1215:                // Add the first offset according to the offsize
1216:                switch (Offsize) {
1217:                case 1:
1218:                    OutputList.addLast(new UInt8Item((char) First)); // first offset
1219:                    break;
1220:                case 2:
1221:                    OutputList.addLast(new UInt16Item((char) First)); // first offset
1222:                    break;
1223:                case 3:
1224:                    OutputList.addLast(new UInt24Item((char) First)); // first offset
1225:                    break;
1226:                case 4:
1227:                    OutputList.addLast(new UInt32Item((char) First)); // first offset
1228:                    break;
1229:                default:
1230:                    break;
1231:                }
1232:            }
1233:
1234:            /**
1235:             * Function adds the keys into the TopDict
1236:             * @param fdarrayRef OffsetItem for the FDArray
1237:             * @param fdselectRef OffsetItem for the FDSelect
1238:             * @param charsetRef OffsetItem for the CharSet
1239:             * @param charstringsRef OffsetItem for the CharString
1240:             */
1241:            protected void CreateKeys(OffsetItem fdarrayRef,
1242:                    OffsetItem fdselectRef, OffsetItem charsetRef,
1243:                    OffsetItem charstringsRef) {
1244:                // create an FDArray key
1245:                OutputList.addLast(fdarrayRef);
1246:                OutputList.addLast(new UInt8Item((char) 12));
1247:                OutputList.addLast(new UInt8Item((char) 36));
1248:                // create an FDSelect key
1249:                OutputList.addLast(fdselectRef);
1250:                OutputList.addLast(new UInt8Item((char) 12));
1251:                OutputList.addLast(new UInt8Item((char) 37));
1252:                // create an charset key
1253:                OutputList.addLast(charsetRef);
1254:                OutputList.addLast(new UInt8Item((char) 15));
1255:                // create a CharStrings key
1256:                OutputList.addLast(charstringsRef);
1257:                OutputList.addLast(new UInt8Item((char) 17));
1258:            }
1259:
1260:            /**
1261:             * Function takes the original string item and adds the new strings
1262:             * to accomodate the CID rules
1263:             * @param Font the font
1264:             */
1265:            protected void CreateNewStringIndex(int Font) {
1266:                String fdFontName = fonts[Font].name + "-OneRange";
1267:                if (fdFontName.length() > 127)
1268:                    fdFontName = fdFontName.substring(0, 127);
1269:                String extraStrings = "Adobe" + "Identity" + fdFontName;
1270:
1271:                int origStringsLen = stringOffsets[stringOffsets.length - 1]
1272:                        - stringOffsets[0];
1273:                int stringsBaseOffset = stringOffsets[0] - 1;
1274:
1275:                byte stringsIndexOffSize;
1276:                if (origStringsLen + extraStrings.length() <= 0xff)
1277:                    stringsIndexOffSize = 1;
1278:                else if (origStringsLen + extraStrings.length() <= 0xffff)
1279:                    stringsIndexOffSize = 2;
1280:                else if (origStringsLen + extraStrings.length() <= 0xffffff)
1281:                    stringsIndexOffSize = 3;
1282:                else
1283:                    stringsIndexOffSize = 4;
1284:
1285:                OutputList.addLast(new UInt16Item(
1286:                        (char) ((stringOffsets.length - 1) + 3))); // count
1287:                OutputList.addLast(new UInt8Item((char) stringsIndexOffSize)); // offSize
1288:                for (int i = 0; i < stringOffsets.length; i++)
1289:                    OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,
1290:                            stringOffsets[i] - stringsBaseOffset));
1291:                int currentStringsOffset = stringOffsets[stringOffsets.length - 1]
1292:                        - stringsBaseOffset;
1293:                //l.addLast(new IndexOffsetItem(stringsIndexOffSize,currentStringsOffset));
1294:                currentStringsOffset += ("Adobe").length();
1295:                OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,
1296:                        currentStringsOffset));
1297:                currentStringsOffset += ("Identity").length();
1298:                OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,
1299:                        currentStringsOffset));
1300:                currentStringsOffset += fdFontName.length();
1301:                OutputList.addLast(new IndexOffsetItem(stringsIndexOffSize,
1302:                        currentStringsOffset));
1303:
1304:                OutputList.addLast(new RangeItem(buf, stringOffsets[0],
1305:                        origStringsLen));
1306:                OutputList.addLast(new StringItem(extraStrings));
1307:            }
1308:
1309:            /**
1310:             * Function creates new FDSelect for non-CID fonts.
1311:             * The FDSelect built uses a single range for all glyphs
1312:             * @param fdselectRef OffsetItem for the FDSelect
1313:             * @param nglyphs the number of glyphs in the font
1314:             */
1315:            protected void CreateFDSelect(OffsetItem fdselectRef, int nglyphs) {
1316:                OutputList.addLast(new MarkerItem(fdselectRef));
1317:                OutputList.addLast(new UInt8Item((char) 3)); // format identifier
1318:                OutputList.addLast(new UInt16Item((char) 1)); // nRanges
1319:
1320:                OutputList.addLast(new UInt16Item((char) 0)); // Range[0].firstGlyph
1321:                OutputList.addLast(new UInt8Item((char) 0)); // Range[0].fd
1322:
1323:                OutputList.addLast(new UInt16Item((char) nglyphs)); // sentinel
1324:            }
1325:
1326:            /**
1327:             * Function creates new CharSet for non-CID fonts.
1328:             * The CharSet built uses a single range for all glyphs
1329:             * @param charsetRef OffsetItem for the CharSet
1330:             * @param nglyphs the number of glyphs in the font
1331:             */
1332:            protected void CreateCharset(OffsetItem charsetRef, int nglyphs) {
1333:                OutputList.addLast(new MarkerItem(charsetRef));
1334:                OutputList.addLast(new UInt8Item((char) 2)); // format identifier
1335:                OutputList.addLast(new UInt16Item((char) 1)); // first glyph in range (ignore .notdef)
1336:                OutputList.addLast(new UInt16Item((char) (nglyphs - 1))); // nLeft
1337:            }
1338:
1339:            /**
1340:             * Function creates new FDArray for non-CID fonts.
1341:             * The FDArray built has only the "Private" operator that points to the font's
1342:             * original private dict 
1343:             * @param fdarrayRef OffsetItem for the FDArray
1344:             * @param privateRef OffsetItem for the Private Dict
1345:             * @param Font the font
1346:             */
1347:            protected void CreateFDArray(OffsetItem fdarrayRef,
1348:                    OffsetItem privateRef, int Font) {
1349:                OutputList.addLast(new MarkerItem(fdarrayRef));
1350:                // Build the header (count=offsize=first=1)
1351:                BuildIndexHeader(1, 1, 1);
1352:
1353:                // Mark
1354:                OffsetItem privateIndex1Ref = new IndexOffsetItem(1);
1355:                OutputList.addLast(privateIndex1Ref);
1356:                IndexBaseItem privateBase = new IndexBaseItem();
1357:                // Insert the private operands and operator
1358:                OutputList.addLast(privateBase);
1359:                // Calc the new size of the private after subsetting
1360:                // Origianl size
1361:                int NewSize = fonts[Font].privateLength;
1362:                // Calc the original size of the Subr offset in the private
1363:                int OrgSubrsOffsetSize = CalcSubrOffsetSize(
1364:                        fonts[Font].privateOffset, fonts[Font].privateLength);
1365:                // Increase the ptivate's size
1366:                if (OrgSubrsOffsetSize != 0)
1367:                    NewSize += 5 - OrgSubrsOffsetSize;
1368:                OutputList.addLast(new DictNumberItem(NewSize));
1369:                OutputList.addLast(privateRef);
1370:                OutputList.addLast(new UInt8Item((char) 18)); // Private
1371:
1372:                OutputList.addLast(new IndexMarkerItem(privateIndex1Ref,
1373:                        privateBase));
1374:            }
1375:
1376:            /**
1377:             * Function reconstructs the FDArray, PrivateDict and LSubr for CID fonts
1378:             * @param Font the font
1379:             */
1380:            void Reconstruct(int Font) {
1381:                // Init for later use
1382:                OffsetItem[] fdPrivate = new DictOffsetItem[fonts[Font].FDArrayOffsets.length - 1];
1383:                IndexBaseItem[] fdPrivateBase = new IndexBaseItem[fonts[Font].fdprivateOffsets.length];
1384:                OffsetItem[] fdSubrs = new DictOffsetItem[fonts[Font].fdprivateOffsets.length];
1385:                // Reconstruct each type
1386:                ReconstructFDArray(Font, fdPrivate);
1387:                ReconstructPrivateDict(Font, fdPrivate, fdPrivateBase, fdSubrs);
1388:                ReconstructPrivateSubrs(Font, fdPrivateBase, fdSubrs);
1389:            }
1390:
1391:            /**
1392:             * Function subsets the FDArray and builds the new one with new offsets
1393:             * @param Font The font
1394:             * @param fdPrivate OffsetItem Array (one for each FDArray)
1395:             */
1396:            void ReconstructFDArray(int Font, OffsetItem[] fdPrivate) {
1397:                // Build the header of the index
1398:                BuildIndexHeader(fonts[Font].FDArrayCount,
1399:                        fonts[Font].FDArrayOffsize, 1);
1400:
1401:                // For each offset create an Offset Item
1402:                OffsetItem[] fdOffsets = new IndexOffsetItem[fonts[Font].FDArrayOffsets.length - 1];
1403:                for (int i = 0; i < fonts[Font].FDArrayOffsets.length - 1; i++) {
1404:                    fdOffsets[i] = new IndexOffsetItem(
1405:                            fonts[Font].FDArrayOffsize);
1406:                    OutputList.addLast(fdOffsets[i]);
1407:                }
1408:
1409:                // Declare beginning of the object array
1410:                IndexBaseItem fdArrayBase = new IndexBaseItem();
1411:                OutputList.addLast(fdArrayBase);
1412:
1413:                // For each object check if that FD is used.
1414:                // if is used build a new one by changing the private object
1415:                // Else do nothing
1416:                // At the end of each object mark its ending (Even if wasn't written)
1417:                for (int k = 0; k < fonts[Font].FDArrayOffsets.length - 1; k++) {
1418:                    if (FDArrayUsed.containsKey(new Integer(k))) {
1419:                        // Goto begining of objects
1420:                        seek(fonts[Font].FDArrayOffsets[k]);
1421:                        while (getPosition() < fonts[Font].FDArrayOffsets[k + 1]) {
1422:                            int p1 = getPosition();
1423:                            getDictItem();
1424:                            int p2 = getPosition();
1425:                            // If the dictItem is the "Private" then compute and copy length, 
1426:                            // use marker for offset and write operator number
1427:                            if (key == "Private") {
1428:                                // Save the original length of the private dict
1429:                                int NewSize = ((Integer) args[0]).intValue();
1430:                                // Save the size of the offset to the subrs in that private
1431:                                int OrgSubrsOffsetSize = CalcSubrOffsetSize(
1432:                                        fonts[Font].fdprivateOffsets[k],
1433:                                        fonts[Font].fdprivateLengths[k]);
1434:                                // Increase the private's length accordingly
1435:                                if (OrgSubrsOffsetSize != 0)
1436:                                    NewSize += 5 - OrgSubrsOffsetSize;
1437:                                // Insert the new size, OffsetItem and operator key number
1438:                                OutputList.addLast(new DictNumberItem(NewSize));
1439:                                fdPrivate[k] = new DictOffsetItem();
1440:                                OutputList.addLast(fdPrivate[k]);
1441:                                OutputList.addLast(new UInt8Item((char) 18)); // Private
1442:                                // Go back to place 
1443:                                seek(p2);
1444:                            }
1445:                            // Else copy the entire range
1446:                            else
1447:                                // other than private
1448:                                OutputList.addLast(new RangeItem(buf, p1, p2
1449:                                        - p1));
1450:                        }
1451:                    }
1452:                    // Mark the ending of the object (even if wasn't written)
1453:                    OutputList.addLast(new IndexMarkerItem(fdOffsets[k],
1454:                            fdArrayBase));
1455:                }
1456:            }
1457:
1458:            /**
1459:             * Function Adds the new private dicts (only for the FDs used) to the list
1460:             * @param Font the font
1461:             * @param fdPrivate OffsetItem array one element for each private
1462:             * @param fdPrivateBase IndexBaseItem array one element for each private
1463:             * @param fdSubrs OffsetItem array one element for each private
1464:             */
1465:            void ReconstructPrivateDict(int Font, OffsetItem[] fdPrivate,
1466:                    IndexBaseItem[] fdPrivateBase, OffsetItem[] fdSubrs) {
1467:
1468:                // For each fdarray private dict check if that FD is used.
1469:                // if is used build a new one by changing the subrs offset
1470:                // Else do nothing
1471:                for (int i = 0; i < fonts[Font].fdprivateOffsets.length; i++) {
1472:                    if (FDArrayUsed.containsKey(new Integer(i))) {
1473:                        // Mark beginning
1474:                        OutputList.addLast(new MarkerItem(fdPrivate[i]));
1475:                        fdPrivateBase[i] = new IndexBaseItem();
1476:                        OutputList.addLast(fdPrivateBase[i]);
1477:                        // Goto begining of objects
1478:                        seek(fonts[Font].fdprivateOffsets[i]);
1479:                        while (getPosition() < fonts[Font].fdprivateOffsets[i]
1480:                                + fonts[Font].fdprivateLengths[i]) {
1481:                            int p1 = getPosition();
1482:                            getDictItem();
1483:                            int p2 = getPosition();
1484:                            // If the dictItem is the "Subrs" then, 
1485:                            // use marker for offset and write operator number
1486:                            if (key == "Subrs") {
1487:                                fdSubrs[i] = new DictOffsetItem();
1488:                                OutputList.addLast(fdSubrs[i]);
1489:                                OutputList.addLast(new UInt8Item((char) 19)); // Subrs
1490:                            }
1491:                            // Else copy the entire range
1492:                            else
1493:                                OutputList.addLast(new RangeItem(buf, p1, p2
1494:                                        - p1));
1495:                        }
1496:                    }
1497:                }
1498:            }
1499:
1500:            /**
1501:             * Function Adds the new LSubrs dicts (only for the FDs used) to the list
1502:             * @param Font  The index of the font
1503:             * @param fdPrivateBase The IndexBaseItem array for the linked list
1504:             * @param fdSubrs OffsetItem array for the linked list
1505:             */
1506:
1507:            void ReconstructPrivateSubrs(int Font,
1508:                    IndexBaseItem[] fdPrivateBase, OffsetItem[] fdSubrs) {
1509:                // For each private dict
1510:                for (int i = 0; i < fonts[Font].fdprivateLengths.length; i++) {
1511:                    // If that private dict's Subrs are used insert the new LSubrs
1512:                    // computed earlier
1513:                    if (fdSubrs[i] != null
1514:                            && fonts[Font].PrivateSubrsOffset[i] >= 0) {
1515:                        OutputList.addLast(new SubrMarkerItem(fdSubrs[i],
1516:                                fdPrivateBase[i]));
1517:                        OutputList.addLast(new RangeItem(
1518:                                new RandomAccessFileOrArray(NewLSubrsIndex[i]),
1519:                                0, NewLSubrsIndex[i].length));
1520:                    }
1521:                }
1522:            }
1523:
1524:            /**
1525:             * Calculates how many byte it took to write the offset for the subrs in a specific
1526:             * private dict.
1527:             * @param Offset The Offset for the private dict
1528:             * @param Size The size of the private dict
1529:             * @return The size of the offset of the subrs in the private dict
1530:             */
1531:            int CalcSubrOffsetSize(int Offset, int Size) {
1532:                // Set the size to 0
1533:                int OffsetSize = 0;
1534:                // Go to the beginning of the private dict
1535:                seek(Offset);
1536:                // Go until the end of the private dict 
1537:                while (getPosition() < Offset + Size) {
1538:                    int p1 = getPosition();
1539:                    getDictItem();
1540:                    int p2 = getPosition();
1541:                    // When reached to the subrs offset
1542:                    if (key == "Subrs") {
1543:                        // The Offsize (minus the subrs key)
1544:                        OffsetSize = p2 - p1 - 1;
1545:                    }
1546:                    // All other keys are ignored
1547:                }
1548:                // return the size
1549:                return OffsetSize;
1550:            }
1551:
1552:            /**
1553:             * Function computes the size of an index
1554:             * @param indexOffset The offset for the computed index
1555:             * @return The size of the index
1556:             */
1557:            protected int countEntireIndexRange(int indexOffset) {
1558:                // Go to the beginning of the index 
1559:                seek(indexOffset);
1560:                // Read the count field
1561:                int count = getCard16();
1562:                // If count==0 -> size=2
1563:                if (count == 0)
1564:                    return 2;
1565:                else {
1566:                    // Read the offsize field
1567:                    int indexOffSize = getCard8();
1568:                    // Go to the last element of the offset array
1569:                    seek(indexOffset + 2 + 1 + count * indexOffSize);
1570:                    // The size of the object array is the value of the last element-1
1571:                    int size = getOffset(indexOffSize) - 1;
1572:                    // Return the size of the entire index
1573:                    return 2 + 1 + (count + 1) * indexOffSize + size;
1574:                }
1575:            }
1576:
1577:            /**
1578:             * The function creates a private dict for a font that was not CID
1579:             * All the keys are copied as is except for the subrs key 
1580:             * @param Font the font
1581:             * @param Subr The OffsetItem for the subrs of the private 
1582:             */
1583:            void CreateNonCIDPrivate(int Font, OffsetItem Subr) {
1584:                // Go to the beginning of the private dict and read untill the end
1585:                seek(fonts[Font].privateOffset);
1586:                while (getPosition() < fonts[Font].privateOffset
1587:                        + fonts[Font].privateLength) {
1588:                    int p1 = getPosition();
1589:                    getDictItem();
1590:                    int p2 = getPosition();
1591:                    // If the dictItem is the "Subrs" then, 
1592:                    // use marker for offset and write operator number
1593:                    if (key == "Subrs") {
1594:                        OutputList.addLast(Subr);
1595:                        OutputList.addLast(new UInt8Item((char) 19)); // Subrs
1596:                    }
1597:                    // Else copy the entire range
1598:                    else
1599:                        OutputList.addLast(new RangeItem(buf, p1, p2 - p1));
1600:                }
1601:            }
1602:
1603:            /**
1604:             * the function marks the beginning of the subrs index and adds the subsetted subrs
1605:             * index to the output list. 
1606:             * @param Font the font
1607:             * @param PrivateBase IndexBaseItem for the private that's referencing to the subrs
1608:             * @param Subrs OffsetItem for the subrs
1609:             */
1610:            void CreateNonCIDSubrs(int Font, IndexBaseItem PrivateBase,
1611:                    OffsetItem Subrs) {
1612:                // Mark the beginning of the Subrs index
1613:                OutputList.addLast(new SubrMarkerItem(Subrs, PrivateBase));
1614:                // Put the subsetted new subrs index
1615:                OutputList.addLast(new RangeItem(new RandomAccessFileOrArray(
1616:                        NewSubrsIndexNonCID), 0, NewSubrsIndexNonCID.length));
1617:            }
1618:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.