Text Formatting

Text is created in the output document using the fo:block element. The simplest possible block is shown in Figure 8-1.

<fo:block>hello world</fo:block>

Figure 8-1: A simple block

This creates a paragraph in the output document which has the default font (which is helvetica) and the default alignment (which is left). The sections below describe elements and attributes used to control the formatting of text.

Using the font attribute

The quickest way to get the font you require is to use the font attribute, as shown in Figure 8-2.

<fo:block font="bold 12pt garamond">hello world</fo:block>

Figure 8-2: Using the font attribute

Using the font attribute is simpler than specifying all the individual attributes such as font-weight and font-size, but does need some care. When using the font attribute the order of the words is important. The font style (normal, italic) and the font weight (bold, normal) must come before the font size. The font name must come after the font size. If the font name contains spaces, it must be enclosed in quotes, as shown in Figure 8-3.

<fo:block font="bold 12pt "times new roman"">
	hello world
</fo:block>

Figure 8-3: A font name with spaces

The full syntax of the font attribute is shown in Figure 8-4.

[ [ <fo:font-style> || <fo:font-variant> || <fo:font-weight> ]?
<fo:font-size> [ / <fo:lineheight>]?
		<fo:font-family> ]

Figure 8-4: Syntax of font attribute

Using the font-family attribute

The font-family attribute is used to specify the name of the font to use. More than one font name can be listed. These names can be specific font names such as "times roman" or "garamond", or generic names such as "monospace". Ibex will use the first name in the list which matches a font on your system. Font names are separated by a comma.

The ability to list multiple font names derives from the CSS standard. It is designed to support the creation of a web page which will be rendered on a computer that may not have the same fonts installed as the page's author. In practice when you generate a PDF file you know what fonts you have installed, so you will probably just specify one font.

Italic text

Text is made italic using the font-style attribute.

The font style can be "normal" or "italic". Other font values such as the font-family are inherited from the current font, as shown in Figure 8-5.

<fo:block font-family="arial">
		hello <fo:inline font-style="italic">world</fo:inline>
</fo:block>

Figure 8-5: Using font-style

Bold text

Text is made bold using the font-weight attribute.

The font weight can be "normal" or "bold", as shown in Figure 8-6.

<fo:block font-family="arial">
		hello <fo:inline font-weight="bold">world</fo:inline>
</fo:block>

Figure 8-6: Using the font-weight attribute

Text size

The size of text is set using the font-size attribute. The font size specifies the size of the font and can be specified in a number of ways listed below.

A numeric size

The most common approach is to specify the size you want in points, for example font-size="12pt" or font-size="30pt".

An absolute size

Attribute Value Size
xx-small 7.0pt
x-small 8.3pt
small 10.0pt
medium 12.0pt
large 14.4pt
x-large 17.4pt
xx-large 20.7pt

A relative size

This sets the font size based on the size of the prevailing font.

Attribute Value Size
smaller existing size / 1.2
larger existing size * 1.2

Another way of setting the font size relative to the current font size is to use the "em" unit. "1.0em" is the current font size, so "2.0em" specifies a size which is twice as big as the current size.

Underlining text

Text is underlined using the text-decoration attribute.

Specifying text-decoration="underline" will cause text to be underlined, like this.

Striking out text

You can strike out text using the text-decoration attribute.

Specifying text-decoration="line-through" will cause text to be underlined, like this. The precise position of the horizontal line from the baseline is read from the prevailing font file.

Horizontal alignment

Horizontal alignment is specified using the text-align attribute. The default alignment is left. Valid values for text-align are shown in the table below.

Value Effect
left text is aligned against the left edge of the block
right text is aligned against the right edge of the block
center text is centered in the middle of the block
justify text is aligned against both the left and right edges of the block. Space is inserted between words to achieve this effect. Setting text-align = "justify" does not align the last line of the paragraph, this is done using text-align-last = "justify".
start text is aligned against the start edge, which for a block that is not rotated, with the default left-to-right writing direction, is the left edge.
end text is aligned against the end edge, which for a block that is not rotated, with the default left-to-right writing direction, is the right edge.
inside assuming the document is to be bound as a book, text is aligned against the edge which is nearest the binding. For an odd-numbered page this will be the left edge, for an even numbered page it will be the right edge.
outside assuming the document is to be bound as a book, text is aligned against the edge which is furtherest from the binding. For an odd-numbered page this will be the right edge, for an even numbered page it will be the left edge.

For text-align values of "inside" and "outside" the page number is used to determine the binding edge, which is assumed to be the left hand edge of odd-numbered pages and the right hand edge of even-numbered pages.

The effect of some of the text-align values is shown in Figure 8-7.

Figure 8-7: Effects of text-align values

Justifying the last line of a paragraph

Specifying text-align="justify" will justify all lines of a paragraph except the last. This is because a justified paragraph typically looks like the one in Figure 8-8, with the last line not being justified.

Figure 8-8: Paragraph without the last line justified

The text-align-last attribute controls the alignment of the last line of a paragraph. Values include are shown in the table below:

Value Effect
relative if text-align is "justify", align the last line against the start edge (normally the left edge), otherwise use the setting if the text-align attribute.
left text is aligned against the left edge of the block
right text is aligned against the right edge of the block
start text is aligned against the start edge, which for a block that is not rotated, with the default left-to-right writing direction, is the left edge.
end text is aligned against the end edge, which for a block that is not rotated, with the default left-to-right writing direction, is the right edge.
inside assuming the document is to be bound as a book, text is aligned against the edge which is nearest the binding. For an odd-numbered page this will be the left edge, for an even numbered page it will be the right edge.
outside assuming the document is to be bound as a book, text is aligned against the edge which is furtherest from the binding. For an odd-numbered page this will be the right edge, for an even numbered page it will be the left edge.
justify justify the last line across the whole width of page.

Left and right margins

The margins of a fo:block are specified using the margin-left and margin-right attributes. The margin properties indent the edge of the paragraph by the specified amount from the edge of the containing area. The FO for a block with a 2.5cm left margin is shown in Figure 8-9.

<fo:block margin-left="2.5cm">hello world</fo:block>

Figure 8-9: Setting the left margin

If we nest another block inside this one, as shown in Figure 8-10, the margins are cumulative.

<fo:block margin-left="2.5cm">
	block 1
	<fo:block margin-left="2.5cm">
		block 2
	</fo:block>
</fo:block>

Figure 8-10: Nested blocks

<fo:block margin-left="2.5cm" background-color="#777777">
	block 1
	<fo:block margin-left="2.5cm"  background-color="#999999">
				block 2
	</fo:block>
</fo:block>

Figure 8-11: Nested blocks with background color

The approach to indentation defined in the XSL-FO standard is that the content of two nested blocks which do not specify a margin have the same left edge.

The edges of the content (which in our example is the text) are aligned, and any borders and padding are placed outside those edges. Figure 8-12 shows the FO for two nested blocks with no margin attributes. The text will be vertically aligned and the background colors will be placed outside the text.

<fo:block padding="1cm" background-color="#777777">
	block 1
	<fo:block padding="1cm" background-color="#999999">
		block 2
	</fo:block>
</fo:block>

Figure 8-12: Nested blocks with no margins specified

In XSL-FO terms, both areas have the same start-indent and hence the same content rectangle, and the padding on the outer block extends outside its content rectangle. This may seem counter-intuitive to some developers used to the CSS model. You can invoke the CSS nested areas model by specifying a margin-left value, even "0pt".

Spacing between letters

The amount of space between two letters is dependent on the font used. Ibex reads the TrueType or Type 1 font file and loads the width of each character. Kerning information which specifies adjustments to the gaps between particular pairs of characters is also read from the font file and used in the text formatting process. The spacing between letters can be changed using the letter-spacing attribute. Any value specified using this attribute is added to the default spacing specified by the font. Figure 8-13 shows the FO to increase the letter spacing of some text.

<fo:block letter-spacing="0.2em">WELLINGTON NEW ZEALAND</fo:block>

Figure 8-13: Using letter-spacing

It is possible to make letters closer than normal using a negative value for letter-spacing. Example FO for this is shown in Figure 8-14 and the result in Figure 8-15.

<fo:block letter-spacing="-0.1em">WELLINGTON NEW ZEALAND</fo:block>

Figure 8-14: Moving letters closer together

Figure 8-15: Text formatted using negative letter-spacing

Spacing before and after words

Spacing before and after text is specified using the space-start and space-end attributes on the inline element.

The space-start attribute specifies space to appear before text, space-end specifies space to appear after the text.

Figure 8-16 shows how to specify a gap between two words. This FO produces a 3cm gap between the words.

<fo:block>
	hello <fo:inline space-start="3cm">world</fo:inline>
</fo:block>

Figure 8-16: Using space-start

Space between words is collapsed (i.e. merged) by default. If a word has space-end="1.0cm" and the following word has space-start="0.5cm", the gap between the two words will be the larger of the two spaces (i.e. 1.0cm), not the sum. FO showing this is in Figure 8-17.

<fo:block>
	<fo:inline space-end="1cm">hello</fo:inline>
	<fo:inline space-start="0.5cm">world</fo:inline>
</fo:block>

Figure 8-17: FO showing merging of spaces

Forcing a line break

You can cause a line break in normal text by inserting an empty fo:block element. Figure 8-18 shows an FO example which does this and Figure 8-19 shows the resulting output.

<fo:block>
	this will be line one <fo:block/>this will be line two
</fo:block>

Figure 8-18: Forcing a line break

Space at the start of a line

Space specified with the space-start attribute is normally discarded at the start of the line. To force it to be retained use the space-start.conditionality attribute.

Figure 8-20 shows two blocks which create two lines. The first block will have no space at the start of the word. The second block has space-start.conditionality="retain" so the space specified by the space-start="1cm" will be retained. The output created by this FO is shown in Figure 8-21.

<fo:block background-color="#eeeeee"> 
	<fo:inline space-start="1cm">
		discard
	</fo:inline>
</fo:block>
<fo:block background-color="#eeeeee">
	<fo:inline space-start="1cm" space-start.conditionality="retain">
		retain
	</fo:inline>
</fo:block>

Figure 8-20: Using retain

Figure 8-21: Output from using retain

Vertical alignment

The vertical alignment of blocks of text within a containing fo:flow or fo:block is controlled by the display-align attribute.

The vertical alignment of words on a line is controlled by the vertical-align attribute.

Text on a line is positioned relative to the baseline, which is shown in Figure 8-22.

By default text sits on the baseline. In the terms of the XSL-FO specification, this is the alphabetic baseline.

Figure 8-22: The baseline

The height of the font above the baseline is the ascender. The height of the font below the baseline is the descender. Adding the ascender and descender values for the font (not for individual characters) gives the font size. The leading is the space above and below the characters, and is the difference between the line-height and the font-size.

The XSL-FO specification refers to the ascender value as the text-altitude and the descender as the text-depth. Together these two values add up to the allocation rectangle height. In these terms:

*leading = ( line-height - text-altitude - text-depth ) * so

1/2 leading = ( line-height - text-altitude - text-depth ) / 2 By default the line height is 1.2em. The em unit is proportional to the size of the current font, so as the font size increases so does the line height. This can be changed by setting the Settings.LineHeightNormal value. For instance to make the line height larger and so space text out more vertically you could use the code in Figure 8-23.

FODocument doc = new FODocument();
doc.Settings.LineHeightNormal = "1.4em";

Figure 8-23: Changing the default line height

The effect of subscript and superscript text on line spacing

When calculating the largest characters on this line, we really mean those whose ascender and descender values are greatest (i.e. futherest from the baseline). When making this calculation, the value of the line-height-shift-adjustment attribute is considered. If text is a subscript or superscript and so has a baseline-shift value which changes its position vertically, this will also change its effective ascender and descender values. If line-height-shift-adjustment = "consider-shifts" (the default value) then the baseline-shift amount is taken into account when working out the greatest ascender and descender. If line-height-shift-adjustment = "disregard-shifts" then the effect of the baseline-shift is ignored. Setting line-height-shift-adjustment = "disregard-shifts" makes lines stay the same distance apart regardless of subscript and superscript elements.

The effect line-height-shift-adjustment is shown in Figure 8-24; the first two lines are in a block which has line-height-shift-adjustment= "consider-shifts" and so are further apart than the second two which are in a block which has line-height-shift-adjustment = "disregard-shifts":

Figure 8-24: Effect of disregard-shifts

The baseline

The baseline is below the top of the text block a distance equal to 1/2 leading + max(ascender), which places the baseline in the same place for all text elements. This means that normally text rests on the same baseline regardless of the font size, as shown in Figure 8-25.

Figure 8-25: Text on the baseline

Subscript and superscript

Subscripted and superscripted text is created by using the baseline-shift attribute on an fo:inline element.

The effect of the baseline shift is shown in Figure 8-26, where the "pt" characters are in an inline element with baseline-shift = "5pt".

Figure 8-26: Effect of baseline shift

The FO to move a word above the current baseline by 5 points is shown in Figure 8-27 with the resulting output appears in Figure 8-28.

<fo:block>
	hello
	<fo:inline color="red" baseline-shift="5pt">
		super
	</fo:inline>
</fo:block>

Figure 8-27: FO showing baseline-shift

Figure 8-28: Output from the above FO

Font files contain default baseline shift values for superscripted and subscripted text. Rather than specifying baseline-shift="5pt", you can use the values "super" and "sub". The FO to move a word above the current baseline by the default amount for the current font is shown in Figure 8-29 with the resulting output in Figure 8-30. Using the "sub" and "super" values is preferable to using specific measurements because it means (a) if you change the font size of the paragraph you do not have to change all the baseline-shift values and (b) you get the baseline sift the font designer intended.

<fo:block>
	hello
	<fo:inline color="red" baseline-shift="super">
		super
	</fo:inline>
</fo:block>

Figure 8-29: Using the default superscript

Figure 8-30: Output from the above FO

Line stacking strategies

XSL-FO uses the line-stacking-strategy attribute to determine how lines are stacked vertically on a page. The default value of this attribute is "max-height". When the "max-height" strategy is used the height of a line depends on the height of the characters or images on that line.

The information which follows assumes that this default value is used. The other values for line-stacking-strategy, namely "font-height" and "line-height" will produce different results, since the height of the line using these strategies does not change when the content of the line changes.

The leading value is calculated from the line-height and font-size specified for the fo:block element which contains the text. It is constant for the whole block and is not affected by other values specified on contained within the block.

The height the line is calculated using "largest" characters found on the line, i.e. the sum of the max(ascender) and max(descender) values.

Positioning images

An inline element such as fo:external-graphic is treated similarly to a text element. The height of the image is used as the ascender value. The descender value is zero.

This means that by default an image will be positioned on the baseline, as shown in Figure 8-31 .

Figure 8-31: An image on the baseline

A large image will contribute a large ascender value to the baseline placement calculation, but will still sit on that baseline as shown in Figure 8-32.

Figure 8-32: Large image on baseline

The before-edge baseline

By default an element has an alignment-baseline value of "baseline" and so sits on the baseline shown in the above diagrams. For a given line, the largest thing on that line which has alignment-baseline = "baseline" establishes the position of the before edge baseline. This is shown in Figure 8-33.

Figure 8-33: Image aligned to before-edge baseline

To align another object with the before edge baseline, either set vertical-align = "top" or alignment-baseline = "before-edge". Figure 8-34 shows a second smaller image with default alignment, which positions it on the baseline.

Figure 8-34: Differently aligned images

By specifying vertical-align="top" on the external-graphic for the second image, we can align this image to the before edge baseline and get the layout shown in Figure 8-35.

Figure 8-35: Two images aligned using vertical-align

If all the elements on the line have vertical-align = "top", then the before edge baseline cannot be calculated, so the text before edge baseline is used. This is the top of the ascender for the font specified for the block which contains the elements.