These boxes were not available through the "descendants" function, because they
are represented by placeholders. They are also not available in the list of
absolute boxes of the page, because they’re not relative to the root page.
The new "placeholders" parameter of "descendants" goes through placeholders and
gets all the absolute children.
Putting "descendants" and "children" in all boxes, not just parents, avoids
useless checks and special cases.
Fix#2029.
This commit uses an "option" dictionary to store various API options that were
used as arguments in many public and private functions. This change allows to
easily document default values, to reduce the number of arguments and to avoid
many repetitions in documentation and signatures.
The changes to the public API are minimal, and should only have an impact for
users who passed unnamed arguments.
This solution is by far the cleanest I’ve found to follow max-height without
changing everything. Contrary to my previous tries, it keeps the original style
untouched, doesn’t add dirty properties on the box and only assumes that the
overflowing children are caused by the max-height set on the area. This last
condition is probably true in real-life cases, but we’ll sure find soon that
other users don’t have the real life we expect them to have.
It also has the side effect of following the height attribute too. There’s
nothing in the specification about which properties are allowed in @footnote
rules, only a classical "How would one describe this in the grammar of
CSS3-Page?", so … who cares? We’ll sure find soon that other users actually
care more than the W3C.
The existing tests pass, that’s good news, but we’ll need solid new tests.
Related to #1674.
Removing placeholders is something we have to do when we must discard a part of
the layout that has already been done. It currently removes absolutely
positioned placeholders and footnotes.
The same has to be done with split floats, that’s what this commit is about.
We have to change the structure of the broken_out_of_flow attribute, as we have
to get a reliable way to reach the saved data using from the real element in
the tree. The new structure is thus a dictionary whose keys are the boxes in
the tree (placeholder for absolutes, partial elements for floats) and whose
values are the original_box+parent+resume_at.
Fix#1669.
This fixes a bug accidentally introduced in #1566, where we would try to
unlayout a footnote that had not yet been laid out, if the algorithm
decided that there would be insufficient space on a page before laying
out a further footnote.
If a footnote has been output but we then decide to cancel the line it
was output on, we should cancel the output of the footnote itself.
This requires a bit of extra bookkeeping, so we know which footnotes are
relevant, but otherwise largely works using the existing
remove_placeholders code.
Includes a minor refactor of footnote area management in LayoutContext,
and a new testing utility: `tree_position`.
Closes#1564.
Handling footnote-display requires the footnote area children to be recreated
each time one footnote is added: as footnotes can be blocks or inlines, we have
to create anonymous boxes each time, and thus to do the whole footnote area
layout.
As the bottom of the page is now dynamic (because it changes with footnotes),
passing the max_position_y is difficult: it would require the value to be
passed to layout functions, and returned (possibly updated) by these functions.
The new solution is to store the page bottom in the context, and to update it
when a footnote is included. The new max position y is calculated when needed,
using the updated position of the page bottom.
To handle extra bottom spaces (bottom padding/border/margin of a parent box for
example), a bottom_space parameter is given when needed. This value can be set
to -inf when we don’t want to take care of the page bottom (that’s equivalent
to max_position_y=inf).
Many operations, including page breaks, require a pointer to a specific
position of the box tree. For example, we used to have this structure to point
to the beginning of the first child of the second child:
(1, (2, None))
We now use:
{1: {2: None}}
This change is the first step to handle parallel flows (see #36). It doesn’t
change anything to the layout for now, but it allows us to store multiple
pointers in the same structure.
The next step is to handle multiple pointers in skip_stack during boxes layout.
It means that most of the *_layout() function need an extra for-loop to manage
multiple skip stacks.
We’ll then need to split new types of boxes: table cells, floats, absolutes…
box.string_set is a pointer and is updated automatically when
parse_again() is called for page based counters and target-*.
box.bookmark_label is just a string an we must copy it explicitly
from the re-evaluated original boxes to the page's children.
On pages where the string was defined, the returned value was the entry value
instead of being the empty string. It doesn’t change anything on pages where
the value is defined for the first time, but it was different otherwise.