/*
* Copyright 2004 The Apache Software Foundation.
*
* 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.
*/
/* $Id$ */
package org.apache.fop.fonts;
// Java
import java.util.Map;
/**
* 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 {
/** 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(Font.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
if (f == null) {
f = (String)triplets.get(Font.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);
}
}