Jeremias Maerki wrote:

Could work for most cases although it would probably be difficult again
on tables and a little less so on lists. I had to do some special stuff
on tables and have still not solved everything. For example:

| cell1 line1   | cell2 line1    |
|               | cell2 line2    |
| cell3 line1   | cell4 line1    |

A keep-with-previous on the second row should create a "glue" (not a
knuth glue) not only between cell2 line2 and cell4 line1 but also
between cell2 line1 and cell3 line1. This means that in the combined
element list you get multiple infinite penalties. Your alternative
approach might really help here. But I keep coming to the conclusion
that I might have to get the cell content element lists of the following
row (group) before I can finish the combined element list for the
current one (because you might have a keep-with-previous in there).

As the combined list is created for a single row group at a time, I think that the presence of keeps could be signaled using a couple of boolean parameters:
    getCombinedKnuthElementsForRowGroup(..., bKeepWithPrevious, bKeepWithNext)

In order to compute this boolean values, it should be enough to look for keep constraints in the first and last cell LM of each column in the row group; for example, if the table has M columns
    bKeepWithPrevious = cell[1,1].mustKeepWithPrevious()
                        || cell[1,2].mustKeepWithPrevious()
                        || ...
                        || cell[1,M].mustKeepWithPrevious()
    bKeepWithNext = cell[N,1].mustKeepWithNext()
                    || cell[P,2].mustKeepWithNext()
                    || ...
                    || cell[Q,M].mustKeepWithNext()
where N,P and Q are the last row indexes in the first, second and last column (which could be different if there are row spans).

During the creation of the combined list:
- if there is a keep-with-previous, the first step must be get something from each column (it must be the greater among the column steps); - if there is a keep-with-next, the last step must be "synchronized" between all columns: is is allowed to place the last fragment of a column only if it will create the last combined element.

So, if a row group has both keep-with-previous and keep-with-next and one of the columns contains just a single line (or a single group of lines that cannot be parted) the combined list will have just a single step and no inner breaking points.

The synchronization of the last step could be achieved this way:

    // initializations

    bSynchronizeLastStep = bKeepWithNext
    for (each column) {
        // compute normally the width of the next sub-sequence
        if (bKeepWithNext
            && we have reached the end of the column sequence) {
            // signal this is the last step, for example
            width[i] = -width[i]
        } else {
            bLastStep = false

    if (bSynchronizeLastStep) {
        // take the "greater" last step
        step = - min{width[i]};
    } else {
        // the normal behaviour

This is not enough: if there are both a keep-with-previus constraint and a keep-with-next constraint, the whole process could be performed several times until the computed step is ok (because a column could have inner breaking points while another has none):

    bStepOk = false;
    while (!bStepOK) {
        // step computation

        bStepOK = true;
        if ((this is the first step)
            && bKeepWithPrevious) {
            for (each column) {
                bStepOk = bStepOk
                    && (the remaining width is < than the total width)

Sorry for the long message, but everything seems quite complicated when applied to tables! :-)

I also must add that these are just thoughts: as I did not yet try and implement them, they could prove to be completely wrong.


Reply via email to