KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > pdf > FontReader


1 /*
2  * $Id: FontReader.java,v 1.4.2.3 2003/02/25 14:58:08 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.render.pdf;
52
53 import java.util.List JavaDoc;
54 import java.util.Map JavaDoc;
55 import java.io.IOException JavaDoc;
56 import java.net.URL JavaDoc;
57
58 import org.apache.fop.render.pdf.fonts.*;
59 import org.apache.fop.pdf.PDFCIDFont;
60 import org.apache.fop.configuration.ConfigurationReader;
61 import org.apache.fop.configuration.Configuration;
62 import org.apache.fop.apps.FOPException;
63 import org.apache.fop.tools.URLBuilder;
64
65 import org.xml.sax.helpers.DefaultHandler JavaDoc;
66 import org.xml.sax.XMLReader JavaDoc;
67 import org.xml.sax.SAXException JavaDoc;
68 import org.xml.sax.InputSource JavaDoc;
69 import org.xml.sax.Locator JavaDoc;
70 import org.xml.sax.Attributes JavaDoc;
71
72 /**
73  * Class for reading a metric.xml file and creating a font object.
74  * Typical usage:
75  * <pre>
76  * FontReader reader = new FontReader(<path til metrics.xml>);
77  * reader.setFontEmbedPath(<path to a .ttf or .pfb file or null to diable embedding>);
78  * reader.useKerning(true);
79  * Font f = reader.getFont();
80  * </pre>
81  */

82 public class FontReader extends DefaultHandler JavaDoc {
83     private Locator JavaDoc locator = null;
84     private boolean isCID = false;
85     private MultiByteFont multiFont = null;
86     private SingleByteFont singleFont = null;
87     private Font returnFont = null;
88     // private SingleByteFont singleFont = null;
89
private String JavaDoc text = null;
90
91     private List JavaDoc cidWidths = null;
92     private int cidWidthIndex = 0;
93
94     private Map JavaDoc currentKerning = null;
95
96     private List JavaDoc bfranges = null;
97
98     private void createFont(URL JavaDoc url) throws FOPException {
99         XMLReader JavaDoc parser = ConfigurationReader.createParser();
100         if (parser == null)
101             throw new FOPException("Unable to create SAX parser");
102
103         try {
104             parser.setFeature("http://xml.org/sax/features/namespace-prefixes",
105                               false);
106         } catch (SAXException JavaDoc e) {
107             throw new FOPException("You need a SAX parser which supports SAX version 2",
108                                    e);
109         }
110
111         parser.setContentHandler(this);
112
113         try {
114             parser.parse(new InputSource JavaDoc(url.openStream()));
115         } catch (SAXException JavaDoc e) {
116             throw new FOPException(e);
117         } catch (IOException JavaDoc e) {
118             throw new FOPException(e);
119         }
120
121     }
122
123     /**
124      * Sets the path to embed a font. a null value disables font embedding
125      */

126     public void setFontEmbedPath(URL JavaDoc path) {
127         if (isCID)
128             multiFont.embedFileName = path;
129         else
130             singleFont.embedFileName = path;
131     }
132
133     /**
134      * Enable/disable use of kerning for the font
135      */

136     public void useKerning(boolean kern) {
137         if (isCID)
138             multiFont.useKerning = true;
139         else
140             singleFont.useKerning = true;
141     }
142
143
144     /**
145      * Get the generated font object
146      */

147     public Font getFont() {
148         return returnFont;
149     }
150
151     /**
152      * Construct a FontReader object from a path to a metric.xml file
153      * and read metric data
154      */

155     public FontReader(URL JavaDoc path) throws FOPException {
156         createFont(path);
157     }
158
159     public void startDocument() {}
160
161     public void setDocumentLocator(Locator JavaDoc locator) {
162         this.locator = locator;
163     }
164
165     public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName,
166                              Attributes JavaDoc attributes) throws SAXException JavaDoc {
167         if (localName.equals("font-metrics")) {
168             if ("TYPE0".equals(attributes.getValue("type"))) {
169                 multiFont = new MultiByteFont();
170                 returnFont = multiFont;
171                 isCID = true;
172             } else if ("TRUETYPE".equals(attributes.getValue("type"))) {
173                 singleFont = new SingleByteFont();
174                 singleFont.subType = org.apache.fop.pdf.PDFFont.TRUETYPE;
175                 returnFont = singleFont;
176                 isCID = false;
177             } else {
178                 singleFont = new SingleByteFont();
179                 singleFont.subType = org.apache.fop.pdf.PDFFont.TYPE1;
180                 returnFont = singleFont;
181                 isCID = false;
182             }
183         } else if ("embed".equals(localName)) {
184             if (isCID) {
185                 /**@todo This *is* annoying... should create a common
186                   interface for sing/multibytefonts...*/

187                 String JavaDoc filename = attributes.getValue("file");
188                 if (filename != null) {
189                     try {
190                         multiFont.embedFileName = URLBuilder.buildURL(
191                                 Configuration.getFontBaseURL(), filename);
192                     } catch (java.net.MalformedURLException JavaDoc mfue) {
193                         throw new SAXException JavaDoc(mfue);
194                     }
195                 }
196                 multiFont.embedResourceName = attributes.getValue("class");
197             } else {
198                 String JavaDoc filename = attributes.getValue("file");
199                 if (filename != null) {
200                     try {
201                         singleFont.embedFileName = URLBuilder.buildURL(
202                                 Configuration.getFontBaseURL(), filename);
203                     } catch (java.net.MalformedURLException JavaDoc mfue) {
204                         throw new SAXException JavaDoc(mfue);
205                     }
206                 }
207                 singleFont.embedResourceName = attributes.getValue("class");
208             }
209         } else if ("cid-widths".equals(localName)) {
210             cidWidthIndex = getInt(attributes.getValue("start-index"));
211             cidWidths = new java.util.ArrayList JavaDoc();
212         } else if ("kerning".equals(localName)) {
213             currentKerning = new java.util.HashMap JavaDoc();
214             if (isCID)
215                 multiFont.kerning.put(new Integer JavaDoc(attributes.getValue("kpx1")),
216                                       currentKerning);
217             else
218                 singleFont.kerning.put(new Integer JavaDoc(attributes.getValue("kpx1")),
219                                        currentKerning);
220         } else if ("bfranges".equals(localName)) {
221             bfranges = new java.util.ArrayList JavaDoc();
222         } else if ("bf".equals(localName)) {
223             BFEntry entry = new BFEntry();
224             entry.unicodeStart = getInt(attributes.getValue("us"));
225             entry.unicodeEnd = getInt(attributes.getValue("ue"));
226             entry.glyphStartIndex = getInt(attributes.getValue("gi"));
227             bfranges.add(entry);
228         } else if ("wx".equals(localName)) {
229             cidWidths.add(new Integer JavaDoc(attributes.getValue("w")));
230         } else if ("widths".equals(localName)) {
231             singleFont.width = new int[256];
232         } else if ("char".equals(localName)) {
233             try {
234                 singleFont.width[Integer.parseInt(attributes.getValue("idx"))] =
235                     Integer.parseInt(attributes.getValue("wdt"));
236             } catch (NumberFormatException JavaDoc ne) {
237                 System.out.println("Malformed width in metric file: "
238                                    + ne.getMessage());
239             }
240         } else if ("pair".equals(localName)) {
241             currentKerning.put(new Integer JavaDoc(attributes.getValue("kpx2")),
242                                new Integer JavaDoc(attributes.getValue("kern")));
243         }
244     }
245
246     private int getInt(String JavaDoc str) {
247         int ret = 0;
248         try {
249             ret = Integer.parseInt(str);
250         } catch (Exception JavaDoc e) {}
251         return ret;
252     }
253
254     public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName) {
255         if ("font-name".equals(localName))
256             if (isCID)
257                 multiFont.fontName = text;
258             else
259                 singleFont.fontName = text;
260         if ("ttc-name".equals(localName) && isCID)
261             multiFont.ttcName = text;
262         else if ("cap-height".equals(localName))
263             if (isCID)
264                 multiFont.capHeight = getInt(text);
265             else
266                 singleFont.capHeight = getInt(text);
267         else if ("x-height".equals(localName))
268             if (isCID)
269                 multiFont.xHeight = getInt(text);
270             else
271                 singleFont.xHeight = getInt(text);
272         else if ("ascender".equals(localName))
273             if (isCID)
274                 multiFont.ascender = getInt(text);
275             else
276                 singleFont.ascender = getInt(text);
277         else if ("descender".equals(localName))
278             if (isCID)
279                 multiFont.descender = getInt(text);
280             else
281                 singleFont.descender = getInt(text);
282         else if ("left".equals(localName))
283             if (isCID)
284                 multiFont.fontBBox[0] = getInt(text);
285             else
286                 singleFont.fontBBox[0] = getInt(text);
287         else if ("bottom".equals(localName))
288             if (isCID)
289                 multiFont.fontBBox[1] = getInt(text);
290             else
291                 singleFont.fontBBox[1] = getInt(text);
292         else if ("right".equals(localName))
293             if (isCID)
294                 multiFont.fontBBox[2] = getInt(text);
295             else
296                 singleFont.fontBBox[2] = getInt(text);
297         else if ("first-char".equals(localName))
298             singleFont.firstChar = getInt(text);
299         else if ("last-char".equals(localName))
300             singleFont.lastChar = getInt(text);
301         else if ("top".equals(localName))
302             if (isCID)
303                 multiFont.fontBBox[3] = getInt(text);
304             else
305                 singleFont.fontBBox[3] = getInt(text);
306         else if ("flags".equals(localName))
307             if (isCID)
308                 multiFont.flags = getInt(text);
309             else
310                 singleFont.flags = getInt(text);
311         else if ("stemv".equals(localName))
312             if (isCID)
313                 multiFont.stemV = getInt(text);
314             else
315                 singleFont.stemV = getInt(text);
316         else if ("italic-angle".equals(localName))
317             if (isCID)
318                 multiFont.italicAngle = getInt(text);
319             else
320                 singleFont.italicAngle = getInt(text);
321         else if ("missing-width".equals(localName))
322             if (isCID)
323                 multiFont.missingWidth = getInt(text);
324             else
325                 singleFont.missingWidth = getInt(text);
326         else if ("cid-type".equals(localName)) {
327             if ("CIDFontType2".equals(text))
328                 multiFont.cidType = PDFCIDFont.CID_TYPE2;
329         } else if ("default-width".equals(localName)) {
330             multiFont.defaultWidth = getInt(text);
331         } else if ("cid-widths".equals(localName)) {
332             int[] wds = new int[cidWidths.size()];
333             for (int i = 0; i < cidWidths.size(); i++ ) {
334                 wds[i] = ((Integer JavaDoc)cidWidths.get(i)).intValue();
335             }
336
337             multiFont.warray.addEntry(cidWidthIndex, wds);
338             multiFont.width = wds;
339
340         } else if ("bfranges".equals(localName)) {
341             BFEntry[] entries = new BFEntry[bfranges.size()];
342             entries = (BFEntry[])bfranges.toArray(entries);
343             multiFont.bfentries = entries;
344         }
345
346     }
347
348     public void characters(char[] ch, int start, int length) {
349         char c[] = new char[length];
350         System.arraycopy(ch, start, c, 0, length);
351         text = new String JavaDoc(c);
352     }
353
354 }
355
356
357
Popular Tags