Re: Keep-with-next handling

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Re: Keep-with-next handling

Luca Furini-2
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()
and
     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.

Regards
     Luca