Interpret vertical page number alignment differently

The vertical alignment of `number-align` now selects header or footer instead of aligning within the footer. This is a minor breaking change because
- top behaves differently now
- horizon is now forbidden
- bottom (the new default) behaves differently, too
Typical number-align usage will likely not use the vertical component at all, though.

Fixes #645
This commit is contained in:
Laurenz 2023-09-06 10:30:45 +02:00
parent 87c0a5171a
commit b76e8d5db9
4 changed files with 73 additions and 18 deletions

View File

@ -177,7 +177,8 @@ pub struct PageElem {
/// How to [number]($func/numbering) the pages.
///
/// If an explicit `footer` is given, the numbering is ignored.
/// If an explicit `footer` (or `header` for top-aligned numbering) is
/// given, the numbering is ignored.
///
/// ```example
/// #set page(
@ -192,6 +193,11 @@ pub struct PageElem {
/// The alignment of the page numbering.
///
/// If the vertical component is `top`, the numbering is placed into the
/// header and if it is `bottom`, it is placed in the footer. Horizon
/// alignment is forbidden. If an explicit matching `header` or `footer` is
/// given, the numbering is ignored.
///
/// ```example
/// #set page(
/// margin: (top: 16pt, bottom: 24pt),
@ -202,6 +208,15 @@ pub struct PageElem {
/// #lorem(30)
/// ```
#[default(Align::Center.into())]
#[parse({
let spanned: Option<Spanned<Axes<_>>> = args.named("number-align")?;
if let Some(Spanned { v, span }) = spanned {
if matches!(v.y, Some(GenAlign::Specific(Align::Horizon))) {
bail!(span, "page number cannot be `horizon`-aligned");
}
}
spanned.map(|s| s.v)
})]
pub number_align: Axes<Option<GenAlign>>,
/// The page's header. Fills the top margin of each page.
@ -372,25 +387,40 @@ impl PageElem {
let fill = self.fill(styles);
let foreground = self.foreground(styles);
let background = self.background(styles);
let header = self.header(styles);
let header_ascent = self.header_ascent(styles);
let footer = self.footer(styles).or_else(|| {
self.numbering(styles).map(|numbering| {
let both = match &numbering {
Numbering::Pattern(pattern) => pattern.pieces() >= 2,
Numbering::Func(_) => true,
};
Counter::new(CounterKey::Page)
.display(Some(numbering), both)
.aligned(self.number_align(styles))
})
});
let footer_descent = self.footer_descent(styles);
let numbering = self.numbering(styles);
let number_align = self.number_align(styles);
let mut header = self.header(styles);
let mut footer = self.footer(styles);
let numbering_meta = FrameItem::Meta(
Meta::PageNumbering(self.numbering(styles).into_value()),
Size::zero(),
);
// Construct the numbering (for header or footer).
let numbering_marginal = numbering.clone().map(|numbering| {
let both = match &numbering {
Numbering::Pattern(pattern) => pattern.pieces() >= 2,
Numbering::Func(_) => true,
};
let mut counter =
Counter::new(CounterKey::Page).display(Some(numbering), both);
// We interpret the Y alignment as selecting header or footer
// and then ignore it for aligning the actual number.
if let Some(x) = number_align.x {
counter = counter.aligned(Axes::with_x(Some(x)));
}
counter
});
if matches!(number_align.y, Some(GenAlign::Specific(Align::Top))) {
header = header.or(numbering_marginal);
} else {
footer = footer.or(numbering_marginal);
}
let numbering_meta =
FrameItem::Meta(Meta::PageNumbering(numbering.into_value()), Size::zero());
// Post-process pages.
for frame in frames.iter_mut() {

View File

@ -34,7 +34,7 @@ document or in your template.
"iso-b7",
header: rect[Header],
footer: rect[Footer],
number-align: top + center,
number-align: center,
)
#rect(fill: rgb("#565565"))

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,25 @@
// Test page number alignment.
---
#set page(
height: 100pt,
margin: 30pt,
numbering: "(1)",
number-align: top + right,
)
#block(width: 100%, height: 100%, fill: aqua.lighten(50%))
---
#set page(
height: 100pt,
margin: 30pt,
numbering: "[1]",
number-align: bottom + left,
)
#block(width: 100%, height: 100%, fill: aqua.lighten(50%))
---
// Error: 25-39 page number cannot be `horizon`-aligned
#set page(number-align: left + horizon)