Jeremias Maerki wrote:
I'll start from scratch to come up with a better strategy of
implementing these rules. I'll probably start by documenting a few cases
in the Wiki and try to develop the right element list for them. After
that I'll try to find out who exactly to implement everything. Help is
welcome.
I think spaces and keeps are quite similar and very connected: in both
cases, the constraints can invole formatting objects that are not at the
same depth in the tree.
So, my idea for handling space resolution is tho have a LM ask its
children about their spaces, and create the necessary elements (while at
the moment each LM creates elements for its own spaces).
For example, if we have this LM tree
Outer BlockLM
|
+------------+------------+
| | |
BlockLM 1 BlockLM 2 BlockLM 3
|
+------+-----+
| |
BlockLM A BlockLM B
BlockLM1.getNextKnuthElements() would return to the outer BlockLM only the
elements representing its block content, without any space.
In order to decide which elements it has to create, the outer BlockLM
could have some lines like:
(currentChild = BlockLM 1
nextChild = BlockLM 2)
space1 = currentChild.getSpaceAfter();
space2 = nextChild.getSpaceBefore();
if (this.mustKeepTogether()
|| currentChild.mustKeepWithNext() && !nextChild.hasBreakBefore()
|| !currentChild.hasBreakAfter() && nextChild.mustKeepWithPrevious) {
// there cannot be a break between the two children,
createElementsForSpace(resolve(space1, space2, false, false));
} else {
// there can be a break between the children
createElementsForSpace(resolve(space1, null, false, true),
resolve(null, space2, true, false),
resolve(space1, space2, false, false));
}
where:
- the method createElementsForSpace() can have a single space parameter
(returning a sequence that has no feasible breaks [1]) or three
different spaces parameters (returing a sequence with a feasible break
[2]);
- resolve takes two spaces and two booleans, signalling if the space will
be at the beginning / end of a page (as this affects the resolved space)
- getSpaceAfter() would be something like
return resolve(this.spaceAfter, lastChild.getSpaceAfter(), false, false);
vice-versa, getSpaceBefore would be
return resolve(this.spaceBefore, firstChild.getSpaceBefore(), false, false);
(a similar mechanism could be used for keeps)
but I'm not sure that adding two spaces at a time would always give the
same result.
Otherwise, we could follow the implementation of keeps, using the
LayoutContext to keep track of the spaces met and not yet converted into
elements.
Regards
Luca
[1] this would be a simple glue element, preceded by a penalty with value
= inf
[2] maybe a sequence glue - penalty - glue - box - PENALTY - glue,
with
glue #1 is the resolved space after block 1 if a break occurs
glue #3 is the resolved space before block 2 if a break occurs
penalty is a feasible break
PENALTY forbids a break
glue #3 is the difference between glue #1 + glue #3 and the resolved
space if there is no break