blob: 0cb44d7f83a7f09ca15ac8506d3457247f057e1a [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.fo.properties;
import org.apache.fop.fo.Constants;
import org.apache.fop.fo.FObj;
import org.apache.fop.fo.PropertyList;
import org.apache.fop.fo.expr.PropertyException;
/**
* Property subclass for the font shorthand
*/
public class FontShorthandProperty extends ListProperty {
/**
* Inner class for creating instances of FontShorthandProperty
*/
public static class Maker extends PropertyMaker {
private static final int[] PROP_IDS = {
Constants.PR_FONT_SIZE, Constants.PR_FONT_FAMILY,
Constants.PR_LINE_HEIGHT, Constants.PR_FONT_STYLE,
Constants.PR_FONT_VARIANT, Constants.PR_FONT_WEIGHT
};
/**
* @param propId ID of the property for which Maker should be created
*/
public Maker(int propId) {
super(propId);
}
/**
* {@inheritDoc}
*/
public Property make(PropertyList propertyList,
String value, FObj fo) throws PropertyException {
try {
FontShorthandProperty newProp = new FontShorthandProperty();
newProp.setSpecifiedValue(value);
String specVal = value;
Property prop = null;
if ("inherit".equals(specVal)) {
/* fill the list with the individual properties from the parent */
for (int i = PROP_IDS.length; --i >= 0;) {
prop = propertyList.getFromParent(PROP_IDS[i]);
newProp.addProperty(prop, i);
}
} else {
/* initialize list with nulls */
for (int pos = PROP_IDS.length; --pos >= 0;) {
newProp.addProperty(null, pos);
}
prop = checkEnumValues(specVal);
if (prop == null) {
/* not an enum:
* value should consist at least of font-size and font-family
* separated by a space
* mind the possible spaces from quoted font-family names
*/
int spaceIndex = value.indexOf(' ');
int quoteIndex = (value.indexOf('\'') == -1)
? value.indexOf('\"') : value.indexOf('\'');
if (spaceIndex == -1
|| (quoteIndex != -1 && spaceIndex > quoteIndex)) {
/* no spaces or first space appears after the first
* single/double quote, so malformed value string
*/
throw new PropertyException("Invalid property value: "
+ "font=\"" + value + "\"");
}
PropertyMaker m = null;
int fromIndex = spaceIndex + 1;
int toIndex = specVal.length();
/* at least one space that appears before the first
* single/double quote, so extract the individual properties
*/
boolean fontFamilyParsed = false;
int commaIndex = value.indexOf(',');
while (!fontFamilyParsed) {
/* value contains a (list of) possibly quoted
* font-family name(s)
*/
if (commaIndex == -1) {
/* no list, just a single name
* (or first name in the list)
*/
if (quoteIndex != -1) {
/* a single name, quoted
*/
fromIndex = quoteIndex;
}
m = FObj.getPropertyMakerFor(PROP_IDS[1]);
prop = m.make(propertyList, specVal.substring(fromIndex), fo);
newProp.addProperty(prop, 1);
fontFamilyParsed = true;
} else {
if (quoteIndex != -1 && quoteIndex < commaIndex) {
/* a quoted font-family name as first name
* in the comma-separated list
* fromIndex = index of the first quote
*/
fromIndex = quoteIndex;
quoteIndex = -1;
} else {
fromIndex = value.lastIndexOf(' ', commaIndex) + 1;
}
commaIndex = -1;
}
}
toIndex = fromIndex - 1;
fromIndex = value.lastIndexOf(' ', toIndex - 1) + 1;
value = specVal.substring(fromIndex, toIndex);
int slashIndex = value.indexOf('/');
String fontSize = value.substring(0,
(slashIndex == -1) ? value.length() : slashIndex);
m = FObj.getPropertyMakerFor(PROP_IDS[0]);
prop = m.make(propertyList, fontSize, fo);
/* need to make sure subsequent call to LineHeightPropertyMaker.make()
* doesn't generate the default font-size property...
*/
propertyList.putExplicit(PROP_IDS[0], prop);
newProp.addProperty(prop, 0);
if (slashIndex != -1) {
/* line-height */
String lineHeight = value.substring(slashIndex + 1);
m = FObj.getPropertyMakerFor(PROP_IDS[2]);
prop = m.make(propertyList, lineHeight, fo);
newProp.addProperty(prop, 2);
}
if (fromIndex != 0) {
toIndex = fromIndex - 1;
value = specVal.substring(0, toIndex);
fromIndex = 0;
spaceIndex = value.indexOf(' ');
do {
toIndex = (spaceIndex == -1) ? value.length() : spaceIndex;
String val = value.substring(fromIndex, toIndex);
for (int i = 6; --i >= 3;) {
if (newProp.list.get(i) == null) {
/* not set */
m = FObj.getPropertyMakerFor(PROP_IDS[i]);
val = m.checkValueKeywords(val);
prop = m.checkEnumValues(val);
if (prop != null) {
newProp.addProperty(prop, i);
}
}
}
fromIndex = toIndex + 1;
spaceIndex = value.indexOf(' ', fromIndex);
} while (toIndex != value.length());
}
} else {
//TODO: implement enum values
log.warn("Enum values other than \"inherit\""
+ " not yet supported for the font shorthand.");
return null;
}
}
if (newProp.list.get(0) == null || newProp.list.get(1) == null) {
throw new PropertyException("Invalid property value: "
+ "font-size and font-family are required for the font shorthand"
+ "\nfont=\"" + value + "\"");
}
return newProp;
} catch (PropertyException pe) {
pe.setLocator(propertyList.getFObj().getLocator());
pe.setPropertyName(getName());
throw pe;
}
}
}
private void addProperty(Property prop, int pos) {
while (list.size() < (pos + 1)) {
list.add(null);
}
list.set(pos, prop);
}
}