Skip to content

Improve realization and page layout#4840

Merged
laurmaedje merged 1 commit intomainfrom
page-improvements
Aug 26, 2024
Merged

Improve realization and page layout#4840
laurmaedje merged 1 commit intomainfrom
page-improvements

Conversation

@laurmaedje
Copy link
Member

This pull request refactors and improves realization and page layout, fixing various bugs in the process.

Changes

  • Page styles are now resolved in a smarter way: Beyond taking the intersection of the styles of all elements in a page run (consecutive content between two pagebreaks / document boundaries), there are a now few rules according to which styles are filtered: To be used at the page level, styles must now be outside && (initial || liftable).

    • "Outside" means they were not produced within a show rule or that the show rule "broke free" to the page level by emitting page styles.
    • "Initial" means they were active at the pagebreak that introduced the page. Since these are intuitively already active, they should be kept if not liftable. (E.g. text(red, page(..)) makes the footer red.)
    • "Liftable" means they can be lifted to the page-level even though they weren't yet active at the very beginning. Set rule styles are liftable as opposed to direct constructor calls:
      • For set page(..); set text(red) the red text is kept even though it comes after the weak pagebreak from set page.
      • For set page(..); text(red)[..] the red isn't kept because the constructor styles are not liftable.

    This fixes the problem that the page's header and footer inherit styles from headings or other elements on the page.

  • All locatable elements now emit a start and an end tag instead of just a single tag. This is primarily useful for future work on Tagged PDF, but it also allows us to correctly determine the exact position of an element in cases where we previously couldn't. In the case of show heading: it => pagebreak() + it, the heading's position will be after the pagebreak because neither visible content nor the matching end tag occurred before the pagebreak. Meanwhile, in metadata("hi") + pagebreak(), the position of the metadata will be before the pagebreak because it's end tag already appeared before the pagebreak. Notably, this means that the nesting of zero-sized elements is not necessarily preserved in the tag output (if the metadata was inside of the heading show rule, it remains before the pagebreak, but the heading migrates to after it).

  • Fixes for various interactions between tags and layout & styling: Unless there is a bug, a tag should never have any effect on the page layout anymore. In particular, it shouldn't append, prepend, or force any empty pages. It will also not affect shared page style resolution anymore. There is also a new mechanism where tags can be conceptually "between pages" (or more concretely, at the very start or end of pages, even before the header or footer). This behaviour is triggered when a tag is sandwiched in between two weak pagebreaks (or a weak pagebreak and a document boundary). This is primarily useful to step the page counter between a header and a footer, which was previously not possible.

  • The page constructor does not emit a page element anymore. Instead, it works like the par and text constructors. It merely inserts pagebreaks and applies styling. This unifies things and also means that context page.margin also works within a page(margin: ..)[..]. The notion of an instantiated page element is not useful anyway because page show rules are (a) currently completely useless and (b) will be special when they are not useless anymore.

  • Weak pagebreaks are now resolved during layout instead of realization, fixing weird interactions between to: "odd" | "even" and weak, and the problem that a single weak pagebreak produced an empty document.

Linked issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment