### 9.9. `FoDim.confactor()`: Find the conversion factor between two units

We support the dimensional-unit codes defined in Section 7.2, “Dimensional units”.

Some conversions are exact (e.g., `cm` to `mm` and `pc` to `pt`), while others are approximate. We would like to use exact conversions where possible, so we order the units into a sequence named `unitList`, and group units together if they have exact conversions. We define another sequence `factorList` that specifies the conversion factors between two adjacent units in this sequence. Then, the problem of converting arbitrary units reduces to finding the position of the old and new units within this sequence, and finding the product of the conversion factors for each step.

fohelpers.py
```# - - -   F o D i m . c o n f a c t o r  (static method)

unitList = (UNITS_PC, UNITS_PT, UNITS_IN, UNITS_CM, UNITS_MM)
factorList = ( Decimal(12),        # 1pc = 12pt
Decimal(1)/Decimal('72.27'),   # 1pt = 1/72.27in
Decimal('2.54'),               # 1in = 2.54cm
Decimal(10) )                  # 1cm = 10mm

@staticmethod
def confactor(fromUnits, toUnits):
'''Find any arbitrary conversion factor.

[ fromUnits and toUnits are XSL-FO dimensional units ->
return the factor that must be multiplied by a
quantity using fromUnits to express it as toUnits ]
'''
```

The first step is to locate the two units by their position in `unitList`. Note that this step will raise `ValueError` if the units are not standard XSL-FO units.

fohelpers.py
```        #-- 1 --
# [ fromPos  :=  position of fromUnits in unitList
#   toPos  :=  position of toUnits in unitList
#   result  :=  Decimal(1) ]
fromPos = FoDim.unitList.index(fromUnits)
toPos = FoDim.unitList.index(toUnits)
result = Decimal(1)
```

To move from lower-numbered units to higher ones, we multiple the `result` by the factors for each step. In the reverse direction, we divide by those factors. If `fromPos==toPos`, the result remains at value 1.0.

fohelpers.py
```        #-- 2 --
# [ if fromPos < toPos ->
#     result  *:=  elements of FoDim.factorList in positions
#         fromPos, fromPos+1, ..., toPos-1, inclusive
#   else if fromPos > toPos ->
#     result  /:=  elements of FoDim.factorList in positions
#         fromPos-1, fromPos-2, ..., toPos, inclusive ]
if fromPos < toPos:
for pos in range(fromPos, toPos):
result *= FoDim.factorList[pos]
elif fromPos > toPos:
for pos in range(fromPos-1, toPos-1, -1):
result /= FoDim.factorList[pos]

#-- 3 --
return result
```