Skip to content

Conversation

@holdenrohrer
Copy link

When building pages and there are multiple options with the same lowest badness (for example, when there is at least one vfill inside the page, so all possible pages are badness 0), SILE will prefer the first possible break with that minimal badness. This doesn't match TeX's behavior, so I expect it is likely a bug.

My fix makes it take the last possible break with that minimum badness. This makes pages fuller and leads to less pathological behavior.

@holdenrohrer
Copy link
Author

I think any build errors are from environment issues rather than my change, which is ridiculously small (one line). @alerque would you be able to take a look at this? This was breaking a lot of my documents (which use some of Knuth's glue-tricks), so I think others would be also interested in fixing this edge case.

@Omikhleia
Copy link
Member

Omikhleia commented Oct 10, 2025

which use some of Knuth's glue-tricks

Hi @holdenrohrer
Can you possibly develop further which kind of tricks, possibly with a MWE?
(I am experimenting other page building strategies and I am interested in knowing which differences with the TeX-derived one I can also face there).

I think any build errors are from environment issues rather than my change

Yep, automated CI test are currently broken for another reason (#2297).

@Omikhleia Omikhleia added the needs MWE Minimum working example needed for investigation label Oct 10, 2025
@holdenrohrer
Copy link
Author

Sure, here's a simple example using vfill:

%SILE
\begin{document}
\use[module=packages.rules]

\define[command=segment]{%
  \hrule[height=2in]
  \vfill
}

\segment
\segment
\segment
\segment
\segment
\segment
\segment
\segment

\end{document}
%TeX
\def\segment{%
  \vrule height 2in
  \vfill
}
\segment
\segment
\segment
\segment
\segment
\segment
\segment
\segment
\bye

The TeX document generates 2 pages, with 4 rules on each page.
The SILE document generates 5 pages, with one rule on the first 4 pages and 4 on the last. (I'm using letterpaper)

This means that SILE is packing content really inefficiently when there are a bunch of glues on the page.

This is a very simple version of a trick that Knuth mentions on page 111 of the TeXbook:

The most interesting macro that plain TEX provides for page make-up is called
\filbreak. It means, roughly, “Break the page here and fill the bottom with
blank space, unless there is room for more copy that is itself followed by \filbreak.”
Thus if you put \filbreak at the end of every paragraph, and if your paragraphs aren’t
too long, every page break will occur between paragraphs, and TEX will fit as many
paragraphs as possible on each page. The precise meaning of \filbreak is

\vfil\penalty-200\vfilneg

according to Appendix B; and this simple combination of TEX’s primitives produces
the desired result: If a break is taken at the \penalty-200, the preceding \vfil will
fill the bottom of the page with blank space, and the \vfilneg will be discarded after
the break; but if no break is taken at the penalty, the \vfil and \vfilneg will cancel
each other and have no effect.

As it is, this macro couldn't work in SILE because SILE tries to break too early rather than pack more material into the page. However, I'm pretty sure with my change and a way to discard glue at the top of the page (which might already be the default iirc?), these macros would work.

@Omikhleia Omikhleia added this to the v0.15.x milestone Oct 16, 2025
@Omikhleia Omikhleia removed the needs MWE Minimum working example needed for investigation label Oct 16, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants