KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > fonts > type1 > PFBParser


1 /*
2  * $Id: PFBParser.java,v 1.1.2.4 2003/05/08 17:18:30 jeremias Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.fonts.type1;
52
53 import java.io.IOException JavaDoc;
54 import java.io.InputStream JavaDoc;
55 import java.io.DataInputStream JavaDoc;
56 import java.io.BufferedInputStream JavaDoc;
57
58 //FOP
59
import org.apache.fop.tools.IOUtil;
60
61 /**
62  * This class represents a parser for Adobe Type 1 PFB files.
63  *
64  * @see PFBData
65  */

66 public class PFBParser {
67
68     private static final byte[] CURRENTFILE_EEXEC;
69     private static final byte[] CLEARTOMARK;
70
71     static {
72         try {
73             CURRENTFILE_EEXEC = "currentfile eexec".getBytes("US-ASCII");
74             CLEARTOMARK = "cleartomark".getBytes("US-ASCII");
75         } catch (java.io.UnsupportedEncodingException JavaDoc e) {
76             throw new RuntimeException JavaDoc("Incompatible VM. It doesn't support the US-ASCII encoding");
77         }
78     }
79
80
81     /**
82      * Parses a PFB file into a PFBData object.
83      * @param url URL to load the PFB file from
84      * @return PFBData memory representation of the font
85      * @throws IOException In case of an I/O problem
86      */

87     public PFBData parsePFB(java.net.URL JavaDoc url) throws IOException JavaDoc {
88         InputStream JavaDoc in = url.openStream();
89         try {
90             return parsePFB(in);
91         } finally {
92             in.close();
93         }
94     }
95
96
97     /**
98      * Parses a PFB file into a PFBData object.
99      * @param pfbFile File to load the PFB file from
100      * @return PFBData memory representation of the font
101      * @throws IOException In case of an I/O problem
102      */

103     public PFBData parsePFB(java.io.File JavaDoc pfbFile) throws IOException JavaDoc {
104         InputStream JavaDoc in = new java.io.FileInputStream JavaDoc(pfbFile);
105         try {
106             return parsePFB(in);
107         } finally {
108             in.close();
109         }
110     }
111
112
113     /**
114      * Parses a PFB file into a PFBData object.
115      * @param in InputStream to load the PFB file from
116      * @return PFBData memory representation of the font
117      * @throws IOException In case of an I/O problem
118      */

119     public PFBData parsePFB(InputStream JavaDoc in) throws IOException JavaDoc {
120         PFBData pfb = new PFBData();
121         BufferedInputStream JavaDoc bin = new BufferedInputStream JavaDoc(in);
122         DataInputStream JavaDoc din = new DataInputStream JavaDoc(bin);
123         din.mark(32);
124         int firstByte = din.readUnsignedByte();
125         din.reset();
126         if (firstByte == 128) {
127             pfb.setPFBFormat(PFBData.PFB_PC);
128             parsePCFormat(pfb, din);
129         } else {
130             pfb.setPFBFormat(PFBData.PFB_RAW);
131             parseRAWFormat(pfb, bin);
132         }
133         return pfb;
134     }
135
136
137     private static int swapInteger(final int value) {
138         return (((value >> 0) & 0xff) << 24)
139              + (((value >> 8) & 0xff) << 16)
140              + (((value >> 16) & 0xff) << 8)
141              + (((value >> 24) & 0xff) << 0);
142     }
143
144
145     private void parsePCFormat(PFBData pfb, DataInputStream JavaDoc din) throws IOException JavaDoc {
146         int segmentHead;
147         int segmentType;
148         int bytesRead;
149
150         //Read first segment
151
segmentHead = din.readUnsignedByte();
152         if (segmentHead != 128) {
153             throw new IOException JavaDoc("Invalid file format. Expected ASCII 80hex");
154         }
155         segmentType = din.readUnsignedByte(); //Read
156
int len1 = swapInteger(din.readInt());
157         byte[] headerSegment = new byte[len1];
158         din.readFully(headerSegment);
159         pfb.setHeaderSegment(headerSegment);
160
161         //Read second segment
162
segmentHead = din.readUnsignedByte();
163         if (segmentHead != 128) {
164             throw new IOException JavaDoc("Invalid file format. Expected ASCII 80hex");
165         }
166         segmentType = din.readUnsignedByte();
167         int len2 = swapInteger(din.readInt());
168         byte[] encryptedSegment = new byte[len2];
169         din.readFully(encryptedSegment);
170         pfb.setEncryptedSegment(encryptedSegment);
171
172         //Read third segment
173
segmentHead = din.readUnsignedByte();
174         if (segmentHead != 128) {
175             throw new IOException JavaDoc("Invalid file format. Expected ASCII 80hex");
176         }
177         segmentType = din.readUnsignedByte();
178         int len3 = swapInteger(din.readInt());
179         byte[] trailerSegment = new byte[len3];
180         din.readFully(trailerSegment);
181         pfb.setTrailerSegment(trailerSegment);
182
183         //Read EOF indicator
184
segmentHead = din.readUnsignedByte();
185         if (segmentHead != 128) {
186             throw new IOException JavaDoc("Invalid file format. Expected ASCII 80hex");
187         }
188         segmentType = din.readUnsignedByte();
189         if (segmentType != 3) {
190             throw new IOException JavaDoc("Expected segment type 3, but found: " + segmentType);
191         }
192     }
193
194
195     private static final boolean byteCmp(byte[] src, int srcOffset, byte[] cmp) {
196         for (int i = 0; i < cmp.length; i++) {
197             // System.out.println("Compare: " + src[srcOffset + i] + " " + cmp[i]);
198
if (src[srcOffset + i] != cmp[i]) {
199                 return false;
200             }
201         }
202         return true;
203     }
204
205     private void calcLengths(PFBData pfb, byte[] originalData) {
206         // Calculate length 1 and 3
207
// System.out.println ("Checking font, size = "+originalData.length);
208

209         // Length1 is the size of the initial ascii portion
210
// search for "currentfile eexec"
211
// Get the first binary number and search backwards for "eexec"
212
int len1 = 30;
213
214         // System.out.println("Length1="+len1);
215
while (!byteCmp(originalData, len1 - CURRENTFILE_EEXEC.length, CURRENTFILE_EEXEC)) {
216             len1++;
217         }
218
219         // Skip newline
220
len1++;
221
222         // Length3 is length of the last portion of the file
223
int len3 = 0;
224         len3 -= CLEARTOMARK.length;
225         while (!byteCmp(originalData, originalData.length + len3, CLEARTOMARK)) {
226             len3--;
227             // System.out.println("Len3="+len3);
228
}
229         len3 = -len3;
230         len3++;
231         // Eat 512 zeroes
232
int numZeroes = 0;
233         byte[] ws1 = new byte[]{0x0D}; //CR
234
byte[] ws2 = new byte[]{0x0A}; //LF
235
byte[] ws3 = new byte[]{0x30}; //"0"
236
while ((originalData[originalData.length - len3] == ws1[0]
237                 || originalData[originalData.length - len3] == ws2[0]
238                 || originalData[originalData.length - len3] == ws3[0])
239                 && numZeroes < 512) {
240             len3++;
241             if (originalData[originalData.length - len3] == ws3[0]) {
242                 numZeroes++;
243             }
244         }
245         // System.out.println("Length3="+len3);
246

247         //Create the 3 segments
248
byte[] buffer = new byte[len1];
249         System.arraycopy(originalData, 0, buffer, 0, len1);
250         pfb.setHeaderSegment(buffer);
251
252         int len2 = originalData.length - len3 - len1;
253         buffer = new byte[len2];
254         System.arraycopy(originalData, len1, buffer, 0, len2);
255         pfb.setEncryptedSegment(buffer);
256
257         buffer = new byte[len3];
258         System.arraycopy(originalData, len1 + len2, buffer, 0, len3);
259         pfb.setTrailerSegment(buffer);
260     }
261
262     private void parseRAWFormat(PFBData pfb, BufferedInputStream JavaDoc bin)
263             throws IOException JavaDoc {
264         calcLengths(pfb, IOUtil.toByteArray(bin, 32768));
265     }
266
267 }
Popular Tags