001: /*
002: * @(#)QtFontMetrics.java 1.8 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: import java.awt.font.TextAttribute;
035:
036: /**
037: * A font metrics object for a font.
038: *
039: * @version 1.18, 05/14/02
040: */
041: class QtFontMetrics extends FontMetrics {
042:
043: static final long serialVersionUID = -4956160226949100590L;
044:
045: /** A map which maps from Java logical font names and styles to native font names. */
046:
047: private static Map fontNameMap;
048:
049: private static native void initIDs();
050:
051: static {
052: initIDs();
053: String s = File.separator;
054: String javaHome = (String) AccessController
055: .doPrivileged(new PrivilegedAction() {
056: public Object run() {
057: return System.getProperty("java.home");
058: }
059: });
060: // String dir = "lib" + s + "fonts";
061: File f = new File(javaHome, "lib" + s + "fonts");
062: // String dir = f.getAbsolutePath();
063: fontNameMap = new HashMap(10);
064:
065: String dir = "";
066: s = "";
067:
068: /* Initialise table to map standard Java font names and styles to TrueType Fonts */
069:
070: //6177148
071: // Changed all the physical font family names to the names that
072: // Qt can understand. We were having "times", "helvetica" etc
073: // as the physical font names and since it did not match what qt
074: // expects, we were rendering with some font that qt picked up.
075: // Following J2SE's convention of mapping
076: // "monospaced" and "dialoginput" has MonoSpaced Font (Courier)
077: // "sansserif" and "sanserif" has a sans serif Font (We just use
078: // "Sans Serif" for qt to pick some San Serif font. and the
079: // "default" font is a Sans Serif font
080: fontNameMap.put("serif", dir + s + "Serif");
081:
082: fontNameMap.put("sansserif", dir + s + "Sans Serif");
083:
084: fontNameMap.put("monospaced", dir + s + "Courier");
085:
086: fontNameMap.put("dialog", dir + s + "Sans Serif");
087:
088: fontNameMap.put("dialoginput", dir + s + "Courier");
089:
090: /* This should always exist and is used for fonts whose name is not any of the above. */
091:
092: fontNameMap.put("default", dir + s + "Sans Serif");
093: //6177148
094: }
095:
096: /**
097: * The standard ascent of the font. This is the logical height
098: * above the baseline for the Alphanumeric characters and should
099: * be used for determining line spacing. Note, however, that some
100: * characters in the font may extend above this height.
101: */
102: int ascent;
103:
104: /**
105: * The standard descent of the font. This is the logical height
106: * below the baseline for the Alphanumeric characters and should
107: * be used for determining line spacing. Note, however, that some
108: * characters in the font may extend below this height.
109: */
110: int descent;
111:
112: /**
113: * The standard leading for the font. This is the logical amount
114: * of space to be reserved between the descent of one line of text
115: * and the ascent of the next line. The height metric is calculated
116: * to include this extra space.
117: */
118: int leading;
119:
120: /**
121: * The standard height of a line of text in this font. This is
122: * the distance between the baseline of adjacent lines of text.
123: * It is the sum of the ascent+descent+leading. There is no
124: * guarantee that lines of text spaced at this distance will be
125: * disjoint; such lines may overlap if some characters overshoot
126: * the standard ascent and descent metrics.
127: */
128: // 6286830
129: /*
130: int height;
131: */
132:
133: /**
134: * The maximum ascent for all characters in this font. No character
135: * will extend further above the baseline than this metric.
136: */
137: int maxAscent;
138:
139: /**
140: * The maximum descent for all characters in this font. No character
141: * will descend further below the baseline than this metric.
142: */
143: int maxDescent;
144:
145: /**
146: * The maximum possible height of a line of text in this font.
147: * Adjacent lines of text spaced this distance apart will be
148: * guaranteed not to overlap. Note, however, that many paragraphs
149: * that contain ordinary alphanumeric text may look too widely
150: * spaced if this metric is used to determine line spacing. The
151: * height field should be preferred unless the text in a given
152: * line contains particularly tall characters.
153: */
154: // Code cleanup while fixing 6286830
155: /*
156: int maxHeight;
157: */
158:
159: /**
160: * The maximum advance width of any character in this font.
161: */
162: int maxAdvance;
163:
164: /** Native font handle */
165:
166: int nativeFont;
167:
168: /** Cache of first 256 Unicode characters as these map to ASCII characters and are often used. */
169:
170: private int[] widths;
171:
172: /**
173: * Loads MicroWindows Font and sets up the Font Metric fields
174: */
175:
176: private native int pLoadFont(String fontName, int fontHeight,
177: int fontStyle, boolean st, boolean ul);
178:
179: private static native void pDestroyFont(int nativeFont);
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 FontMetrics 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 QtFontMetrics getFontMetrics(Font font,
192: boolean backwardCompat) {
193:
194: /* See if metrics has been stored in font already. */
195:
196: QtFontMetrics fm = (QtFontMetrics) font.metrics;
197:
198: if (fm == null) {
199: boolean strikethrough = false, underline = false;
200:
201: /* See if a font metrics of the same native name and size has already been loaded.
202: If it has then we use that one. */
203:
204: String nativeName = (String) fontNameMap.get(font.name
205: .toLowerCase());
206:
207: if (nativeName == null)
208: nativeName = (String) fontNameMap.get("default");
209:
210: String key = nativeName + "." + font.style + "."
211: + font.size;
212:
213: if (!backwardCompat) {
214: Map fa = font.getAttributes();
215: Object obj;
216:
217: if ((obj = fa.get(TextAttribute.STRIKETHROUGH)) != null) {
218: if (obj.equals(TextAttribute.STRIKETHROUGH_ON)) {
219: key += ".s";
220: strikethrough = true;
221: }
222: }
223:
224: if ((obj = fa.get(TextAttribute.UNDERLINE)) != null) {
225: if (obj.equals(TextAttribute.UNDERLINE_ON)) {
226: key += ".u";
227: underline = true;
228: }
229: }
230: }
231:
232: fm = (QtFontMetrics) fontMetricsMap.get(key);
233:
234: if (fm == null) {
235: fontMetricsMap.put(key, fm = new QtFontMetrics(font,
236: nativeName, font.style, strikethrough,
237: underline));
238: }
239:
240: font.metrics = fm;
241: }
242:
243: return fm;
244: }
245:
246: /**
247: * Creates a font metrics for the supplied font. To get a font metrics for a font
248: * use the static method getFontMetrics instead which does caching.
249: */
250: private QtFontMetrics(Font font, String nativeName, int style,
251: boolean st, boolean ul) {
252:
253: super (font);
254:
255: nativeFont = pLoadFont(nativeName, font.size, style, st, ul);
256:
257: /* Cache first 256 char widths for use by the getWidths method and for faster metric
258: calculation as they are commonly used (ASCII) characters. */
259:
260: widths = new int[256];
261:
262: int i;
263:
264: for (i = 0; i < 256; i++) {
265: widths[i] = pStringWidth(nativeFont, new String(
266: new char[] { (char) i }));
267: }
268: }
269:
270: static String[] getFontList() {
271: Vector fontNames = new Vector();
272: Iterator fonts = fontNameMap.keySet().iterator();
273: int dotidx;
274:
275: while (fonts.hasNext()) {
276: String fontname = (String) fonts.next();
277:
278: if ((dotidx = fontname.indexOf('.')) == -1)
279: dotidx = fontname.length();
280:
281: fontname = fontname.substring(0, dotidx);
282:
283: if (!fontNames.contains(fontname))
284: fontNames.add(fontname);
285:
286: }
287:
288: String[] tmpFontNames = new String[fontNames.size()];
289:
290: System.arraycopy(fontNames.toArray(), 0, tmpFontNames, 0,
291: tmpFontNames.length);
292:
293: return tmpFontNames;
294:
295: }
296:
297: /**
298: * Get leading
299: */
300: public int getLeading() {
301: return leading;
302: }
303:
304: /**
305: * Get ascent.
306: */
307: public int getAscent() {
308: return ascent;
309: }
310:
311: /**
312: * Get descent
313: */
314: public int getDescent() {
315: return descent;
316: }
317:
318: /**
319: * Get height
320: */
321: // 6286830
322: // QtFontMetrics::height() is different from AWT's idea of
323: // java.awt.FontMetrics.getHeight(). So don't override it.
324: /*
325: public int getHeight() {
326: return height;
327: }
328: */
329:
330: /**
331: * Get maxAscent
332: */
333: public int getMaxAscent() {
334: return maxAscent;
335: }
336:
337: /**
338: * Get maxDescent
339: */
340: public int getMaxDescent() {
341: return maxDescent;
342: }
343:
344: /**
345: * Get maxAdvance
346: */
347: public int getMaxAdvance() {
348: return maxAdvance;
349: }
350:
351: /**
352: * Fast lookup of first 256 chars as these are always the same eg. ASCII charset.
353: */
354:
355: public int charWidth(char c) {
356: if (c < 256)
357: return widths[c];
358:
359: return pStringWidth(nativeFont, new String(new char[] { c }));
360: }
361:
362: /**
363: * Return the width of the specified string in this Font.
364: */
365: public int stringWidth(String string) {
366:
367: if (string == null)
368: throw new NullPointerException("String can't be null");
369:
370: return pStringWidth(nativeFont, string);
371: }
372:
373: /**
374: * Return the width of the specified char[] in this Font.
375: */
376: public int bytesWidth(byte chars[], int offset, int length) {
377: if (chars == null)
378: throw new NullPointerException("Byte array can't be null");
379:
380: if ((offset < 0) || (offset + length < 0)
381: || (offset + length > chars.length))
382: throw new ArrayIndexOutOfBoundsException(
383: "offset or length inappropriate");
384:
385: return pStringWidth(nativeFont, new String(chars, offset,
386: length));
387: }
388:
389: /**
390: * Return the width of the specified char[] in this Font.
391: */
392: public int charsWidth(char chars[], int offset, int length) {
393: if (chars == null)
394: throw new NullPointerException("Char array can't be null");
395:
396: if ((offset < 0) || (offset + length < 0)
397: || (offset + length > chars.length))
398: throw new ArrayIndexOutOfBoundsException(
399: "offset or length inappropriate");
400:
401: return pStringWidth(nativeFont, new String(chars, offset,
402: length));
403: }
404:
405: /**
406: * Get the widths of the first 256 characters in the font.
407: */
408: public int[] getWidths() {
409:
410: int[] newWidths = new int[256];
411:
412: System.arraycopy(widths, 0, newWidths, 0, 256);
413:
414: return newWidths;
415: }
416:
417: protected void finalize() throws Throwable {
418: pDestroyFont(nativeFont);
419: super.finalize();
420: }
421: }
|