001: /*
002: * @(#)X11FontMetrics.java 1.17 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.util.*;
031:
032: /**
033: * A font metrics object for a WServer font.
034: *
035: * @version 1.6, 10/18/01
036: */
037: class X11FontMetrics extends FontMetrics {
038: private static native void initIDs();
039:
040: private static Map XFontMap;
041: static {
042: initIDs();
043: XFontMap = new HashMap(21);
044: /* Table to map magic 5 names * styles to X Fonts
045: * To internationalize simply comma seperate further necessary fonts and ensure
046: * the appropriate chartobyte convertors are supplied with String() the rest will
047: * automatically happen
048: */
049:
050: XFontMap.put("serif.0", "adobe-times-medium-r-*--*-%d-*");
051: XFontMap.put("serif.2", "-adobe-times-medium-i-*--*-%d-*");
052: XFontMap.put("serif.1", "-adobe-times-bold-r-*--*-%d-*");
053: XFontMap.put("serif.3", "-adobe-times-bold-i-*--*-%d-*");
054: XFontMap.put("sansserif.0",
055: "-adobe-helvetica-medium-r-normal--*-%d-*");
056: XFontMap.put("sansserif.2",
057: "-adobe-helvetica-medium-i-normal--*-%d-*");
058: XFontMap.put("sansserif.1",
059: "-adobe-helvetica-bold-r-normal--*-%d-*");
060: XFontMap.put("sansserif.3",
061: "-adobe-helvetica-bold-i-normal--*-%d-*");
062: XFontMap.put("monospaced.0",
063: "-adobe-courier-medium-r-*--*-%d-*");
064: XFontMap.put("monospaced.2",
065: "-adobe-courier-medium-i-*--*-%d-*");
066: XFontMap.put("monospaced.1", "-adobe-courier-bold-r-*--*-%d-*");
067: XFontMap.put("monospaced.3", "-adobe-courier-bold-i-*--*-%d-*");
068: XFontMap.put("dialog.0",
069: "-adobe-helvetica-medium-r-normal--*-%d-*");
070: XFontMap.put("dialog.2",
071: "-adobe-helvetica-medium-i-normal--*-%d-*");
072: XFontMap.put("dialog.1",
073: "-adobe-helvetica-bold-r-normal--*-%d-*");
074: XFontMap.put("dialog.3",
075: "-adobe-helvetica-bold-i-normal--*-%d-*");
076: XFontMap.put("dialoginput.0",
077: "-adobe-courier-medium-r-*--*-%d-*");
078: XFontMap.put("dialoginput.2",
079: "-adobe-courier-medium-i-*--*-%d-*");
080: XFontMap
081: .put("dialoginput.1", "-adobe-courier-bold-r-*--*-%d-*");
082: XFontMap
083: .put("dialoginput.3", "-adobe-courier-bold-i-*--*-%d-*");
084: XFontMap.put("default", "-adobe-courier-medium-r-*--*-%d-*");
085: }
086: /**
087: * The standard ascent of the font. This is the logical height
088: * above the baseline for the Alphanumeric characters and should
089: * be used for determining line spacing. Note, however, that some
090: * characters in the font may extend above this height.
091: */
092: int ascent;
093: /**
094: * The standard descent of the font. This is the logical height
095: * below the baseline for the Alphanumeric characters and should
096: * be used for determining line spacing. Note, however, that some
097: * characters in the font may extend below this height.
098: */
099: int descent;
100: /**
101: * The standard leading for the font. This is the logical amount
102: * of space to be reserved between the descent of one line of text
103: * and the ascent of the next line. The height metric is calculated
104: * to include this extra space.
105: */
106: int leading;
107: /**
108: * The standard height of a line of text in this font. This is
109: * the distance between the baseline of adjacent lines of text.
110: * It is the sum of the ascent+descent+leading. There is no
111: * guarantee that lines of text spaced at this distance will be
112: * disjoint; such lines may overlap if some characters overshoot
113: * the standard ascent and descent metrics.
114: */
115: int height;
116: /**
117: * The maximum ascent for all characters in this font. No character
118: * will extend further above the baseline than this metric.
119: */
120: int maxAscent;
121: /**
122: * The maximum descent for all characters in this font. No character
123: * will descend further below the baseline than this metric.
124: */
125: int maxDescent;
126: /**
127: * The maximum possible height of a line of text in this font.
128: * Adjacent lines of text spaced this distance apart will be
129: * guaranteed not to overlap. Note, however, that many paragraphs
130: * that contain ordinary alphanumeric text may look too widely
131: * spaced if this metric is used to determine line spacing. The
132: * height field should be preferred unless the text in a given
133: * line contains particularly tall characters.
134: */
135: int maxHeight;
136: /**
137: * The maximum advance width of any character in this font.
138: */
139: int maxAdvance;
140: /* Native font handle */
141: int XFontSet;
142: private int[] widths;
143:
144: /**
145: * Loads XFontSet and sets up the Font Metric fields
146: */
147:
148: private native int pLoadFont(byte[] fontName);
149:
150: /**
151: * Calculate the metrics from the given WServer and font.
152: */
153: public X11FontMetrics(Font font) {
154: super (font);
155: /* Here I should load the right font */
156: String XLFD;
157: if ((XLFD = (String) XFontMap.get(font.getName().toLowerCase()
158: + "." + font.getStyle())) == null)
159: XLFD = (String) XFontMap.get("default");
160: StringBuffer newXLFD = new StringBuffer(30);
161: int idx1 = 0;
162: int idx2;
163: while ((idx2 = XLFD.indexOf("%d", idx1)) != -1) {
164: newXLFD.append(XLFD.substring(idx1, idx2));
165: newXLFD.append(Integer.toString(font.getSize() * 10));
166: idx1 = idx2 + 2;
167: }
168: newXLFD.append(XLFD.substring(idx1));
169: XFontSet = pLoadFont(newXLFD.toString().getBytes());
170: widths = new int[256];
171: byte[] byteCharacter = new byte[1];
172: int i;
173: for (i = 0; i < 128; i++) {
174: byteCharacter[0] = (byte) i;
175: widths[i] = bytesWidth(byteCharacter, 0, 1);
176: }
177: for (; i < widths.length; i++)
178: widths[i] = -1;
179: }
180:
181: static String[] getFontList() {
182: Vector fontNames = new Vector();
183: Iterator fonts = XFontMap.keySet().iterator();
184: int dotidx;
185: while (fonts.hasNext()) {
186: String fontname = (String) fonts.next();
187: if ((dotidx = fontname.indexOf('.')) == -1)
188: dotidx = fontname.length();
189: fontname = fontname.substring(0, dotidx);
190: if (!fontNames.contains(fontname))
191: fontNames.add(fontname);
192: }
193: String[] tmpFontNames = new String[fontNames.size()];
194: System.arraycopy(fontNames.toArray(), 0, tmpFontNames, 0,
195: tmpFontNames.length);
196: return tmpFontNames;
197: }
198:
199: /**
200: * Get leading
201: */
202: public int getLeading() {
203: return leading;
204: }
205:
206: /**
207: * Get ascent.
208: */
209: public int getAscent() {
210: return ascent;
211: }
212:
213: /**
214: * Get descent
215: */
216: public int getDescent() {
217: return descent;
218: }
219:
220: /**
221: * Get height
222: */
223: public int getHeight() {
224: return height;
225: }
226:
227: /**
228: * Get maxAscent
229: */
230: public int getMaxAscent() {
231: return maxAscent;
232: }
233:
234: /**
235: * Get maxDescent
236: */
237: public int getMaxDescent() {
238: return maxDescent;
239: }
240:
241: /**
242: * Get maxAdvance
243: */
244: public int getMaxAdvance() {
245: return maxAdvance;
246: }
247:
248: /**
249: * Fast lookup of first 127 chars as these are always the same eg. ASCII charset.
250: */
251:
252: public int charWidth(char c) {
253: if (c < 128)
254: return widths[c];
255: char[] ca = new char[1];
256: ca[0] = c;
257: return stringWidth(new String(ca));
258: }
259:
260: /**
261: * Return the width of the specified string in this Font.
262: */
263: public int stringWidth(String string) {
264: byte[] tmpbarr = string.getBytes();
265: return pBytesWidth(XFontSet, tmpbarr, 0, tmpbarr.length);
266: }
267:
268: /**
269: * Return the width of the specified char[] in this Font.
270: */
271: public int charsWidth(char chars[], int offset, int length) {
272: String tmpstr = new String(chars).substring(offset, length);
273: byte[] tmpbarr = tmpstr.getBytes();
274: return pBytesWidth(XFontSet, tmpbarr, 0, tmpbarr.length);
275: }
276:
277: /**
278: * Return the width of the specified byte[] in this Font.
279: */
280: public int bytesWidth(byte data[], int offset, int len) {
281: return pBytesWidth(XFontSet, data, offset, len);
282: }
283:
284: private native int pBytesWidth(int fontSet, byte data[],
285: int offset, int len);
286:
287: /**
288: * Get the widths of the first 256 characters in the font.
289: */
290: public int[] getWidths() {
291: int[] newWidths = new int[widths.length];
292: System.arraycopy(widths, 0, newWidths, 0, newWidths.length);
293: return newWidths;
294: }
295:
296: private static Map table = new HashMap();
297: // fix for 4187686 Several class objects are used for synchronization
298: private static Object classLock = new Object();
299:
300: static X11FontMetrics getFontMetrics(Font font) {
301: // fix for 4187686 Several class objects are used for synchronization
302: synchronized (classLock) {
303: X11FontMetrics fm = (X11FontMetrics) table.get(font);
304: if (fm == null) {
305: table.put(font, fm = new X11FontMetrics(font));
306: }
307: return fm;
308: }
309: }
310: }
|