It should be possible to add page numbers, and possibly also the total number of pages, like "3/7". This should be needed in a header or in a footer, possibly excluding the first page.
Adding page numbers is already possible as demonstrated in the
demo
example (PDF). Adding the total page number would be nice but pretty hard to implement with the current rendering process.
On 10/12/22 14:11, ~ireas wrote:
Adding page numbers is already possible as demonstrated in the
demo
example (PDF). Adding the total page number would be nice but pretty hard to implement with the current rendering process.I can print a header, but I cannot find how to print a footer.
-- Carlo Milanesi
I can print a header, but I cannot find how to print a footer.
It is not supported by
SimplePageDecorator
at the moment because you have to specify the position of the top-left corner of an element before rendering it. As you cannot determine the height of an element without rendering it, it is hard to do that for a footer with generic elements.But if you use a fixed height for the footer, you can create your own
PageDecorator
implementation that uses the fixed height to calculate the position of the element before rendering it.In the long-term, the
Element
trait should be extended to provide a size estimate without rendering the element. Then we could add a genericadd_footer
method toSimplePageDecorator
.
I did it this way. I opened a new area layer and padded the previous one by 10 so that I had 10 mm of space for the footer. Then I rendered the footer element at the bottom of the new layer (padding it to the bottom) and shortened the original area if the footer was too long.
#[derive(Default, Clone, Debug)] pub struct CustomPageDecorator { page: usize, } impl CustomPageDecorator { pub fn generate_footer(&self, top_padding: genpdf::Mm) -> Box<dyn Element> { Box::new( Paragraph::new(format!("Page {}", self.page)) .aligned(genpdf::Alignment::Right) .styled(genpdf::style::Style::new().with_font_size(8)) .padded(genpdf::Margins::trbl(top_padding, 0, 0, 0)), ) } }And then called it like so
impl PageDecorator for CustomPageDecorator { fn decorate_page<'a>( &mut self, context: &genpdf::Context, mut area: genpdf::render::Area<'a>, style: genpdf::style::Style, ) -> Result<genpdf::render::Area<'a>, genpdf::error::Error> { self.page += 1; let mut footer_area = area.next_layer(); //? Header let mut element = Paragraph::new("Header"); area.add_margins(10); let result = element.render(context, area.clone(), style)?; area.add_offset(Position::new(0, result.size.height + genpdf::Mm::from(5))); //? Footer footer_area.add_margins(Margins::trbl(0, 10, 0, 10)); let height = footer_area.size().height; let mut element = self.generate_footer(height - genpdf::Mm::from(11)); let result = element.render(context, footer_area.clone(), style)?; let footer_size = result.size.height - height + genpdf::Mm::from(15); area.set_height(area.size().height - footer_size); Ok(area) } }So far it works great, could probably be improved.