KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > awt > AWTFontMetrics


1 /*
2  * $Id: AWTFontMetrics.java,v 1.3.2.5 2003/02/25 14:39:33 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.awt;
52
53 // FOP
54
import org.apache.fop.messaging.MessageHandler;
55
56 // Java
57
import java.io.InputStream JavaDoc;
58 import java.net.URL JavaDoc;
59 import java.awt.Font JavaDoc;
60 import java.awt.Graphics2D JavaDoc;
61 import java.awt.geom.Rectangle2D JavaDoc;
62 import java.awt.FontMetrics JavaDoc;
63 import java.awt.font.TextLayout JavaDoc;
64 import java.util.Map JavaDoc;
65
66 /**
67  * This is a FontMetrics to be used for AWT rendering.
68  * It instanciates a font, depening on famil and style
69  * values. The java.awt.FontMetrics for this font is then
70  * created to be used for the actual measurement.
71  * Since layout is word by word and since it is expected that
72  * two subsequent words often share the same style, the
73  * Font and FontMetrics is buffered and only changed if needed.
74  * <p>
75  * Since FontState and FontInfo multiply all factors by
76  * size, we assume a "standard" font of FONT_SIZE.
77  */

78
79 public class AWTFontMetrics {
80
81     /**
82      * Font size standard used for metric measurements
83      */

84     public static final int FONT_SIZE = 1;
85
86     /**
87      * This factor multiplies the calculated values to scale
88      * to FOP internal measurements
89      */

90     public static final int FONT_FACTOR = (1000 * 1000) / FONT_SIZE;
91
92     /**
93      * The width of all 256 character, if requested
94      */

95     private int width[] = null;
96
97     /**
98      * The typical height of a small cap latter
99      */

100     private int xHeight = 0;
101
102     /**
103      * Buffered font.
104      * f1 is bufferd for metric measurements during layout.
105      * fSized is buffered for display purposes
106      */

107     private Font JavaDoc f1 = null; // , fSized = null;
108

109     /**
110      * The family type of the font last used
111      */

112     private String JavaDoc family = "";
113
114     /**
115      * The style of the font last used
116      */

117     private int style = 0;
118
119     /**
120      * The size of the font last used
121      */

122     private float size = 0;
123
124     /**
125      * The FontMetrics object used to calculate character width etc.
126      */

127     private FontMetrics JavaDoc fmt = null;
128
129     /**
130      * Temp graphics object needed to get the font metrics
131      */

132     Graphics2D JavaDoc graphics;
133
134     /**
135      * Embed Font List.
136      */

137     private Map JavaDoc embedFontList = null;
138
139     /**
140      * Physical Font Cache.
141      */

142     private Map JavaDoc fontCache = null;
143
144     /**
145      * Constructs a new Font-metrics.
146      * @param parent an temp graphics object - this is needed so
147      * that we can get an instance of
148      * java.awt.FontMetrics
149      */

150     public AWTFontMetrics(Graphics2D JavaDoc graphics) {
151         this.graphics = graphics;
152     }
153
154     /**
155      * Determines the font ascent of the Font described by this
156      * FontMetrics object
157      * @param family font family (jave name) to use
158      * @param style font style (jave def.) to use
159      * @return ascent in milliponts
160      */

161     public int getAscender(String JavaDoc family, int style, int size) {
162         setFont(family, style, size);
163         // return (int)(FONT_FACTOR * fmt.getAscent());
164

165         // workaround for sun bug on FontMetric.getAscent()
166
// http://developer.java.sun.com/developer/bugParade/bugs/4399887.html
167
int realAscent = fmt.getAscent()
168                          - (fmt.getDescent() + fmt.getLeading());
169         return FONT_FACTOR * realAscent;
170     }
171
172
173     /**
174      * The size of a capital letter measured from the font's baseline
175      */

176     public int getCapHeight(String JavaDoc family, int style, int size) {
177         // currently just gets Ascent value but maybe should use
178
// getMaxAcent() at some stage
179
return getAscender(family, style, size);
180     }
181
182     /**
183      * Determines the font descent of the Font described by this
184      * FontMetrics object
185      * @param family font family (jave name) to use
186      * @param style font style (jave def.) to use
187      * @return descent in milliponts
188      */

189     public int getDescender(String JavaDoc family, int style, int size) {
190         setFont(family, style, size);
191         return (-1 * FONT_FACTOR * fmt.getDescent());
192     }
193
194     /**
195      * Determines the typical font height of a small cap letter
196      * FontMetrics object
197      * @param family font family (jave name) to use
198      * @param style font style (jave def.) to use
199      * @return font height in milliponts
200      */

201     public int getXHeight(String JavaDoc family, int style, int size) {
202         setFont(family, style, size);
203         return (int)(FONT_FACTOR * xHeight);
204     }
205
206     /**
207      * Returns width (in 1/1000ths of point size) of character at
208      * code point i
209      * @param i the character for which to get the width
210      * @param family font family (jave name) to use
211      * @param style font style (jave def.) to use
212      * @param size the of the font
213      */

214     public int width(int i, String JavaDoc family, int style, int size) {
215         int w;
216         setFont(family, style, size);
217         
218         // Nov 18, 2002, aml/rlc
219
// measure character width using getStringBounds for better results
220

221         char [] ac = new char [1];
222         ac [0] = (char)i;
223         
224         double dWidth = fmt.getStringBounds (ac, 0, 1, graphics).getWidth() * FONT_FACTOR;
225         
226         // The following was left in based on this comment from the past (may be vestigial)
227

228         // the output seems to look a little better if the
229
// space is rendered larger than given by
230
// the FontMetrics object
231

232         if (i <=32) {
233           dWidth = dWidth * 1.4;
234         }
235
236         return (int) dWidth;
237     }
238
239     /**
240      * Return widths (in 1/1000ths of point size) of all
241      * characters
242      * @param family font family (jave name) to use
243      * @param style font style (jave def.) to use
244      */

245     public int[] getWidths(String JavaDoc family, int style, int size) {
246         int i;
247
248         if (width == null) {
249             width = new int[256];
250         }
251         setFont(family, style, size);
252         for (i = 0; i < 256; i++) {
253             width[i] = FONT_FACTOR * fmt.charWidth(i);
254         }
255         return width;
256     }
257
258     /**
259      * Checks whether the font for which values are
260      * requested is the one used immediately before or
261      * whether it is a new one
262      * @param family font family (jave name) to use
263      * @param style font style (jave def.) to use
264      * @return true if the font was changed, false otherwise
265      */

266     private boolean setFont(String JavaDoc family, int style, int size) {
267         boolean changed = false;
268         Rectangle2D JavaDoc rect;
269         TextLayout JavaDoc layout;
270         int s = (int)(size / 1000f);
271
272         if (f1 == null) {
273             f1 = createFont(family, style, s);
274             fmt = graphics.getFontMetrics(f1);
275             changed = true;
276         } else {
277             if ((this.style != style) ||!this.family.equals(family)
278                     || this.size != s) {
279                 if (family.equals(this.family)) {
280                     f1 = f1.deriveFont(style, (float)s);
281                 } else
282                     f1 = createFont(family, style, s);
283                 fmt = graphics.getFontMetrics(f1);
284                 changed = true;
285             }
286             // else the font is unchanged from last time
287
}
288         if (changed) {
289             layout = new TextLayout JavaDoc("m", f1, graphics.getFontRenderContext());
290             rect = layout.getBounds();
291             xHeight = (int)rect.getHeight();
292         }
293         // save the family and style for later comparison
294
this.family = family;
295         this.style = style;
296         this.size = s;
297         return changed;
298     }
299
300     /**
301      * set embed font.
302      * @param family font-family name
303      * @param style font style
304      * @param fontURL URL to physical font
305      */

306     public void setEmbedFont(String JavaDoc family, int style, URL JavaDoc fontURL) {
307         if (embedFontList == null)
308             embedFontList = new java.util.HashMap JavaDoc();
309         embedFontList.put(family+style, fontURL);
310     }
311
312     /**
313      * create Font to draw.
314      * @param family font-family name
315      * @param style font style
316      * @param size font size
317      */

318     public java.awt.Font JavaDoc createFont(String JavaDoc family, int style, int size) {
319         URL JavaDoc fontURL = null;
320         if (embedFontList != null)
321             fontURL = (URL JavaDoc)embedFontList.get(family+style);
322         if (fontURL == null)
323             return new Font JavaDoc(family, style, size);
324         // lazy instanciation for fontCache.
325
if (fontCache == null)
326             fontCache = new java.util.HashMap JavaDoc();
327         Font JavaDoc cachedFont = (Font JavaDoc)fontCache.get(fontURL.toExternalForm());
328         if (cachedFont == null) {
329             // Create specified TrueType Font.
330
InputStream JavaDoc fontStream = null;
331             try {
332                 MessageHandler.logln("Create embedded AWT font from stream "+fontURL.toExternalForm());
333                 fontStream = fontURL.openStream();
334                 // createFont methods supports higer than JDK1.3
335
// Currently supports only TrueType font.
336
cachedFont = Font.createFont(Font.TRUETYPE_FONT, fontStream);
337             } catch(Throwable JavaDoc th) {
338                 MessageHandler.error("Failed to create embedded AWT font "+
339                                      fontURL.toExternalForm() + ": " + th.toString());
340                 // if failed create font, use system "Dialog" logical font
341
// name for each Locale.
342
cachedFont = new Font JavaDoc("Dialog", style, size);
343             } finally {
344                 if (fontStream != null)
345                     try { fontStream.close(); } catch(Exception JavaDoc ex) {}
346             }
347             fontCache.put(fontURL.toExternalForm(), cachedFont);
348         }
349         Font JavaDoc font = cachedFont.deriveFont(style, (float)size);
350         return font;
351     }
352
353     /**
354      * Returns a java.awt.Font instance for the desired
355      * family, style and size type.
356      * This is here, so that the font-mapping
357      * of FOP-defined fonts to java-fonts can be done
358      * in one place and does not need to occur in
359      * AWTFontRenderer.
360      * @param family font family (jave name) to use
361      * @param style font style (jave def.) to use
362      * @param size font size
363      * @return font with the desired characeristics.
364      */

365     public java.awt.Font JavaDoc getFont(String JavaDoc family, int style, int size) {
366         Font JavaDoc f;
367
368         setFont(family, style, size);
369         return f1;
370         /*
371          * if( setFont(family,style, size) ) fSized = null;
372          * if( fSized == null || this.size != size ) {
373          * fSized = f1.deriveFont( size / 1000f );
374          * }
375          * this.size = size;
376          * return fSized;
377          */

378     }
379
380 }
381
382
383
384
385
386
387
Popular Tags