001: /*
002: * $Id: Type3Font.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.AffineTransform;
025: import java.awt.geom.GeneralPath;
026: import java.awt.geom.Point2D;
027: import java.awt.geom.Rectangle2D;
028: import java.io.IOException;
029: import java.util.HashMap;
030: import java.util.Map;
031:
032: import com.sun.pdfview.PDFObject;
033: import com.sun.pdfview.PDFPage;
034: import com.sun.pdfview.PDFParser;
035:
036: /**
037: * A Type 3 Font, in which each glyph consists of a sequence of PDF
038: * commands.
039: *
040: * @author Mike Wessler
041: */
042: public class Type3Font extends PDFFont {
043: /** resources for the character definitions */
044: HashMap rsrc;
045:
046: /** the character processes, mapped by name */
047: Map charProcs;
048:
049: /** bounding box for the font characters */
050: Rectangle2D bbox;
051:
052: /** affine transform for the font characters */
053: AffineTransform at;
054:
055: /** the widths */
056: float[] widths;
057:
058: /** the start code */
059: int firstChar;
060:
061: /** the end code */
062: int lastChar;
063:
064: /**
065: * Generate a Type 3 font.
066: * @param baseFont the postscript name of this font
067: * @param fontObj a dictionary containing references to the character
068: * definitions and font information
069: * @param resources a set of resources used by the character definitions
070: * @param descriptor the descriptor for this font
071: */
072: public Type3Font(String baseFont, PDFObject fontObj,
073: HashMap resources, PDFFontDescriptor descriptor)
074: throws IOException {
075: super (baseFont, descriptor);
076:
077: rsrc = new HashMap();
078:
079: if (resources != null) {
080: rsrc.putAll(resources);
081: }
082:
083: // get the transform matrix
084: PDFObject matrix = fontObj.getDictRef("FontMatrix");
085: float matrixAry[] = new float[6];
086: for (int i = 0; i < 6; i++) {
087: matrixAry[i] = matrix.getAt(i).getFloatValue();
088: }
089: at = new AffineTransform(matrixAry);
090:
091: // get the scale from the matrix
092: float scale = matrixAry[0] + matrixAry[2];
093:
094: // put all the resources in a Hash
095: PDFObject rsrcObj = fontObj.getDictRef("Resources");
096: if (rsrcObj != null) {
097: rsrc.putAll(rsrcObj.getDictionary());
098: }
099:
100: // get the character processes, indexed by name
101: charProcs = fontObj.getDictRef("CharProcs").getDictionary();
102:
103: // get the font bounding box
104: PDFObject[] bboxdef = fontObj.getDictRef("FontBBox").getArray();
105: float[] bboxfdef = new float[4];
106: for (int i = 0; i < 4; i++) {
107: bboxfdef[i] = bboxdef[i].getFloatValue();
108: }
109: bbox = new Rectangle2D.Float(bboxfdef[0], bboxfdef[1],
110: bboxfdef[2] - bboxfdef[0], bboxfdef[3] - bboxfdef[1]);
111: if (bbox.isEmpty()) {
112: bbox = null;
113: }
114:
115: // get the widths
116: PDFObject[] widthArray = fontObj.getDictRef("Widths")
117: .getArray();
118: widths = new float[widthArray.length];
119: for (int i = 0; i < widthArray.length; i++) {
120: widths[i] = widthArray[i].getFloatValue();
121: }
122:
123: // get first and last chars
124: firstChar = fontObj.getDictRef("FirstChar").getIntValue();
125: lastChar = fontObj.getDictRef("LastChar").getIntValue();
126: }
127:
128: /**
129: * Get the first character code
130: */
131: public int getFirstChar() {
132: return firstChar;
133: }
134:
135: /**
136: * Get the last character code
137: */
138: public int getLastChar() {
139: return lastChar;
140: }
141:
142: /**
143: * Get the glyph for a given character code and name
144: *
145: * The preferred method of getting the glyph should be by name. If the
146: * name is null or not valid, then the character code should be used.
147: * If the both the code and the name are invalid, the undefined glyph
148: * should be returned.
149: *
150: * Note this method must *always* return a glyph.
151: *
152: * @param src the character code of this glyph
153: * @param name the name of this glyph or null if unknown
154: * @return a glyph for this character
155: */
156: protected PDFGlyph getGlyph(char src, String name) {
157: if (name == null) {
158: throw new IllegalArgumentException(
159: "Glyph name required for Type3 font!"
160: + "Source character: " + (int) src);
161: }
162:
163: PDFObject pageObj = (PDFObject) charProcs.get(name);
164: if (pageObj == null) {
165: // glyph not found. Return an empty glyph...
166: return new PDFGlyph(src, name, new GeneralPath(),
167: new Point2D.Float(0, 0));
168: }
169:
170: try {
171: PDFPage page = new PDFPage(bbox, 0);
172: page.addXform(at);
173:
174: PDFParser prc = new PDFParser(page, pageObj.getStream(),
175: rsrc);
176: prc.go(true);
177:
178: float width = widths[src - firstChar];
179:
180: Point2D advance = new Point2D.Float(width, 0);
181: advance = at.transform(advance, null);
182:
183: return new PDFGlyph(src, name, page, advance);
184: } catch (IOException ioe) {
185: // help!
186: System.out.println("IOException in Type3 font: " + ioe);
187: ioe.printStackTrace();
188: return null;
189: }
190: }
191: }
|