//----------------------------------------------------------------------------//
// //
// O m r F o n t //
// //
//----------------------------------------------------------------------------//
// <editor-fold defaultstate="collapsed" desc="hdr"> //
// Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. //
// This software is released under the GNU General Public License. //
// Goto http://kenai.com/projects/audiveris to report bugs or suggestions. //
//----------------------------------------------------------------------------//
// </editor-fold>
package omr.ui.symbol;
import omr.WellKnowns;
import omr.util.UriUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Point;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.InputStream;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Map;
/**
* Class {@code OmrFont} is meant to simplify the use of rendering
* symbols when using a Text or a Music font.
*
* @author Hervé Bitteur
*/
public abstract class OmrFont
extends Font
{
//~ Static fields/initializers ---------------------------------------------
/** Usual logger utility */
private static final Logger logger = LoggerFactory.getLogger(OmrFont.class);
/** Default interline value, consistent with base font: {@value} */
public static final int DEFAULT_INTERLINE = 16;
/** Default staff height value, consistent with base font: {@value} */
public static final int DEFAULT_STAFF_HEIGHT = 67;
/** Needed for font size computation */
protected static final FontRenderContext frc = new FontRenderContext(
null,
true,
true);
/** Default color for images */
public static final Color defaultImageColor = Color.BLACK;
/** Cache for fonts. */
private static final Map<String, Font> fontCache = new HashMap<>();
//~ Constructors -----------------------------------------------------------
//---------//
// OmrFont //
//---------//
/**
* Creates a new OmrFont object.
*
* @param name the font name
* @param style generally PLAIN
* @param size the point size of the font
*/
protected OmrFont (String name,
int style,
int size)
{
super(createFont(name, style, size));
}
//~ Methods ----------------------------------------------------------------
//
//------------//
// createFont //
//------------//
private static Font createFont (String fontName,
int style,
int size)
{
Font font;
// Font already registered?
font = fontCache.get(fontName);
if (font != null) {
logger.debug("Using cached font {}", fontName);
return font.deriveFont(style, size);
}
// Lookup our own fonts (defined in "res" folder)
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
try (InputStream input = UriUtil.toURI(WellKnowns.RES_URI, fontName + ".ttf").toURL().openStream()) {
font = Font.createFont(Font.TRUETYPE_FONT, input);
fontCache.put(fontName, font);
ge.registerFont(font);
logger.debug("Created custom font {}", fontName);
return font.deriveFont(style, size);
} catch (Exception ex) {
logger.debug("Could not create custom font {} {}", fontName, ex);
}
// Finally, try a platform font
font = new Font(fontName, style, size);
fontCache.put(fontName, font);
logger.debug("Using platform font {}", font.getFamily());
return font;
}
//--------//
// layout //
//--------//
/**
* Build a TextLayout from a String of OmrFont characters
* (transformed by the provided AffineTransform if any).
*
* @param str the string of proper codes
* @param fat potential affine transformation
* @return the (sized) TextLayout ready to be drawn
*/
public TextLayout layout (String str,
AffineTransform fat)
{
Font font = (fat == null) ? this : this.deriveFont(fat);
return new TextLayout(str, font, frc);
}
//--------//
// layout //
//--------//
/**
* Build a TextLayout from a String of OmrFont characters.
*
* @param str the string of proper codes
* @return the TextLayout ready to be drawn
*/
public TextLayout layout (String str)
{
return layout(str, null);
}
//--------//
// layout //
//--------//
/**
* Build a TextLayout from a ShapeSymbol.
*
* @param symbol the symbol to draw
* @return the TextLayout ready to be drawn
*/
public TextLayout layout (BasicSymbol symbol)
{
return layout(symbol.getString(), null);
}
//-------//
// paint //
//-------//
/**
* This is the general paint method for drawing a symbol layout, at
* a specified location, using a specified alignment.
*
* @param g the graphics environment
* @param layout what: the symbol, perhaps transformed
* @param location where: the precise location in the display
* @param alignment how: the way the symbol is aligned wrt the location
*/
public static void paint (Graphics2D g,
TextLayout layout,
Point location,
Alignment alignment)
{
try {
// Compute symbol origin
Rectangle2D bounds = layout.getBounds();
Point2D toTextOrigin = alignment.toTextOrigin(bounds);
Point2D origin = new Point2D.Double(
location.x + toTextOrigin.getX(),
location.y + toTextOrigin.getY());
// Draw the symbol
layout.draw(g, (float) origin.getX(), (float) origin.getY());
} catch (ConcurrentModificationException ignored) {
} catch (Exception ex) {
logger.warn("Cannot paint at " + location, ex);
}
}
}