blob: b7473d72f46c39fb9dd1171020143226c1ca69be [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.substitute;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fop.fonts.Font;
import org.apache.fop.fonts.FontInfo;
import org.apache.fop.fonts.FontTriplet;
import org.apache.fop.fonts.FontUtil;
/**
* Encapsulates a font substitution qualifier
*/
public class FontQualifier {
/** logger instance */
private static Log log = LogFactory.getLog(FontQualifier.class);
/** font family attribute value */
private AttributeValue fontFamilyAttributeValue;
/** font style attribute value */
private AttributeValue fontStyleAttributeValue;
/** font weight attribute value */
private AttributeValue fontWeightAttributeValue;
/**
* Default constructor
*/
public FontQualifier() {
}
/**
* Sets the font family
* @param fontFamily the font family
*/
public void setFontFamily(String fontFamily) {
AttributeValue fontFamilyAttribute = AttributeValue.valueOf(fontFamily);
if (fontFamilyAttribute == null) {
log.error("Invalid font-family value '" + fontFamily + "'");
return;
}
this.fontFamilyAttributeValue = fontFamilyAttribute;
}
/**
* Sets the font style
* @param fontStyle the font style
*/
public void setFontStyle(String fontStyle) {
AttributeValue fontStyleAttribute = AttributeValue.valueOf(fontStyle);
if (fontStyleAttribute != null) {
this.fontStyleAttributeValue = fontStyleAttribute;
}
}
/**
* Sets the font weight
* @param fontWeight the font weight
*/
public void setFontWeight(String fontWeight) {
AttributeValue fontWeightAttribute = AttributeValue.valueOf(fontWeight);
if (fontWeightAttribute != null) {
for (Iterator it = fontWeightAttribute.iterator(); it.hasNext();) {
Object weightObj = it.next();
if (weightObj instanceof String) {
String weightString = ((String)weightObj).trim();
try {
FontUtil.parseCSS2FontWeight(weightString);
} catch (IllegalArgumentException ex) {
log.error("Invalid font-weight value '" + weightString + "'");
return;
}
}
}
this.fontWeightAttributeValue = fontWeightAttribute;
}
}
/**
* @return the font family attribute
*/
public AttributeValue getFontFamily() {
return this.fontFamilyAttributeValue;
}
/**
* @return the font style attribute
*/
public AttributeValue getFontStyle() {
if (fontStyleAttributeValue == null) {
return AttributeValue.valueOf(Font.STYLE_NORMAL);
}
return this.fontStyleAttributeValue;
}
/**
* @return the font weight attribute
*/
public AttributeValue getFontWeight() {
if (fontWeightAttributeValue == null) {
return AttributeValue.valueOf(Integer.toString(Font.WEIGHT_NORMAL));
}
return this.fontWeightAttributeValue;
}
/**
* @return true if this rule has a font weight
*/
public boolean hasFontWeight() {
return this.fontWeightAttributeValue != null;
}
/**
* @return true if this rule has a font style
*/
public boolean hasFontStyle() {
return this.fontStyleAttributeValue != null;
}
/**
* Returns a list of matching font triplet found in a given font info
*
* @param fontInfo the font info
* @return a list of matching font triplets
*/
protected List/*<FontTriplet>*/ match(FontInfo fontInfo) {
AttributeValue fontFamilyValue = getFontFamily();
AttributeValue weightValue = getFontWeight();
AttributeValue styleValue = getFontStyle();
List/*<FontTriplet>*/ matchingTriplets = new java.util.ArrayList/*<FontTriplet>*/();
// try to find matching destination font triplet
for (Iterator attrIt = fontFamilyValue.iterator(); attrIt.hasNext();) {
String fontFamilyString = (String)attrIt.next();
Map/*<FontTriplet>*/ triplets = (Map/*<FontTriplet>*/)fontInfo.getFontTriplets();
if (triplets != null) {
Set/*<FontTriplet>*/ tripletSet = triplets.keySet();
for (Iterator/*<FontTriplet>*/ tripletIt = tripletSet.iterator();
tripletIt.hasNext();) {
FontTriplet triplet = (FontTriplet)tripletIt.next();
String fontName = triplet.getName();
// matched font family name
if (fontFamilyString.toLowerCase().equals(fontName.toLowerCase())) {
// try and match font weight
boolean weightMatched = false;
int fontWeight = triplet.getWeight();
for (Iterator weightIt = weightValue.iterator(); weightIt.hasNext();) {
Object weightObj = weightIt.next();
if (weightObj instanceof FontWeightRange) {
FontWeightRange intRange = (FontWeightRange)weightObj;
if (intRange.isWithinRange(fontWeight)) {
weightMatched = true;
}
} else if (weightObj instanceof String) {
String fontWeightString = (String)weightObj;
int fontWeightValue = FontUtil.parseCSS2FontWeight(
fontWeightString);
if (fontWeightValue == fontWeight) {
weightMatched = true;
}
} else if (weightObj instanceof Integer) {
Integer fontWeightInteger = (Integer)weightObj;
int fontWeightValue = fontWeightInteger.intValue();
if (fontWeightValue == fontWeight) {
weightMatched = true;
}
}
}
// try and match font style
boolean styleMatched = false;
String fontStyleString = triplet.getStyle();
for (Iterator styleIt = styleValue.iterator(); styleIt.hasNext();) {
String style = (String)styleIt.next();
if (fontStyleString.equals(style)) {
styleMatched = true;
}
}
if (weightMatched && styleMatched) {
matchingTriplets.add(triplet);
}
}
}
}
}
return matchingTriplets;
}
/**
* Returns the highest priority matching font triplet found in a given font info
* @param fontInfo the font info
* @return the highest priority matching font triplet
*/
protected FontTriplet bestMatch(FontInfo fontInfo) {
List/*<FontTriplet>*/ matchingTriplets = match(fontInfo);
FontTriplet bestTriplet = null;
if (matchingTriplets.size() == 1) {
bestTriplet = (FontTriplet)matchingTriplets.get(0);
} else {
for (Iterator iterator = matchingTriplets.iterator(); iterator.hasNext();) {
FontTriplet triplet = (FontTriplet)iterator.next();
if (bestTriplet == null) {
bestTriplet = triplet;
} else {
int priority = triplet.getPriority();
if (priority < bestTriplet.getPriority()) {
bestTriplet = triplet;
}
}
}
}
return bestTriplet;
}
/**
* @return a list of font triplets matching this qualifier
*/
public List/*<FontTriplet>*/ getTriplets() {
List/*<FontTriplet>*/ triplets = new java.util.ArrayList/*<FontTriplet>*/();
AttributeValue fontFamilyValue = getFontFamily();
for (Iterator fontFamilyIt = fontFamilyValue.iterator(); fontFamilyIt.hasNext();) {
String name = (String)fontFamilyIt.next();
AttributeValue styleValue = getFontStyle();
for (Iterator styleIt = styleValue.iterator(); styleIt.hasNext();) {
String style = (String)styleIt.next();
AttributeValue weightValue = getFontWeight();
for (Iterator weightIt = weightValue.iterator(); weightIt.hasNext();) {
Object weightObj = weightIt.next();
if (weightObj instanceof FontWeightRange) {
FontWeightRange fontWeightRange = (FontWeightRange)weightObj;
int[] weightRange = fontWeightRange.toArray();
for (int i = 0; i < weightRange.length; i++) {
triplets.add(new FontTriplet(name, style, weightRange[i]));
}
} else if (weightObj instanceof String) {
String weightString = (String)weightObj;
int weight = FontUtil.parseCSS2FontWeight(weightString);
triplets.add(new FontTriplet(name, style, weight));
} else if (weightObj instanceof Integer) {
Integer weightInteger = (Integer)weightObj;
int weight = weightInteger.intValue();
triplets.add(new FontTriplet(name, style, weight));
}
}
}
}
return triplets;
}
/**
* {@inheritDoc}
*/
public String toString() {
String str = new String();
if (fontFamilyAttributeValue != null) {
str += "font-family=" + fontFamilyAttributeValue;
}
if (fontStyleAttributeValue != null) {
if (str.length() > 0) {
str += ", ";
}
str += "font-style=" + fontStyleAttributeValue;
}
if (fontWeightAttributeValue != null) {
if (str.length() > 0) {
str += ", ";
}
str += "font-weight=" + fontWeightAttributeValue;
}
return str;
}
}