KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > layout > FontState


1 /*
2  * $Id: FontState.java,v 1.14.2.8 2003/03/02 16:55:15 pietsch 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.layout;
52
53 import org.apache.fop.apps.FOPException;
54 import org.apache.fop.render.pdf.CodePointMapping;
55
56 import java.util.Map JavaDoc;
57 import java.util.StringTokenizer JavaDoc;
58
59 public class FontState {
60
61     private FontInfo _fontInfo;
62     private String JavaDoc _fontName;
63     private int _fontSize;
64     private String JavaDoc _fontFamily;
65     private String JavaDoc _fontStyle;
66     private String JavaDoc _fontWeight;
67     private int _fontVariant;
68
69     private FontMetric _metric;
70     private int _letterSpacing;
71
72     private static final Map JavaDoc EMPTY_MAP = new java.util.HashMap JavaDoc();
73
74
75     public FontState(FontInfo fontInfo, String JavaDoc fontFamily, String JavaDoc fontStyle,
76                      String JavaDoc fontWeight, int fontSize,
77                      int fontVariant) throws FOPException {
78         _fontInfo = fontInfo;
79         _fontFamily = fontFamily;
80         _fontStyle = fontStyle;
81         _fontWeight = fontWeight;
82         _fontSize = fontSize;
83         String JavaDoc _fontKey = FontInfo.createFontKey(_fontFamily, _fontStyle, _fontWeight);
84         //Quick check-out for simple font family
85
if (!fontInfo.hasFont(_fontKey)) {
86             //Tokenizes font-family list
87
StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(_fontFamily, ",");
88             while (st.hasMoreTokens()) {
89                 String JavaDoc token = st.nextToken().trim();
90                 //Checks for quoted font family name
91
if (token.charAt(0) == '"' || token.charAt(0) == '\'')
92                     token = token.substring(1, token.length()-1);
93                 else {
94                     //In a nonquoted font family name any sequence of whitespace
95
//inside should be converted to a single space
96
StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
97                     boolean spaced = false;
98                     for (int i=0; i<token.length(); i++) {
99                         char c = token.charAt(i);
100                         if (!isWhitespace(c)) {
101                             sb.append(c);
102                             spaced = false;
103                         }
104                         else if (!spaced) {
105                             sb.append(c);
106                             spaced = true;
107                         }
108                     }
109                     token = sb.toString();
110                 }
111                 //Checks found font family name for existence
112
_fontKey = FontInfo.createFontKey(token, _fontStyle, _fontWeight);
113                 if (fontInfo.hasFont(_fontKey)) {
114                     _fontFamily = token;
115                     break;
116                 }
117             }
118         }
119         _fontName = fontInfo.fontLookup(_fontKey);
120         _metric = fontInfo.getMetricsFor(_fontName);
121         _fontVariant = fontVariant;
122         _letterSpacing = 0;
123     }
124
125     public FontState(FontInfo fontInfo, String JavaDoc fontFamily, String JavaDoc fontStyle,
126                      String JavaDoc fontWeight, int fontSize,
127                      int fontVariant, int letterSpacing) throws FOPException {
128         this(fontInfo, fontFamily, fontStyle, fontWeight, fontSize,
129              fontVariant);
130         _letterSpacing = letterSpacing;
131     }
132
133     private static boolean isWhitespace(char ch) {
134         return (ch <= 0x0020) &&
135             (((((1L << 0x0009) |
136             (1L << 0x000A) |
137             (1L << 0x000C) |
138             (1L << 0x000D) |
139             (1L << 0x0020)) >> ch) & 1L) != 0);
140     }
141
142     public int getAscender() {
143         return _metric.getAscender(_fontSize) / 1000;
144     }
145
146     public int getLetterSpacing() {
147         return _letterSpacing;
148     }
149
150
151     public int getCapHeight() {
152         return _metric.getCapHeight(_fontSize) / 1000;
153     }
154
155     public int getDescender() {
156         return _metric.getDescender(_fontSize) / 1000;
157     }
158
159     public String JavaDoc getFontName() {
160         return _fontName;
161     }
162
163     public int getFontSize() {
164         return _fontSize;
165     }
166
167     public String JavaDoc getFontWeight() {
168         return _fontWeight;
169     }
170
171     public String JavaDoc getFontFamily() {
172         return _fontFamily;
173     }
174
175     public String JavaDoc getFontStyle() {
176         return _fontStyle;
177     }
178
179     public int getFontVariant() {
180         return _fontVariant;
181     }
182
183     public FontInfo getFontInfo() {
184         return _fontInfo;
185     }
186
187     public int getXHeight() {
188         return _metric.getXHeight(_fontSize) / 1000;
189     }
190
191     public Map JavaDoc getKerning() {
192         if (_metric instanceof FontDescriptor) {
193             Map JavaDoc ret = ((FontDescriptor)_metric).getKerningInfo();
194             if (ret != null)
195                 return ret;
196         }
197         return EMPTY_MAP;
198     }
199
200     public int width(int charnum) {
201         // returns width of given character number in millipoints
202
return _letterSpacing + (_metric.width(charnum, _fontSize) / 1000);
203     }
204
205     /**
206      * Map a java character (unicode) to a font character
207      * Default uses CodePointMapping
208      */

209     public char mapChar(char c) {
210
211         if (_metric instanceof org.apache.fop.render.pdf.Font) {
212             return ((org.apache.fop.render.pdf.Font)_metric).mapChar(c);
213         } else if (_metric instanceof org.apache.fop.render.awt.FontMetricsMapper) {
214             return c;
215         }
216
217         // Use default CodePointMapping
218
char d = CodePointMapping.getMapping("WinAnsiEncoding").mapChar(c);
219         if (d != 0) {
220             c = d;
221         } else {
222             c = '#';
223         }
224         return c;
225     }
226
227     private int enWidth=-1;
228     private int emWidth=-1;
229
230     private final int getEmWidth() {
231         if (emWidth<0) {
232             char mappedChar = mapChar('m');
233             // The mapping returns '#' for unmapped characters in
234
// standard fonts. What happens for other fonts?
235
if (mappedChar == '#') {
236                 emWidth = 500 * getFontSize();
237             } else {
238                 emWidth = width(mappedChar);
239             }
240         }
241         return emWidth;
242     }
243
244     private final int getEnWidth() {
245         if (enWidth<0) {
246             char mappedChar = mapChar('n');
247             // The mapping returns '#' for unmapped characters in
248
// standard fonts. What happens for other fonts?
249
if (mappedChar != '#') {
250                 // Should do something to discover non-proportional fonts.
251
enWidth = (getEmWidth()*9)/10;
252             } else {
253                 enWidth = width(mappedChar);
254             }
255         }
256         return enWidth;
257     }
258
259     /**
260      * Helper method for getting the width of a unicode char
261      * from the current fontstate.
262      * This also performs some guessing on widths on various
263      * versions of space that might not exists in the font.
264      */

265     public int getCharWidth(char c) {
266         if ((c == '\n') || (c == '\r') || (c == '\t')) {
267             return getCharWidth(' ');
268         } else {
269             char mappedChar = mapChar(c);
270             if (mappedChar == '#' || mappedChar == 0) {
271                 // Estimate the width of spaces not represented in
272
// the font
273
if (c == '#') {
274                     return width(mappedChar);
275                 } else if (c == ' ') {
276                     return getEmWidth();
277                 } else if (c == '\u00A0') {
278                     return getCharWidth(' ');
279                 } else if (c == '\u2000') {
280                     return getEnWidth();
281                 } else if (c == '\u2001') {
282                     return getEmWidth();
283                 } else if (c == '\u2002') {
284                     return getEnWidth();
285                 } else if (c == '\u2003') {
286                     return getEmWidth();
287                 } else if (c == '\u2004') {
288                     return getEmWidth() / 3;
289                 } else if (c == '\u2005') {
290                     return getEmWidth() / 4;
291                 } else if (c == '\u2006') {
292                     return getEmWidth() / 6;
293                 } else if (c == '\u2007') {
294                     return getCharWidth(' ');
295                 } else if (c == '\u2008') {
296                     return getCharWidth('.');
297                 } else if (c == '\u2009') {
298                     return getEmWidth() / 5;
299                 } else if (c == '\u200A') {
300                     return getEmWidth() / 10;
301                 } else if (c == '\u200B') {
302                     return 1;
303                 } else if (c == '\u202F') {
304                     return getCharWidth(' ') / 2;
305                 } else if (c == '\u3000') {
306                     return getCharWidth(' ') * 2;
307                 } else {
308                     return width(mappedChar);
309                 }
310             } else {
311                 return width(mappedChar);
312             }
313         }
314     }
315
316     /**
317      * Calculates the word width.
318      */

319     public int getWordWidth(String JavaDoc word) {
320         if (word == null)
321             return 0;
322         int wordLength = word.length();
323         int width = 0;
324         char[] characters = new char[wordLength];
325         word.getChars(0, wordLength, characters, 0);
326         for (int i = 0; i < wordLength; i++) {
327             width += getCharWidth(characters[i]);
328         }
329         return width;
330     }
331
332 }
333
334
335
336
Popular Tags