ch.randelshofer.quaqua.util.Fonts Maven / Gradle / Ivy
Show all versions of Quaqua Show documentation
/*
* @(#)Fonts.java
*
* Copyright (c) 2003-2010 Werner Randelshofer, Immensee, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package ch.randelshofer.quaqua.util;
import ch.randelshofer.quaqua.*;
import java.util.*;
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import javax.swing.*;
/**
* Fonts.
*
* @author Werner Randelshofer, Hausmatt 10, CH-6405 Immensee, Switzerland
* @version $Id: Fonts.java 363 2010-11-21 17:41:04Z wrandelshofer $
*/
public class Fonts {
private static volatile HashMap fonts;
/**
* Default font render context for Mac OS X.
* XXX - We should create the default depending on properties of the current
* Look and Feel.
*/
private static FontRenderContext defaultFontRenderContext = new FontRenderContext(new AffineTransform(), true, true);
/** Creates a new instance. */
private Fonts() {
}
private static void init() {
if (fonts == null) {
synchronized (Fonts.class) {
if (fonts == null) {
fonts = new HashMap();
Font dialogFont = UIManager.getFont("Label.font");
Font emphasizedDialogFont = dialogFont.deriveFont(Font.BOLD);
Font smallDialogFont;
if (dialogFont.getSize() >= 13) {
smallDialogFont = dialogFont.deriveFont((float) (dialogFont.getSize() - 2));
} else {
smallDialogFont = dialogFont;
}
Font emphasizedSmallDialogFont = smallDialogFont.deriveFont(Font.BOLD);
fonts.put("Dialog", dialogFont);
fonts.put("EmphasizedDialog", emphasizedDialogFont);
fonts.put("SmallDialog", smallDialogFont);
fonts.put("EmphasizedSmallDialog", emphasizedSmallDialogFont);
fonts.put("Application", dialogFont);
fonts.put("Label", dialogFont.deriveFont(10f));
fonts.put("MiniDialog", dialogFont.deriveFont(9f));
fonts.put("Monospace", new Font("Courier", Font.PLAIN, dialogFont.getSize()));
if (QuaquaManager.getProperty("java.version").startsWith("1.3")) {
fonts.put("DialogTag", "");
fonts.put("/DialogTag", "");
fonts.put("SmallDialogTag", "");
fonts.put("/SmallDialogTag", "");
fonts.put("MiniDialogTag", "");
fonts.put("/MiniDialogTag", "");
fonts.put("EmphasizedDialogTag", "");
fonts.put("/EmphasizedDialogTag", "");
} else {
fonts.put("DialogTag", "");
fonts.put("/DialogTag", "");
fonts.put("SmallDialogTag", "");
fonts.put("/SmallDialogTag", "");
fonts.put("MiniDialogTag", "");
fonts.put("/MiniDialogTag", "");
fonts.put("EmphasizedDialogTag", "");
fonts.put("/EmphasizedDialogTag", "");
}
}
}
}
}
/**
* The dialog font is used for text in menus, modeless dialogs, and titles
* of document windows.
*/
public static Font getDialogFont() {
init();
return (Font) fonts.get("Dialog");
}
/**
* Use emphasized dialog fonts sparingly. Emphasized (bold) dialog font is
* used in only two places in the interface: the application name in an
* About window and the message text in an option pane.
*/
public static Font getEmphasizedDialogFont() {
init();
return (Font) fonts.get("EmphasizedDialog");
}
/**
* The small dialog font is used for informative text in alerts.
* It is also the default font for headings in lists, for help tags, and for
* text in the small versions of many controls. You can also use it to
* provide additional information about settings in various windows.
*/
public static Font getSmallDialogFont() {
init();
return (Font) fonts.get("SmallDialog");
}
/**
* You might use emphasized small dialog font to title a group of settings
* that appear without a group box, or for brief informative text below a
* text field.
*/
public static Font getEmphasizedSmallDialogFont() {
init();
return (Font) fonts.get("EmphasizedSmallDialog");
}
/**
* If your application creates text documents, use the application font as
* the default for user-created content.
*/
public static Font getApplicationFont() {
init();
return (Font) fonts.get("Application");
}
/**
* If your application needs monospaced fonts, use the monospace font.
*/
public static Font getMonospaceFont() {
init();
return (Font) fonts.get("Monospace");
}
/**
* The label font is used for labels with controls such as sliders and icon
* bevel buttons. You should rarely need to use this font in dialogs, but
* may find it useful in utility windows when space is at a premium.
*/
public static Font getLabelFont() {
init();
return (Font) fonts.get("Label");
}
/**
* If necessary, the mini dialog font can be used for utility window labels
* and text.
*/
public static Font getMiniDialogFont() {
init();
return (Font) fonts.get("MiniDialog");
}
/**
* Puts an HTML font tag for the Dialog Font around the specified text.
*/
public static String dialogFontTag(String text) {
init();
return fonts.get("DialogTag") + text + fonts.get("/DialogTag");
}
/**
* Puts an HTML font tag for the Small Dialog Font around the specified text.
*/
public static String smallDialogFontTag(String text) {
init();
return fonts.get("SmallDialogTag") + text + fonts.get("/SmallDialogTag");
}
/**
* Puts an HTML font tag for the Small Dialog Font around the specified text.
*/
public static String miniDialogFontTag(String text) {
init();
return fonts.get("MiniDialogTag") + text + fonts.get("/MiniDialogTag");
}
/**
* Puts an HTML font tag for the Emphasized Dialog Font around the specified text.
*/
public static String emphasizedDialogFontTag(String text) {
init();
return fonts.get("EmphasizedDialogTag") + text + fonts.get("/EmphasizedDialogTag");
}
/**
* Gets the visually perceived ascent of the specified character.
*/
public static int getVisualAscent(Font f, Component c, char ch) {
Graphics2D g = (Graphics2D) c.getGraphics();
FontRenderContext frc = (g == null) ? defaultFontRenderContext : g.getFontRenderContext();
GlyphVector gv = f.createGlyphVector(frc, new char[]{ch});
return -gv.getVisualBounds().getBounds().y;
}
/**
* Returns the perceived bounds of the specified string, if it is rendered
* using the specified font on the provided component.
*/
public static Rectangle getPerceivedBounds(String str, Font f, Component c) {
if (str == null) {
return new Rectangle(0, 0, 0, 0);
} else {
FontRenderContext frc;
Graphics2D g = ((Graphics2D) c.getGraphics());
if (g != null) {
frc = g.getFontRenderContext();
g.dispose();
} else {
frc = new FontRenderContext(new AffineTransform(), true, true);
}
int scriptSystem = (str == null || str.length() == 0) ? ScriptSystem.LATIN : ScriptSystem.getScriptSystemOf(str.charAt(0));
int ascent = getPerceivedAscent(f, frc, scriptSystem);
int descent = getPerceivedDescent(f, frc, scriptSystem);
Rectangle2D stringBounds = f.getStringBounds(str, frc);
return new Rectangle(1, -ascent, (int) stringBounds.getWidth() - 2, ascent + descent);
}
}
/**
* Returns the perceived ascent of the specified font, if text is written
* using the specified script system and font render context.
*
* The perceived ascent is a distance above the baseline, chosen by the
* font designer and the same for all glyphs in a script system, that often
* corresponds approximately to the tops of the uppercase letters in a Latin
* script system. Uppercase letters are chosen because, among the regularly
* used glyphs in a font, they are generally the tallest.
*
* The value returned by this method differs from the ascent returned by
* java.awt.font.LineMetrics.getAscent(), in that the perceived ascent does
* not include diacritical marks of the font. Therefore the perceived ascent
* is useful for visually north alignig text with graphical elements.
*/
public static int getPerceivedAscent(Font f, FontRenderContext frc, int system) {
if (ScriptSystem.getBaseline(system) == Font.HANGING_BASELINE) {
// Shortcut, also prevents that we are returning bad values based
// on the measurement character used.
return 0;
} else {
char ch = ScriptSystem.getMeasurementChar(system);
GlyphVector gv = f.createGlyphVector(frc, new char[]{ch});
return gv.getVisualBounds().getBounds().height;
}
}
/**
* Returns the perceived descent of the specified font, if text is written
* using the specified script system and font render context.
*
* The perceived descent is a distance below the baseline that usually
* corresponds to the bottoms of uppercase letters in a Latin script system,
* whithout the descenders of lower case characters. In a Latin script
* system the perceived descent is usually 0. The descent is the same
* distance from the baseline for all glyphs in the script system.
*
* The value returned by this method differs from the one that would be
* returned by java.awt.font.LineMetrics.getAscent(), in that the perceived
* descent does not include the descender of lower case characters and
* diacritical marks below them. Therefore the perceived descent is useful
* for visully south aligning text with graphical elements.
*/
public static int getPerceivedDescent(Font f, FontRenderContext frc, int system) {
if (ScriptSystem.getBaseline(system) == Font.ROMAN_BASELINE) {
// Shortcut, also prevents that we are returning bad values based
// on the measurement character used.
return 0;
} else {
char ch = ScriptSystem.getMeasurementChar(system);
GlyphVector gv = f.createGlyphVector(frc, new char[]{ch});
Rectangle bounds = gv.getVisualBounds().getBounds();
return bounds.y + bounds.height;
}
}
}