This example explores what happens if the border of one of the rows has precedence over the header and footer borders. The difference to Simon's example is that a third column is added which has a cell border that's dominant over everything else and therefore adds some irregularity into the whole example.

See http://people.apache.org/~jeremias/fop/KnuthBoxesForTablesWithBorders.pdf (page 3) for a graphical representation of the example.

<fo:table table-layout="fixed" border="solid 5pt black">
  <fo:table-column column-width="proportional-column-width(1)"/>
  <fo:table-column column-width="proportional-column-width(1)"/>
  <fo:table-column column-width="proportional-column-width(1)"/>
  <fo:table-header border="solid 4pt green">
    <fo:table-row>
      <fo:table-cell font-size="8pt" line-height="8pt" border="solid 1pt orange" number-columns-spanned="3">
        <fo:block>HEADER</fo:block>
      </fo:table-cell>
    </fo:table-row>
  </fo:table-header>
  <fo:table-footer border="solid 4pt green">
    <fo:table-row>
      <fo:table-cell font-size="8pt" line-height="8pt" border="solid 1pt orange" number-columns-spanned="3">
        <fo:block>FOOTER</fo:block>
      </fo:table-cell>
    </fo:table-row>
  </fo:table-footer>
  <fo:table-body border="solid 3pt red">
    <fo:table-row border="solid 6pt blue">
      <fo:table-cell font-size="8pt" line-height="10pt" border="solid 1pt orange" number-rows-spanned="2">
        <fo:block>
          <fo:block background-color="yellow">block1</fo:block>
          <fo:block>block2</fo:block>
          <fo:block background-color="yellow">block3</fo:block>
        </fo:block>
      </fo:table-cell>
      <fo:table-cell line-height="15pt" border="solid 1pt orange">
        <fo:block background-color="yellow">blockA</fo:block>
      </fo:table-cell>
      <fo:table-cell line-height="15pt" border="solid 8pt violet">
        <fo:block>blockA</fo:block>
      </fo:table-cell>
    </fo:table-row>
    <fo:table-row>
      <fo:table-cell line-height="20pt" border="solid 1pt orange">
        <fo:block background-color="yellow">blockB</fo:block>
      </fo:table-cell>
      <fo:table-cell line-height="20pt" border="solid 8pt violet">
        <fo:block>blockB</fo:block>
      </fo:table-cell>
    </fo:table-row>
  </fo:table-body>
</fo:table>

A full XSL-FO file with this example can be downloaded from: http://people.apache.org/~jeremias/fop/table-border-special1.fo

An sketch of this example:

  no breaks  |    step 1   |    step 2   |    step 3   |    step 4   |    step 5   |    step 6   |
             |             |             |             |             |             |             |
      5      |      5      |      5      |      5      |      5      |      5      |      5      |
      8      |      8      |      8      |      8      |      8      |      8      |      8      |
     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |
 2+1 2+1 2+2!| 2+1 2+1 2+2!| 2+1 2+1 2+2!| 2+1 2+1 2+2!| 2+1 2+1 2+2!| 2+1 2+1 2+2!| 2+1 2+1 2+2!|
          XX |  XX         |      XX     |          XX |  XX         |  XX         |          XX |
  10  15  15 |  10   -   - |  10  15   - |  10  15  15 |  10  15  15 |  10  15  15 |  10  15  15 |
  10 3+3 4+4 |             |             |             |  10         |  10 3+3 4+4 |  10 3+3 4+4 |
             |             |             |             |             |             |      XX     | (step 6 => 4+3)
  10  20  20 |             |             |             |             |  10         |  10  20   - |
   2   2 2+2!| 2+1 2+1 2+2!| 2+1 2+1 2+2!| 2+1 2+1 2+2!| 2+1 2+1 2+2!|   2   2 2+2!|   2   2 2+2!|
     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |
      8      |      8      |      8      |      8      |      8      |      8      |      8      |
      5      |      5      |      5      |      5      |      5      |      5      |      5      |
-------------------------------------------------------------------------------------------------- page break
             |      5      |      5      |      5      |      5      |      5      |      5      |
             |      8      |      8      |      8      |      8      |      8      |      8      |
             |     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |
             | 2+1 2+1 2+2!| 2+1 2+1 2+2!|  2    2 2+2!|  2    2 2+2!|   2   2 2+2!|   2   2 2+2!|
             |          XX |          XX |          XX |          XX |          XX |          XX |
             |  10  15  15 |  10   -  15 | 10   20  20 | 10   20  20 |   -  20  20 |   -   -  20 |
             |  10 3+3 4+4 |  10 3+3 4+4 | 10          |             |             |             |
             |      20  20 |      20  20 |             |             |             |             |
             |   2   2 2+2!|   2   2 2+2!|  2    2 2+2!|  2    2 2+2!|   2   2 2+2!|   2   2 2+2!|
             |     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |     2+2     |
             |      8      |      8      |      8      |      8      |      8      |      8      |
             |      5      |      5      |      5      |      5      |      5      |      5      |
================================================================================================== result
     85      |    50/85    |    55/85    |    57/62    |   60/62     |    69/62    |    82/62    |
     
(!) means dominant border which influences the header/footer height (see 3rd and 3rd to last line)
(XX) indicates the height determining column (step 6 is special, column changes)

Note: the column with the dominant border for the header/footer can differ from the height determining column. Therefore the borders must be processed in halves.

Header is 5 + 8 = 13, border after = 8
Footer is 8 + 5 = 13, border before = 8

Note: the borders of the header/footer may not be always the same and therefore have to be calculated for each break possibility.

Row heights

row1: 4 (extra border height) + 15 + (8/2) => (23,23,23)
row2: 4 (extra border height) + 20 + (8/2) => (28,28,28)
row group (51,51,51)

Steps

Step 1:
stepw = 2 (th) + 1 (r1) + 10 + 1 (r1) + 2 (tf) = 16
maxRemainingHeight = 51
addedBoxHeight = 0
penalty = 16 + 51 - 51 = 16
effPenalty: w = 16 (space for block1) + 13 (header) + 4 (border-after-header) + 4 (border-before-footer) + 13 (footer) = 50
box = 16 - 0 - 16 = 0

Step 2:
stepw = 2 (th) + 1 (r1) + 15 + 1 (r1) + 2 (tf) = 21
maxRemainingHeight = 51
addedBoxHeight = 0
penalty = 21 + 51 - 51 = 21
effPenalty: w = 21 (calc penalty) + 13 + 4 + 4 + 13 = 55
box = 21 - 0 - (21) = 0

Step 3:
stepw = 2 (th) + 2 (r1) + 15 + 2 (r1) + 2 (tf) = 23
maxRemainingHeight = 28
addedBoxHeight = 0
penalty = 23 + 28 - 51 = 0
effPenalty: w = 0 (calc penalty) + 13 + 4 + 4 + 13 = 34
box = 23 - 0 - (0) = 23

Step 4:
stepw = 2 (th) + 1 (r1) + 10 + 10 + 1 (r1) + 2 (tf) = 26
maxRemainingHeight = 28
addedBoxHeight = 23
penalty = 26 + 28 - 51 = 3
effPenalty: w = 3 (calc penalty) + 13 + 4 + 4 + 13 = 37
box = 26 - 23 - (3) = 0

Step 5:
stepw = 2 (th) + 1 (r1) + 10 + 10 + 10 + 0 (r1) + 2 (tf) = 35
maxRemainingHeight = 28
addedBoxHeight = 23
penalty = 35 + 28 - 51 = 12
effPenalty: w = 12 (calc penalty) + 13 + 4 + 4 + 13 = 46
box = 35 - 23 - 12 = 0

Step 6:
stepw = 2 (th) + 2 (r1) + 15 + 4 (half r1/2, col3) + 3 (half r1/2, col2) + 20 + 0 (r1) + 2 (tf) = 48
maxRemainingHeight = 28
addedBoxHeight = 23
penalty = 48 + 28 - 51 = 25
effPenalty: w = 25 (calc penalty) + 13 + 4 + 4 + 13 = 59
box = 48 - 23 - 25 = 0

Step 7:
stepw = 2 (th) + 2 (r1) + 15 + 4 (half r1/2, col3) + 4 (half r1/2, col4) + 20 + 2 (r1) + 2 (tf) = 51
maxRemainingHeight = 0
addedBoxHeight = 23
penalty = 51 + 0 - 51 = 0 (last step, omit penalty)
box = 51 - 23 - 0 = 28

End result (with raw penalties)

box(0)
penalty(16)  -> 16/43
box(0)
penalty(21)  -> 21/43
box(23)
penalty(0)   -> 23/20
box(0)
penalty(3)   -> 26/20
box(0)
penalty(12)  -> 35/20
box(0)
penalty(25)  -> 48/20
box(20)
             -> 51

End result (effective)

box(0)
penalty(50) //incl. header and footer -> 50/85
box(0)
penalty(55) //incl. header and footer -> 55/85
box(23)
penalty(34) //incl. header and footer -> 57/62
box(0)
penalty(37) //incl. header and footer -> 60/62
box(0)
penalty(46) //incl. header and footer -> 69/62
box(0)
penalty(59) //incl. header and footer -> 82/62
box(28)
box(17) //header
box(17) //footer
                                      -> 85


Hand-written notes that should help understand how to write the algorithm for "nextStep()": http://people.apache.org/~jeremias/fop/NextStepAlgoNotes.pdf

TableLayout/KnuthElementsForTables/RowBorder2 (last edited 2009-09-20 23:52:29 by localhost)