001: /*
002: * $Id: BuiltinFont.java,v 1.2 2007/12/20 18:33:32 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.Font;
025: import java.io.IOException;
026: import java.io.InputStream;
027: import java.util.Map;
028: import java.util.Properties;
029:
030: import com.sun.pdfview.PDFObject;
031:
032: /**
033: * This class represents the 14 built-in fonts. It reads these fonts
034: * from files in the "res" directory, as specified in
035: * BaseNames.properties.
036: */
037: public class BuiltinFont extends Type1Font {
038: /** the properties file */
039: private static Properties props;
040:
041: /** the fonts themselves */
042: private static Map fonts;
043:
044: /** the names of the 14 base fonts */
045: private static final String[] baseFonts = { "Courier",
046: "Courier-Bold", "Courier-BoldOblique", "Courier-Oblique",
047: "Helvetica", "Helvetica-Bold", "Helvetica-BoldOblique",
048: "Helvetica-Oblique", "Times-Roman", "Times-Bold",
049: "Times-BoldItalic", "Times-Italic", "Symbol",
050: "ZapfDingbats" };
051:
052: /** fonts others (e.g. Acrobad PDFWriter 3.02 for Windows) assume
053: * are there, even though they're not in the spec. Grrr...
054: *
055: * the format is <Name_in_PDF> <Builtin_To_Use>
056: */
057: private static final String[] mappedFonts = {
058: // map arial to helvetica
059: "Arial", "Helvetica", "Arial,Bold", "Helvetica-Bold",
060: "Arial,BoldItalic", "Helvetica-BoldOblique",
061: "Arial,Italic",
062: "Helvetica-Oblique",
063: // map TimesNewRoman to Times
064: "TimesNewRoman", "Times-Roman", "TimesNewRoman,Bold",
065: "Times-Bold", "TimesNewRoman,BoldItalic",
066: "Times-BoldItalic", "TimesNewRoman,Italic", "Times-Italic", };
067:
068: /**
069: * Create a new Builtin object based on the name of a built-in font
070: *
071: * This must be the name of one of the 14 built-in fonts!
072: *
073: * @param baseFont the name of the font, from the PDF file
074: * @param fontObj the object containing font information
075: */
076: public BuiltinFont(String baseFont, PDFObject fontObj)
077: throws IOException {
078: super (baseFont, fontObj, null);
079:
080: parseFont(baseFont);
081: }
082:
083: /**
084: * create a new BuiltingFont object based on a description of the
085: * font from the PDF file. Parse the description for key information
086: * and use that to generate an appropriate font.
087: */
088: public BuiltinFont(String baseFont, PDFObject fontObj,
089: PDFFontDescriptor descriptor) throws IOException {
090: super (baseFont, fontObj, descriptor);
091:
092: String fontName = descriptor.getFontName();
093:
094: // check if it's one of the 14 base fonts
095: for (int i = 0; i < baseFonts.length; i++) {
096: if (fontName.equalsIgnoreCase(baseFonts[i])) {
097: parseFont(fontName);
098: return;
099: }
100: }
101:
102: // check if it's a mapped font
103: for (int i = 0; i < mappedFonts.length; i += 2) {
104: if (fontName.equalsIgnoreCase(mappedFonts[i])) {
105: parseFont(mappedFonts[i + 1]);
106: return;
107: }
108: }
109:
110: int flags = descriptor.getFlags();
111: int style = ((flags & (1 << 18)) != 0) ? Font.BOLD : Font.PLAIN;
112:
113: if (fontName.indexOf("Bold") > 0) {
114: style |= Font.BOLD;
115: }
116: if ((descriptor.getItalicAngle() != 0)
117: || ((flags & (1 << 6)) != 0)) {
118: style |= Font.ITALIC;
119: }
120:
121: String name = null;
122:
123: if ((flags & 1) != 0) { // fixed width
124: if (((style & Font.BOLD) > 0)
125: && ((style & Font.ITALIC) > 0)) {
126: name = "Courier-BoldOblique";
127: } else if ((style & Font.BOLD) > 0) {
128: name = "Courier-Bold";
129: } else if ((style & Font.ITALIC) > 0) {
130: name = "Courier-Oblique";
131: } else {
132: name = "Courier";
133: }
134: } else if ((flags & 1 << 1) != 0) { // serif font
135: if (((style & Font.BOLD) > 0)
136: && ((style & Font.ITALIC) > 0)) {
137: name = "Times-BoldItalic";
138: } else if ((style & Font.BOLD) > 0) {
139: name = "Times-Bold";
140: } else if ((style & Font.ITALIC) > 0) {
141: name = "Times-Italic";
142: } else {
143: name = "Times-Roman";
144: }
145: } else {
146: if (((style & Font.BOLD) > 0)
147: && ((style & Font.ITALIC) > 0)) {
148: name = "Helvetica-BoldOblique";
149: } else if ((style & Font.BOLD) > 0) {
150: name = "Helvetica-Bold";
151: } else if ((style & Font.ITALIC) > 0) {
152: name = "Helvetica-Oblique";
153: } else {
154: name = "Helvetica";
155: }
156: }
157:
158: parseFont(name);
159: }
160:
161: /**
162: * Parse a font given only the name of a builtin font
163: */
164: private void parseFont(String baseFont) throws IOException {
165: // load the base fonts properties files, if it isn't already loaded
166: if (props == null) {
167: props = new Properties();
168: props.load(BuiltinFont.class
169: .getResourceAsStream("res/BaseFonts.properties"));
170: }
171:
172: // make sure we're a known font
173: if (!props.containsKey(baseFont + ".file")) {
174: throw new IllegalArgumentException("Unknown Base Font: "
175: + baseFont);
176: }
177:
178: // get the font information from the properties file
179: String file = props.getProperty(baseFont + ".file");
180:
181: // the size of the file
182: int length = Integer.parseInt(props.getProperty(baseFont
183: + ".length"));
184: // the size of the unencrypted portion
185: int length1 = 0;
186: // the size of the encrypted portion
187: int length2 = 0;
188:
189: // read the data from the file
190: byte[] data = new byte[length];
191: InputStream fontStream = NativeFont.class
192: .getResourceAsStream("res/" + file);
193: int cur = 0;
194: while (cur < length) {
195: cur += fontStream.read(data, cur, length - cur);
196: }
197: fontStream.close();
198:
199: // are we a pfb file?
200: if ((data[0] & 0xff) == 0x80) {
201: // read lengths from the file
202: length1 = (data[2] & 0xff);
203: length1 |= (data[3] & 0xff) << 8;
204: length1 |= (data[4] & 0xff) << 16;
205: length1 |= (data[5] & 0xff) << 24;
206: length1 += 6;
207:
208: length2 = (data[length1 + 2] & 0xff);
209: length2 |= (data[length1 + 3] & 0xff) << 8;
210: length2 |= (data[length1 + 4] & 0xff) << 16;
211: length2 |= (data[length1 + 5] & 0xff) << 24;
212: length1 += 6;
213: } else {
214: // get the values from the properties file
215: length1 = Integer.parseInt(props.getProperty(baseFont
216: + ".length1"));
217:
218: if (props.containsKey(baseFont + ".length2")) {
219: length2 = Integer.parseInt(props.getProperty(baseFont
220: + ".lenth2"));
221: } else {
222: length2 = length - length1;
223: }
224: }
225:
226: parseFont(data, length1, length2);
227: }
228: }
|