Source code for pdfje.layout.pages

from __future__ import annotations

from dataclasses import dataclass
from functools import partial
from itertools import chain, count
from typing import Callable, Iterable, Iterator, final

from ..common import always, flatten, setattr_frozen
from ..page import Page, RenderedPage
from ..resources import Resources
from ..style import StyleFull
from .common import Block, PageFill, fill_pages
from .paragraph import Paragraph


[docs] @final @dataclass(slots=True, frozen=True, init=False) class AutoPage: """Automatically lays out content on multiple pages. Parameters ---------- content: ~typing.Iterable[~pdfje.Block | str] | ~pdfje.Block | str The content to lay out on the pages. Can be parsed from single string or block. template: ~pdfje.Page | ~typing.Callable[[int], ~pdfje.Page] A page to use as a template for the layout. If a callable is given, it is called with the page number as the only argument to generate the page. Defaults to the default :class:`Page`. """ content: Iterable[str | Block] template: Callable[[int], Page] def __init__( self, content: str | Block | Iterable[Block | str], template: Page | Callable[[int], Page] = always(Page()), ) -> None: if isinstance(content, str): content = [Paragraph(content)] elif isinstance(content, Block): content = [content] setattr_frozen(self, "content", content) if isinstance(template, Page): template = always(template) setattr_frozen(self, "template", template) def render( self, r: Resources, s: StyleFull, pnum: int, / ) -> Iterator[RenderedPage]: pages: Iterator[PageFill] = map( PageFill.new, map(self.template, count(pnum)) ) for block in map(_as_block, self.content): pages, filled = fill_pages( pages, partial(block.into_columns, r, s) ) for p in filled: yield p.base.fill(r, s, flatten(p.done)) last = next(pages) yield last.base.fill(r, s, flatten(chain(last.done, last.todo)))
def _as_block(b: str | Block) -> Block: return Paragraph(b) if isinstance(b, str) else b