4.3. Resolving a mixed property value

Example: Resolving the value of the property margin-left of the FO node fo:region-body. This value was specified as <fo:region-body margin="4pt+20%"/>. margin is a shorthand property for margin-left.

The property list of fo:region-body reads:

 this = "{margin=[(4000mpt +20.0%)]}"

The retrieved property value is a RelativeNumericProperty:

 prop = "(4000mpt +20.0%)"
 prop = {
    operation: 1
    op1: instance of org.apache.fop.fo.properties.FixedLength(id=817)
    op2: instance of org.apache.fop.fo.properties.PercentLength(id=818)
    dimension: 1
    org.apache.fop.fo.properties.Property.specVal: null
}

The value 1 for the operation corresponds to RelativeProperty.ADDITION. The value 1 for the dimension indicates that this is a length.

 op2 = "20.0%"
 op2 = {
    factor: 0.2
    lbase: instance of org.apache.fop.datatypes.LengthBase(id=751)
    org.apache.fop.fo.properties.Property.specVal: null
}
 lbase = "org.apache.fop.datatypes.LengthBase@171f189"
 lbase = {
    parentFO: instance of org.apache.fop.fo.pagination.SimplePageMaster(id=786)
    propertyList: instance of org.apache.fop.fo.PropertyList(id=807)
    iBaseType: 5
}

The RelativeNumericProperty is resolved in the method call

 props.marginLeft =
   this.propertyList.get(PR_MARGIN_LEFT).getLength().getValue();

in PropertyManager.getMarginProps(). getLength() is a sort of cast; it returns the property value if it is a length. The getValue() method invoked is RelativeNumericProperty.getValue(). This calls RelativeNumericProperty.getNumericValue(), which calls RelativeNumericProperty.getResolved(). This invokes the operation on its two operands, NumericOp.addition2, which invokes getNumericValue() on each operand. PercentLength.getNumericValue() calls LengthBase.getBaseLength on its member lbase.

Due to its value iBaseType == 5 == LengthBase.BLOCK_WIDTH this invokes parentFO.getLayoutDimension(PercentBase.BLOCK_IPD).intValue() on its parent FO. The simple page master FO node does not have any layout dimensions, its member layoutDimension is null. Therefore it consults its parent FO. This goes all the way up to the root FO node.

The root FO node does have the required layout dimensions, which are the page dimensions. These have been set on it by the PageLayoutManager when the page was created in its method createPageAreas:

((FObj) fobj.getParent()).setLayoutDimension(PercentBase.BLOCK_IPD,pageWidth)
((FObj) fobj.getParent()).setLayoutDimension(PercentBase.BLOCK_BPD,pageHeight)
PercentBase.BLOCK_IPD = 2, PercentBase.BLOCK_BPD = 3 

As a result:

 layoutDimension = "{2=576000, 3=792000}"
 key = "2"
 getName() = "fo:root"

  [1] org.apache.fop.fo.FObj.getLayoutDimension (FObj.java:241)
  [2] org.apache.fop.datatypes.LengthBase.getBaseLength (LengthBase.java:120)
  [3] org.apache.fop.fo.properties.PercentLength.getNumericValue (PercentLength.java:82)
  [4] org.apache.fop.fo.expr.NumericOp.addition2 (NumericOp.java:52)
  [5] org.apache.fop.fo.expr.RelativeNumericProperty.getResolved (RelativeNumericProperty.java:105)
  [6] org.apache.fop.fo.expr.RelativeNumericProperty.getNumericValue (RelativeNumericProperty.java:132)
  [7] org.apache.fop.fo.expr.RelativeNumericProperty.getValue (RelativeNumericProperty.java:170)
  [8] org.apache.fop.fo.PropertyManager.getMarginProps (PropertyManager.java:267)

PercentLength.getNumericValue() returns the page width, which is multiplied by the requested factor of 0.2, and added to the value of the fixed length, 4000. The resulting value is returned and used for the variable marginLeft:

 value = 119200.0
 props.marginLeft = 119200