Notes on Table Markers and Friends

Apache FOP 0.20.5 had a proprietary extension fox:continued-label to add some inline content on the non-first parts of a table. Table markers from XSL 1.1 could take over that task but they haven't been implemented, yet. RenderX uses another proprietary extension attribute (rx:table-omit-initial-header) on fo:table which, as the name says, omit the first table header if activated. That way the user can add a different table header for the first part.

fox:continued-label is slightly more powerful and probably easier to comprehend (for the user) than rx:table-omit-initial-header. Probably even simpler than table-markers. Still, the goal is obviously to support table markers at some point.

At first, it would appear that a fox:table-omit-initial-header should be much easier to implement than a fox:continued-label. The problem with the latter: we have to implement a complete layout manager for the continued-label element which is an inline-level object. Furthermore, the table layouter has to put some kind of signal in the layout context on which the ContinuedLabelLayoutManager has to react and not return any Knuth elements. The table layout manager has to run the layout for the header at least twice, once with the signal and once without.

But then one would think that for fox:table-omit-initial-header it should be easy to suppress the Knuth Elements for the header at the first break. But at the time of element generation, we don't know whether a break will be the first break of the table or not. And that seems to make both approaches pretty much impossible with total-fit.

Here's how we do headers and footers:


  • P=penalty
  • H=header
  • Hc=header continued
  • F=footer
  • S=step (i.e. some table content)

Simplified element List for table with no break:


Real element list for a table:

S P(H+F) S P(H+F) S P(H+F) S P(H+F) S H F

Investigating the implementation of table-omit-initial-header

For table-omit-initial-header, we would have to modify the H for certain penalties but we don't know which will cause the break for the first page.

The last "H" serves two cases:

  1. no break: H is the single table header. 2. break: H is the last table header.

For case 1 we'd actually have to suppress the final H. And that we can't do at the time of element list generation. Only in first-fit could we react on such a case. And that will also make table markers really hard if not impossible for total-fit.

For case 2, the final "H" is actually rather "Hc". So, in one case it should represent "H" and in another "Hc". As soon as the heights of the two variants are not the same, the problem arises.

Additional thoughts

For very special cases, it would be possible to take a similar approach as taken for page-number-citation. But where page numbers have a relatively small width change, "continued" labels are usually much wider which can produce problems. And it would be a big hack, of course.

Maybe a new Knuth element would have to be introduced that would allow adding stuff after a break. We may have talked about something like that a few years back.

In the end, it looks like many page breaking problems could be solved by refactoring the layout engine's page breaking from total-fit to first-fit or best-fit. That would also offer to optimize memory usage of FOP, but obviously, that would require a major work investment.

  • No labels