001: /*
002: * $Id: CIDFontType2.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;
023:
024: import java.awt.geom.GeneralPath;
025: import java.io.IOException;
026: import java.nio.ByteBuffer;
027: import java.util.HashMap;
028: import java.util.Map;
029:
030: import com.sun.pdfview.PDFObject;
031:
032: /**
033: * a font object derived from a CID font.
034: *
035: * @author Jonathan Kaplan
036: */
037: public class CIDFontType2 extends TTFFont {
038: /**
039: * The width of each glyph from the DW and W arrays
040: */
041: private Map widths;
042:
043: /*
044: * the default width
045: */
046: private int defaultWidth = 1000;
047:
048: /** the CIDtoGID map, if any */
049: private ByteBuffer cidToGidMap;
050:
051: /**
052: * create a new CIDFontType2 object based on the name of a built-in font
053: * and the font descriptor
054: * @param baseName the name of the font, from the PDF file
055: * @param fontObj a dictionary that contains the DW (defaultWidth) and
056: * W (width) parameters
057: * @param descriptor a descriptor for the font
058: */
059: public CIDFontType2(String baseName, PDFObject fontObj,
060: PDFFontDescriptor descriptor) throws IOException {
061: super (baseName, fontObj, descriptor);
062:
063: parseWidths(fontObj);
064:
065: // read the cid to gid map (optional)
066: PDFObject mapObj = fontObj.getDictRef("CIDToGIDMap");
067:
068: // only read the map if it is a stream (if it is a name, it
069: // is "Identity" and can be ignored
070: if (mapObj != null && (mapObj.getType() == PDFObject.STREAM)) {
071: cidToGidMap = mapObj.getStreamBuffer();
072: }
073: }
074:
075: /** Parse the Widths array and DW object */
076: private void parseWidths(PDFObject fontObj) throws IOException {
077: // read the default width (otpional)
078: PDFObject defaultWidthObj = fontObj.getDictRef("DW");
079: if (defaultWidthObj != null) {
080: defaultWidth = defaultWidthObj.getIntValue();
081: }
082:
083: // read the widths table
084: PDFObject widthObj = fontObj.getDictRef("W");
085: if (widthObj == null) {
086: return;
087: }
088:
089: // initialize the widths array
090: widths = new HashMap();
091:
092: // parse the width array
093: PDFObject[] widthArray = widthObj.getArray();
094:
095: /* an entry can be in one of two forms:
096: * <startIndex> <endIndex> <value> or
097: * <startIndex> [ array of values ]
098: * we use the entryIdx to differentitate between them
099: */
100: int entryIdx = 0;
101: int first = 0;
102: int last = 0;
103:
104: for (int i = 0; i < widthArray.length; i++) {
105: if (entryIdx == 0) {
106: // first value in an entry. Just store it
107: first = widthArray[i].getIntValue();
108: } else if (entryIdx == 1) {
109: // second value -- is it an int or array?
110: if (widthArray[i].getType() == PDFObject.ARRAY) {
111: // add all the entries in the array to the width array
112: PDFObject[] entries = widthArray[i].getArray();
113: for (int c = 0; c < entries.length; c++) {
114: Character key = new Character(
115: (char) (c + first));
116:
117: // value is width / default width
118: float value = entries[c].getIntValue();
119: widths.put(key, new Float(value));
120: }
121: // all done
122: entryIdx = -1;
123: } else {
124: last = widthArray[i].getIntValue();
125: }
126: } else {
127: // third value. Set a range
128: int value = widthArray[i].getIntValue();
129:
130: // set the range
131: for (int c = first; c <= last; c++) {
132: widths.put(new Character((char) c),
133: new Float(value));
134: }
135:
136: // all done
137: entryIdx = -1;
138: }
139:
140: entryIdx++;
141: }
142: }
143:
144: /** Get the default width in text space */
145: @Override
146: public int getDefaultWidth() {
147: return defaultWidth;
148: }
149:
150: /** Get the width of a given character */
151: @Override
152: public float getWidth(char code, String name) {
153: Float w = (Float) widths.get(new Character(code));
154: if (w == null) {
155: return 1f;
156: }
157:
158: return w.floatValue() / getDefaultWidth();
159: }
160:
161: /**
162: * Get the outline of a character given the character code. We
163: * interpose here in order to avoid using the CMap of the font in
164: * a CID mapped font.
165: */
166: @Override
167: protected synchronized GeneralPath getOutline(char src, float width) {
168: int glyphId = (int) (src & 0xffff);
169:
170: // check if there is a cidToGidMap
171: if (cidToGidMap != null) {
172: // read the map
173: glyphId = cidToGidMap.getChar(glyphId * 2);
174: }
175:
176: // call getOutline on the glyphId
177: return getOutline(glyphId, width);
178: }
179: }
|