001: /*
002: * @(#)MWFontMetrics.java 1.25 06/10/10
003: *
004: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: *
026: */
027:
028: package java.awt;
029:
030: import java.io.*;
031: import java.security.*;
032: import java.util.*;
033:
034: /**
035: * A font metrics object for a font.
036: *
037: * @version 1.19, 08/19/02
038: */
039: class MWFontMetrics extends FontMetrics {
040: // serialVersionUID - 4683929
041: static final long serialVersionUID = -4956160226949100590L;
042: /** A map which maps from Java logical font names and styles to native font names. */
043:
044: private static Map fontNameMap;
045:
046: private static native void initIDs();
047:
048: static {
049: initIDs();
050: String s = File.separator;
051: String javaHome = (String) AccessController
052: .doPrivileged(new PrivilegedAction() {
053: public Object run() {
054: return System.getProperty("java.home");
055: }
056: });
057: //dir += s + "lib" + s + "fonts";
058: File f = new File(javaHome, "lib" + s + "fonts");
059: String dir = f.getAbsolutePath();
060: fontNameMap = new HashMap(24);
061: /* Initialise table to map standard Java font names and styles to TrueType Fonts */
062:
063: fontNameMap.put("serif.0", dir + s + "LucidaBrightRegular.ttf");
064: fontNameMap
065: .put("serif.1", dir + s + "LucidaBrightDemiBold.ttf");
066: fontNameMap.put("serif.2", dir + s + "LucidaBrightItalic.ttf");
067: fontNameMap.put("serif.3", dir + s
068: + "LucidaBrightDemiItalic.ttf");
069: fontNameMap.put("sansserif.0", dir + s
070: + "LucidaSansRegular.ttf");
071: fontNameMap.put("sansserif.1", dir + s
072: + "LucidaSansDemiBold.ttf");
073: fontNameMap.put("sansserif.2", dir + s
074: + "LucidaSansOblique.ttf");
075: fontNameMap.put("sansserif.3", dir + s
076: + "LucidaSansDemiOblique.ttf");
077: fontNameMap.put("monospaced.0", dir + s
078: + "LucidaTypewriterRegular.ttf");
079: fontNameMap.put("monospaced.1", dir + s
080: + "LucidaTypewriterBold.ttf");
081: fontNameMap.put("monospaced.2", dir + s
082: + "LucidaTypewriterOblique.ttf");
083: fontNameMap.put("monospaced.3", dir + s
084: + "LucidaTypewriterBoldOblique.ttf");
085: fontNameMap.put("dialog.0", dir + s + "LucidaSansRegular.ttf");
086: fontNameMap.put("dialog.1", dir + s + "LucidaSansDemiBold.ttf");
087: fontNameMap.put("dialog.2", dir + s + "LucidaSansOblique.ttf");
088: fontNameMap.put("dialog.3", dir + s
089: + "LucidaSansDemiOblique.ttf");
090: fontNameMap.put("dialoginput.0", dir + s
091: + "LucidaTypewriterRegular.ttf");
092: fontNameMap.put("dialoginput.1", dir + s
093: + "LucidaTypewriterBold.ttf");
094: fontNameMap.put("dialoginput.2", dir + s
095: + "LucidaTypewriterOblique.ttf");
096: fontNameMap.put("dialoginput.3", dir + s
097: + "LucidaTypewriterBoldOblique.ttf");
098: /* This should always exist and is used for fonts whose name is not any of the above. */
099:
100: fontNameMap.put("default.0", dir + s + "LucidaSansRegular.ttf");
101: fontNameMap
102: .put("default.1", dir + s + "LucidaSansDemiBold.ttf");
103: fontNameMap.put("default.2", dir + s + "LucidaSansOblique.ttf");
104: fontNameMap.put("default.3", dir + s
105: + "LucidaSansDemiOblique.ttf");
106: }
107: /**
108: * The standard ascent of the font. This is the logical height
109: * above the baseline for the Alphanumeric characters and should
110: * be used for determining line spacing. Note, however, that some
111: * characters in the font may extend above this height.
112: */
113: int ascent;
114: /**
115: * The standard descent of the font. This is the logical height
116: * below the baseline for the Alphanumeric characters and should
117: * be used for determining line spacing. Note, however, that some
118: * characters in the font may extend below this height.
119: */
120: int descent;
121: /**
122: * The standard leading for the font. This is the logical amount
123: * of space to be reserved between the descent of one line of text
124: * and the ascent of the next line. The height metric is calculated
125: * to include this extra space.
126: */
127: int leading;
128: /**
129: * The standard height of a line of text in this font. This is
130: * the distance between the baseline of adjacent lines of text.
131: * It is the sum of the ascent+descent+leading. There is no
132: * guarantee that lines of text spaced at this distance will be
133: * disjoint; such lines may overlap if some characters overshoot
134: * the standard ascent and descent metrics.
135: */
136: int height;
137: /**
138: * The maximum ascent for all characters in this font. No character
139: * will extend further above the baseline than this metric.
140: */
141: int maxAscent;
142: /**
143: * The maximum descent for all characters in this font. No character
144: * will descend further below the baseline than this metric.
145: */
146: int maxDescent;
147: /**
148: * The maximum possible height of a line of text in this font.
149: * Adjacent lines of text spaced this distance apart will be
150: * guaranteed not to overlap. Note, however, that many paragraphs
151: * that contain ordinary alphanumeric text may look too widely
152: * spaced if this metric is used to determine line spacing. The
153: * height field should be preferred unless the text in a given
154: * line contains particularly tall characters.
155: */
156: int maxHeight;
157: /**
158: * The maximum advance width of any character in this font.
159: */
160: int maxAdvance;
161: /** Native font handle */
162:
163: int nativeFont;
164: /** Cache of first 256 Unicode characters as these map to ASCII characters and are often used. */
165:
166: private int[] widths;
167:
168: /**
169: * Loads MicroWindows Font and sets up the Font Metric fields
170: */
171:
172: private native int pLoadFont(String fontName, int fontHeight);
173:
174: private static native void pDestroyFont(int nativeFont);
175:
176: private static native int pCharWidth(int nativeFont, char c);
177:
178: private static native int pCharsWidth(int nativeFont, char chars[],
179: int offset, int len);
180:
181: private static native int pStringWidth(int nativeFont, String string);
182:
183: /** A map which maps a native font name and size to a font metrics object. This is used
184: as a cache to prevent loading the same fonts multiple times. */
185:
186: private static Map fontMetricsMap = new HashMap();
187:
188: /** Gets the MWFontMetrics object for the supplied font. This method caches font metrics
189: to ensure native fonts are not loaded twice for the same font. */
190:
191: static synchronized MWFontMetrics getFontMetrics(Font font) {
192: /* See if metrics has been stored in font already. */
193:
194: MWFontMetrics fm = (MWFontMetrics) font.metrics;
195: if (fm == null) {
196: /* See if a font metrics of the same native name and size has already been loaded.
197: If it has then we use that one. */
198:
199: String nativeName = (String) fontNameMap.get(font.name
200: .toLowerCase()
201: + "." + font.style);
202: if (nativeName == null)
203: nativeName = (String) fontNameMap.get("default."
204: + font.style);
205: String key = nativeName + "." + font.size;
206: fm = (MWFontMetrics) fontMetricsMap.get(key);
207: if (fm == null) {
208: fontMetricsMap.put(key, fm = new MWFontMetrics(font,
209: nativeName));
210: }
211: font.metrics = fm;
212: }
213: return fm;
214: }
215:
216: /**
217: * Creates a font metrics for the supplied font. To get a font metrics for a font
218: * use the static method getFontMetrics instead which does caching.
219: */
220: private MWFontMetrics(Font font, String nativeName) {
221: super (font);
222: nativeFont = pLoadFont(nativeName, font.size);
223: /* Cache first 256 char widths for use by the getWidths method and for faster metric
224: calculation as they are commonly used (ASCII) characters. */
225:
226: widths = new int[256];
227: int i;
228: for (i = 0; i < 256; i++) {
229: widths[i] = pCharWidth(nativeFont, (char) i);
230: }
231: }
232:
233: static String[] getFontList() {
234: Vector fontNames = new Vector();
235: Iterator fonts = fontNameMap.keySet().iterator();
236: int dotidx;
237: while (fonts.hasNext()) {
238: String fontname = (String) fonts.next();
239: if ((dotidx = fontname.indexOf('.')) == -1)
240: dotidx = fontname.length();
241: fontname = fontname.substring(0, dotidx);
242: if (!fontNames.contains(fontname))
243: fontNames.add(fontname);
244: }
245: String[] tmpFontNames = new String[fontNames.size()];
246: System.arraycopy(fontNames.toArray(), 0, tmpFontNames, 0,
247: tmpFontNames.length);
248: return tmpFontNames;
249: }
250:
251: /**
252: * Get leading
253: */
254: public int getLeading() {
255: return leading;
256: }
257:
258: /**
259: * Get ascent.
260: */
261: public int getAscent() {
262: return ascent;
263: }
264:
265: /**
266: * Get descent
267: */
268: public int getDescent() {
269: return descent;
270: }
271:
272: /**
273: * Get height
274: */
275: public int getHeight() {
276: return height;
277: }
278:
279: /**
280: * Get maxAscent
281: */
282: public int getMaxAscent() {
283: return maxAscent;
284: }
285:
286: /**
287: * Get maxDescent
288: */
289: public int getMaxDescent() {
290: return maxDescent;
291: }
292:
293: /**
294: * Get maxAdvance
295: */
296: public int getMaxAdvance() {
297: return maxAdvance;
298: }
299:
300: /**
301: * Fast lookup of first 256 chars as these are always the same eg. ASCII charset.
302: */
303:
304: public int charWidth(char c) {
305: if (c < 256)
306: return widths[c];
307: return pCharWidth(nativeFont, c);
308: }
309:
310: /**
311: * Return the width of the specified string in this Font.
312: */
313: public int stringWidth(String string) {
314: return pStringWidth(nativeFont, string);
315: }
316:
317: /**
318: * Return the width of the specified char[] in this Font.
319: */
320: public int charsWidth(char chars[], int offset, int length) {
321: return pCharsWidth(nativeFont, chars, offset, length);
322: }
323:
324: /**
325: * Get the widths of the first 256 characters in the font.
326: */
327: public int[] getWidths() {
328: int[] newWidths = new int[256];
329: System.arraycopy(widths, 0, newWidths, 0, 256);
330: return newWidths;
331: }
332:
333: protected void finalize() throws Throwable {
334: pDestroyFont(nativeFont);
335: super.finalize();
336: }
337: }
|