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

Reply via email to