All Downloads are FREE. Search and download functionalities are using the official Maven repository.

echopointng.util.FontKit Maven / Gradle / Ivy

Go to download

Echo2 bundled with Echo2_Extras, Echo2_FileTransfer and echopointing and various improvements/bugfixes

There is a newer version: 2.0.4
Show newest version
package echopointng.util;
/* 
 * This file is part of the Echo Point Project.  This project is a collection
 * of Components that have extended the Echo Web Application Framework.
 *
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 */

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import nextapp.echo2.app.Component;
import nextapp.echo2.app.Extent;
import nextapp.echo2.app.Font;

import echopointng.util.collections.ConcurrentReaderHashMap;

/**
 * A utility to class to help with Font manipulation
 *
 * @author Brad Baker 
 */
public class FontKit {

	/* our static cache of Font objects by Font String representation */ 
	private static Map fontMap = new ConcurrentReaderHashMap();
	
   private static final Map FONTSTYLE_TEXT_TO_CONSTANT;
    static {
        Map constantMap = new HashMap();
        constantMap.put("PLAIN", new Integer(Font.PLAIN));
        constantMap.put("FONT.PLAIN", new Integer(Font.PLAIN));
        constantMap.put("BOLD", new Integer(Font.BOLD));
        constantMap.put("FONT.BOLD", new Integer(Font.BOLD));
        constantMap.put("ITALIC", new Integer(Font.ITALIC));
        constantMap.put("FONT.ITALIC", new Integer(Font.ITALIC));
        constantMap.put("LINETHROUGH", new Integer(Font.LINE_THROUGH));
        constantMap.put("FONT.LINETHROUGH", new Integer(Font.LINE_THROUGH));
        constantMap.put("OVERLINE", new Integer(Font.OVERLINE));
        constantMap.put("FONT.OVERLINE", new Integer(Font.OVERLINE));
        constantMap.put("UNDERLINE", new Integer(Font.UNDERLINE));
        constantMap.put("FONT.UNDERLINE", new Integer(Font.UNDERLINE));
        FONTSTYLE_TEXT_TO_CONSTANT = Collections.unmodifiableMap(constantMap);
    }
    

    private static final Map TYPEFACE_TEXT_TO_CONSTANT;
    static {
        Map constantMap = new HashMap();
        constantMap.put("HELVETICA", Font.HELVETICA);
        constantMap.put("ARIAL", Font.ARIAL);
        constantMap.put("VERDANA", Font.VERDANA);
        constantMap.put("TIMES", Font.TIMES);
        constantMap.put("TIMES ROMAN", Font.TIMES_ROMAN);
        constantMap.put("TIMES NEW ROMAN", Font.TIMES_NEW_ROMAN);
        constantMap.put("COURIER", Font.COURIER);
        constantMap.put("COURIER NEW", Font.COURIER_NEW);
        TYPEFACE_TEXT_TO_CONSTANT = Collections.unmodifiableMap(constantMap);
    }

    
	/** not instantiable */
	private FontKit() {
	}
	
	/**
	 * Creates an AWT font object from a Echo font object.  This is
	 * useful for drawing on AWT images.
	 * 
	 * @param echoFont - the nextapp.echo2.app.Font object to convert
	 * @param awtDefaultFont - a default AWT font to use if the conversion cant be done.
	 * @return - a new java.awt.Font object base don echoFont.  
	 */
	public static java.awt.Font makeAwtFont(Font echoFont, java.awt.Font awtDefaultFont) {
		if (echoFont == null)
			return awtDefaultFont;
		else {
			int size = echoFont.getSize() == null ? 12 : echoFont.getSize().getValue();
			int style = 0;
			if (echoFont.isBold())
				style |= java.awt.Font.BOLD;
			if (echoFont.isItalic())
				style |= java.awt.Font.ITALIC;
			if (echoFont.isUnderline());
			if (style == 0)
				style = java.awt.Font.PLAIN;

			return new java.awt.Font(echoFont.getTypeface().getName(), style, size);
		}
	}
	
	/**
	 * Makes a W3C CSS font string in the special format
	 * 

* fontstyle, fontsize, fontnames *

* @param font - the font to represent as a W3C CSS string * @return the W3C CSS string represenation */ public static String makeCSSFont(Font font) { StringBuffer sb = new StringBuffer(); if (font.isBold()) sb.append("bold "); if (font.isItalic()) sb.append("italic "); if (font.isUnderline()) sb.append("underline "); sb.append(font.getSize()); sb.append(" "); int i = 0; Font.Typeface face = font.getTypeface(); while (face != null) { if (i > 0) sb.append(", "); sb.append("'"); sb.append(face.getName()); sb.append("'"); face = face.getAlternate(); i++; } return sb.toString(); } /** * Adds bold to a Component's font. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#addBold(Font) * * @param c - the component in question */ public static void addBold(Component c) { Font font = findFont(c); font = addBold(font); c.setFont(font); } /** * Adds italic to a Component's font. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#addItalic(Font) * * @param c - the component in question */ public static void addItalic(Component c) { Font font = findFont(c); c.setFont(addItalic(font)); } /** * Adds underline to a Component's font. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#addUnderline(Font) * * @param c - the component in question */ public static void addUnderline(Component c) { Font font = findFont(c); c.setFont(addUnderline(font)); } /** * Adds the specified style to a Component's font. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#addStyle(Font, int) * * @param c - the component in question */ public static void addStyle(Component c, int style) { Font font = findFont(c); c.setFont(addStyle(font,style)); } /** * Sets a component's font smaller or large by the specified * delta amount. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#addSize(Font, int) * * @param c - the component in question * @param sizeDelta - a positive or negative delta amount */ public static void addSize(Component c, int sizeDelta) { Font font = findFont(c); c.setFont(addSize(font,sizeDelta)); } /** * Sets Component's font to bold. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#setStyle(Font, int) * * @param c - the component in question */ public static void setBold(Component c) { Font font = findFont(c); c.setFont(setStyle(font, Font.BOLD)); } /** * Sets Component's font to italic. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#setStyle(Font, int) * * @param c - the component in question */ public static void setItalic(Component c) { Font font = findFont(c); c.setFont(setStyle(font, Font.ITALIC)); } /** * Sets Component's font to underline. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#setStyle(Font, int) * * @param c - the component in question */ public static void setUnderline(Component c) { Font font = findFont(c); c.setFont(setStyle(font, Font.UNDERLINE)); } /** * Sets the size of a Component's font. *

* If the component has no font, a findFont is performed and * the result is set in as the font. *

* @see FontKit#setSize(Font, int) * * @param c - the component in question * @param size - the new font size */ public static void setSize(Component c, int size) { Font font = findFont(c); c.setFont(addSize(font,size)); } /** * Searchs the heirarchy tree of the component and finds the first * non null Font object. It will return Font(Font.SANS_SERIF,Font.PLAIN,new Extent(10,Extent.PT) * if no ancestor components have a Font set. * */ public static Font findFont(Component comp) { while (comp != null) { Font fnt = comp.getFont(); if (fnt != null) return fnt; comp = comp.getParent(); } return new Font(Font.SANS_SERIF,Font.PLAIN,new Extent(10,Extent.PT)); } /** * Returns the Font value of the given Font string representation. *

* The allowable forms are :

* - fontName,fontStyle,fontSize
* - font( fontName, fontStyle, fontSize)
*

* where *

* fontName - eg. Verdana or 'Times New Roman'. * If multiple font names are specified or there is * white space in the font name, then it must be enclosed * in single quotes and commas eg. 'Verdana, Times New Roman, Tahoma'. *
* fontStyle - PLAIN|BOLD|ITALIC|UNDERLINE|OVERLINE|LINETHROUGH or nothing! (this is case insenstive) *
* fontSize - an integer size value or an Extent value. (In the case where * only an integer is specified, the default Extent units * are points (pt). *

* Examples :
*

	 * 	Verdana,,9 									- is a legal font string
	 * 	Verdana,PLAIN,9 							- is a legal font string
	 * 	Verdana,plain,9 							- is a legal font string
	 * 	Verdana,plain,9em 							- is a legal font string
	 * 	Verdana,plain,9pt 							- is a legal font string
	 * 	Verdana,bold|italic,9						- is a legal font string
	 * 	'Times New Roman',plain,9 					- is a legal font string
	 * 	'Verdana, Times New Roman',plain,9 			- is a legal font string
	 * 
	 * 	font(Verdana,,9)							- is a legal font string
	 * 	font(Verdana,PLAIN,9pt)						- is a legal font string
	 * 	font(Verdana,plain,9)						- is a legal font string
	 * 	font(Verdana,bold|italic,9em)				- is a legal font string
	 * 	font('Verdana, Times New Roman',plain,9)	- is a legal font string
	 * 
	 * 	Verdana, 3, 9								- is an ILLEGAL font string
	 * 	Verdana, Times New Roman,PLAIN,9			- is an ILLEGAL font string
	 * 	font(Verdana, 3, 9)							- is an ILLEGAL font string
	 * 	font(Verdana, Times New Roman,PLAIN,9)		- is an ILLEGAL font string
	 * 
*

* The results of this operations is cached in a global static * cache, so that Font objects can be re-used. This is okay * since Font objects are immutable once created. * * @param fontString - the font string in question * @return a new Font object * @throws IllegalArgumentException - if the fontString is in an invalid format */ public static Font makeFont(String fontString) { if (fontString == null) throw new IllegalArgumentException("The fontString must be non null"); Font font = _getCachedFont(fontString); if (font != null) return font; if (! isFont(fontString)) throw new IllegalArgumentException("The font string is invalid : " + fontString); int index = 0; String tokens[] = TokenizerKit.tokenize(fontString, "(,)|"); if (fontString.indexOf("font(") == 0) index = 1; // font names String fontName = tokens[index].trim(); Font.Typeface fontNameVal = makeTypeface(fontName); // font styles int fontStyleVal = 0; String fontStyleString = tokens[++index]; for (int i = index; i < tokens.length; i++) { fontStyleString = tokens[i].trim(); if (_isInteger(fontStyleString) || ExtentKit.isExtent(fontStyleString)) break; String arr[] = TokenizerKit.tokenize(fontStyleString,"|"); for (int j = 0; j < arr.length; j++) { fontStyleString = arr[j].trim(); int k = _getFontStyle(fontStyleString); if (k >= 0) { fontStyleVal |= k; } } } // font size String fontSize = fontStyleString; Font newFont; if (ExtentKit.isExtent(fontSize)) { newFont = new Font(fontNameVal, fontStyleVal, ExtentKit.makeExtent(fontSize)); } else { int fontSizeVal = Integer.parseInt(fontSize); newFont = new Font(fontNameVal, fontStyleVal, new Extent(fontSizeVal,Extent.PT)); } return _putCachedFont(fontString, newFont); } /** * Shortcut synonym for makeFont(fontString); *

* @see FontKit#makeFont(String) */ public static Font font(String fontString) { return makeFont(fontString); } /** * Returns true if the fontString is a valid * representation of a Font value. *

* The allowable forms are :

* - fontName,fontStyle,fontSize
* - font( fontName, fontStyle, fontSize)
*

* where *

* fontName - eg. Verdana or 'Times New Roman'. * If multiple font names are specified or there is * white space in the font name, then it must be enclosed * in single quotes and commas eg. 'Verdana, Times New Roman, Tahoma'. *
* fontStyle - PLAIN|BOLD|ITALIC|UNDERLINE|OVERLINE|LINETHROUGH or nothing! (this is case insenstive) *
* fontSize - an integer size value or an Extent value. (In the case where * only an integer is specified, the default Extent units * are points (pt). *

* Examples :
*

	 * 	Verdana,,9 									- is a legal font string
	 * 	Verdana,PLAIN,9 							- is a legal font string
	 * 	Verdana,plain,9 							- is a legal font string
	 * 	Verdana,bold|italic,9						- is a legal font string
	 * 	'Times New Roman',plain,9 					- is a legal font string
	 * 	'Verdana, Times New Roman',plain,9 			- is a legal font string
	 * 
	 * 	font(Verdana,,9)							- is a legal font string
	 * 	font(Verdana,PLAIN,9)						- is a legal font string
	 * 	font(Verdana,plain,9)						- is a legal font string
	 * 	font(Verdana,bold|italic,9)					- is a legal font string
	 * 	font('Verdana, Times New Roman',plain,9)	- is a legal font string
	 * 
	 * 	Verdana, 3, 9								- is an ILLEGAL font string
	 * 	Verdana, Times New Roman,PLAIN,9			- is an ILLEGAL font string
	 * 	font(Verdana, 3, 9)							- is an ILLEGAL font string
	 * 	font(Verdana, Times New Roman,PLAIN,9)		- is an ILLEGAL font string
	 * 
* * @param fontString - the font string representation to check * @return true if the string is in the correct format */ public static boolean isFont(String fontString) { if (fontString == null) return false; int index = 0; String tokens[] = TokenizerKit.tokenize(fontString, "(,)|"); if (fontString.indexOf("font(") == 0) index = 1; if (tokens.length < 2) return false; // font name is ok. Technically anything is OK // font styles String font = tokens[++index]; for (;index < tokens.length; index++) { font = tokens[index].trim(); if (_isInteger(font) || ExtentKit.isExtent(font)) break; String arr[] = TokenizerKit.tokenize(font,"|"); for (int i = 0; i < arr.length; i++) { font = arr[i].trim(); if (_getFontStyle(font) == -1) { return false; } } } // font size String fontSize = font; if (! ExtentKit.isExtent(fontSize)) { if (!_isInteger(fontSize)) return false; } if (index != tokens.length-1) return false; return true; } /** * This will return a Font.Typeface object by first rtying to match * the names against System provided ones and failing that it will * create a font.Typeface for you. *

* Multi named type faces must be encluded in spaces. *

* Valid typeface name forms are : *

	 * 'Font1, Font 2, Font2'
	 * 'Font1'
	 * Font1
	 * 
	 * 
	 * @param typeFaceNames - the name(s) of the intended typeface
	 */
	public static Font.Typeface makeTypeface(String typeFaceNames) {
		if (typeFaceNames.charAt(0) == '\'' && typeFaceNames.charAt(typeFaceNames.length()-1) == '\'') {
			typeFaceNames = typeFaceNames.substring(1,typeFaceNames.length()-1);
		}
		String[] tokens = TokenizerKit.tokenizeStrict(typeFaceNames,",");
		if (tokens.length == 0)
			return null;
		Font.Typeface typeFace;
		typeFace = getSystemTypeface(tokens[0].toUpperCase());
		//
		// if we have only one token and it matches a System
		// Typeface, then we will go with it
		if (tokens.length == 1 && typeFace != null) {
			return typeFace;
		} else {
			if (_exactMatchingTypeFace(typeFace,tokens)) {
				return typeFace;
			} else {
				typeFace = null;
				for (int i = tokens.length-1; i >= 0; i--) {
					typeFace = new Font.Typeface(tokens[i],typeFace);
				}
				return typeFace;
			}
		}
	}

	/*
	 * Returns true if the type face provided exactly matches the list of font names
	 */
	private static boolean _exactMatchingTypeFace(Font.Typeface typeFace, String[] fontNames) {
		if (typeFace == null)
			return false;
		int i = 0;
		while (typeFace != null) {
			if (i >= fontNames.length)
				return false;
			if (! fontNames[i].equalsIgnoreCase(typeFace.getName())) {
				return false;
			}
			typeFace = typeFace.getAlternate();
			i++;
		}
		return true;
	}

	/*
	 * Gets a Font from the cache if its matches the font string
	 * It may be null if is not been cached.  The strings are
	 * always stored in lower case for consistency
	 */
	private static Font _getCachedFont(String fontString) {
		fontString = fontString.trim().toLowerCase();
		Font font = (Font) fontMap.get(fontString);
		return font;
	}
	
	/*
	 * Puts a Font into the shared cache and then returns it
	 */
	private static Font _putCachedFont(String fontString, Font font) {
		fontString = fontString.trim().toLowerCase();
		fontMap.put(fontString, font);
		return font;
	}
	 
	
	/*
	 * Well is it an integer?
	 */
	private static boolean _isInteger(String propertyValue) {
		try {
			Integer.parseInt(propertyValue.trim());
		} catch (NumberFormatException nfe) {
			return false;
		}
		return true;
	}

	/**
	 * Makes a string representation of a font in the format
	 * 

* font(fontName, fontStyle, fontSize) *

* where : *

* fontName - is a font name such as 'Verdana' or 'Times New Roman'. * fontStyle - PLAIN|BOLD|ITALIC|UNDERLINE * fontSize - an integer size value or an Extent value. (In the case where * only an integer is specified, the default Extent units * are points (pt). * * @param font - the font to make into a String representation * @return the string representation of the font */ public static String makeFontString(Font font) { return _buildFontString(font.getTypeface(),_getStyle(font),font.getSize()); } /** * Returns one the standard Echo Font.Typefaces if the name string * matches the first Typeface in the chain. * * @param name - the font typeface name to match. * @return a TypeFace of null if a system one cannot be found */ public static Font.Typeface getSystemTypeface(String name) { if (TYPEFACE_TEXT_TO_CONSTANT.containsKey(name.toUpperCase())) { return (Font.Typeface) TYPEFACE_TEXT_TO_CONSTANT.get(name.toUpperCase()); } else { return null; } } /* * Returns a font style integer value of -1 if it cant be found */ private static int _getFontStyle(String styleName) { Integer styleInt = (Integer) FONTSTYLE_TEXT_TO_CONSTANT.get(styleName.toUpperCase()); if (styleInt == null) return -1; return styleInt.intValue(); } /* * Builds a Font string from the given font attributes, This * can then be used for font caching etc.. as well as returned * as a Font String representation * */ private static String _buildFontString(Font.Typeface typeFace, int style, Extent sizeExtent) { StringBuffer sb = new StringBuffer(); sb.append("font("); int i = 0; while (typeFace != null) { if (i > 0) sb.append(", "); else sb.append("'"); sb.append(typeFace.getName()); i++; typeFace = typeFace.getAlternate(); if (typeFace == null) sb.append("'"); } boolean isplain = true; boolean needsOr = false; sb.append(","); if ((style & Font.BOLD) == Font.BOLD) { if (needsOr) sb.append("|"); sb.append("BOLD"); needsOr = true; isplain = false; } if ((style & Font.ITALIC) == Font.ITALIC) { if (needsOr) sb.append("|"); sb.append("ITALIC"); needsOr = true; isplain = false; } if ((style & Font.UNDERLINE) == Font.UNDERLINE) { if (needsOr) sb.append("|"); sb.append("UNDERLINE"); needsOr = true; isplain = false; } if ((style & Font.OVERLINE) == Font.OVERLINE) { if (needsOr) sb.append("|"); sb.append("OVERLINE"); needsOr = true; isplain = false; } if ((style & Font.LINE_THROUGH) == Font.LINE_THROUGH) { if (needsOr) sb.append("|"); sb.append("LINETHROUGH"); needsOr = true; isplain = false; } if (isplain) sb.append("PLAIN"); if (sizeExtent != null) { sb.append(","); sb.append(sizeExtent.toString()); } sb.append(")"); return sb.toString(); } /* * Builds a Font object from a valid font string, which is * then cached in our global Font cache. */ private static Font _buildFontObj(Font.Typeface typeface, int style, Extent sizeExtent) { String fontString = _buildFontString(typeface,style,sizeExtent); return makeFont(fontString); } /* * Adds style bits to an exisitng font */ static private int _addFontStyle(Font font, int newStyle) { int style = Font.PLAIN; if (font.isBold()) style |= Font.BOLD; if (font.isItalic()) style |= Font.ITALIC; if (font.isUnderline()) style |= Font.UNDERLINE; style |= newStyle; return style; } /* * Returns the style bits of the font. */ static private int _getStyle(Font font) { return _addFontStyle(font,0); } /** * Adds the Font.BOLD attribute to an exisitng Font object * and returns a new Font. *

* @param font - the font in question * @return - a new Font object */ public static Font addBold(Font font) { return addStyle(font,Font.BOLD); } /** * Adds the Font.ITALIC attribute to an exisitng Font object * and returns a new Font. *

* @param font - the font in question * @return - a new Font object */ public static Font addItalic(Font font) { if (font == null) return null; return addStyle(font,Font.ITALIC); } /** * Adds the Font.UNDERLINE attribute to an exisitng Font object * and returns a new Font. *

* @param font - the font in question * @return - a new Font object */ public static Font addUnderline(Font font) { return addStyle(font,Font.UNDERLINE); } /** * Adds the specified style to the Font * and returns a new Font. *

* @param font - the font in question * @param style - the new font style to added to the font * @return - a new Font object */ public static Font addStyle(Font font, int style) { if (font == null) return null; return _buildFontObj(font.getTypeface(),_addFontStyle(font, style),font.getSize()); } /** * Makes a font smaller or larger by adding the specified amount to * its current font size. The Font is made smaller if a negative * value is used. * * @param font - the font in question * @param sizeDelta - the size delta to add to the current size * @return - a new Font object * */ public static Font addSize(Font font, int sizeDelta) { if (font == null) return null; Extent now = font.getSize(); if (now != null) now = new Extent(now.getValue()+sizeDelta, now.getUnits()); return _buildFontObj(font.getTypeface(),_getStyle(font),now); } /** * Returns a new Font object, based on font, that * has the specified size. * * @param font - the font to use as a template * @param size - the new size * @return a new Font object with the new size */ public static Font setSize(Font font, int size) { if (font == null) return null; Extent now = font.getSize(); if (now != null) now = new Extent(size, now.getUnits()); return _buildFontObj(font.getTypeface(),_getStyle(font),now); } /** * Returns a new Font object, based on font, that * has the specified style. * * @param font - the font to use as a template * @param style - the new style * @return a new Font object with the new style */ public static Font setStyle(Font font, int style) { if (font == null) return null; return _buildFontObj(font.getTypeface(),style,font.getSize()); } /** * Returns a new Font object, based on font, that * has the specified typeFace. * * @param font - the font to use as a template * @param typeFace - the new TypeFace to use * @return a new Font object with the new font names */ public static Font setNames(Font font, Font.Typeface typeFace) { if (font == null) return null; return _buildFontObj(typeFace,_getStyle(font),font.getSize()); } /** * Returns a new Font object, based on font, that * has the specified fontName. *

* If fontName has whitespace in it, then * you need to surround it in single quotes. * * @param font - the font to use as a template * @param fontName - the new font name to use * @return a new Font object with the new font name */ public static Font setName(Font font, String fontName) { if (font == null) return null; Font.Typeface typeFace = makeTypeface(fontName); return _buildFontObj(typeFace,_getStyle(font),font.getSize()); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy