@SubSection
@Tag { constraints }
@Title { Size constraints and size adjustments }
@Begin
@PP
The galley flushing algorithm needs to know the available width and
height at each receptive symbol. These symbols may lie within
arbitrarily complex objects, and they may compete with each other for
available space (as body text and footnote targets do), so this
information must be extracted from the tree structure when required.
@PP
For example, consider the object
@ID @Code "5i @Wide { a / b }"
and suppose that the width of @Code { a } is @Eq { 1i, 2i } (@Eq {1i} to
the left of the mark, @Eq { 2i } to the right). What then is the
available width at {@Code { b }}? If we let the width of @Code b be
@Eq {l,r}, we must have
@ID @Eq { (1i up l) + (2i up r) <= 5i }
with the @Eq {non up } (i.e. max) operations arising from mark
alignment. Eliminating them gives
@ID @OneRow @Eq {
matrix {
{ 1i + 2i ^<= 5i }
mabove { l + 2i ^<= 5i }
mabove { 1i + r ^<= 5i }
mabove { l + r ^<= 5i }
}
}
and since we assume that @Code a fits into the available space, the
first inequality may be dropped, leaving
@ID @OneRow @Eq {
matrix {
{ l ^<= 3i }
mabove { l + r ^<= 5i }
mabove { r ^<= 4i }
}
}
Object @Code b may have width @Eq {l, r} for any @Eq { l } and
@Eq { r } satisfying these inequalities, and no others.
@PP
Here is another example:
@ID @Code "5i @High { a /2ix b }"
Assuming that @Code a has height @Eq {1i,1i}, the height @Eq {l, r} of
@Code b must satisfy
@ID @Eq { 1i + ((1i + l) up 2i) + r <= 5i }
This time the @Eq { non up } operation arises from the mark-to-mark gap
mode, which will widen the @Eq { 2i } gap if necessary to prevent
@Code a and @Code b from overlapping. This inequality can be rewritten as
@ID @OneRow @Eq {
matrix {
{ l ^<= infinity }
mabove { l + r ^<= 3i }
mabove { r ^<= 2i }
}
}
In general, Lout is designed so that the available width or height at
any point can be expressed by three inequalities of the form
@ID @OneRow @Eq {
matrix {
{ l ^<= x }
mabove { l + r ^<= y }
mabove { r ^<= z }
}
}
where @Eq {x }, @Eq {y} and @Eq {z} may be @Eq { infinity }. We
abbreviate these three inequalities to @Eq { l, r <= x, y, z }, and we
call @Eq {x, y, z} a {@I{size constraint}}.
@PP
The two examples above showed how to propagate the size constraint
@Eq { infinity, 5i, infinity } for
@Code "a / b" down one level to the child {@Code b}. Basser Lout
contains a complete set of general rules for all node types, too
complicated to give here. Instead, we give just one example of how
these rules are derived, using the object
@ID @OneRow {
@Eq {x sub 1} @Code "/" @Eq {x sub 2} @Code "/" @Eq {ldots} @Code
"/" @Eq {x sub n}
}
where @Eq { x sub j } has width @Eq { l sub j , r sub j } for all @Eq {j}.
@PP
Suppose the whole object has width constraint @OneCol @Eq {X,Y,Z}, and we
require the width constraint of {@Eq { x sub i }}. Let
@Eq { L = max sub j ` l sub j } and @Eq { R = max sub j ` r sub j },
so that @OneCol @Eq {L, R} is the width of the whole object. We assume
@Eq {L, R <= X,Y,Z}. Then @Eq { x sub i } can be enlarged to any size
@Eq { l sub i ` , r sub i } satisfying
@ID @Eq { ( l sub i up L), ( r sub i up R) <= X, Y, Z }
which expands to eight inequalities:
@ID @OneRow @Eq {
matrix {
{ l sub i ^<= X }
mabove { L ^<= X }
mabove { l sub i + r sub i ^<= Y }
mabove { l sub i + R ^<= Y }
mabove { L + r sub i ^<= Y }
mabove { L + R ^<= Y }
mabove { r sub i ^<= Z }
mabove { R ^<= Z }
}
}
Three are already known, and slightly rearranging the others gives
@ID @OneRow @Eq {
matrix {
{ l sub i ^<= X }
mabove { l sub i ^<= Y - R }
mabove { l sub i + r sub i ^<= Y }
mabove { r sub i ^<= Z }
mabove { r sub i ^<= Y - L }
}
}
Therefore the width constraint of @Eq { x sub i } is
@ID @Eq { min(X, Y-R), Y, min(Z, Y-L) }
The size constraint of any node can be found by climbing the tree to a
@I WIDE or @I HIGH node where the constraint is trivial, then propagating
it back down to the node, and this is the function of procedure
{@I Constrained} in Basser Lout.
@PP
After some components have been promoted into a target, the sizes stored
in its parent and higher ancestors must be adjusted to reflect the
increased size. This is done by yet another set of recursive rules,
upward-moving this time, which cease as soon as some ancestor's size
does not change. These rules are embodied in procedure @I AdjustSize
of Basser Lout. The adjustment must be done before relinquishing
control to any other galley, but not after every component.
@End @SubSection