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