/*
* $Id$
* Copyright (C) 2001-2003 The Apache Software Foundation. All rights reserved.
* For details on use and redistribution please refer to the
* LICENSE file included with these sources.
*/
package org.apache.fop.layout;
// Java
import java.util.Map;
// FOP
import org.apache.fop.fonts.FontMetrics;
/**
* The FontInfo for the layout and rendering of a fo document.
* This stores the list of available fonts that are setup by
* the renderer. The font name can be retrieved for the
* family style and weight.
*
* Currently font supported font-variant small-caps is not
* implemented.
*/
public class FontInfo {
/** Default fallback key */
public static final String DEFAULT_FONT = "any,normal,400";
/** Normal font weight */
public static final int NORMAL = 400;
/** Bold font weight */
public static final int BOLD = 700;
/** Map containing fonts that have been used */
private Map usedFonts;
/** look up a font-triplet to find a font-name */
private Map triplets;
/** look up a font-name to get a font (that implements FontMetrics at least) */
private Map fonts;
/**
* Main constructor
*/
public FontInfo() {
this.triplets = new java.util.HashMap();
this.fonts = new java.util.HashMap();
this.usedFonts = new java.util.HashMap();
}
/**
* Checks if the font setup is valid (At least the ultimate fallback font
* must be registered.)
* @return True if valid
*/
public boolean isSetupValid() {
return triplets.containsKey(DEFAULT_FONT);
}
/**
* Adds a new font triplet.
* @param name internal key
* @param family font family name
* @param style font style (normal, italic, oblique...)
* @param weight font weight
*/
public void addFontProperties(String name, String family, String style,
int weight) {
/*
* add the given family, style and weight as a lookup for the font
* with the given name
*/
String key = createFontKey(family, style, weight);
this.triplets.put(key, name);
}
/**
* Adds font metrics for a specific font.
* @param name internal key
* @param metrics metrics to register
*/
public void addMetrics(String name, FontMetrics metrics) {
// add the given metrics as a font with the given name
this.fonts.put(name, metrics);
}
/**
* Lookup a font.
*
* Locate the font name for a given family, style and weight.
* The font name can then be used as a key as it is unique for
* the associated document.
* This also adds the font to the list of used fonts.
* @param family font family
* @param style font style
* @param weight font weight
* @return internal key
*/
public String fontLookup(String family, String style,
int weight) {
String key;
// first try given parameters
key = createFontKey(family, style, weight);
String f = (String)triplets.get(key);
if (f == null) {
// then adjust weight, favouring normal or bold
f = findAdjustWeight(family, style, weight);
// then try any family with orig weight
if (f == null) {
key = createFontKey("any", style, weight);
f = (String)triplets.get(key);
}
// then try any family with adjusted weight
if (f == null) {
f = findAdjustWeight(family, style, weight);
}
// then use default
f = (String)triplets.get(DEFAULT_FONT);
}
usedFonts.put(f, fonts.get(f));
return f;
}
/**
* Find a font with a given family and style by trying
* different font weights according to the spec.
* @param family font family
* @param style font style
* @param weight font weight
* @return internal key
*/
public String findAdjustWeight(String family, String style,
int weight) {
String key;
String f = null;
int newWeight = weight;
if (newWeight < 400) {
while (f == null && newWeight > 0) {
newWeight -= 100;
key = createFontKey(family, style, newWeight);
f = (String)triplets.get(key);
}
} else if (newWeight == 500) {
key = createFontKey(family, style, 400);
f = (String)triplets.get(key);
} else if (newWeight > 500) {
while (f == null && newWeight < 1000) {
newWeight += 100;
key = createFontKey(family, style, newWeight);
f = (String)triplets.get(key);
}
newWeight = weight;
while (f == null && newWeight > 400) {
newWeight -= 100;
key = createFontKey(family, style, newWeight);
f = (String)triplets.get(key);
}
}
if (f == null) {
key = createFontKey(family, style, 400);
f = (String)triplets.get(key);
}
return f;
}
/**
* Determines if a particular font is available.
* @param family font family
* @param style font style
* @param weight font weight
* @return True if available
*/
public boolean hasFont(String family, String style, int weight) {
String key = createFontKey(family, style, weight);
return this.triplets.containsKey(key);
}
/**
* Creates a key from the given strings.
* @param family font family
* @param style font style
* @param weight font weight
* @return internal key
*/
public static String createFontKey(String family, String style,
int weight) {
return family + "," + style + "," + weight;
}
/**
* Gets a Map of all registred fonts.
* @return a read-only Map with font key/FontMetrics pairs
*/
public Map getFonts() {
return java.util.Collections.unmodifiableMap(this.fonts);
}
/**
* This is used by the renderers to retrieve all the
* fonts used in the document.
* This is for embedded font or creating a list of used fonts.
* @return a read-only Map with font key/FontMetrics pairs
*/
public Map getUsedFonts() {
return this.usedFonts;
}
/**
* Returns the FontMetrics for a particular font
* @param fontName internal key
* @return font metrics
*/
public FontMetrics getMetricsFor(String fontName) {
usedFonts.put(fontName, fonts.get(fontName));
return (FontMetrics)fonts.get(fontName);
}
}