Next / Previous / Contents / NM Tech homepage

11. zdp_fo.xsl: PDF customization layer

The PDF customization layer, which produces its output using XSL-FO (Formatting Objects), starts out with an xsl:stylesheet element similar to the HTML customization layer (see Section 7, “zdp_html.xsl: HTML customization layer”), with one difference: it includes the XSL-FO namespace as prefix “fo:”.

<xsl:stylesheet version="1.0" 
    exclude-result-prefixes="date d">
  <!-- XSL-FO stylesheet customization layer.
   !   Do not edit this file directly.  It is extracted mechanically
   !   from the documentation:

Here we import the stock FO templates.

<!--Import the base PDF stylesheet.-->

Next we import the branding parameters defined in Section 12, “The fo_params.xsl file: PDF branding”.

<!--Import the PDF branding parameters.-->

Because the output is XSL-FO, an XML document type, we set the output format to XML.

<!--Select output in XML form-->
<xsl:output method="xml"/>

Write the current version on the controlling terminal. The xsl:message construct is allowed only with a template, variable, or param, so we enclose it in a dummy param.

<xsl:param name="greeting">
  <xsl:message>=== doc5style (FO) 1.0 ===</xsl:message>  

The PDF customizations are divided into these sections:

11.1. General page layout

This section contains parameter settings that affect the overall PDF page format. To make changes here, you need to understand a number of XSL-FO concepts such as regions, blocks and inlines, block and inline progression directions, and such. Dave Pawson's book XSL-FO is absolutely indispensable for this background information; see Section 3, “Required skills”.

Turn on double-sided formatting, which places the “outer” margin on the left of even pages and the right of odd pages, and the “inner” margin in the opposite positions.

<!--Turn on double-sided printing-->
<xsl:param name="double.sided">1</xsl:param>

Make the body font 10-point.

<!--Set the body font size-->
<xsl:param name="body.font.master">10</xsl:param>

Our chosen monospaced font, Vera Sans Mono, is too big at the body font size. Reduce it to 90% of the body face size. We also make this a parameter so it can be altered on the command line.

<!--Set up the monospaced font-->
<xsl:attribute-set name="">
  <xsl:attribute name="font-family">
    <xsl:value-of select="$"/>
  <xsl:attribute name="font-size">
    <xsl:value-of select="font-size"
<xsl:param name=""

The margins are defined next. For double-sided formatting, the default inner margin is 1.25" and the outer 0.75". To save paper, we set the inner margin to 1".

<!--Set up inner and outer side margins-->
<xsl:param name="page.margin.inner">1in</xsl:param>
<xsl:param name="page.margin.outer">0.75in</xsl:param>

In the old DocBook 4.2 customizations, titles were unindented relative to the left margin of the page body. However, since version 1.68.1 of the style sheets, the titles are not indented; instead, the body indentation is set by the parameter body.start.indent, which defaults to 4pc. We'll reduce that a bit, to 3pc.

<!--body.start.indent: Set the body indentation level-->
<xsl:param name="body.start.indent">3pc</xsl:param>

In the stock book style, each chapter's sections are numbere 1, 1.1, and so on. We want the chapter number prepended; Stayton covers this in the chapter on HTML output optios, the section on “Chapter and section numbering.”

<!--Prepend the chapter number to section numbers.-->
<xsl:param name="section.label.includes.component.label" select="1" />

In the stock style, the xref element does not include a page number. We want internal cross-references to use the page number.

<! Cross-reference by page no.-->
<xsl:param name="">1</xsl:param>

The next parameter is a bit obscure. The stock style defaults to “draft mode”, which overlays each page with a user-supplied image named draft.png. We do not support draft mode, and would prefer not to see a bunch of messages about how it can't find draft.png.

<!--draft.mode: Turn off draft mode-->
<xsl:param name="draft.mode">no</xsl:param>

Because the current style has no running header, we reclaim most of the space allocated to the header, but leave 0.25" so that the FO processor won't complain about inadequate space for the (empty) content that goes there. The area occupied by the header is called the “region before”, and its size paramater is region.before.extent.

<!--region.before.extent: Height of the (empty) running header-->
<xsl:param name="region.before.extent">0.25in</xsl:param>


The and attribute sets define the appearance of subscripts and superscripts. Unmodified, superscripts sit on a baseline well above the x-height of the line, and this usually runs into the previous line. The font-size attribute comes from the base fo/param.xsl file in the stock stylesheets. If this gets too annoying, here's the fix:

  1. From stock stylesheet fo/inline.xsl, find the template inline.superscriptseq and copy it here.

  2. Find the attribute definition for baseline-shift and change its value to “0.6em” (or other pleasing value).

The next few sections set up the vertical spacing used in page makeup. Each of these is an xsl:attribute-set that contain attributes that define the minimum, optimum, and maximum spacing before or after a given element.

The values we use here were determined by trying various values to see how they look. This is a trade-off: smaller spacing saves paper, and tends to put more on a page, reducing the number of cases where blocks of related content are divided across page breaks. On the other hand, larger spaces can make the document more readable.

First, the normal.para.spacing attribute set defines the spacing around paragraphs. The stock (minimum, optimal, maximum) spaces are (0.8em, 1em, 1.2em), but those are rather generous. To save paper we scrunch them down a bunch. (The “em” is the usual printer's measure—the point size of the font, so in a 12-point font, 0.5em is 6 points.)

<!--normal.para.spacing: Spacing above and below paragraphs-->
<xsl:attribute-set name="normal.para.spacing">
  <xsl:attribute name="space-before.minimum">0.50em</xsl:attribute>
  <xsl:attribute name="space-before.optimum">0.60em</xsl:attribute>
  <xsl:attribute name="space-before.maximum">0.70em</xsl:attribute>

Next we set up the spacing for itemizedlist and similar elements. The list.block.spacing attribute set describes the space before and after the entire list. The default spacing is (0.8em, 1.0em, 1.2em) before and after.

<!--list.block.spacing: Space before/after lists-->
<xsl:attribute-set name="list.block.spacing">
  <xsl:attribute name="space-before.minimum">0.70em</xsl:attribute>
  <xsl:attribute name="space-before.optimum">0.75em</xsl:attribute>
  <xsl:attribute name="space-before.maximum">0.80em</xsl:attribute>
  <xsl:attribute name="space-after.minimum">0.70em</xsl:attribute>
  <xsl:attribute name="space-after.optimum">0.75em</xsl:attribute>
  <xsl:attribute name="space-after.maximum">0.80em</xsl:attribute>

The list.item.spacing attribute set describes the space around individual items in the list. The default values are also (0.8em, 1.0em, 1.2em).

<!--list.item.spacing: Space between list items-->
<xsl:attribute-set name="list.item.spacing">
  <xsl:attribute name="space-before.minimum">0.50em</xsl:attribute>
  <xsl:attribute name="space-before.optimum">0.60em</xsl:attribute>
  <xsl:attribute name="space-before.maximum">0.70em</xsl:attribute>

Finally, the attribute set defines the vertical spacing around the various verbatim-type elements (programlisting, literallayout, and screen).

<! Spacing around verbatim blocks-->
<xsl:attribute-set name="">
  <xsl:attribute name="space-before.minimum">0.4em</xsl:attribute>
  <xsl:attribute name="space-before.optimum">0.5em</xsl:attribute>
  <xsl:attribute name="space-before.maximum">0.6em</xsl:attribute>
  <xsl:attribute name="space-after.minimum">0.4em</xsl:attribute>
  <xsl:attribute name="space-after.optimum">0.5em</xsl:attribute>
  <xsl:attribute name="space-after.maximum">0.6em</xsl:attribute>

We add a very thin black border (0.1mm) around verbatim elements. This has the advantage of showing clearly when a verbatim element is broken across a page boundary: the side facing the break will have no border. The default border style is none, so we must set the style to solid.

  <xsl:attribute name="border-width">0.1mm</xsl:attribute>
  <xsl:attribute name="border-style">solid</xsl:attribute>

The padding attribute insures that the content does not actually touch the border.

  <xsl:attribute name="padding">1mm</xsl:attribute>