Source code for pdfnaut.objects.destinations

from __future__ import annotations

from collections.abc import Sequence
from typing import TYPE_CHECKING, Literal, cast

from typing_extensions import Self

from pdfnaut.cos.objects import PdfArray, PdfHexString, PdfName, PdfNull, PdfObject, PdfReference

if TYPE_CHECKING:
    from pdfnaut.objects import Page

DestinationKind = Literal["XYZ", "Fit", "FitH", "FitV", "FitR", "FitB", "FitBH", "FitBV"]


def nullify(*objs: PdfObject | None) -> list[PdfObject]:
    return [obj if obj is not None else PdfNull() for obj in objs]


[docs] class Destination(PdfArray): """A explicit destination points to a page within a PDF document with a specified location and zoom factor. See ISO 32000-2:2020 ยง 12.3.2 "Destinations" for details. """
[docs] @classmethod def xyz( cls, page: Page, left: int | float | None = None, top: int | float | None = None, zoom: int | float | None = None, ) -> Self: """Creates a coordinate destination to ``page`` with the coordinates (``left``, ``top``) positioned at the upper-left corner of the window and the contents of the page magnified by the specified ``zoom`` factor. Omitting these parameters means that the current value shall remain unchanged. """ if page.indirect_ref is None: raise ValueError("page must be in document") return cls([page.indirect_ref, PdfName(b"XYZ"), *nullify(left, top, zoom)])
[docs] @classmethod def fit(cls, page: Page) -> Self: """Creates a destination to ``page`` with its contents magnified enough to fit the entire page within the window.""" if page.indirect_ref is None: raise ValueError("page must be in document") return cls([page.indirect_ref, PdfName(b"Fit")])
[docs] @classmethod def fit_horizontal(cls, page: Page, top: int | float | None = None) -> Self: """Creates a destination to ``page`` with its contents magnified enough to fit the entire page within the window horizontally and the top edge of the window positioned at the vertical coordinate ``top``.""" if page.indirect_ref is None: raise ValueError("page must be in document") return cls([page.indirect_ref, PdfName(b"FitH"), *nullify(top)])
[docs] @classmethod def fit_vertical(cls, page: Page, left: int | float | None = None) -> Self: """Creates a destination to ``page`` with its contents magnified enough to fit the entire page within the window vertically and the left edge of the window positioned at the horizontal coordinate ``left``.""" if page.indirect_ref is None: raise ValueError("page must be in document") return cls([page.indirect_ref, PdfName(b"FitV"), *nullify(left)])
[docs] @classmethod def fit_rectangle( cls, page: Page, left: int | float, bottom: int | float, right: int | float, top: int | float, ) -> Self: """Creates a destination to ``page`` with its contents magnified enough to fit the rectangle formed by the coordinates ``left``, ``bottom``, ``right``, and ``top``. """ if page.indirect_ref is None: raise ValueError("page must be in document") return cls([page.indirect_ref, PdfName(b"FitR"), left, bottom, right, top])
[docs] @classmethod def fit_bbox(cls, page: Page) -> Self: """Creates a destination to ``page`` with its contents magnified enough to fit the page bounding box.""" if page.indirect_ref is None: raise ValueError("page must be in document") return cls([page.indirect_ref, PdfName(b"FitB")])
[docs] @classmethod def fit_bbox_horizontal(cls, page: Page, top: int | float | None = None) -> Self: """Creates a destination to ``page`` with its contents magnified enough to fit the entire bounding box of the page within the window horizontally and the top edge of the window positioned at the vertical coordinate ``top``.""" if page.indirect_ref is None: raise ValueError("page must be in document") return cls([page.indirect_ref, PdfName(b"FitBH"), *nullify(top)])
[docs] @classmethod def fit_bbox_vertical(cls, page: Page, left: int | float | None = None) -> Self: """Creates a destination to ``page`` with its contents magnified enough to fit the entire bounding box of the page within the window vertically and the left edge of the window positioned at the horizontal coordinate ``left``.""" if page.indirect_ref is None: raise ValueError("page must be in document") return cls([page.indirect_ref, PdfName(b"FitBV"), *nullify(left)])
@property def page(self) -> Page: """The page the destination jumps to.""" from pdfnaut.objects import Page page_ref = cast(PdfReference, self.data[0]) return Page.from_dict(page_ref.get(), indirect_ref=page_ref) @property def kind(self) -> DestinationKind: """The kind of destination.""" name = cast(PdfName, self[1]).value.decode() return cast(DestinationKind, name) @property def args(self) -> Sequence[PdfObject]: """The arguments provided to the destination, such as coordinates or the zoom factor.""" return self[2:]
NamedDestination = PdfName | PdfHexString | bytes DestType = NamedDestination | Destination