Differences between revisions 1 and 2
Revision 1 as of 2005-03-22 05:54:03
Size: 9933
Editor: anonymous
Comment: missing edit-log entry for this revision
Revision 2 as of 2009-09-20 23:52:37
Size: 9933
Editor: localhost
Comment: converted to 1.6 markup
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
Back to ["FOPProjectPages"] Back to [[FOPProjectPages]]

Back to FOPProjectPages


Integrating Alt-Design FO Tree into Redesign

Bridging the 0.20.0 -> 0.20.5 gap

Cleaning up org.apache.fop.apps

The org.apache.fop.apps package, in particular requires upgrading to compatibility with 0.20.5. To work on alt.design, the apps code at the time of branching was mercilessy hacked to provide a minimal front-end for alt.design. Logging, for instance, is still performed by MessageHandler.

Checkstyle

Anyone with an interest in the integration, but cautious about approaching the code would do a great service by cleaning the alt.design codebase up with Checkstyle. I have recently been developing with Eclipse and the 3.1.1 Checkstyle plugin, so a basic environment for such a cleanup process now exists.

Issues in the alt.design code

Tidying existing structure

  • Add corresponding properties handling
    • The properties all have unique integer values in alt.design, and for most purposes the properties are represented by these integer indices. The correspondence between property and integer is defined in { { { fo/PropNames.java } } }. This list also defines the order in which property attributes on FOs are processed. The list begins

    public static final int 
                                    NO_PROPERTY = 0, 
            // Properties setting up environment for from-table-column(), 
            // e.g. font-size = from-table-column() 
                                  COLUMN_NUMBER = 1, 
                         NUMBER_COLUMNS_SPANNED = 2, 
            // Properties setting font-size first 
            // Shorthand first 
                                           FONT = 3, 
                                      FONT_SIZE = 4, 
            // Writing mode early for handling of corresponding values 
                                   WRITING_MODE = 5, 
            // All other shorthands 
  • After the shorthands are defined, comes this comment and the remainder of the properties:

            // Non-shorthand properties 
            // Within these, compounds precede their components 
            // and corresponding relative properties 
            // precede corresponding absolute properties 
  • All of this should ensure that, when a property with corresponding properties is processed all other values required for the resolution of those corresponding properties will have been resolved.
  • Attributes (property values) are handled in { { { fo/FoNode.processAttributes() } } }. This method cycles through attributes defined on an FO node in numerical property order. The point at which I originally intended corresponding property processing to occur is indicated by the comment

                    // Handle corresponding properties here 
  • in two places.
  • Extend the initial handling of markers to all affected FO classes.
    • Only some of the FO classes which allow initial markers are noticing them. { { { flow/FoTable.java } } } provides an example of initial marker handling.

            /** The number of markers on this FO. */ 
            private int numMarkers = 0; 

            ... 
            while ((ev = xmlevents.expectStartElement 
                    (FObjectNames.MARKER, XMLEvent.DISCARD_W_SPACE)) 
                   != null) { 
                new FoMarker(getFOTree(), this, ev, stateFlags); 
                numMarkers++; 
                ev = xmlevents.getEndElement(xmlevents.DISCARD_EV, ev); 
                pool.surrenderEvent(ev); 
  • Marker handling is simply deferred at this level.  { { { numMarkers } } }  indicates the number of initial children of the  { { { FoTable } } }  node which are markers.

  • Cleaning up validation of data types
    • { { { fo/properties/Property.refineParsing() } } } contains the following code:

        case PropertyValue.FROM_PARENT: 
            pv = ((FromParent)value).resolve(foNode); 
            if (pv == value) return value;  // unable to resolve 
            // TODO: validate here 
            return pv; 
        case PropertyValue.FROM_NEAREST_SPECIFIED: 
            pv = ((FromNearestSpecified)value).resolve(foNode); 
            if (pv == value) return value;  // unable to resolve 
            // TODO: validate here 
            return pv; 
        case PropertyValue.INHERITED_VALUE: 
            pv = ((InheritedValue)value).resolve(foNode); 
            if (pv == value) return value;  // unable to resolve 
            // TODO: validate here 
            return pv; 
  • Validation was originally conceived as a method on a datatype. E.g. { { { datatypes/AbstractPropertyValue.validate() } } }

    public void validate(int testProperty, int type) 
        throws PropertyException 
    { 
        // N.B. PROPERTY_SPECIFIC inheritance may require more specialized 
        // checks.  Only line-height comes into this category. 
        if ((propertyConsts.getDataTypes(testProperty) & type) == 0) { 
            String pname = PropNames.getPropertyName(testProperty); 
            throw new PropertyException 
                    ("Datatype(s) " + 
                     Property.listDataTypes(type) + 
                     " not defined on " + pname); 
        } 
    } 
  • I was unhappy with this approach for reasons I cannot now remember.

Accessing property values

No property objects

Only singleton property objects exist. The data in property objects is regarded as a set of constants. How are property values maintained? The property value objects (e.g. Numeric, Literal) are associated with Flow Objects. The property whose value these property value objects represents is maintained in the property value object itself as an integer property index. The list of these integers is maintained in  { { { .../fo/PropNames.java } } } .

The singletons are generated in the  { { { setupProperty(int) } } }  method of  { { { .../fo/PropertyConsts.java } } } .  { { { setupProperty() } } }  is called within all of the getters of  { { { PropertyConsts } } } .

Storage of property values

The set of property values applicable to an FO is kept, when the building of an subtrees of the FO is completed, in the array  { { { private PropertyValue[] sparsePropsSet; } } }  The property indices of properties in  { { { sparePropsSet } } }  are contained in property index order in  { { { private final int[] sparseIndices; } } }  Both of these arrays have only enough elements to contain the applicable properties for the FO. In order to map from a property index to the associated  { { { PropertyValue } } }  in  { { { sparsePropsSet } } } , the array  { { { private final int[] sparsePropsMap; } } }  is required. Indexed by property index, it contains the corresponding index into  { { { sparsePropsSet } } } .

For example, suppose that only three properties are applicable to a certain FO. The indices of those properties are 25, 200 and 201.  { { { sparsePropsSet } } }  and  { { { sparseIndices } } }  will both contain three values;  { { { sparsePropsSet } } }  the actual property values for properties 25, 200 and 201 in elements 0, 1 and 2 respectively, and  { { { sparseIndices } } }  the  int  values 25, 200 and 201 in elements 0, 1 and 2 respectively.  { { { sparsePropsMap } } }  contains  { { { PropNames.LAST_PROPERTY_INDEX + 1 } } }  elements, initialized to -1. Elements 25, 200, and 201 will be reset to contain the values 0, 1 and 2 respectively.

Given a property index  property , the property value associated with the the index can be obtained by  sparsePropsSet[ sparsePropsMap[property] ] 

The accessor for property values within  { { { .../fo/FONode.java } } }  and descendants is the method  public PropertyValue getPropertyValue(int property) 

Potential problem with static-content

Depending on the results of an enquiry now before the xsl-editors, the handling of properties within static-content may have to change slightly. The above minimal scheme of properties data, compressed to only those properties which are relevant to a particular FO, builds the  { { { sparsePropsSet } } }  after the FO subtree of all of its children has been built. The assumption here is that properties which are not actaull applicable to the FO in question are no longer required. Any reference to such a property from within the FO's subtree (e.g. via the  { { { FromNearestSpecifiedValue() } } }  function) will have been resolved.

This may not be the case when marker subtrees are conceptually subpended to a node within static-content during the resolution of markers. In this case, for FOs within static-content, some indication of properties specified on the node may need to be kept.

Extending current design

Add support for FOP extensions

  • FOP extensions cannot simply be defined in isolation, because of the nature of pull parsing. In any case, the semantics of extensions require intervention in the code downstream of parsing. The immediate implications are that the pull parsing classes, including { { { xml/FoXMLEvent.java } } } and { { { xml/SyncedFoXmlEventsBuffer.java } } } will have to be extended to handle the  fox:  events, and the fo/flow classes, which effectively perform input XML validation, will have to be extended to accommodate extensions.

Tighter Area Tree integration

  • This is a large and interesting topic. It is driven by the need for Area Tree context information in order to resolve additive expressions involving percentages defined against enclosing areas. (More on this to come.)

FOPAltDesignIntegration (last edited 2009-09-20 23:52:37 by localhost)