Whitespace Management Extension

Overview

What is meant by Whitespace management? Whitespace management is the ability to dynamically select alternative content to ensure that a page is fully populated. XSL-FO 1.1 doesn't provide any means to fulfill this requirement, but this requirement was discussed at the XSL-FO 2.0 requirements meeting and it is a requirement that users of digital publishing tools often expect.

To explain the requirement a bit more, lets consider an example extension element fox:best-fit.

<fox:best-fit>
  <fox:alternative>
    <fo:block>
      Short Message
    </fo:block>
  </fox:alternative>
  <fox:alternative>
    <fo:block>
      2 Line Message
      2 Line Message
    </fo:block>
  <fox:alternative>
  </fox:alternative>
    <fo:block>
      3 Line Message
      3 Line Message
      3 Line Message
    </fo:block>
  </fox:alternative>
  <fox:alternative>
    <fo:block>
      Long Message.
      Long Message.
      Long Message.
      Long Message.
    </fo:block>
  </fox:alternative>
</fox:best-fit>

When the Renderer encounters a fox:best-fit element it analyses the available space in BPD within the current page and selects the alternative which fits "best" within the remaining BPD. By best fit, I mean the BPD of the alternative is less than remaining BPD but more than the BPD of all other alternatives which are less than the remaining BPD.

Questions

<fo:table-cell>
  <fo:block>
    <fox:best-fit>
       <fox:best-fit-alternative>John Ronald Reuel Tolkien</fox:best-fit-alternative>
       <fox:best-fit-alternative>John R. R. Tolkien</fox:best-fit-alternative>
       <fox:best-fit-alternative>J. R. R. Tolkien</fox:best-fit-alternative>
    </fox:best-fit>
  </fo:block>
  <fo:block>
    <fox:best-fit>
       <fox:best-fit-alternative>Literature Street 76</fox:best-fit-alternative>
       <fox:best-fit-alternative>Literature Str. 76</fox:best-fit-alternative>
    </fox:best-fit>
  </fo:block>
</fo:table-cell>

Thoughts for a possible implementation

First thought is to implement it similarly to a block-container with stretch and shrink. The implementation could measure the min/opt/max of every alternative and could calculate a combined min/opt/max from that. Creating Knuth elements for this combined min/opt/max is easy (a single box plus glue for the whole best-fit block with no break opportunity in between). After the page breaking, generating the contents of a particular alternative is easy and can be done the same way as for block-container.

What's critical is the optimum BPD for the whole block. Assuming you are creating a catalog with each article starting with the same larger structure. After that you have some variable length content. Since the first block always takes some space you will want to keep it together. This can lead to larger white areas on a page after the end of an article. You may be able to fill that with additional content, an additional picture perhaps. But that should only happen if there's really room to waste. So in this case the optimum value is 0pt. Maybe each alternative would have to have an id attribute and the best-fit block will contain a reference to the preferred alternative. The preferred alternative's optimum height will then become the best-fit block's optimum height. In the case where you don't want any additional content in the normal case, you'd specify an empty alternative and assign its id to the best-fit block.

The general situation in which the alternative blocks could be broken seems quite similar to the MultiLayoutSequence one. [LF]

[VH] Unless I missed something this will work only if the min/opt/max of the several alternatives are overlapping. If each alternative has only a fixed length, you can't create a min/opt/max representing them, because glue is a continuous value (not a discrete one). Suppose you have 3 alternatives of fixed lengths 8, 10 and 12. You can't simply create a min/opt/max of 8/10/12: what if the glue is stretched so that the block ends up having a size of 11? There is no suitable alternative for such a length.

However, if the situation is similar to the one on the picture below, it becomes possible to create a combining min/opt/max:

If this is not the case, I don't see any other possibility than computing break points once for each alternative... which will quickly lead to combinatorial explosion. If we implemented a best-fit strategy in addition to the current total-fit one, we could reduce the complexity a lot by making a decision at the end of each page. Anyway, it seems to me that this whole approach has an interest only with a best-fit strategy.

[JM] With the addition of the inline-progression-direction variant, the implementation gets more complicated. Since it's about two different orientations, I assume the two implementations would have to be done separately, i.e. best-fit-block and best-fit-inline.

Possible implementation

Although my requirements are slightly different compared to what has been previously said, or should I say simpler, the core idea is still the same. This work should be considered as a possible interpretation of the above discussion with some differences tailored to some particular needs. However, it is worth mentioning that this is still a work in progress and any issues or limitations will be shortly addressed as more tests are performed. The end goal is to implement a high quality, highly extensible whitespace management extension that conforms to FOP architecture and best practices.

1- Fitting strategy:

2- Best fit penalty:

WhitespaceManagement (last edited 2013-09-06 15:06:31 by GlennAdams)