/*
* @(#)MWFontMetrics.java 1.25 06/10/10
*
* Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 only, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License version 2 for more details (a copy is
* included at /legal/license.txt).
*
* You should have received a copy of the GNU General Public License
* version 2 along with this work; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 or visit www.sun.com if you need additional
* information or have any questions.
*
*/
package java.awt;
import java.io.*;
import java.security.*;
import java.util.*;
/**
* A font metrics object for a font.
*
* @version 1.19, 08/19/02
*/
class MWFontMetrics extends FontMetrics {
// serialVersionUID - 4683929
static final long serialVersionUID = -4956160226949100590L;
/** A map which maps from Java logical font names and styles to native font names. */
private static Map fontNameMap;
private static native void initIDs();
static {
initIDs();
String s = File.separator;
String javaHome = (String) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return System.getProperty("java.home");
}
}
);
//dir += s + "lib" + s + "fonts";
File f = new File(javaHome, "lib" + s + "fonts");
String dir = f.getAbsolutePath();
fontNameMap = new HashMap(24);
/* Initialise table to map standard Java font names and styles to TrueType Fonts */
fontNameMap.put("serif.0", dir + s + "LucidaBrightRegular.ttf");
fontNameMap.put("serif.1", dir + s + "LucidaBrightDemiBold.ttf");
fontNameMap.put("serif.2", dir + s + "LucidaBrightItalic.ttf");
fontNameMap.put("serif.3", dir + s + "LucidaBrightDemiItalic.ttf");
fontNameMap.put("sansserif.0", dir + s + "LucidaSansRegular.ttf");
fontNameMap.put("sansserif.1", dir + s + "LucidaSansDemiBold.ttf");
fontNameMap.put("sansserif.2", dir + s + "LucidaSansOblique.ttf");
fontNameMap.put("sansserif.3", dir + s + "LucidaSansDemiOblique.ttf");
fontNameMap.put("monospaced.0", dir + s + "LucidaTypewriterRegular.ttf");
fontNameMap.put("monospaced.1", dir + s + "LucidaTypewriterBold.ttf");
fontNameMap.put("monospaced.2", dir + s + "LucidaTypewriterOblique.ttf");
fontNameMap.put("monospaced.3", dir + s + "LucidaTypewriterBoldOblique.ttf");
fontNameMap.put("dialog.0", dir + s + "LucidaSansRegular.ttf");
fontNameMap.put("dialog.1", dir + s + "LucidaSansDemiBold.ttf");
fontNameMap.put("dialog.2", dir + s + "LucidaSansOblique.ttf");
fontNameMap.put("dialog.3", dir + s + "LucidaSansDemiOblique.ttf");
fontNameMap.put("dialoginput.0", dir + s + "LucidaTypewriterRegular.ttf");
fontNameMap.put("dialoginput.1", dir + s + "LucidaTypewriterBold.ttf");
fontNameMap.put("dialoginput.2", dir + s + "LucidaTypewriterOblique.ttf");
fontNameMap.put("dialoginput.3", dir + s + "LucidaTypewriterBoldOblique.ttf");
/* This should always exist and is used for fonts whose name is not any of the above. */
fontNameMap.put("default.0", dir + s + "LucidaSansRegular.ttf");
fontNameMap.put("default.1", dir + s + "LucidaSansDemiBold.ttf");
fontNameMap.put("default.2", dir + s + "LucidaSansOblique.ttf");
fontNameMap.put("default.3", dir + s + "LucidaSansDemiOblique.ttf");
}
/**
* The standard ascent of the font. This is the logical height
* above the baseline for the Alphanumeric characters and should
* be used for determining line spacing. Note, however, that some
* characters in the font may extend above this height.
*/
int ascent;
/**
* The standard descent of the font. This is the logical height
* below the baseline for the Alphanumeric characters and should
* be used for determining line spacing. Note, however, that some
* characters in the font may extend below this height.
*/
int descent;
/**
* The standard leading for the font. This is the logical amount
* of space to be reserved between the descent of one line of text
* and the ascent of the next line. The height metric is calculated
* to include this extra space.
*/
int leading;
/**
* The standard height of a line of text in this font. This is
* the distance between the baseline of adjacent lines of text.
* It is the sum of the ascent+descent+leading. There is no
* guarantee that lines of text spaced at this distance will be
* disjoint; such lines may overlap if some characters overshoot
* the standard ascent and descent metrics.
*/
int height;
/**
* The maximum ascent for all characters in this font. No character
* will extend further above the baseline than this metric.
*/
int maxAscent;
/**
* The maximum descent for all characters in this font. No character
* will descend further below the baseline than this metric.
*/
int maxDescent;
/**
* The maximum possible height of a line of text in this font.
* Adjacent lines of text spaced this distance apart will be
* guaranteed not to overlap. Note, however, that many paragraphs
* that contain ordinary alphanumeric text may look too widely
* spaced if this metric is used to determine line spacing. The
* height field should be preferred unless the text in a given
* line contains particularly tall characters.
*/
int maxHeight;
/**
* The maximum advance width of any character in this font.
*/
int maxAdvance;
/** Native font handle */
int nativeFont;
/** Cache of first 256 Unicode characters as these map to ASCII characters and are often used. */
private int[] widths;
/**
* Loads MicroWindows Font and sets up the Font Metric fields
*/
private native int pLoadFont(String fontName, int fontHeight);
private static native void pDestroyFont(int nativeFont);
private static native int pCharWidth(int nativeFont, char c);
private static native int pCharsWidth(int nativeFont, char chars[], int offset, int len);
private static native int pStringWidth(int nativeFont, String string);
/** A map which maps a native font name and size to a font metrics object. This is used
as a cache to prevent loading the same fonts multiple times. */
private static Map fontMetricsMap = new HashMap();
/** Gets the MWFontMetrics object for the supplied font. This method caches font metrics
to ensure native fonts are not loaded twice for the same font. */
static synchronized MWFontMetrics getFontMetrics(Font font) {
/* See if metrics has been stored in font already. */
MWFontMetrics fm = (MWFontMetrics) font.metrics;
if (fm == null) {
/* See if a font metrics of the same native name and size has already been loaded.
If it has then we use that one. */
String nativeName = (String) fontNameMap.get(font.name.toLowerCase() + "." + font.style);
if (nativeName == null)
nativeName = (String) fontNameMap.get("default." + font.style);
String key = nativeName + "." + font.size;
fm = (MWFontMetrics) fontMetricsMap.get(key);
if (fm == null) {
fontMetricsMap.put(key, fm = new MWFontMetrics(font, nativeName));
}
font.metrics = fm;
}
return fm;
}
/**
* Creates a font metrics for the supplied font. To get a font metrics for a font
* use the static method getFontMetrics instead which does caching.
*/
private MWFontMetrics(Font font, String nativeName) {
super(font);
nativeFont = pLoadFont(nativeName, font.size);
/* Cache first 256 char widths for use by the getWidths method and for faster metric
calculation as they are commonly used (ASCII) characters. */
widths = new int[256];
int i;
for (i = 0; i < 256; i++) {
widths[i] = pCharWidth(nativeFont, (char) i);
}
}
static String[] getFontList() {
Vector fontNames = new Vector();
Iterator fonts = fontNameMap.keySet().iterator();
int dotidx;
while (fonts.hasNext()) {
String fontname = (String) fonts.next();
if ((dotidx = fontname.indexOf('.')) == -1)
dotidx = fontname.length();
fontname = fontname.substring(0, dotidx);
if (!fontNames.contains(fontname))
fontNames.add(fontname);
}
String[] tmpFontNames = new String[fontNames.size()];
System.arraycopy(fontNames.toArray(), 0, tmpFontNames, 0, tmpFontNames.length);
return tmpFontNames;
}
/**
* Get leading
*/
public int getLeading() {
return leading;
}
/**
* Get ascent.
*/
public int getAscent() {
return ascent;
}
/**
* Get descent
*/
public int getDescent() {
return descent;
}
/**
* Get height
*/
public int getHeight() {
return height;
}
/**
* Get maxAscent
*/
public int getMaxAscent() {
return maxAscent;
}
/**
* Get maxDescent
*/
public int getMaxDescent() {
return maxDescent;
}
/**
* Get maxAdvance
*/
public int getMaxAdvance() {
return maxAdvance;
}
/**
* Fast lookup of first 256 chars as these are always the same eg. ASCII charset.
*/
public int charWidth(char c) {
if (c < 256)
return widths[c];
return pCharWidth(nativeFont, c);
}
/**
* Return the width of the specified string in this Font.
*/
public int stringWidth(String string) {
return pStringWidth(nativeFont, string);
}
/**
* Return the width of the specified char[] in this Font.
*/
public int charsWidth(char chars[], int offset, int length) {
return pCharsWidth(nativeFont, chars, offset, length);
}
/**
* Get the widths of the first 256 characters in the font.
*/
public int[] getWidths() {
int[] newWidths = new int[256];
System.arraycopy(widths, 0, newWidths, 0, 256);
return newWidths;
}
protected void finalize() throws Throwable {
pDestroyFont(nativeFont);
super.finalize();
}
}