Source Code Cross Referenced for TrueTypeFont.java in  » PDF » PDF-Renderer » com » sun » pdfview » font » ttf » 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 Renderer » com.sun.pdfview.font.ttf 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: TrueTypeFont.java,v 1.3 2007/12/20 18:33:30 rbair Exp $
003:         *
004:         * Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
005:         * Santa Clara, California 95054, U.S.A. All rights reserved.
006:         *
007:         * This library is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU Lesser General Public
009:         * License as published by the Free Software Foundation; either
010:         * version 2.1 of the License, or (at your option) any later version.
011:         * 
012:         * This library is distributed in the hope that it will be useful,
013:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015:         * Lesser General Public License for more details.
016:         * 
017:         * You should have received a copy of the GNU Lesser General Public
018:         * License along with this library; if not, write to the Free Software
019:         * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
020:         */
021:
022:        package com.sun.pdfview.font.ttf;
023:
024:        import java.awt.Font;
025:        import java.io.ByteArrayInputStream;
026:        import java.io.InputStream;
027:        import java.io.RandomAccessFile;
028:        import java.nio.ByteBuffer;
029:        import java.util.Collections;
030:        import java.util.Iterator;
031:        import java.util.Map;
032:        import java.util.SortedMap;
033:        import java.util.TreeMap;
034:
035:        /**
036:         *
037:         * @author  jkaplan
038:         */
039:        public class TrueTypeFont {
040:
041:            private int type;
042:            private SortedMap tables;
043:
044:            /** Creates a new instance of TrueTypeParser */
045:            public TrueTypeFont(int type) {
046:                this .type = type;
047:
048:                tables = Collections.synchronizedSortedMap(new TreeMap());
049:            }
050:
051:            /**
052:             * Parses a TrueType font from a byte array
053:             */
054:            public static TrueTypeFont parseFont(byte[] orig) {
055:                ByteBuffer inBuf = ByteBuffer.wrap(orig);
056:                return parseFont(inBuf);
057:            }
058:
059:            /**
060:             * Parses a TrueType font from a byte buffer
061:             */
062:            public static TrueTypeFont parseFont(ByteBuffer inBuf) {
063:                int type = inBuf.getInt();
064:                short numTables = inBuf.getShort();
065:                short searchRange = inBuf.getShort();
066:                short entrySelector = inBuf.getShort();
067:                short rangeShift = inBuf.getShort();
068:
069:                TrueTypeFont font = new TrueTypeFont(type);
070:                parseDirectories(inBuf, numTables, font);
071:
072:                return font;
073:            }
074:
075:            /**
076:             * Get the type of this font
077:             */
078:            public int getType() {
079:                return type;
080:            }
081:
082:            /**
083:             * Add a table to the font
084:             *
085:             * @param tagString the name of this table, as a 4 character string
086:             *        (i.e. cmap or head)
087:             * @param data the data for this table, as a byte buffer
088:             */
089:            public void addTable(String tagString, ByteBuffer data) {
090:                tables.put(tagString, data);
091:            }
092:
093:            /**
094:             * Add a table to the font
095:             *
096:             * @param tagString the name of this table, as a 4 character string
097:             *        (i.e. cmap or head)
098:             * @param table the table
099:             */
100:            public void addTable(String tagString, TrueTypeTable table) {
101:                tables.put(tagString, table);
102:            }
103:
104:            /**
105:             * Get a table by name.  This command causes the table in question
106:             * to be parsed, if it has not already been parsed.
107:             *
108:             * @param tagString the name of this table, as a 4 character string
109:             *        (i.e. cmap or head)
110:             */
111:            public TrueTypeTable getTable(String tagString) {
112:                Object tableObj = tables.get(tagString);
113:
114:                TrueTypeTable table = null;
115:
116:                if (tableObj instanceof  ByteBuffer) {
117:                    // the table has not yet been parsed.  Parse it, and add the
118:                    // parsed version to the map of tables.
119:                    ByteBuffer data = (ByteBuffer) tableObj;
120:
121:                    table = TrueTypeTable.createTable(this , tagString, data);
122:                    addTable(tagString, table);
123:                } else {
124:                    table = (TrueTypeTable) tableObj;
125:                }
126:
127:                return table;
128:            }
129:
130:            /**
131:             * Remove a table by name
132:             *
133:             * @param tagString the name of this table, as a 4 character string
134:             *        (i.e. cmap or head)
135:             */
136:            public void removeTable(String tagString) {
137:                tables.remove(tagString);
138:            }
139:
140:            /**
141:             * Get the number of tables
142:             */
143:            public short getNumTables() {
144:                return (short) tables.size();
145:            }
146:
147:            /**
148:             * Get the search range
149:             */
150:            public short getSearchRange() {
151:                double pow2 = Math
152:                        .floor(Math.log(getNumTables()) / Math.log(2));
153:                double maxPower = Math.pow(2, pow2);
154:
155:                return (short) (16 * maxPower);
156:            }
157:
158:            /**
159:             * Get the entry selector
160:             */
161:            public short getEntrySelector() {
162:                double pow2 = Math
163:                        .floor(Math.log(getNumTables()) / Math.log(2));
164:                double maxPower = Math.pow(2, pow2);
165:
166:                return (short) (Math.log(maxPower) / Math.log(2));
167:            }
168:
169:            /**
170:             * Get the range shift
171:             */
172:            public short getRangeShift() {
173:                double pow2 = Math
174:                        .floor(Math.log(getNumTables()) / Math.log(2));
175:                double maxPower = Math.pow(2, pow2);
176:
177:                return (short) ((maxPower * 16) - getSearchRange());
178:            }
179:
180:            /**
181:             * Write a font given the type and an array of Table Directory Entries
182:             */
183:            public byte[] writeFont() {
184:                // allocate a buffer to hold the font
185:                ByteBuffer buf = ByteBuffer.allocate(getLength());
186:
187:                // write the font header
188:                buf.putInt(getType());
189:                buf.putShort(getNumTables());
190:                buf.putShort(getSearchRange());
191:                buf.putShort(getEntrySelector());
192:                buf.putShort(getRangeShift());
193:
194:                // first offset is the end of the table directory entries
195:                int curOffset = 12 + (getNumTables() * 16);
196:
197:                // write the tables
198:                for (Iterator i = tables.keySet().iterator(); i.hasNext();) {
199:                    String tagString = (String) i.next();
200:                    int tag = TrueTypeTable.stringToTag(tagString);
201:
202:                    ByteBuffer data = null;
203:
204:                    Object tableObj = tables.get(tagString);
205:                    if (tableObj instanceof  TrueTypeTable) {
206:                        data = ((TrueTypeTable) tableObj).getData();
207:                    } else {
208:                        data = (ByteBuffer) tableObj;
209:                    }
210:
211:                    int dataLen = data.remaining();
212:
213:                    // write the table directory entry
214:                    buf.putInt(tag);
215:                    buf.putInt(calculateChecksum(tagString, data));
216:                    buf.putInt(curOffset);
217:                    buf.putInt(dataLen);
218:
219:                    // save the current position
220:                    buf.mark();
221:
222:                    // move to the current offset and write the data
223:                    buf.position(curOffset);
224:                    buf.put(data);
225:
226:                    // reset the data start pointer
227:                    data.flip();
228:
229:                    // return to the table directory entry
230:                    buf.reset();
231:
232:                    // udate the offset
233:                    curOffset += dataLen;
234:
235:                    // don't forget the padding
236:                    while ((curOffset % 4) > 0) {
237:                        curOffset++;
238:                    }
239:                }
240:
241:                buf.position(curOffset);
242:                buf.flip();
243:
244:                // adjust the checksum
245:                updateChecksumAdj(buf);
246:
247:                return buf.array();
248:            }
249:
250:            /**
251:             * Calculate the checksum for a given table
252:             * 
253:             * @param tagString the name of the data
254:             * @param data the data in the table
255:             */
256:            private static int calculateChecksum(String tagString,
257:                    ByteBuffer data) {
258:                int sum = 0;
259:
260:                data.mark();
261:
262:                // special adjustment for head table
263:                if (tagString.equals("head")) {
264:                    data.putInt(8, 0);
265:                }
266:
267:                int nlongs = (data.remaining() + 3) / 4;
268:
269:                while (nlongs-- > 0) {
270:                    if (data.remaining() > 3) {
271:                        sum += data.getInt();
272:                    } else {
273:                        byte b0 = (data.remaining() > 0) ? data.get() : 0;
274:                        byte b1 = (data.remaining() > 0) ? data.get() : 0;
275:                        byte b2 = (data.remaining() > 0) ? data.get() : 0;
276:
277:                        sum += ((0xff & b0) << 24) | ((0xff & b1) << 16)
278:                                | ((0xff & b2) << 8);
279:                    }
280:                }
281:
282:                data.reset();
283:
284:                return sum;
285:            }
286:
287:            /**
288:             * Get directory entries from a font
289:             */
290:            private static void parseDirectories(ByteBuffer data,
291:                    int numTables, TrueTypeFont ttf) {
292:                for (int i = 0; i < numTables; i++) {
293:                    int tag = data.getInt();
294:                    String tagString = TrueTypeTable.tagToString(tag);
295:                    //            System.out.println("TTFFont.parseDirectories: " + tagString);
296:                    int checksum = data.getInt();
297:                    int offset = data.getInt();
298:                    int length = data.getInt();
299:
300:                    // read the data
301:                    data.mark();
302:                    data.position(offset);
303:
304:                    ByteBuffer tableData = data.slice();
305:                    tableData.limit(length);
306:
307:                    //            String tagString = TrueTypeTable.tagToString(tag);
308:
309:                    int calcChecksum = calculateChecksum(tagString, tableData);
310:
311:                    if (calcChecksum == checksum) {
312:                        ttf.addTable(tagString, tableData);
313:                    } else {
314:                        /* System.out.println("Mismatched checksums on table " + 
315:                                            tagString + ": " + calcChecksum + " != " +
316:                                            checksum);*/
317:
318:                        ttf.addTable(tagString, tableData);
319:
320:                    }
321:                    data.reset();
322:                }
323:            }
324:
325:            /**
326:             * Get the length of the font
327:             *
328:             * @return the length of the entire font, in bytes
329:             */
330:            private int getLength() {
331:                // the size of all the table directory entries
332:                int length = 12 + (getNumTables() * 16);
333:
334:                // for each directory entry, get the size,
335:                // and don't forget the padding!
336:                for (Iterator i = tables.values().iterator(); i.hasNext();) {
337:                    Object tableObj = i.next();
338:
339:                    // add the length of the entry
340:                    if (tableObj instanceof  TrueTypeTable) {
341:                        length += ((TrueTypeTable) tableObj).getLength();
342:                    } else {
343:                        length += ((ByteBuffer) tableObj).remaining();
344:                    }
345:
346:                    // pad
347:                    if ((length % 4) != 0) {
348:                        length += (4 - (length % 4));
349:                    }
350:                }
351:
352:                return length;
353:            }
354:
355:            /**
356:             * Update the checksumAdj field in the head table
357:             */
358:            private void updateChecksumAdj(ByteBuffer fontData) {
359:                int checksum = calculateChecksum("", fontData);
360:                int checksumAdj = 0xb1b0afba - checksum;
361:
362:                // find the head table
363:                int offset = 12 + (getNumTables() * 16);
364:
365:                // find the head table
366:                for (Iterator i = tables.keySet().iterator(); i.hasNext();) {
367:                    String tagString = (String) i.next();
368:
369:                    // adjust the checksum
370:                    if (tagString.equals("head")) {
371:                        fontData.putInt(offset + 8, checksumAdj);
372:                        return;
373:                    }
374:
375:                    // add the length of the entry 
376:                    Object tableObj = tables.get(tagString);
377:                    if (tableObj instanceof  TrueTypeTable) {
378:                        offset += ((TrueTypeTable) tableObj).getLength();
379:                    } else {
380:                        offset += ((ByteBuffer) tableObj).remaining();
381:                    }
382:
383:                    // pad
384:                    if ((offset % 4) != 0) {
385:                        offset += (4 - (offset % 4));
386:                    }
387:                }
388:            }
389:
390:            /**
391:             * Write the font to a pretty string
392:             */
393:            public String toString() {
394:                StringBuffer buf = new StringBuffer();
395:
396:                System.out.println("Type         : " + getType());
397:                System.out.println("NumTables    : " + getNumTables());
398:                System.out.println("SearchRange  : " + getSearchRange());
399:                System.out.println("EntrySelector: " + getEntrySelector());
400:                System.out.println("RangeShift   : " + getRangeShift());
401:
402:                for (Iterator i = tables.entrySet().iterator(); i.hasNext();) {
403:                    Map.Entry e = (Map.Entry) i.next();
404:
405:                    TrueTypeTable table = null;
406:                    if (e.getValue() instanceof  ByteBuffer) {
407:                        table = getTable((String) e.getKey());
408:                    } else {
409:                        table = (TrueTypeTable) e.getValue();
410:                    }
411:
412:                    System.out.println(table);
413:                }
414:
415:                return buf.toString();
416:            }
417:
418:            /**
419:             * @param args the command line arguments
420:             */
421:            public static void main(String[] args) {
422:                if (args.length != 1) {
423:                    System.out.println("Usage: ");
424:                    System.out.println("    TrueTypeParser <filename>");
425:                    System.exit(-1);
426:                }
427:
428:                try {
429:                    RandomAccessFile raf = new RandomAccessFile(args[0], "r");
430:
431:                    int size = (int) raf.length();
432:                    byte[] data = new byte[size];
433:
434:                    raf.readFully(data);
435:
436:                    TrueTypeFont ttp = TrueTypeFont.parseFont(data);
437:
438:                    System.out.println(ttp);
439:
440:                    InputStream fontStream = new ByteArrayInputStream(ttp
441:                            .writeFont());
442:
443:                    Font f = Font.createFont(Font.TRUETYPE_FONT, fontStream);
444:                } catch (Exception e) {
445:                    e.printStackTrace();
446:                }
447:            }
448:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.