/*
* Copyright (C) 2011 Cozycode.net
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.cozycode.swing.text;
import java.awt.Font;
import java.awt.GraphicsEnvironment;
import java.awt.Paint;
import java.awt.font.TextAttribute;
import java.awt.font.TransformAttribute;
import java.text.AttributedCharacterIterator.Attribute;
import java.util.HashMap;
import java.util.Map;
import net.cozycode.constructs.Tuple2;
public final class FontUtilities {
private FontUtilities() { /* Static Singleton */ }
////// GETTERS /////////////////////////////////////////////////
public static boolean isSet( Font font, Attribute attribute ) {
return font.getAttributes().containsKey( attribute );
}
public static String getFamily( Font font ) {
return font.getFamily();
}
public static Number getWeight( Font font ) {
return getAsNumber( font, TextAttribute.WEIGHT );
}
public static Number getSize( Font font ) {
return getAsNumber( font, TextAttribute.SIZE );
}
public static Number getWidth( Font font ) {
return getAsNumber( font, TextAttribute.WIDTH );
}
public static Number getPosture( Font font ) {
return getAsNumber( font, TextAttribute.POSTURE );
}
public static Number getUnderline( Font font ) {
return getAsNumber( font, TextAttribute.UNDERLINE );
}
public static Boolean getStrikethrough( Font font ) {
return getAsBoolean( font, TextAttribute.STRIKETHROUGH );
}
public static Number getSuperscript( Font font ) {
return getAsNumber( font, TextAttribute.SUPERSCRIPT );
}
public static Number getKerning( Font font ) {
return getAsNumber( font, TextAttribute.KERNING );
}
public static Number getTracking( Font font ) {
return getAsNumber( font, TextAttribute.TRACKING );
}
public static Number getLigatures( Font font ) {
return getAsNumber( font, TextAttribute.LIGATURES );
}
public static Boolean getSwapColors( Font font ) {
return getAsBoolean( font, TextAttribute.SWAP_COLORS );
}
public static Paint getForeground( Font font ) {
return getAsPaint( font, TextAttribute.FOREGROUND );
}
public static Paint getBackground( Font font ) {
return getAsPaint( font, TextAttribute.BACKGROUND );
}
public static Boolean getRunDirection( Font font ) {
return getAsBoolean( font, TextAttribute.RUN_DIRECTION );
}
public static TransformAttribute getTransform( Font font ) {
Object obj = font.getAttributes().get( TextAttribute.TRANSFORM );
return obj instanceof TransformAttribute ? (TransformAttribute)obj : null;
}
public static Number getBidiEmbedding( Font font, Attribute attribute ) {
return getAsNumber( font, TextAttribute.BIDI_EMBEDDING );
}
public static Number getAsNumber( Font font, Attribute attribute ) {
Object obj = font.getAttributes().get( attribute );
return obj instanceof Number ? (Number)obj : null;
}
public static Boolean getAsBoolean( Font font, Attribute attribute ) {
Object obj = font.getAttributes().get( attribute );
return obj instanceof Boolean ? (Boolean)obj : null;
}
public static Paint getAsPaint( Font font, Attribute attribute ) {
Object obj = font.getAttributes().get( attribute );
return obj instanceof Paint ? (Paint)obj : null;
}
////// SETTERS /////////////////////////////////////////////////
public static Font deriveFamily( Font font, String name ) {
return deriveFont( font, TextAttribute.FAMILY, name );
}
/**
* Derives a new font using the specified font weight.
* While any positive float value can be supplied,
* there are several default values are provided:
* <ul>
* <li>TextAttribute.WEIGHT_EXTRA_LIGHT</li>
* <li>TextAttribute.WEIGHT_LIGHT</li>
* <li>TextAttribute.WEIGHT_DEMILIGHT</li>
* <li>TextAttribute.WEIGHT_REGULAR</li>
* <li>TextAttribute.WEIGHT_SEMIBOLD</li>
* <li>TextAttribute.WEIGHT_MEDIUM</li>
* <li>TextAttribute.WEIGHT_DEMIBOLD</li>
* <li>TextAttribute.WEIGHT_BOLD</li>
* <li>TextAttribute.WEIGHT_HEAVY</li>
* <li>TextAttribute.WEIGHT_EXTRABOLD</li>
* <li>TextAttribute.WEIGHT_ULTRABOLD</li>
* </ul>
*
* @param font - The font to derive from
* @param weight - The weight of the derived font
* @return the derived font
*/
public static Font deriveWeight( Font font, Float weight ) {
return deriveFont( font, TextAttribute.WEIGHT, weight );
}
/**
* Derives a new font using the specified font width.
* while any positive float value can be supplied,
* there are several default values provided:
* <ul>
* <li>TextAttribute.WIDTH_CONDENSED</li>
* <li>TextAttribute.WIDTH_SEMI_CONDENSED</li>
* <li>TextAttribute.WIDTH_REGULAR</li>
* <li>TextAttribute.WIDTH_SEMI_EXTENDED</li>
* <li>TextAttribute.WIDTH_EXTENDED</li>
* </ul>
* @param font - The font to derive from
* @param width - The width of the derived font
* @return the derived font
*/
public static Font deriveWidth( Font font, Float width ) {
return deriveFont( font, TextAttribute.WIDTH, width );
}
/**
* In layman's terms, this is italic slope of the font.
* The value is roughly the slope of the stems of the font,
* expressed as the run over the rise. Positive values lean right.
* <p>
* There are a couple default values:
* <ul>
* <li>TextAttribute.POSTURE_REGULAR</li>
* <li>TextAttribute.POSTURE_OBLIQUE</li>
* </ul>
*
* @param font - The font to derive from
* @param posture - the posture of the derived font
* @return the derived font
*/
public static Font derivePosture( Font font, Float posture ) {
return deriveFont( font, TextAttribute.POSTURE, posture );
}
/**
* Derives a new font using the specified underline style,
* The underline style should be one of:
* <ul>
* <li>TextAttribute.UNDERLINE_ON</li>
* <li>TextAttribute.UNDERLINE_LOW_ONE_PIXEL</li>
* <li>TextAttribute.UNDERLINE_LOW_TWO_PIXEL</li>
* <li>TextAttribute.UNDERLINE_LOW_DASHED</li>
* <li>TextAttribute.UNDERLINE_LOW_DOTTED</li>
* <li>TextAttribute.UNDERLINE_LOW_GRAY</li>
* <ul>
*
* @param font - The font to derive from
* @param style - The underline style
* @return the derived font
*/
public static Font deriveUnderline( Font font, Integer style ) {
return deriveFont( font, TextAttribute.UNDERLINE, style );
}
/**
* Derives a new font with the specified strikethrough value.
*/
public static Font deriveStrikethrough( Font font, Boolean enabled ) {
return deriveFont( font, TextAttribute.STRIKETHROUGH, enabled );
}
/**
* Derives a new font with the specified superscript/subscript value.
* Negative values are subscripts and positive values superscripts.
* <p>
* The following default values are provided:
* <ul>
* <li>TextAttribute.SUPERSCRIPT_SUPER</li>
* <li>TextAttribute.SUPERSCRIPT_SUB</li>
* </ul>
*
* @param font
* @param value
* @return
*/
public static Font deriveSuperscript( Font font, Integer value ) {
return deriveFont( font, TextAttribute.SUPERSCRIPT, value );
}
/**
* Derives a font with the requested kerning style.
* <p>
* Currently, the only supported values are:
* <ul>
* <li>TextAttribute.KERNING_ON</li>
* <ul>
*
* @param font
* @param flag
* @return
*/
public static Font deriveKerning( Font font, Integer flag ) {
return deriveFont( font, TextAttribute.KERNING, flag );
}
/**
* Derives a font with the requested tracking value.
* <p>
* The tracking value is multiplied by the font point size and
* passed through the font transform to determine an additional
* amount to add to the advance of each glyph cluster. Positive
* tracking values will inhibit formation of optional ligatures.
* Tracking values are typically between <code>-0.1</code> and
* <code>0.3</code>; values outside this range are generally not
* desirable. (Note: this excerpt was from TextAttribute.TRACKING)
* <p>
* The following constants are provided:
* <ul>
* <li>TextAttributes.TRACKING_TIGHT</li>
* <li>TextAttributes.TRACKING_LOOSE</li>
* </ul>
*/
public static Font deriveTracking( Font font, Float value ) {
return deriveFont( font, TextAttribute.TRACKING, value );
}
/**
* Derives a font which enables or disables ligatures.
* <p>
* Currently available values are:
* <ul>
* <li>TextAttributes.LIGATURES_ON</li>
* </ul>
*/
public static Font deriveLigatures( Font font, Integer flag ) {
return deriveFont( font, TextAttribute.LIGATURES, flag );
}
/**
* Derives a font which enables or disables color swapping.
* If color swapping is enabled then the paints in FOREGROUND
* or BACKGROUND will override the paint used by the Graphics
* object used to render the font.
*
* @param font - the font to derive from
* @param isEnabled - if true sets SWAP_COLORS to SWAP_COLORS_ON
* @return the derived font
*/
public static Font deriveSwapColors( Font font, boolean isEnabled ) {
Object value = isEnabled ? TextAttribute.SWAP_COLORS_ON : null;
return deriveFont( font, TextAttribute.SWAP_COLORS, value );
}
/**
* Derives a font which uses the specified foreground paint
*/
public static Font deriveForeground( Font font, Paint paint ) {
return deriveFont( font, TextAttribute.FOREGROUND, paint );
}
/**
* Derives a font which uses the specified background paint
*/
public static Font deriveBackground( Font font, Paint paint ) {
return deriveFont( font, TextAttribute.BACKGROUND, paint );
}
/**
* Derives a new font using the specified font size
*
* @param font - The font to derive from
* @param size - The the size of the derived font
* @return the derived font
*/
public static Font deriveSize( Font font, Number size ) {
return deriveFont( font, TextAttribute.SIZE, size );
}
/**
* Lets you override the run direction of the font.
* See TextAttribute.RUN_DIRECTION for details on how to use this.
* <p>
* Available values are:
* <ul>
* <li>TextAttribute.RUN_DIRECTION_LTR</li>
* <li>TextAttribute.RUN_DIRECTION_RTL</li>
* </ul>
*/
public static Font deriveRunDirection( Font font, Boolean direction ) {
return deriveFont( font, TextAttribute.RUN_DIRECTION, direction );
}
/**
* Derives a new font using the specified transform.
* <p>
* See TextAttribute.TRANSFORM for more details.
*/
public static Font deriveTransform( Font font, TransformAttribute transform ) {
return deriveFont( font, TextAttribute.TRANSFORM, transform );
}
/**
* See TextAttribute.BIDI_EMBEDDING for details on how to use this.
*/
public static Font deriveBidiEmbedding( Font font, Integer level ) {
return deriveFont( font, TextAttribute.BIDI_EMBEDDING, level );
}
/**
* Derives a new font using the specified key, value pair
*
* @param font - the font to derive from.
* @param key - the Attribute key to change
* @param value - The new value to set
* @return the derived font
*/
public static Font deriveFont( Font font, Attribute key, Object value ) {
Map<Attribute, Object> attribs = getAttributes( font );
attribs.put( key, value );
return new Font( attribs );
}
/**
* Derives a new font from a list of (Attribute,value) pairs.
*
* @param font - The font to derive from
* @param derivations - a list of derivations specified as (Attribute,value) pairs.
* @return the derived font
*/
public static Font deriveFont( Font font, Tuple2<Attribute,Object>... derivations ) {
Map<Attribute, Object> attribs = getAttributes( font );
for( Tuple2<Attribute,Object> item : derivations ) {
attribs.put( item.getFirst(), item.getSecond() );
}
return new Font( attribs );
}
////// OTHER HELPER METHODS ////////////////////////////////////
/**
* Returns a map of known types rather than the unusable (poorly typed) map returned by Font.
*/
public static Map<Attribute, Object> getAttributes( Font font ) {
return new HashMap<Attribute, Object>( font.getAttributes() );
}
/**
* @return all available fonts
*/
public static Font[] getAvailableFonts() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts();
}
/**
* @return The names of all available fonts
*/
public static String[] getAvailableFontNames() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
}
}