package MDUtils; /* * FontUtils.java * * Created on February 9, 2003, 12:53 PM * * Modified Feb. 11, 2003. */ import java.awt.Font; import java.awt.GraphicsEnvironment; import java.util.List; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; /** Static methods for choosing and modifying fonts. * * @author dickey */ public class FontUtils { /** A list of font names. These may or may not be available on any given * computer. The names are listed in order of preference, starting from zero. */ public static final String[] defaultPreferredFonts = new String[] { "Code2000", "Arial Unicode MS", "Bitstream Cyberbit", "Batang", "MS Mincho", "SansSerif", "Default"}; /** Select a Unicode Font, from a named font or from a default list of preferred fonts. * @return the requested font, if available, otherwise, the first available one in the default list of preferred fonts. Will never return null. */ public static Font setUnicodeFont(String fontName) { return setUnicodeFont(new String[] {fontName}); } /** Select an available Unicode Font, from a default list of preferred fonts. * @return a Unicode Font: the first available one in the list of preferred fonts. Will never return null. */ public static Font setUnicodeFont( ) { assert defaultPreferredFonts != null; return setUnicodeFont(defaultPreferredFonts); } /** Select an available Unicode Font, from a list of preferred fonts. * @return a Unicode Font: the first available one in the requested list of preferred fonts.; failing that, the first in the list of defaults. Will never return null. */ public static Font setUnicodeFont(String[] fontNames) { Font uniFont = null; if (fontNames != null) { int currF = 0; //index into font names table while (uniFont == null && currF < fontNames.length) { String thisName = fontNames[currF]; if (thisName == null) { //throw new IllegalArgumentException("null font name in array."); System.out.println("Argument error? null font name in array."); } else { if (isAvailableFont(thisName) || isFontFamilyName(thisName) || isLogicalFontName(thisName)) { uniFont = new Font(thisName, Font.BOLD, 24); assert 0 == uniFont.getName().compareToIgnoreCase(fontNames[currF]); } } currF++; } } if (uniFont == null && fontNames != defaultPreferredFonts) { //note: that was one case where == (or !=) is correct, instead of equals. uniFont = setUnicodeFont(defaultPreferredFonts); //use defaults only } assert uniFont != null; return uniFont; //end setUnicodeFont } /** Find out which fonts installed on the system can display a particular * character. * @return a list of the fonts. */ public static List getGoodFontsForChar(char testchar) { return getGoodFontsForString(testchar); } /** Find out which fonts installed on the system can display a particular * character. * @return a list of the fonts. */ public static List getGoodFontsForString(char testchar) { return getGoodFontsForString("" + testchar); } /** See if a font occurs on this system. * @param fname the name of a font. * @return true iff a font with that name is available on the system. */ public static boolean isAvailableFont(String fName) { Font[] allFonts = getSystemFonts(); for (int f = 0; f < allFonts.length; f++) { if (0 == fName.compareTo(allFonts[f].getFontName())) { return true; } } return false; } /** See if a string is the name of a font family on this system. */ public static boolean isFontFamilyName(String fName) { String[] fNames = getFontFamilyNames(); //List allFonts = Collections.asList(fNames); //return allFonts.contains(fName); for (int f = 0; f < fNames.length; f++) { if (0 == fName.compareTo(fNames[f])) { return true; } } return false; } /** See if a string is the name of a generic (logical) font. */ public static boolean isLogicalFontName(String fName) { String[] fNames = getLogicalFontNames(); for (int f = 0; f < fNames.length; f++) { if (0 == fName.compareTo(fNames[f])) { return true; } } return false; } /** @return an array of all system fonts. */ public static Font[] getSystemFonts() { GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font[] allFonts = g.getAllFonts(); //an array of all fonts on this system return allFonts; } /** @return an array of the names of all available font families.*/ public static String[] getFontFamilyNames() { GraphicsEnvironment g = GraphicsEnvironment.getLocalGraphicsEnvironment(); String[] allFonts = g.getAvailableFontFamilyNames(); //an array of all fonts on this system return allFonts; } /** @return an array of the names of all generic (logical) fonts. This list * is derived from the 1.4 Font Javadoc. */ public static String[] getLogicalFontNames() { return new String[] {"Serif", "SansSerif", "Monospaced", "Dialog", "DialogInput"}; } /** Find out which fonts installed on the system can display all the characters of a particular string. * @return a list of the fonts. */ public static List getGoodFontsForString(String testchars) { Font[] allFonts = getSystemFonts(); //an array of all fonts on this system List fontList = new java.util.LinkedList(); for (int i = 0; i < allFonts.length; i++) { Font f = allFonts[i]; int c = 0; //count chars which have succeeded for (c = 0; c < testchars.length(); c++) { if (!f.canDisplay(testchars.charAt(c))) { //no good break; //leave the loop } } // out of the inner for loop... why? assert c >=0 && c <= testchars.length(); if (c == testchars.length()) { //all characters were checked and found good boolean addStatus = fontList.add(f); assert addStatus == true; } } //end outer for return fontList; } //end Utest //NOTE: move from here after Project 3. Best would be MDUtils.MDStringUtils, //probably. //BUG: doesn't show leading zeros. /** Generate a string identifying the unicode hex value and block of the char. * @return a string containing the identifying information, with no leading * or trailing spaces, and not containing the character itself. */ public static String charUnicodeID(char c) { String retString = "u" + Integer.toHexString((int) c) + " in Unicode " + Character.UnicodeBlock.of(c) + " block"; return retString; } /** Generate a string showing the unicode hex value of each character * in the string. * @return a string containing the information for each character in sequence, in the same format at charUnicodeID(char), with ",\n\t" between each character, with { ... } around the whole, and no overall leading * or trailing spaces. */ public static String charUnicodeID(String uString) { String separator = ",\n\t"; StringBuffer retString = new StringBuffer(); for (int c = 0; c < uString.length(); c++) { retString.append(charUnicodeID(uString.charAt(c))); if (c < uString.length()-1) { retString.append(separator); } } if (uString.length() > 0) { retString.insert(0, '{'); retString.append('}'); } return retString.toString(); } /** Print a list of suitable fonts on System.out. * @param testCharacter This char must be printable in the font for the * font to be considered suitable. */ public static void testFontsAndReport(char testCharacter) { testFontsAndReport("" + testCharacter, System.out); } /** Print list of suitable fonts on System.out. For details, see * overloaded method descriptions. */ public static void testFontsAndReport(String testChars) { testFontsAndReport(testChars, System.out); } /** Print list of suitable fonts on a PrintStream (such as System.out). * @param outStream a PrintStream, which must non-null, or the report is not written. For more details, see * testFontsAndReport(String). */ public static void testFontsAndReport(String testChars, java.io.PrintStream outStream) { String report = testFontsAndFormatReport(testChars); if (outStream != null && !outStream.checkError()) { outStream.println(report); } } /** Prepare a report of suitable fonts. * @param testChars a string, each of whose characters must be printable in a font * if that font is to be considered printable. * @return a multi-line string, suitable for output as a report. * The report gives the orginal string, plus a list of the suitable fonts. */ public static String testFontsAndFormatReport(String testChars) { String separator = "\n\t\t"; //used to separate consecutive fonts StringBuffer retString = new StringBuffer(); //the eventual message to print List OKFonts = getGoodFontsForString(testChars); Iterator flistIter = OKFonts.iterator(); retString.append("Fonts which can display " + charUnicodeID(testChars) + ":"); if (flistIter.hasNext()) { while (flistIter.hasNext()) { Font f = (Font) flistIter.next(); Font f2 = f.deriveFont(20.0F); //new size //this is tricky. deriveFont has an overloaded method with an int param, for style //For size, param must be float -- not double, but float!! retString.append(separator + f2.getName()); } } else { retString.append("\tno suitable fonts found.\n"); } return retString.toString(); //end method } /** Helper for testing the setFont methods. */ public static void testSet(String[] fNames) { Font fresult = setUnicodeFont(fNames); System.out.print("\nRequested ["); for (int f = 0; f < fNames.length; f++) { System.out.print(fNames[f]); if (f < fNames.length-1) { System.out.print(", "); } } System.out.println("]"); System.out.println("Got: " + fresult.getName()); } /** Just for testing the setFont methods. */ public static void testSetDriver( ) { System.out.println("******* test font setting ******"); testSet(new String[]{"Batang", "Arial Unicode MS"}); testSet(new String[]{"no such font"}); testSet(new String[]{"nosuch 1", "nonexistence 2"}); testSet(new String[]{"default", "Serif", "serif"}); testSet(new String[]{"default", "serif", "Serif"}); testSet(new String[]{"default", "non exisiste", "miNGcho MS", "serif", "Serif"}); } /** Just for testing. */ public static void main(String args[]) { System.out.println("******* FontUtils test **********"); char testGreekUnassignedCharacter = '\u03a2'; testFontsAndReport(testGreekUnassignedCharacter); char testGreekCharacter = '\u03b2'; testFontsAndReport(testGreekCharacter); char testBrailleCharacter = '\u2800'; testFontsAndReport(testBrailleCharacter); char testCJKChar = '\u6c34'; //one CJK character to test the font against testFontsAndReport(testCJKChar); char testIPAChar = '\u0250'; testFontsAndReport(testIPAChar); char testRunicChar = '\u16A0'; testFontsAndReport(testRunicChar); char testMusicChar = (char) 0x1d100; //a plane 1 block -- not supported testFontsAndReport(testMusicChar); //will show up as Hangul (from Plane 0) testFontsAndReport(testBrailleCharacter + "" + (char) (testBrailleCharacter+1)); //testFontsAndReport("AZ"); //most or all fonts on system! //end main } // end class FontUtils }