~ireas/genpdf-rs#65: 
Page numbering

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.

Status
REPORTED
Submitter
~carlomilanesi
Assigned to
No-one
Submitted
1 year, 11 months ago
Updated
1 year, 10 months ago
Labels
No labels applied.

~ireas 1 year, 11 months ago

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.

~carlomilanesi 1 year, 11 months ago

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

~ireas 1 year, 11 months ago

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 generic add_footer method to SimplePageDecorator.

~mglolenstine 1 year, 10 months ago

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.

Register here or Log in to comment, or comment via email.