001: /*
002: * $Id: PostTable.java,v 1.2 2007/12/20 18:33:31 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.nio.ByteBuffer;
025:
026: /**
027: * Model the TrueType Post table
028: *
029: * @author jkaplan
030: */
031: public class PostTable extends TrueTypeTable {
032:
033: /** Holds value of property format. */
034: private int format;
035:
036: /** Holds value of property italicAngle. */
037: private int italicAngle;
038:
039: /** Holds value of property underlinePosition. */
040: private short underlinePosition;
041:
042: /** Holds value of property underlineThickness. */
043: private short underlineThickness;
044:
045: /** Holds value of property isFixedPitch. */
046: private short isFixedPitch;
047:
048: /** Holds value of property minMemType42. */
049: private int minMemType42;
050:
051: /** Holds value of property maxMemType42. */
052: private int maxMemType42;
053:
054: /** Holds value of property minMemType1. */
055: private int minMemType1;
056:
057: /** Holds value of property maxMemType1. */
058: private int maxMemType1;
059:
060: /** A map which character values to names and vice versa */
061: private PostMap nameMap;
062:
063: /** Creates a new instance of PostTable */
064: protected PostTable() {
065: super (TrueTypeTable.POST_TABLE);
066:
067: nameMap = new PostMap();
068: }
069:
070: /**
071: * Map a character name to a glyphNameIndex
072: */
073: public short getGlyphNameIndex(String name) {
074: return nameMap.getCharIndex(name);
075: }
076:
077: /**
078: * Map a character code to a glyphIndex name
079: */
080: public String getGlyphName(char c) {
081: return nameMap.getCharName(c);
082: }
083:
084: /** get the data in this map as a ByteBuffer */
085: public ByteBuffer getData() {
086: int size = getLength();
087:
088: ByteBuffer buf = ByteBuffer.allocate(size);
089:
090: // write the header
091: buf.putInt(getFormat());
092: buf.putInt(getItalicAngle());
093: buf.putShort(getUnderlinePosition());
094: buf.putShort(getUnderlineThickness());
095: buf.putShort(getIsFixedPitch());
096: buf.putShort((short) 0);
097: buf.putInt(getMinMemType42());
098: buf.putInt(getMaxMemType42());
099: buf.putInt(getMinMemType1());
100: buf.putInt(getMaxMemType1());
101:
102: // now write the table
103: buf.put(nameMap.getData());
104:
105: // reset the start pointer
106: buf.flip();
107:
108: return buf;
109: }
110:
111: /** Initialize this structure from a ByteBuffer */
112: public void setData(ByteBuffer data) {
113: setFormat(data.getInt());
114: setItalicAngle(data.getInt());
115: setUnderlinePosition(data.getShort());
116: setUnderlineThickness(data.getShort());
117: setIsFixedPitch(data.getShort());
118: data.getShort();
119: setMinMemType42(data.getInt());
120: setMaxMemType42(data.getInt());
121: setMinMemType1(data.getInt());
122: setMaxMemType1(data.getInt());
123:
124: // create the map, based on the type
125: switch (format) {
126: case 0x10000:
127: nameMap = new PostMapFormat0();
128: break;
129: case 0x20000:
130: nameMap = new PostMapFormat2();
131: break;
132: case 0x30000:
133: // empty post map.
134: nameMap = new PostMap();
135: break;
136: default:
137: nameMap = new PostMap();
138: System.out.println("Unknown post map type: "
139: + Integer.toHexString(format));
140: break;
141: }
142:
143: // fill in the data in the map
144: nameMap.setData(data);
145: }
146:
147: /**
148: * Get the length of this table
149: */
150: public int getLength() {
151: int size = 32;
152: if (nameMap != null) {
153: size += nameMap.getLength();
154: }
155:
156: return size;
157: }
158:
159: /** Getter for property format.
160: * @return Value of property format.
161: *
162: */
163: public int getFormat() {
164: return this .format;
165: }
166:
167: /** Setter for property format.
168: * @param format New value of property format.
169: *
170: */
171: public void setFormat(int format) {
172: this .format = format;
173: }
174:
175: /** Getter for property italicAngle.
176: * @return Value of property italicAngle.
177: *
178: */
179: public int getItalicAngle() {
180: return this .italicAngle;
181: }
182:
183: /** Setter for property italicAngle.
184: * @param italicAngle New value of property italicAngle.
185: *
186: */
187: public void setItalicAngle(int italicAngle) {
188: this .italicAngle = italicAngle;
189: }
190:
191: /** Getter for property underlinePosition.
192: * @return Value of property underlinePosition.
193: *
194: */
195: public short getUnderlinePosition() {
196: return this .underlinePosition;
197: }
198:
199: /** Setter for property underlinePosition.
200: * @param underlinePosition New value of property underlinePosition.
201: *
202: */
203: public void setUnderlinePosition(short underlinePosition) {
204: this .underlinePosition = underlinePosition;
205: }
206:
207: /** Getter for property underlineThickness.
208: * @return Value of property underlineThickness.
209: *
210: */
211: public short getUnderlineThickness() {
212: return this .underlineThickness;
213: }
214:
215: /** Setter for property underlineThickness.
216: * @param underlineThickness New value of property underlineThickness.
217: *
218: */
219: public void setUnderlineThickness(short underlineThickness) {
220: this .underlineThickness = underlineThickness;
221: }
222:
223: /** Getter for property isFixedPitch.
224: * @return Value of property isFixedPitch.
225: *
226: */
227: public short getIsFixedPitch() {
228: return this .isFixedPitch;
229: }
230:
231: /** Setter for property isFixedPitch.
232: * @param isFixedPitch New value of property isFixedPitch.
233: *
234: */
235: public void setIsFixedPitch(short isFixedPitch) {
236: this .isFixedPitch = isFixedPitch;
237: }
238:
239: /** Getter for property minMemType42.
240: * @return Value of property minMemType42.
241: *
242: */
243: public int getMinMemType42() {
244: return this .minMemType42;
245: }
246:
247: /** Setter for property minMemType42.
248: * @param minMemType42 New value of property minMemType42.
249: *
250: */
251: public void setMinMemType42(int minMemType42) {
252: this .minMemType42 = minMemType42;
253: }
254:
255: /** Getter for property maxMemType42.
256: * @return Value of property maxMemType42.
257: *
258: */
259: public int getMaxMemType42() {
260: return this .maxMemType42;
261: }
262:
263: /** Setter for property maxMemType42.
264: * @param maxMemType42 New value of property maxMemType42.
265: *
266: */
267: public void setMaxMemType42(int maxMemType42) {
268: this .maxMemType42 = maxMemType42;
269: }
270:
271: /** Getter for property minMemType1.
272: * @return Value of property minMemType1.
273: *
274: */
275: public int getMinMemType1() {
276: return this .minMemType1;
277: }
278:
279: /** Setter for property minMemType1.
280: * @param minMemType1 New value of property minMemType1.
281: *
282: */
283: public void setMinMemType1(int minMemType1) {
284: this .minMemType1 = minMemType1;
285: }
286:
287: /** Getter for property maxMemType1.
288: * @return Value of property maxMemType1.
289: *
290: */
291: public int getMaxMemType1() {
292: return this .maxMemType1;
293: }
294:
295: /** Setter for property maxMemType1.
296: * @param maxMemType1 New value of property maxMemType1.
297: *
298: */
299: public void setMaxMemType1(int maxMemType1) {
300: this .maxMemType1 = maxMemType1;
301: }
302:
303: /** An empty post map */
304: class PostMap {
305: /** map a name to a character index */
306: short getCharIndex(String charName) {
307: return (short) 0;
308: }
309:
310: /** name a character index to a name */
311: String getCharName(char charIndex) {
312: return null;
313: }
314:
315: /** get the length of the data in this map */
316: int getLength() {
317: return 0;
318: }
319:
320: /** get the data in this map as a ByteBuffer */
321: ByteBuffer getData() {
322: return ByteBuffer.allocate(0);
323: }
324:
325: /** set the data in this map from a ByteBuffer */
326: void setData(ByteBuffer data) {
327: // do nothing
328: return;
329: }
330: }
331:
332: /** A Format 0 post map */
333: class PostMapFormat0 extends PostMap {
334: /** the glyph names in standard Macintosh ordering */
335: protected final String stdNames[] = {
336: /* 0 */".notdef", ".null", "nonmarkingreturn", "space",
337: "exclam", "quotedbl", "numbersign", "dollar",
338: /* 8 */"percent", "ampersand", "quotesingle",
339: "parenleft", "parenright", "asterisk", "plus", "comma",
340: /* 16 */"hyphen", "period", "slash", "zero", "one",
341: "two", "three", "four",
342: /* 24 */"five", "six", "seven", "eight", "nine",
343: "colon", "semicolon", "less",
344: /* 32 */"equal", "greater", "question", "at", "A",
345: "B", "C", "D",
346: /* 40 */"E", "F", "G", "H", "I", "J", "K", "L",
347: /* 48 */"M", "N", "O", "P", "Q", "R", "S", "T",
348: /* 56 */"U", "V", "W", "X", "Y", "Z", "bracketleft",
349: "ackslash",
350: /* 64 */"bracketright", "asciicircum", "underscore",
351: "grave", "a", "b", "c", "d",
352: /* 72 */"e", "f", "g", "h", "i", "j", "k", "l",
353: /* 80 */"m", "n", "o", "p", "q", "r", "s", "t",
354: /* 88 */"u", "v", "w", "x", "y", "z", "braceleft",
355: "bar",
356: /* 96 */"braceright", "asciitilde", "Adieresis",
357: "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis",
358: /* 104 */"Udieresis", "aacute", "agrave",
359: "acircumflex", "adieresis", "atilde", "aring",
360: "ccedilla",
361: /* 112 */"eacute", "egrave", "ecircumflex",
362: "edieresis", "iacute", "igrave", "icircumflex",
363: "idieresis",
364: /* 120 */"ntilde", "oacute", "ograve", "ocircumflex",
365: "odieresis", "otilde", "uacute", "ugrave",
366: /* 128 */"ucircumflex", "udieresis", "dagger",
367: "degree", "cent", "sterling", "section", "bullet",
368: /* 136 */"paragraph", "germandbls", "registered",
369: "copyright", "trademark", "acute", "dieresis",
370: "notequal",
371: /* 144 */"AE", "Oslash", "infinity", "plusminus",
372: "lessequal", "greaterequal", "yen", "mu",
373: /* 152 */"partialdiff", "summation", "product", "pi",
374: "integral", "ordfeminine", "ordmasculine", "Omega",
375: /* 160 */"ae", "oslash", "questiondown", "exclamdown",
376: "logicalnot", "radical", "florin", "approxequal",
377: /* 168 */"Delta", "guillemotleft", "guillemotright",
378: "ellipsis", "nonbreakingspace", "Agrave", "Atilde",
379: "Otilde",
380: /* 176 */"OE", "oe", "endash", "emdash",
381: "quotedblleft", "quotedblright", "quoteleft",
382: "quoteright",
383: /* 184 */"divide", "lozenge", "ydieresis",
384: "Ydieresis", "fraction", "currency", "guilsinglleft",
385: "guilsinglright",
386: /* 192 */"fi", "fl", "daggerdbl", "periodcentered",
387: "quotesinglbase", "quotedblbase", "perthousand",
388: "Acircumflex",
389: /* 200 */"Ecircumflex", "Aacute", "Edieresis",
390: "Egrave", "Iacute", "Icircumflex", "Idieresis",
391: "Igrave",
392: /* 208 */"Oacute", "Ocircumflex", "apple", "Ograve",
393: "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
394: /* 216 */"circumflex", "tilde", "macron", "breve",
395: "dotaccent", "ring", "cedilla", "hungarumlaut",
396: /* 224 */"ogonek", "caron", "Lslash", "lslash",
397: "Scaron", "scaron", "Zcaron", "zcaron",
398: /* 232 */"brokenbar", "Eth", "eth", "Yacute",
399: "yacute", "Thorn", "thorn", "minus",
400: /* 240 */"multiply", "onesuperior", "twosuperior",
401: "threesuperior", "onehalf", "onequarter",
402: "threequarters", "franc",
403: /* 248 */"Gbreve", "gbreve", "Idotaccent", "Scedilla",
404: "scedilla", "Cacute", "cacute", "Ccaron",
405: /* 256 */"ccaron", "dcroat" };
406:
407: /** map a name to a character index */
408: short getCharIndex(String charName) {
409: for (int i = 0; i < stdNames.length; i++) {
410: if (charName.equals(stdNames[i])) {
411: return (short) i;
412: }
413: }
414:
415: return (short) 0;
416: }
417:
418: /** name a character index to a name */
419: String getCharName(char charIndex) {
420: return stdNames[charIndex];
421: }
422:
423: /** get the length of the data in this map */
424: int getLength() {
425: return 0;
426: }
427:
428: /** get the data in this map as a ByteBuffer */
429: ByteBuffer getData() {
430: return ByteBuffer.allocate(0);
431: }
432:
433: /** set the data in this map from a ByteBuffer */
434: void setData(ByteBuffer data) {
435: // do nothing
436: return;
437: }
438: }
439:
440: /** an extension to handle format 2 post maps */
441: class PostMapFormat2 extends PostMapFormat0 {
442: /** the glyph name index */
443: short[] glyphNameIndex;
444:
445: /** the glyph names */
446: String[] glyphNames;
447:
448: /** Map a character name to an index */
449: short getCharIndex(String charName) {
450: // find the index of this character name
451: short idx = -1;
452:
453: // first try the local names map
454: for (int i = 0; i < glyphNames.length; i++) {
455: if (charName.equals(glyphNames[i])) {
456: // this is the value from the glyph name index
457: idx = (short) (stdNames.length + i);
458: break;
459: }
460: }
461:
462: // if that doesn't work, try the standard names
463: if (idx == -1) {
464: idx = super .getCharIndex(charName);
465: }
466:
467: // now get the entry in the index
468: for (int c = 0; c < glyphNameIndex.length; c++) {
469: if (glyphNameIndex[c] == idx) {
470: return (short) c;
471: }
472: }
473:
474: // not found
475: return (short) 0;
476: }
477:
478: /** Map an index to a character name */
479: String getCharName(char charIndex) {
480: if (charIndex >= stdNames.length) {
481: return glyphNames[charIndex - stdNames.length];
482: }
483:
484: return super .getCharName(charIndex);
485: }
486:
487: /** get the length of this class's data */
488: int getLength() {
489: // the size of the header plus the table of mappings
490: int size = 2 + (2 * glyphNameIndex.length);
491:
492: // the size of each string -- note the extra byte for a pascal
493: // string
494: for (int i = 0; i < glyphNames.length; i++) {
495: size += glyphNames[i].length() + 1;
496: }
497:
498: return size;
499: }
500:
501: /** get the data in this map as a byte array */
502: ByteBuffer getData() {
503: ByteBuffer buf = ByteBuffer.allocate(getLength());
504:
505: // write the number of glyphs
506: buf.putShort((short) glyphNameIndex.length);
507:
508: // write the name indices
509: for (int i = 0; i < glyphNameIndex.length; i++) {
510: buf.putShort(glyphNameIndex[i]);
511: }
512:
513: // write the names as pascal strings
514: for (int i = 0; i < glyphNames.length; i++) {
515: buf.put((byte) glyphNames[i].length());
516: buf.put(glyphNames[i].getBytes());
517: }
518:
519: // reset the start pointer
520: buf.flip();
521:
522: return buf;
523: }
524:
525: /** set the contents of this map from a ByteBuffer */
526: void setData(ByteBuffer data) {
527: short numGlyphs = data.getShort();
528: glyphNameIndex = new short[numGlyphs];
529:
530: // the highest glyph index seen so far
531: int maxGlyph = 257;
532: for (int i = 0; i < numGlyphs; i++) {
533: glyphNameIndex[i] = data.getShort();
534:
535: // see if this is the highest glyph
536: if (glyphNameIndex[i] > maxGlyph) {
537: maxGlyph = glyphNameIndex[i];
538: }
539: }
540:
541: // subtract off the default glyphs
542: maxGlyph -= 257;
543:
544: // read in any additional names
545: glyphNames = new String[maxGlyph];
546:
547: // read each name from a pascal string
548: // the length is stored in the first byte, followed by
549: // the data
550: for (int i = 0; i < maxGlyph; i++) {
551: // size in the first byte
552: byte size = data.get();
553:
554: // then the data
555: byte[] stringData = new byte[size];
556: data.get(stringData);
557:
558: glyphNames[i] = new String(stringData);
559: }
560: }
561: }
562: }
|