From 8384a7fb718ade0bb485ce7bb1caed81ac2a4f62 Mon Sep 17 00:00:00 2001 From: Karen Lease Date: Sun, 4 Mar 2001 21:29:46 +0000 Subject: [PATCH] Support for border-related shorthand properties and PropertyManager delegate object git-svn-id: https://svn.apache.org/repos/asf/xmlgraphics/fop/trunk@194124 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/fop/fo/BoxPropShorthandParser.java | 35 ++++ src/org/apache/fop/fo/EnumProperty.java | 5 + src/org/apache/fop/fo/FObj.java | 24 +-- .../apache/fop/fo/GenericShorthandParser.java | 50 ++++++ src/org/apache/fop/fo/ListProperty.java | 35 ++++ src/org/apache/fop/fo/Property.java | 45 ++++++ src/org/apache/fop/fo/PropertyList.java | 83 +++++++++- .../apache/fop/fo/PropertyListBuilder.java | 13 +- src/org/apache/fop/fo/PropertyManager.java | 153 ++++++++++++++++++ src/org/apache/fop/fo/ShorthandParser.java | 6 + 10 files changed, 431 insertions(+), 18 deletions(-) create mode 100644 src/org/apache/fop/fo/BoxPropShorthandParser.java create mode 100644 src/org/apache/fop/fo/GenericShorthandParser.java create mode 100644 src/org/apache/fop/fo/ListProperty.java create mode 100644 src/org/apache/fop/fo/PropertyManager.java create mode 100644 src/org/apache/fop/fo/ShorthandParser.java diff --git a/src/org/apache/fop/fo/BoxPropShorthandParser.java b/src/org/apache/fop/fo/BoxPropShorthandParser.java new file mode 100644 index 000000000..362d4e04c --- /dev/null +++ b/src/org/apache/fop/fo/BoxPropShorthandParser.java @@ -0,0 +1,35 @@ +package org.apache.fop.fo; + +import org.apache.fop.apps.FOPException; + +public class BoxPropShorthandParser extends GenericShorthandParser { + + public BoxPropShorthandParser(ListProperty listprop) { + super(listprop); + } + + // Stores 1 to 4 values of same type + // Set the given property based on the number of values set + // Example: padding, border-width, border-color, border-style, margin + protected Property convertValueForProperty(String propName, + Property.Maker maker, PropertyList propertyList) { + Property p = null; + if (propName.indexOf("-top") >= 0) { + p = getElement(0); + } + else if (propName.indexOf("-right") >= 0) { + p = getElement(count()>1? 1:0); + } + else if (propName.indexOf("-bottom") >= 0) { + p = getElement(count()>2? 2:0); + } + else if (propName.indexOf("-left") >= 0) { + p = getElement(count()>3? 3: (count()>1?1:0)); + } + // if p not null, try to convert it to a value of the correct type + if (p != null) { + return maker.convertShorthandProperty(propertyList, p, null); + } + return p; + } +} diff --git a/src/org/apache/fop/fo/EnumProperty.java b/src/org/apache/fop/fo/EnumProperty.java index 0a46c6e53..41a519491 100644 --- a/src/org/apache/fop/fo/EnumProperty.java +++ b/src/org/apache/fop/fo/EnumProperty.java @@ -75,6 +75,11 @@ public class EnumProperty extends Property { return null; } + public Property convertProperty(Property p, + PropertyList propertyList, FObj fo) throws FOPException { + if (p instanceof EnumProperty) return p; + else return null; + } } private int value; diff --git a/src/org/apache/fop/fo/FObj.java b/src/org/apache/fop/fo/FObj.java index 2011ef140..053758b11 100644 --- a/src/org/apache/fop/fo/FObj.java +++ b/src/org/apache/fop/fo/FObj.java @@ -78,17 +78,23 @@ public class FObj extends FONode { // protected PropertyList properties; public PropertyList properties; + protected PropertyManager propMgr; protected String name; protected FObj(FObj parent, PropertyList propertyList) { super(parent); - this.properties = propertyList; + this.properties = propertyList; // TO BE REMOVED!!! propertyList.setFObj(this); + this.propMgr = makePropertyManager(propertyList); this.name = "default FO"; setWritingMode(); } + protected PropertyManager makePropertyManager(PropertyList propertyList) { + return new PropertyManager(propertyList); + } + /** * adds characters (does nothing here) * @param data text @@ -187,17 +193,15 @@ public class FObj extends FONode { * Set writing mode for this FO. * Find nearest ancestor, including self, which generates * reference areas and use the value of its writing-mode property. + * If no such ancestor is found, use the value on the root FO. */ private void setWritingMode() { - FObj p = this; - while (p!= null && !p.generatesReferenceAreas()) - p = p.getParent(); - if (p != null) { - this.properties.setWritingMode(p.getProperty("writing-mode").getEnum()); - } - else { - // shouldn't happen!!! - } + FObj p ; + FObj parent; + for (p=this; + !p.generatesReferenceAreas() && (parent = p.getParent()) != null; + p=parent); + this.properties.setWritingMode(p.getProperty("writing-mode").getEnum()); } diff --git a/src/org/apache/fop/fo/GenericShorthandParser.java b/src/org/apache/fop/fo/GenericShorthandParser.java new file mode 100644 index 000000000..90f2b725d --- /dev/null +++ b/src/org/apache/fop/fo/GenericShorthandParser.java @@ -0,0 +1,50 @@ +package org.apache.fop.fo; + +import java.util.Vector; +import java.util.Enumeration; + +public class GenericShorthandParser implements ShorthandParser { + + protected Vector list; // Vector of Property objects + + public GenericShorthandParser(ListProperty listprop) { + this.list=listprop.getList(); + } + + protected Property getElement(int index) { + if (list.size() > index) return (Property)list.elementAt(index); + else return null; + } + + protected int count() { + return list.size(); + } + + // Stores 1 to 3 values for border width, style, color + // Used for: border, border-top, border-right etc + public Property getValueForProperty(String propName, Property.Maker maker, + PropertyList propertyList) { + Property prop = null; + // Check for keyword "inherit" + if (count() == 1) { + String sval = ((Property)list.elementAt(0)).getString(); + if (sval != null && sval.equals("inherit")) { + return propertyList.getFromParent(propName); + } + } + return convertValueForProperty(propName, maker, propertyList); + } + + + protected Property convertValueForProperty(String propName, Property.Maker maker, + PropertyList propertyList) { + Property prop = null; + // Try each of the stored values in turn + Enumeration eprop = list.elements(); + while (eprop.hasMoreElements() && prop == null) { + Property p = (Property)eprop.nextElement(); + prop = maker.convertShorthandProperty(propertyList, p, null); + } + return prop; + } +} diff --git a/src/org/apache/fop/fo/ListProperty.java b/src/org/apache/fop/fo/ListProperty.java new file mode 100644 index 000000000..6c76a1ef7 --- /dev/null +++ b/src/org/apache/fop/fo/ListProperty.java @@ -0,0 +1,35 @@ +package org.apache.fop.fo; + +import java.util.Vector; + +public class ListProperty extends Property { + + public static class Maker extends Property.Maker { + + public Maker(String name) { + super(name); + } + + public Property convertProperty(Property p, PropertyList propertyList, + FObj fo) { + if (p instanceof ListProperty) + return p; + else return new ListProperty(p); + } + } + + protected Vector list; + + public ListProperty(Property prop) { + list = new Vector(); + list.addElement(prop); + } + + public void addProperty(Property prop) { + list.addElement(prop); + } + + public Vector getList() { return list; } + public Object getObject() { return list; } + +} diff --git a/src/org/apache/fop/fo/Property.java b/src/org/apache/fop/fo/Property.java index f2fe1bb09..3319ab7dd 100644 --- a/src/org/apache/fop/fo/Property.java +++ b/src/org/apache/fop/fo/Property.java @@ -57,6 +57,7 @@ import org.apache.fop.fo.expr.PropertyParser; import org.apache.fop.fo.expr.PropertyInfo; import org.apache.fop.fo.expr.PropertyException; import org.apache.fop.apps.FOPException; +import java.util.Vector; public class Property { @@ -231,6 +232,45 @@ public class Property { } } + public Property convertShorthandProperty(PropertyList propertyList, + Property prop, FObj fo) + { + Property pret = null; + try { + pret = convertProperty(prop, propertyList, fo); + if (pret == null) { + // If value is a name token, may be keyword or Enum + String sval = prop.getNCname(); + if (sval != null) { + // System.err.println("Convert shorthand ncname " + sval); + pret = checkEnumValues(sval); + if (pret == null) { + /* Check for keyword shorthand values to be substituted. */ + String pvalue = checkValueKeywords(sval); + if (!pvalue.equals(sval)) { + // System.err.println("Convert shorthand keyword" + pvalue); + // Substituted a value: must parse it + Property p = PropertyParser.parse(pvalue, + new PropertyInfo(this, propertyList, fo)); + pret = convertProperty(p, propertyList, fo); + } + } + } + } + } catch (FOPException e) { + + MessageHandler.errorln("convertShorthandProperty caught FOPException " + e); + } + catch (org.apache.fop.fo.expr.PropertyException propEx) { + MessageHandler.errorln("convertShorthandProperty caught PropertyException " + propEx); + } + if (pret != null) { + /* System.err.println("Return shorthand value " + pret.getString() + + " for " + getPropName());*/ + } + return pret; + } + protected boolean isCompoundMaker() { return false; } @@ -333,6 +373,10 @@ public class Property { return false; } + public Property getShorthand(PropertyList propertyList) { + return null; + } + } // end of nested Maker class /** The original specified value for properties which inherit @@ -370,6 +414,7 @@ public class Property { */ public int getEnum() { return 0; } public char getCharacter() { return 0;} + public Vector getList() { return null; } // List of Property objects public Number getNumber() { return null; } diff --git a/src/org/apache/fop/fo/PropertyList.java b/src/org/apache/fop/fo/PropertyList.java index d3bf0541f..52109d4fb 100644 --- a/src/org/apache/fop/fo/PropertyList.java +++ b/src/org/apache/fop/fo/PropertyList.java @@ -119,9 +119,56 @@ public class PropertyList extends Hashtable { /** * Return the value explicitly specified on this FO. * @param propertyName The name of the property whose value is desired. + * It may be a compound name, such as space-before.optimum. + * @return The value if the property is explicitly set or set by + * a shorthand property, otherwise null. + */ + public Property getExplicitOrShorthand(String propertyName) { + /* Handle request for one part of a compound property */ + int sepchar = propertyName.indexOf('.'); + String baseName; + if (sepchar > -1) { + baseName = propertyName.substring(0,sepchar); + } + else baseName = propertyName; + Property p =getExplicitBaseProp(baseName); + if (p == null) { + p = builder.getShorthand(this, namespace, element, baseName); + } + if (p != null && sepchar > -1) { + return builder.getSubpropValue(namespace, element, baseName, + p, propertyName.substring(sepchar+1)); + } + return p; + } + + /** + * Return the value explicitly specified on this FO. + * @param propertyName The name of the property whose value is desired. + * It may be a compound name, such as space-before.optimum. * @return The value if the property is explicitly set, otherwise null. */ public Property getExplicit(String propertyName) { + /* Handle request for one part of a compound property */ + int sepchar = propertyName.indexOf('.'); + if (sepchar > -1) { + String baseName = propertyName.substring(0,sepchar); + Property p =getExplicitBaseProp(baseName); + if (p != null) { + return this.builder.getSubpropValue(namespace, element, baseName, + p, propertyName.substring(sepchar+1)); + } + else return null; + } + return (Property)super.get(propertyName); + } + + /** + * Return the value explicitly specified on this FO. + * @param propertyName The name of the base property whose value is desired. + * @return The value if the property is explicitly set, otherwise null. + */ + public Property getExplicitBaseProp(String propertyName) { return (Property)super.get(propertyName); } @@ -158,25 +205,37 @@ public class PropertyList extends Hashtable { * we try to compute it from the corresponding relative property: this * happends in computeProperty. */ - private Property findProperty(String propertyName) { + private Property findProperty(String propertyName, boolean bTryInherit) { Property p = null; if (builder.isCorrespondingForced(this, namespace, element, propertyName)) { p = builder.computeProperty(this,namespace, element, propertyName); } else { - p = getExplicit(propertyName); + p = getExplicitBaseProp(propertyName); if (p == null) { p = this.builder.computeProperty(this,namespace, element, propertyName); } - if (p == null) { // else inherit (if has parent and is inheritable) + if (p == null) { // check for shorthand specification + p = builder.getShorthand(this, namespace, element, propertyName); + } + if (p == null && bTryInherit) { // else inherit (if has parent and is inheritable) if (this.parentPropertyList != null && builder.isInherited(namespace, element, propertyName)) { - p = parentPropertyList.findProperty(propertyName); + p = parentPropertyList.findProperty(propertyName, true); } } } return p; } + + + /** + * Return the property on the current FlowObject if it is specified, or if a + * corresponding property is specified. If neither is specified, it returns null. + */ + public Property getSpecified(String propertyName) { + return get(propertyName, false, false); + } /** @@ -186,6 +245,16 @@ public class PropertyList extends Hashtable { * the default value. */ public Property get(String propertyName) { + return get(propertyName, true, true); + } + + /** + * Return the property on the current FlowObject. Depending on the passed flags, + * this will try to compute it based on other properties, or if it is + * inheritable, to return the inherited value. If all else fails, it returns + * the default value. + */ + private Property get(String propertyName, boolean bTryInherit, boolean bTryDefault) { if (builder == null) MessageHandler.errorln("OH OH, builder has not been set"); @@ -198,15 +267,15 @@ public class PropertyList extends Hashtable { propertyName = propertyName.substring(0,sepchar); } - Property p = findProperty(propertyName); - if (p == null) { // default value for this FO! + Property p = findProperty(propertyName, bTryInherit); + if (p == null && bTryDefault) { // default value for this FO! try { p = this.builder.makeProperty(this,namespace, element,propertyName); } catch (FOPException e) { // don't know what to do here } } - if (subpropName != null) { + if (subpropName != null && p != null) { return this.builder.getSubpropValue(namespace, element, propertyName, p, subpropName); } diff --git a/src/org/apache/fop/fo/PropertyListBuilder.java b/src/org/apache/fop/fo/PropertyListBuilder.java index c4da11f1b..d7eaa7941 100644 --- a/src/org/apache/fop/fo/PropertyListBuilder.java +++ b/src/org/apache/fop/fo/PropertyListBuilder.java @@ -175,7 +175,7 @@ public class PropertyListBuilder { if (propertyMaker != null) { try { if (subpropName != null) { - Property baseProp = p.getExplicit(propName); + Property baseProp = p.getExplicitBaseProp(propName); if (baseProp == null) { // See if it is specified later in this list String baseValue = attributes.getValue(propName); @@ -227,6 +227,17 @@ public class PropertyListBuilder { return false; } + public Property getShorthand(PropertyList propertyList, String space, + String element, String propertyName) { + Property.Maker propertyMaker = findMaker(space, element, propertyName); + if (propertyMaker != null) { + return propertyMaker.getShorthand(propertyList); + } else { + MessageHandler.errorln("WARNING: no Maker for " + propertyName); + return null; + } + } + public Property makeProperty(PropertyList propertyList, String space, String element, String propertyName) throws FOPException { diff --git a/src/org/apache/fop/fo/PropertyManager.java b/src/org/apache/fop/fo/PropertyManager.java new file mode 100644 index 000000000..ed8a2c56e --- /dev/null +++ b/src/org/apache/fop/fo/PropertyManager.java @@ -0,0 +1,153 @@ +/*-- $Id$ -- */ +/* + * Copyright (C) 2001 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.fo; + +import org.apache.fop.layout.FontState; +import org.apache.fop.layout.FontInfo; +import org.apache.fop.layout.BorderAndPadding; +import org.apache.fop.fo.properties.BreakBefore; +import org.apache.fop.fo.properties.Constants; +import org.apache.fop.layout.HyphenationProps; +import org.apache.fop.apps.FOPException; +import java.text.MessageFormat; +import java.text.FieldPosition; + +public class PropertyManager { + + private PropertyList properties; + private FontState fontState=null; + private BorderAndPadding borderAndPadding = null; + private HyphenationProps hyphProps = null; + + private String[] saLeft ; + private String[] saRight; + private String[] saTop ; + private String[] saBottom ; + + private static MessageFormat msgColorFmt = new MessageFormat("border-{0}-color"); + private static MessageFormat msgStyleFmt = new MessageFormat("border-{0}-style"); + private static MessageFormat msgWidthFmt = new MessageFormat("border-{0}-width"); + private static MessageFormat msgPaddingFmt = new MessageFormat("padding-{0}"); + + public PropertyManager(PropertyList pList) { + this.properties = pList; + } + + private void initDirections() { + saLeft = new String[1]; + saRight = new String[1]; + saTop = new String[1]; + saBottom = new String[1]; + saTop[0] = properties.wmAbsToRel(PropertyList.TOP); + saBottom[0] = properties.wmAbsToRel(PropertyList.BOTTOM); + saLeft[0] = properties.wmAbsToRel(PropertyList.LEFT); + saRight[0] = properties.wmAbsToRel(PropertyList.RIGHT); + } + + public FontState getFontState(FontInfo fontInfo) throws FOPException { + if (fontState == null) { + String fontFamily = properties.get("font-family").getString(); + String fontStyle =properties.get("font-style").getString(); + String fontWeight =properties.get("font-weight").getString(); + // NOTE: this is incomplete. font-size may be specified with + // various kinds of keywords too + int fontSize =properties.get("font-size").getLength().mvalue(); + int fontVariant =properties.get("font-variant").getEnum(); + // fontInfo is same for the whole FOP run but set in all FontState + fontState = new FontState(fontInfo, fontFamily, + fontStyle, fontWeight, fontSize, fontVariant); + } + return fontState ; + } + + + public BorderAndPadding getBorderAndPadding() { + if (borderAndPadding == null) { + this.borderAndPadding = new BorderAndPadding(); + initDirections(); + + initBorderInfo(BorderAndPadding.TOP, saTop); + initBorderInfo(BorderAndPadding.BOTTOM, saBottom); + initBorderInfo(BorderAndPadding.LEFT, saLeft); + initBorderInfo(BorderAndPadding.RIGHT, saRight); + + /**** + // Border color + this.borderAndPadding.borderTopColor = + properties.get(msgFmt.format(saTop)).getColorType(); + this.borderAndPadding.borderBottomColor = + properties.get(msgFmt.format(saBottom)).getColorType(); + this.borderAndPadding.borderLeftColor = + properties.get(msgFmt.format(saLeft)).getColorType(); + this.borderAndPadding.borderRightColor = + properties.get(msgFmt.format(saRight)).getColorType(); + + // Border style + this.borderAndPadding.borderTopStyle = + properties.get(msgFmt.format(saTop)).getEnum(); + this.borderAndPadding.borderBottomStyle = + properties.get(msgFmt.format(saBottom)).getEnum(); + this.borderAndPadding.borderLeftStyle = + properties.get(msgFmt.format(saLeft)).getEnum(); + this.borderAndPadding.borderRightStyle = + properties.get(msgFmt.format(saRight)).getEnum(); + + // Border width + this.borderAndPadding.borderTopWidth = + properties.get(msgFmt.format(saTop)).getCondLength(); + this.borderAndPadding.borderBottomWidth = + properties.get(msgFmt.format(saBottom)).getCondLength(); + this.borderAndPadding.borderLeftWidth = + properties.get(msgFmt.format(saLeft)).getCondLength(); + this.borderAndPadding.borderRightWidth = + properties.get(msgFmt.format(saRight)).getCondLength(); + ****/ + } + return borderAndPadding; + } + + private void initBorderInfo(int whichSide, String[] saSide) { + borderAndPadding.setPadding(whichSide, + properties.get(msgPaddingFmt.format(saSide)).getCondLength()); + // If style = none, force width to 0, don't get Color + int style = properties.get(msgStyleFmt.format(saSide)).getEnum(); + if (style != Constants.NONE) { + borderAndPadding.setBorder(whichSide, style, + properties.get(msgWidthFmt.format(saSide)).getCondLength(), + properties.get(msgColorFmt.format(saSide)).getColorType()); + } + } + + public HyphenationProps getHyphenationProps() { + if (hyphProps == null) { + this.hyphProps = new HyphenationProps(); + hyphProps.hyphenate = this.properties.get("hyphenate").getEnum(); + hyphProps.hyphenationChar = this.properties.get("hyphenation-character").getCharacter(); + hyphProps.hyphenationPushCharacterCount = this.properties.get( "hyphenation-push-character-count").getNumber().intValue(); + hyphProps.hyphenationRemainCharacterCount = this.properties.get( "hyphenation-remain-character-count").getNumber().intValue(); + hyphProps.language = this.properties.get("language").getString(); + hyphProps.country = this.properties.get("country").getString(); + } + return hyphProps; + } + + public int checkBreakBefore() { + switch(properties.get("break-before").getEnum()) { + case BreakBefore.PAGE: + return Status.FORCE_PAGE_BREAK; + case BreakBefore.ODD_PAGE: + return Status.FORCE_PAGE_BREAK_ODD; + case BreakBefore.EVEN_PAGE: + return Status.FORCE_PAGE_BREAK_EVEN; + case BreakBefore.COLUMN: + return Status.FORCE_COLUMN_BREAK; + default: + return Status.OK; + } + } + +} diff --git a/src/org/apache/fop/fo/ShorthandParser.java b/src/org/apache/fop/fo/ShorthandParser.java new file mode 100644 index 000000000..a8a9a55b8 --- /dev/null +++ b/src/org/apache/fop/fo/ShorthandParser.java @@ -0,0 +1,6 @@ +package org.apache.fop.fo; + +public interface ShorthandParser { + public Property getValueForProperty(String propName, Property.Maker maker, + PropertyList propertyList); +} -- 2.39.5