Search code examples
cssapache-fop

How to specify an indent of 2ch in XML-FO using FOP


I'm trying to create an indentation of two characters with a fixed-width font in an XML-FO document. I'm translating it using FOP.

Unfortunately, when I specify a length like "2ch", FOP produces this error message:

[ERROR] PropertyMaker - Unknown length unit 'ch'

The XML-FO documentation states that any CSS-known length unit is allowed, and CSS specifies that ch is the width of the 0 character. So AFAIU this should work and still doesn't.

I also failed to find a concrete list of length units understood by FOP (the ix also didn't work). The em is understood, though. But it represents (even while using the fixed-width font monospace) a width about as wide as 1.5 characters.

Is there a way to specify to have an indent of two characters in monospace?

Is there a comprehensive list of length units supported by FOP?

Is there another way to achieve my goal of indenting by a concrete amount of characters? I could use a hack like 1.3em but that is probably not exact.


Solution

  • The units of measure defined in the XSL recommendation are:

    • cm (centimetres)
    • mm (millimetres)
    • in (inches)
    • pt (points)
    • pc (picas)
    • px (pixels)
    • em (current font-size)

    FOP supports them all, with the addition of mpt (millipoints), but none of them, as you noticed, refer to the width of a character for a monospaced font.

    Other formatters may support additional units of measure, for example I see AntennaHouse XSLFormatter supports ch.

    Possible workarounds for FOP

    If you need only a text-indent (i.e. just for the first line), you can use non-breaking spaces:

    <fo:block>&#x00A0;&#x00A0;Lorem ipsum dolor ...</fo:block>
    

    If you know in advance the block will generate just one line, you could also use preserved regular spaces for easier readability of the FO file:

    <fo:block white-space-treatment="preserve" 
        white-space-collapse="false">  Lorem ipsum dolor ...</fo:block>
    

    In the most general case (if you want to define a start-indent, end-indent, ...), you can compute the exact value using the font information:

    1. create the font metrics

      java -classpath build/fop.jar:fop/lib/avalon-framework-api-4.3.1.jar:fop/lib/commons-logging-1.0.4.jar:fop/lib/commons-io-1.3.1.jar:fop/lib/xmlgraphics-commons-svn-trunk.jar org.apache.fop.fonts.apps.TTFReader -enc ansi /path/to/font.ttf metrics.xml

    2. open metrics.xml and look for an element similar to <char idx="29" wdt="600"/> (the wdt value can be different, but it should be the same for all char elements)

    3. wdt is the width of a character in millipoints: multiply it for the font-size and the number of characters, and you get the length you need

    For example: 600 x 12 x 2 = 14400mpt = 14.4pt = length of two characters with a font-size of 12pt