pbwest 2002/07/30 01:45:22
Modified: src/org/apache/fop/fo Tag: FOP_0-20-0_Alt-Design
Properties.java
Log:
Completed font shorthand. Other minor changes realted to shorthand processing and
verification of expression parsing.
Revision Changes Path
No revision
No revision
1.1.2.15 +302 -82 xml-fop/src/org/apache/fop/fo/Attic/Properties.java
Index: Properties.java
===================================================================
RCS file: /home/cvs/xml-fop/src/org/apache/fop/fo/Attic/Properties.java,v
retrieving revision 1.1.2.14
retrieving revision 1.1.2.15
diff -u -r1.1.2.14 -r1.1.2.15
--- Properties.java 9 Jul 2002 06:49:47 -0000 1.1.2.14
+++ Properties.java 30 Jul 2002 08:45:21 -0000 1.1.2.15
@@ -286,12 +286,11 @@
*
* <p>This method is shadowed by individual property classes which
* require specific processing.
- * @param property <tt>int</tt> property index
+ * @param foTree the <tt>FOTree</tt> being built
* @param value <tt>PropertyValue</tt> returned by the parser
- * @foTree the <tt>FOTree</tt> being built
*/
public static PropertyValue verifyParsing
- (PropertyValue value, FOTree foTree)
+ (FOTree foTree, PropertyValue value)
throws PropertyException
{
int property = value.getProperty();
@@ -1073,25 +1072,35 @@
// the pair, else form a list from this element only
PropertyValueList posnList = new PropertyValueList
(PropNames.BACKGROUND_POSITION);
- posnList.add(pval);
+ PropertyValue tmpval = null;
// Is it followed by another Numeric?
if (elements.hasNext()) {
- PropertyValue tmpval;
if ((tmpval = (PropertyValue)(elements.next()))
instanceof Numeric) {
+ posnList.add(pval);
posnList.add(tmpval);
} else {
// Not a following Numeric, so restore the list
// cursor
- tmpval = (PropertyValue)(elements.previous());
+ Object tmpo = elements.previous();
+ tmpval = null;
}
}
// Now send one or two Numerics to BackgroundPosition
if (position != null)
MessageHandler.log("background: duplicate" +
"position overrides previous position");
- position =
- BackgroundPosition.verifyParsing(foTree, posnList);
+ if (tmpval == null)
+ position = BackgroundPosition.verifyParsing
+ (foTree, pval);
+ else { // 2 elements
+ // make a space-separated list
+ PropertyValueList ssList = new PropertyValueList
+ (PropNames.BACKGROUND_POSITION);
+ ssList.add(posnList);
+ position = BackgroundPosition.verifyParsing
+ (foTree, ssList);
+ }
continue scanning_elements;
}
@@ -1130,7 +1139,7 @@
// Must be a position indicator
// send it to BackgroundPosition.complex for processing
// If it is followed by another NCName, form a list from
- // the pair, else form a list from this element only
+ // the pair, else send this element only
// This is made messy by the syntax of the Background
// shorthand. A following NCName need not be a second
@@ -1160,15 +1169,25 @@
} catch (PropertyException e) {};
if (pos1ok) {
- posnList.add(pval);
- // Is it followed by another position NCName?
- if (pos2ok) posnList.add(tmpval);
- // Now send one or two NCNames to BackgroundPosition
if (position != null)
MessageHandler.log("background: duplicate" +
"position overrides previous position");
- position =
- BackgroundPosition.verifyParsing(foTree, posnList);
+ // Is it followed by another position NCName?
+ if (pos2ok) {
+ posnList.add(pval);
+ posnList.add(tmpval);
+ // Now send two NCNames to BackgroundPosition
+ // as a space-separated list
+ PropertyValueList ssList = new PropertyValueList
+ (PropNames.BACKGROUND_POSITION);
+ ssList.add(posnList);
+ position = BackgroundPosition.verifyParsing
+ (foTree, ssList);
+ } else { // one only
+ // Now send one NCName to BackgroundPosition
+ position = BackgroundPosition.verifyParsing
+ (foTree, pval);
+ }
continue scanning_elements;
}
throw new PropertyException
@@ -1403,7 +1422,7 @@
// Only two Numerics allowed
if (value.size() != 2)
throw new PropertyException
- ("More that 2 elements in BackgroundPosition list.");
+ ("Other than 2 elements in BackgroundPosition list.");
// Analyse the list data.
// Can be a pair of Numeric values, Length or Percentage,
// or a pair of enum tokens. One is from the set
@@ -3569,23 +3588,38 @@
/**
* 'value' is a PropertyValueList or an individual PropertyValue.
*
- * If 'value' is a PropertyValueList it may contain, in turn, a
+ * <p>If 'value' is a PropertyValueList it may contain, in turn, a
* PropertyValueList with the space-separated elements of the
* original expression, or a list of comma-separated elements if
* these were the only elements of the expression.
- *
+ * <p>
* If a top-level list occurs, i.e. if 'value' is a PropertyValueList
* which contains multiple elements, it represents a comma-separated
- * list, which can only legitimately contain a <em>font-family</em>
- * specification. However, a <em>font-family</em> cannot occur
- * without a preceding space-separated <em>font-size</em>, at a
- * minimum, so such a list is an error.
+ * list. Commas can only legitimately occur between elements of
+ * a font-family specifier, but more than one may occur.
+ * The font-family specifier MUST be preceded by at least one other
+ * element, a font-size, and MAY be preceded by more than one.
+ * I.e., if a COMMA is present in the list,
+ * <pre>
+ * value (PropertyValueList)
+ * |
+ * + PropertyValueList COMMA element [...]
+ * (space separated)
+ * |
+ * +- PropertyValue PropertyValue [...]
+ * </pre>
+ * <p>The complication here is that, while the final element of this
+ * list must belong with the comma-separated font-family specifier,
+ * preceding elements MAY also belong to the font-family.
*
+ * <p>If 'value' is <i>not</i> a PropertyValueList,
* 'value' can contain a parsed Inherit value or
* a parsed NCName value containing one of the system font
* enumeration tokens listed in rwEnums, above.
+ * Note that it cannot contain a font-family, because that MUST
+ * be preceded by at least one other element.
*
- * If 'value' is a space-separated list, it may contain:
+ * <p>If 'value' is a space-separated list, it may contain:
* A trailing <em>font-family</em> specification, preceded by
* a dimension specification, possibly
* preceded by an initial detailed font specification.
@@ -3593,50 +3627,112 @@
* element or a comma-separated list of specific or generic font
* names. A single font name may be a space-separated name.
*
- * The optional initial detailed font specification may be
+ * <p>The optional initial detailed font specification may be
* comprised of a trailing dimension specifier, possibly preceded
* by an optional set of font descriptor elements.
*
- * The dimension specifier is comprised of a <em>font-size</em>
+ * <p>The dimension specifier is comprised of a <em>font-size</em>
* specifier, possibly followed by a height
* specifier. The height specifier is made up of a slash
* character followed by a <em>line-height</em> specifier proper.
*
- * The optional set of font descriptor elements may include,
+ * <p>The optional set of font descriptor elements may include,
* in any order, from one to three of
- * a font-style element
- * a font-variant element
- * a font-weight element
- *
+ * <br>a font-style element
+ * <br>a font-variant element
+ * <br>a font-weight element
+ * <p>
* [ [<font-style>||<font-variant>||<font-weight>]?
* <font-size> [/ <line-height>]? <font-family> ]
* |caption|icon|menu|message-box|small-caption|status-bar
* |inherit
*
- * In other words, this is one of the greatest parsing shambles
- * ever conceived by the mind of man.
+ * <p><b>Handling the font-family list.</b>
+ * <p>For any list, the last element or elements must belong to a
+ * font-family specifier. If only a space-separated list is present
+ * only one font is specified in the font-family, but it may have
+ * space-separated components, e.g. 'Times New' in 'Times New Roman'.
+ * If a comma-separated list is present, there are COMMAs + 1 fonts
+ * given in the font-family, but for the first of these, some parts
+ * of the name may be present in the preceding space-separated list,
+ * e.g. (again) 'Times New'.
+ *
+ * <p>This is handled by splitting the passed PropertyValueList into
+ * two sublists:- initial-list and font-family-list. The latter
+ * contains those components which MUST bw part of a font-family
+ * specifier. The trailing elements of the initila-list are scanned
+ * to determine which are components of the font-family-list, and
+ * these are trimmed from initial-list and prepended to
+ * font-family-list.
*
* <p>The value(s) provided, if valid, are converted into a list
* containing the expansion of the shorthand. A minimum of one
* value will be present.
*
+ * <p>N.B. from the specification:<br>
+ * <p>QUOTE<br>
+ * The "font" property is, except as described below, a shorthand
+ * property for setting "font-style", "font-variant", "font-weight",
+ * "font-size", "line-height", and "font-family", at the same place
+ * in the stylesheet. The syntax of this property is based on a
+ * traditional typographical shorthand notation to set multiple
+ * properties related to fonts.
+ *
+ * <p>All font-related properties are first reset to their initial
+ * values, including those listed in the preceding paragraph plus
+ * "font-stretch" and "font-size-adjust". Then, those properties
+ * that are given explicit values in the "font" shorthand are set
+ * to those values. For a definition of allowed and initial values,
+ * see the previously defined properties. For reasons of backward
+ * compatibility, it is not possible to set "font-stretch" and
+ * "font-size-adjust" to other than their initial values using the
+ * "font" shorthand property; instead, set the individual properties.
+ * <br>ENDQUOTE
+ *
+ * <p>The setup of the shorthand expansion list is determined by the
+ * above considerations.
*/
public static PropertyValue verifyParsing
(FOTree foTree, PropertyValue value)
throws PropertyException
{
+ PropertyValueList startList = null;
+ PropertyValueList fontList = null;
if ( ! (value instanceof PropertyValueList)) {
return processValue(foTree, value);
} else {
- PropertyValueList list = null;
+ fontList = (PropertyValueList)value;
try {
- list = spaceSeparatedList((PropertyValueList)value);
+ startList = spaceSeparatedList(fontList);
+ // A space-separated list. Only the last item(s) can
+ // be part of the font-family-specifier
+ // Remove the space-separated list element (the only
+ // element) from fontList, so that the then-empty
+ // fontList can serve as the
+ // cachement list for font-family elements discovered
+ // at the end of startList
+ fontList.removeFirst();
} catch (PropertyException e) {
- throw new PropertyException
- ("Isolated comma-separated list (possibly a "
- + "font-family) found in font expression");
+ // Must be a comma-separated list
+ // Pop the first element off the list; this will then
+ // be equivalent to the space-separated list above.
+ // Keep the remainder as the seed for a list argument
+ // to the FontFamily verifier
+ // Note the assumption that the list is not empty.
+ // This is consistent with the values returned from the
+ // parser.
+ Object tmpo = fontList.removeFirst();
+ // This MUST be a list, because it must contain both the
+ // font-family element preceding the implict COMMA which
+ // separated the original elements, and at least a
+ // font-size element
+ if ( ! (tmpo instanceof PropertyValueList))
+ throw new PropertyException
+ ("No space-separated list preceding COMMA in "
+ + "'font' expression");
+ startList = (PropertyValueList)tmpo;
}
- return processSpaceSepList(foTree, list);
+ return processSpaceSepList(foTree, startList, fontList);
}
}
@@ -3673,17 +3769,15 @@
}
/**
- * The space separated list must end with a font-family specifier.
- * This may be a single font, in which case there will be no comma
- * separated sublist(s) as the final element(s) of the list.
- * <p>However, because font names may contain spaces and may be
- * specified "raw", without enclosing quotes, the comma-separated
- * sublists may be surrounded with space-separated elements which
- * are also part of the font-family list.
- * <p>I.e. all elements from the first comma-separated sublist to the
- * end of the list are part of the font-family value. In addition,
- * however, some preceding elements may be part of an initial
- * font name containing spaces.
+ * The space separated <i>list</i> must end with the first or only
+ * font named in the font-family specifier of the font expression.<br>
+ * The comma-separated <i>fontList</i> contains the second and
+ * subsequent font names from the font-family specifier in the font
+ * expression, or is empty.<br>
+ * <p>Because font names may contain spaces and may be
+ * specified "raw", without enclosing quotes, the font name which
+ * ends the <i>list</i> may occupy more than one element at the end
+ * of the <i>list</i>.
* <p>The font-family is preceded by a compulsory size/height element;
* font-size [ / line-height ]?, so searching backwards for a slash
* character will locate the penultimate and utlimate elements
@@ -3697,20 +3791,28 @@
*
* @param list a <tt>PropertyValueList</tt> containing the actual
* space-separated list; i.e. the single inner list from the
- * outer list returned by the parser.
+ * outer list returned by the parser. or removed from the front of
+ * a comma-separated list.
+ * @param fontList a <tt>PropertyValueList</tt> containing any
+ * font-family elements which followed the first comma of the font
+ * expression. This list may be empty (but is not null) in the case
+ * where there was only one font-family element specified.
* @return <tt>PropertyValueList</tt> containing a
* <tt>PropertyValue</tt> for each property in the expansion of the
* shorthand.
* @exception PropertyValueException
*/
private static PropertyValueList
- processSpaceSepList(FOTree foTree, PropertyValueList list)
+ processSpaceSepList(FOTree foTree,
+ PropertyValueList list,
+ PropertyValueList fontList)
throws PropertyException
{
PropertyValueList newlist = null;
// copy the list into an array for random access
Object[] props = list.toArray();
+ PropertyValue[] propvals = new PropertyValue[props.length];
int slash = -1;
int firstcomma = -1;
int familyStart = -1;
@@ -3719,18 +3821,19 @@
PropertyValue style = null;
PropertyValue variant = null;
PropertyValue weight = null;
- Numeric size = null;
- Numeric height = null;
- FontFamilySet fontset = null;
+ PropertyValue size = null;
+ PropertyValue height = null;
+ PropertyValue fontset = null;
for (int i = 0; i < props.length; i++) {
- if (props[i] instanceof Slash)
+ propvals[i] = (PropertyValue)(props[i]);
+ if (propvals[i] instanceof Slash)
slash = i;
- else if (props[i] instanceof PropertyValueList
+ else if (propvals[i] instanceof PropertyValueList
&& firstcomma == -1)
firstcomma = i;
}
- if (slash != -1 && slash >= (props.length -2))
+ if (slash != -1 && slash >= (propvals.length -2))
throw new PropertyException
("Invalid slash position in font list");
if (slash != -1) {
@@ -3738,19 +3841,26 @@
// font-family begins at slash + 2
familyStart = slash + 2;
fontsize = slash - 1;
+ size = FontSize.verifyParsing(foTree, propvals[fontsize]);
// derive the line-height
+ // line-height is at slash + 1
+ height = LineHeight.verifyParsing
+ (foTree, propvals[slash + 1]);
+ if (size instanceof Inherit || height instanceof Inherit)
+ throw new PropertyException
+ ("'inherit' found in font-size/line-height part "
+ + "of 'font' shorthand expression");
} else {
// Don''t know where slash is. If anything precedes the
// font-family, it must be a font-size. Look for that.
- if (firstcomma == -1) firstcomma = props.length - 1;
+ if (firstcomma == -1) firstcomma = propvals.length - 1;
for (fontsize = firstcomma - 1; fontsize >= 0; fontsize--) {
- if (props[fontsize] instanceof NCName) {
+ if (propvals[fontsize] instanceof NCName) {
// try for a font-size enumeration
- String name = ((NCName)props[fontsize]).getNCName();
+ String name = ((NCName)propvals[fontsize]).getNCName();
try {
- size = (new MappedNumeric
- (PropNames.FONT_SIZE, name, foTree)
- ).getMappedNumValue();
+ size = new MappedNumeric
+ (PropNames.FONT_SIZE, name, foTree);
} catch (PropertyException e) {
// Attempt to derive mapped numeric failed
continue;
@@ -3758,10 +3868,10 @@
// Presumably we have a mapped numeric
break;
}
- if (props[fontsize] instanceof Numeric) {
+ if (propvals[fontsize] instanceof Numeric) {
// Length (incl. Ems) or Percentage allowed
- if (((Numeric)(props[fontsize])).isDistance()) {
- size = (Numeric)(props[fontsize]);
+ if (((Numeric)(propvals[fontsize])).isDistance()) {
+ size = propvals[fontsize];
break;
}
// else don't know what this Numeric is doing here -
@@ -3772,15 +3882,107 @@
}
// Not an NCName, not a Numeric. What the ... ?
throw new PropertyException
- (props[fontsize].getClass().getName() +
+ (propvals[fontsize].getClass().getName() +
" found in 'font' "
+ "expression while looking for font-size");
}
// Indicate start of font-family.
if (size != null) familyStart = fontsize + 1;
- else /* no font-size found */ familyStart = 0;
+ else // no font-size found
+ // A font-size[/line-height] element is compulsory
+ throw new PropertyException
+ ("Required 'font-size' element not found in 'font'"
+ + " shorthand");
+ }
+ // Attempt to derive the FontFamilySet
+ // The discovered font or font-family name must be prepended to
+ // the fontList. If the font name is a single element, and the
+ // fontList is empty, only that single element is passed to the
+ // verifyParsing() method of FontFamily. Otherwise the font
+ // name element or elements is formed into a PropertyValueList,
+ // and that list is prepended to fontList.
+ if (fontList.size() == 0
+ && familyStart == (propvals.length - 1)) {
+ if (propvals[familyStart] instanceof Inherit)
+ throw new PropertyException
+ ("'inherit' found in font-family part "
+ + "of 'font' shorthand expression");
+ fontset =
+ FontFamily.verifyParsing(foTree, propvals[familyStart]);
+ } else {
+ // Must develop a list to prepend to fontList
+ PropertyValueList tmpList =
+ new PropertyValueList(PropNames.FONT_FAMILY);
+ for (int i = familyStart; i < propvals.length; i++)
+ tmpList.add(propvals[i]);
+ fontList.addFirst(tmpList);
+ // Get a FontFamilySet
+ fontset = FontFamily.verifyParsing(foTree, fontList);
+ }
+ // Only font-style font-variant and font-weight, in any order
+ // remain as possibilities at the front of the expression
+ for (int i = 0; i < fontsize; i++) {
+ PropertyValue pv = null;
+ if (propvals[i] instanceof Inherit)
+ throw new PropertyException
+ ("'inherit' found in 'font' expression");
+ try {
+ pv = FontStyle.verifyParsing(foTree, propvals[i]);
+ if (style != null)
+ MessageHandler.log("font: duplicate" +
+ "style overrides previous style");
+ style = pv;
+ } catch(PropertyException e) {}
+
+ try {
+ pv = FontVariant.verifyParsing(foTree, propvals[i]);
+ if (variant != null)
+ MessageHandler.log("font: duplicate" +
+ "variant overrides previous variant");
+ variant = pv;
+ } catch(PropertyException e) {}
+
+ try {
+ pv = FontWeight.verifyParsing(foTree, propvals[i]);
+ if (weight != null)
+ MessageHandler.log("font: duplicate" +
+ "weight overrides previous weight");
+ weight = pv;
+ } catch(PropertyException e) {}
+
+ }
+ // Construct the shorthand expansion list from the discovered
+ // values of individual components
+
+ newlist =
+ PropertySets.initialValueExpansion(foTree, PropNames.FONT);
+ // For each discovered property, override the value in the
+ // initial value expansion.
+ ListIterator expansions = newlist.listIterator();
+ while (expansions.hasNext()) {
+ PropertyValue prop = (PropertyValue)expansions.next();
+ switch (prop.getProperty()) {
+ case PropNames.FONT_STYLE:
+ if (style != null) expansions.set(style);
+ break;
+ case PropNames.FONT_VARIANT:
+ if (variant != null) expansions.set(variant);
+ break;
+ case PropNames.FONT_WEIGHT:
+ if (weight != null) expansions.set(weight);
+ break;
+ case PropNames.FONT_SIZE:
+ if (size != null) expansions.set(size);
+ break;
+ case PropNames.FONT_FAMILY:
+ if (fontset != null) expansions.set(fontset);
+ break;
+ case PropNames.LINE_HEIGHT:
+ if (height != null) expansions.set(height);
+ break;
+ }
}
-
+
return newlist;
}
}
@@ -4084,7 +4286,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger (PropNames.FONT_WEIGHT, 400);
+ return new IntegerType(PropNames.FONT_WEIGHT, 400);
}
public static final int inherited = COMPUTED;
@@ -4098,6 +4300,23 @@
};
public static final ROStringArray enums = new ROStringArray(rwEnums);
public static final ROStringArray enumValues = enums;
+
+ public static PropertyValue verifyParsing
+ (FOTree foTree, PropertyValue value)
+ throws PropertyException
+ {
+ // Override the shadowed method to ensure that Integer values
+ // are limited to the valid numbers
+ PropertyValue fw = Properties.verifyParsing(foTree, value);
+ // If the result is an IntegerType, restrict the values
+ if (fw instanceof IntegerType) {
+ int weight = ((IntegerType)fw).getInt();
+ if (weight % 100 != 0 || weight < 100 || weight > 900)
+ throw new PropertyException
+ ("Invalid integer font-weight value: " + weight);
+ }
+ return fw;
+ }
}
public static class ForcePageCount extends Properties {
@@ -4153,7 +4372,8 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return Angle.makeAngle (PropNames.GLYPH_ORIENTATION_HORIZONTAL, 0d,
Angle.DEG);
+ return new Angle(PropNames.GLYPH_ORIENTATION_HORIZONTAL,
+ Angle.DEG, 0d);
}
public static final int inherited = COMPUTED;
}
@@ -4738,7 +4958,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger (PropNames.LINE_HEIGHT_PRECEDENCE, 0);
+ return new IntegerType(PropNames.LINE_HEIGHT_PRECEDENCE, 0);
}
public static final int inherited = COMPOUND;
@@ -5040,7 +5260,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger(PropNames.ORPHANS, 2);
+ return new IntegerType(PropNames.ORPHANS, 2);
}
public static final int inherited = COMPUTED;
@@ -5510,7 +5730,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger (PropNames.REFERENCE_ORIENTATION, 0);
+ return new IntegerType(PropNames.REFERENCE_ORIENTATION, 0);
}
public static final int inherited = COMPUTED;
@@ -5953,7 +6173,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger (PropNames.SPACE_AFTER_PRECEDENCE, 0);
+ return new IntegerType(PropNames.SPACE_AFTER_PRECEDENCE, 0);
}
public static final int inherited = COMPOUND;
@@ -6029,7 +6249,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger (PropNames.SPACE_BEFORE_PRECEDENCE, 0);
+ return new IntegerType(PropNames.SPACE_BEFORE_PRECEDENCE, 0);
}
public static final int inherited = COMPOUND;
@@ -6105,7 +6325,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger (PropNames.SPACE_END_PRECEDENCE, 0);
+ return new IntegerType(PropNames.SPACE_END_PRECEDENCE, 0);
}
public static final int inherited = COMPOUND;
@@ -6181,7 +6401,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger (PropNames.SPACE_START_PRECEDENCE, 0);
+ return new IntegerType(PropNames.SPACE_START_PRECEDENCE, 0);
}
public static final int inherited = COMPOUND;
@@ -6957,7 +7177,7 @@
public static PropertyValue getInitialValue(int property)
throws PropertyException
{
- return IntegerType.makeInteger(PropNames.WIDOWS, 2);
+ return new IntegerType(PropNames.WIDOWS, 2);
}
public static final int inherited = COMPUTED;
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]