From 3171cb44aa9d7c7ada31ef78720b42ea28acd24a Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 13 Dec 2023 01:31:37 +0100 Subject: [PATCH] Bump fpdf2 to 2.7.7 (#11149) Closes: #11145 --- stubs/fpdf2/METADATA.toml | 2 +- stubs/fpdf2/fpdf/__init__.pyi | 2 + stubs/fpdf2/fpdf/annotations.pyi | 4 +- stubs/fpdf2/fpdf/drawing.pyi | 14 ++++- stubs/fpdf2/fpdf/enums.pyi | 2 + stubs/fpdf2/fpdf/fonts.pyi | 12 +++- stubs/fpdf2/fpdf/fpdf.pyi | 58 ++++++++++++------ stubs/fpdf2/fpdf/graphics_state.pyi | 4 ++ stubs/fpdf2/fpdf/image_datastructures.pyi | 59 ++++++++++++++++++ stubs/fpdf2/fpdf/image_parsing.pyi | 15 +++++ stubs/fpdf2/fpdf/line_break.pyi | 19 +++--- stubs/fpdf2/fpdf/output.pyi | 17 +++++- stubs/fpdf2/fpdf/svg.pyi | 73 +++++++++++++++++++---- stubs/fpdf2/fpdf/table.pyi | 19 +++--- stubs/fpdf2/fpdf/text_region.pyi | 59 +++++++++++++++++- 15 files changed, 300 insertions(+), 59 deletions(-) create mode 100644 stubs/fpdf2/fpdf/image_datastructures.pyi diff --git a/stubs/fpdf2/METADATA.toml b/stubs/fpdf2/METADATA.toml index f531f358fc41..8207ba52774c 100644 --- a/stubs/fpdf2/METADATA.toml +++ b/stubs/fpdf2/METADATA.toml @@ -1,4 +1,4 @@ -version = "2.7.6" +version = "2.7.7" upstream_repository = "https://github.com/PyFPDF/fpdf2" requires = ["types-Pillow>=9.2.0"] diff --git a/stubs/fpdf2/fpdf/__init__.pyi b/stubs/fpdf2/fpdf/__init__.pyi index 0ba2c5cfbfc9..134f8df2664d 100644 --- a/stubs/fpdf2/fpdf/__init__.pyi +++ b/stubs/fpdf2/fpdf/__init__.pyi @@ -1,6 +1,7 @@ from pathlib import Path from .enums import Align as Align, TextMode as TextMode, XPos as XPos, YPos as YPos +from .fonts import FontFace as FontFace from .fpdf import FPDF as FPDF, FPDFException as FPDFException, TitleStyle as TitleStyle from .html import HTML2FPDF as HTML2FPDF, HTMLMixin as HTMLMixin from .prefs import ViewerPreferences as ViewerPreferences @@ -16,6 +17,7 @@ __all__ = [ "__license__", "FPDF", "FPDFException", + "FontFace", "Align", "TextMode", "XPos", diff --git a/stubs/fpdf2/fpdf/annotations.pyi b/stubs/fpdf2/fpdf/annotations.pyi index fc0b765215b9..c67abdf26aea 100644 --- a/stubs/fpdf2/fpdf/annotations.pyi +++ b/stubs/fpdf2/fpdf/annotations.pyi @@ -6,7 +6,7 @@ from .actions import Action from .enums import AnnotationFlag, AnnotationName, FileAttachmentAnnotationName from .syntax import Destination, Name, PDFContentStream, PDFObject -DEFAULT_ANNOT_FLAGS: Incomplete +DEFAULT_ANNOT_FLAGS: tuple[AnnotationFlag, ...] class AnnotationMixin: type: Name @@ -27,6 +27,7 @@ class AnnotationMixin: name: AnnotationName | FileAttachmentAnnotationName | None ink_list: str | None f_s: str | None + d_a: str | None def __init__( self, subtype: str, @@ -48,6 +49,7 @@ class AnnotationMixin: file_spec: str | None = None, field_type: str | None = None, value: Incomplete | None = None, + default_appearance: str | None = None, ) -> None: ... class PDFAnnotation(AnnotationMixin, PDFObject): ... diff --git a/stubs/fpdf2/fpdf/drawing.pyi b/stubs/fpdf2/fpdf/drawing.pyi index ed2aa272c228..9cfa8a0f0be1 100644 --- a/stubs/fpdf2/fpdf/drawing.pyi +++ b/stubs/fpdf2/fpdf/drawing.pyi @@ -1,11 +1,11 @@ import decimal from _typeshed import Incomplete from collections import OrderedDict -from collections.abc import Callable, Generator, Iterator +from collections.abc import Callable, Generator, Iterator, Sequence from contextlib import contextmanager from re import Pattern -from typing import Any, ClassVar, NamedTuple, TypeVar -from typing_extensions import Self, TypeAlias +from typing import Any, ClassVar, NamedTuple, TypeVar, overload +from typing_extensions import Literal, Self, TypeAlias from .syntax import Name, Raw @@ -70,6 +70,14 @@ class DeviceCMYK(_DeviceCMYKBase): def rgb8(r, g, b, a: Incomplete | None = None) -> DeviceRGB: ... def gray8(g, a: Incomplete | None = None) -> DeviceGray: ... +@overload +def convert_to_device_color(r: DeviceGray, g: int = -1, b: int = -1) -> DeviceGray: ... +@overload +def convert_to_device_color(r: DeviceRGB, g: int = -1, b: int = -1) -> DeviceRGB: ... +@overload +def convert_to_device_color(r: int, g: Literal[-1] = -1, b: Literal[-1] = -1) -> DeviceGray: ... +@overload +def convert_to_device_color(r: Sequence[int] | int, g: int, b: int) -> DeviceGray | DeviceRGB: ... def cmyk8(c, m, y, k, a: Incomplete | None = None) -> DeviceCMYK: ... def color_from_hex_string(hexstr) -> DeviceRGB: ... def color_from_rgb_string(rgbstr) -> DeviceRGB: ... diff --git a/stubs/fpdf2/fpdf/enums.pyi b/stubs/fpdf2/fpdf/enums.pyi index a7001c3930bc..a0a0ff8a7700 100644 --- a/stubs/fpdf2/fpdf/enums.pyi +++ b/stubs/fpdf2/fpdf/enums.pyi @@ -70,6 +70,8 @@ class TableCellFillMode(CoerciveEnum): ROWS: str COLUMNS: str + def should_fill_cell(self, i: int, j: int) -> bool: ... + class RenderStyle(CoerciveEnum): D: str F: str diff --git a/stubs/fpdf2/fpdf/fonts.pyi b/stubs/fpdf2/fpdf/fonts.pyi index b99629adb54c..1c0a511553f6 100644 --- a/stubs/fpdf2/fpdf/fonts.pyi +++ b/stubs/fpdf2/fpdf/fonts.pyi @@ -2,6 +2,7 @@ import dataclasses from _typeshed import Incomplete from collections.abc import Generator from dataclasses import dataclass +from typing import overload from .drawing import DeviceGray, DeviceRGB, Number from .enums import TextEmphasis @@ -12,8 +13,8 @@ class FontFace: family: str | None emphasis: TextEmphasis | None size_pt: int | None - color: int | tuple[Number, Number, Number] | DeviceGray | DeviceRGB | None - fill_color: int | tuple[Number, Number, Number] | DeviceGray | DeviceRGB | None + color: DeviceGray | DeviceRGB | None + fill_color: DeviceGray | DeviceRGB | None def __init__( self, @@ -26,6 +27,13 @@ class FontFace: replace = dataclasses.replace + @overload + @staticmethod + def combine(default_style: None, override_style: None) -> None: ... # type: ignore[misc] + @overload + @staticmethod + def combine(default_style: FontFace | None, override_style: FontFace | None) -> FontFace: ... + class _FontMixin: i: int type: str diff --git a/stubs/fpdf2/fpdf/fpdf.pyi b/stubs/fpdf2/fpdf/fpdf.pyi index 079f64e94bff..0b67f20fc600 100644 --- a/stubs/fpdf2/fpdf/fpdf.pyi +++ b/stubs/fpdf2/fpdf/fpdf.pyi @@ -6,7 +6,7 @@ from io import BytesIO from pathlib import PurePath from re import Pattern from typing import Any, ClassVar, NamedTuple, overload -from typing_extensions import Literal, TypeAlias +from typing_extensions import Final, Literal, TypeAlias, deprecated from fpdf import ViewerPreferences from PIL import Image @@ -35,6 +35,13 @@ from .errors import FPDFException as FPDFException from .fonts import FontFace from .graphics_state import GraphicsStateMixin from .html import HTML2FPDF +from .image_datastructures import ( + ImageCache, + ImageInfo as ImageInfo, + RasterImageInfo as RasterImageInfo, + VectorImageInfo as VectorImageInfo, + _AlignLiteral, +) from .output import OutputProducer, PDFPage from .recorder import FPDFRecorder from .structure_tree import StructureTreeBuilder @@ -42,23 +49,26 @@ from .syntax import DestinationXYZ from .table import Table from .util import _Unit -__all__ = ["FPDF", "XPos", "YPos", "get_page_format", "ImageInfo", "TextMode", "TitleStyle", "PAGE_FORMATS"] +__all__ = [ + "FPDF", + "XPos", + "YPos", + "get_page_format", + "ImageInfo", + "RasterImageInfo", + "VectorImageInfo", + "TextMode", + "TitleStyle", + "PAGE_FORMATS", +] _Orientation: TypeAlias = Literal["", "portrait", "p", "P", "landscape", "l", "L"] _Format: TypeAlias = Literal["", "a3", "A3", "a4", "A4", "a5", "A5", "letter", "Letter", "legal", "Legal"] _FontStyle: TypeAlias = Literal["", "B", "I"] _FontStyles: TypeAlias = Literal["", "B", "I", "U", "BU", "UB", "BI", "IB", "IU", "UI", "BIU", "BUI", "IBU", "IUB", "UBI", "UIB"] -PAGE_FORMATS: dict[_Format, tuple[float, float]] -class ImageInfo(dict[str, Any]): - @property - def width(self) -> int: ... - @property - def height(self) -> int: ... - @property - def rendered_width(self) -> int: ... - @property - def rendered_height(self) -> int: ... +FPDF_VERSION: Final[str] +PAGE_FORMATS: dict[_Format, tuple[float, float]] class TitleStyle(FontFace): t_margin: int | None @@ -87,7 +97,6 @@ def get_page_format(format: _Format | tuple[float, float], k: float | None = Non # TODO: TypedDicts _Font: TypeAlias = dict[str, Any] -_Image: TypeAlias = dict[str, Any] class FPDF(GraphicsStateMixin): MARKDOWN_BOLD_MARKER: ClassVar[str] @@ -102,15 +111,14 @@ class FPDF(GraphicsStateMixin): page: int pages: dict[int, PDFPage] fonts: dict[str, _Font] - images: dict[str, _Image] links: dict[int, DestinationXYZ] embedded_files: list[PDFEmbeddedFile] + image_cache: ImageCache in_footer: bool str_alias_nb_pages: str xmp_metadata: str | None - image_filter: str page_duration: int page_transition: Incomplete | None allow_images_transparency: bool @@ -148,6 +156,8 @@ class FPDF(GraphicsStateMixin): w: float h: float + text_shaping: dict[str, Incomplete] | None # TODO: TypedDict + def __init__( self, orientation: _Orientation = "portrait", @@ -371,7 +381,16 @@ class FPDF(GraphicsStateMixin): h: float = 1, name: AnnotationName | str | None = None, flags: tuple[AnnotationFlag, ...] | tuple[str, ...] = ..., - ) -> None: ... + ) -> AnnotationDict: ... + def free_text_annotation( + self, + text: str, + x: float | None = None, + y: float | None = None, + w: float | None = None, + h: float | None = None, + flags: tuple[AnnotationFlag, ...] | tuple[str, ...] = ..., + ) -> AnnotationDict: ... def add_action(self, action, x: float, y: float, w: float, h: float) -> None: ... def highlight( self, @@ -466,10 +485,12 @@ class FPDF(GraphicsStateMixin): def text_columns( self, text: str | None = None, + img: str | None = None, + img_fill_width: bool = False, ncols: int = 1, gutter: float = 10, balance: bool = False, - text_align: Align | str = "LEFT", + text_align: Align | _AlignLiteral = "LEFT", line_height: float = 1, l_margin: float | None = None, r_margin: float | None = None, @@ -490,7 +511,8 @@ class FPDF(GraphicsStateMixin): alt_text: str | None = None, dims: tuple[float, float] | None = None, keep_aspect_ratio: bool = False, - ) -> _Image: ... + ) -> RasterImageInfo | VectorImageInfo: ... + @deprecated("Deprecated since 2.7.7; use fpdf.image_parsing.preload_image() instead") def preload_image( self, name: str | Image.Image | BytesIO, dims: tuple[float, float] | None = None ) -> tuple[str, Any, ImageInfo]: ... diff --git a/stubs/fpdf2/fpdf/graphics_state.pyi b/stubs/fpdf2/fpdf/graphics_state.pyi index 029b4f6bf599..fec06f18ea17 100644 --- a/stubs/fpdf2/fpdf/graphics_state.pyi +++ b/stubs/fpdf2/fpdf/graphics_state.pyi @@ -102,4 +102,8 @@ class GraphicsStateMixin: def denom_lift(self): ... @denom_lift.setter def denom_lift(self, v) -> None: ... + @property + def text_shaping(self): ... + @text_shaping.setter + def text_shaping(self, v) -> None: ... def font_face(self) -> FontFace: ... diff --git a/stubs/fpdf2/fpdf/image_datastructures.pyi b/stubs/fpdf2/fpdf/image_datastructures.pyi new file mode 100644 index 000000000000..42ea9e5e535b --- /dev/null +++ b/stubs/fpdf2/fpdf/image_datastructures.pyi @@ -0,0 +1,59 @@ +from _typeshed import Incomplete +from dataclasses import dataclass +from typing import Any +from typing_extensions import Literal, TypeAlias + +from fpdf.enums import Align +from fpdf.fpdf import FPDF + +from .image_parsing import _ImageFilter + +_AlignLiteral: TypeAlias = Literal[ + "", + "CENTER", + "X_CENTER", + "LEFT", + "RIGHT", + "JUSTIFY", + "center", + "x_center", + "left", + "right", + "justify", + "C", + "X", + "L", + "R", + "J", + "c", + "x", + "l", + "r", + "j", +] + +class ImageInfo(dict[str, Any]): + @property + def width(self) -> int: ... + @property + def height(self) -> int: ... + @property + def rendered_width(self) -> int: ... + @property + def rendered_height(self) -> int: ... + def scale_inside_box(self, x: float, y: float, w: float, h: float) -> tuple[float, float, float, float]: ... + @staticmethod + def x_by_align(x: Align | _AlignLiteral, w: float, pdf: FPDF, keep_aspect_ratio: Literal[False]) -> float: ... + +class RasterImageInfo(ImageInfo): + def size_in_document_units(self, w: float, h: float, scale=1) -> tuple[float, float]: ... + +class VectorImageInfo(ImageInfo): ... + +@dataclass +class ImageCache: + images: dict[str, dict[Incomplete, Incomplete]] = ... + icc_profiles: dict[bytes, int] = ... + image_filter: _ImageFilter = "AUTO" + + def reset_usages(self) -> None: ... diff --git a/stubs/fpdf2/fpdf/image_parsing.pyi b/stubs/fpdf2/fpdf/image_parsing.pyi index acf3b67581f4..8c859cf0b0e9 100644 --- a/stubs/fpdf2/fpdf/image_parsing.pyi +++ b/stubs/fpdf2/fpdf/image_parsing.pyi @@ -1,4 +1,5 @@ from _typeshed import Incomplete +from dataclasses import dataclass from io import BytesIO from logging import Logger from types import TracebackType @@ -7,15 +8,29 @@ from typing_extensions import Literal, TypeAlias from PIL import Image +from .image_datastructures import ImageCache, ImageInfo, VectorImageInfo +from .svg import SVGObject + _ImageFilter: TypeAlias = Literal["AUTO", "FlateDecode", "DCTDecode", "JPXDecode"] RESAMPLE: Image.Resampling + +@dataclass +class ImageSettings: + compression_level: int = -1 + LOGGER: Logger SUPPORTED_IMAGE_FILTERS: tuple[_ImageFilter, ...] +SETTINGS: ImageSettings + TIFFBitRevTable: list[int] +def preload_image( + image_cache: ImageCache, name: str | BytesIO | Image.Image, dims: tuple[float, float] | None = None +) -> tuple[str, BytesIO | Image.Image | None, ImageInfo]: ... def load_image(filename): ... def is_iccp_valid(iccp, filename) -> bool: ... +def get_svg_info(filename: str, img: BytesIO, image_cache: ImageCache) -> tuple[str, SVGObject, VectorImageInfo]: ... # Returned dict could be typed as a TypedDict. def get_img_info( diff --git a/stubs/fpdf2/fpdf/line_break.pyi b/stubs/fpdf2/fpdf/line_break.pyi index 1840ba1a2cd0..302b2e156610 100644 --- a/stubs/fpdf2/fpdf/line_break.pyi +++ b/stubs/fpdf2/fpdf/line_break.pyi @@ -1,14 +1,16 @@ from _typeshed import Incomplete from collections.abc import Callable, Sequence from typing import NamedTuple +from typing_extensions import Final from .enums import Align, WrapMode -SOFT_HYPHEN: str -HYPHEN: str -SPACE: str -NBSP: str -NEWLINE: str +SOFT_HYPHEN: Final[str] +HYPHEN: Final[str] +SPACE: Final[str] +NBSP: Final[str] +NEWLINE: Final[str] +FORM_FEED: Final[str] class Fragment: characters: list[str] @@ -70,7 +72,8 @@ class TextLine(NamedTuple): align: Align height: float max_width: float - trailing_nl: bool = ... + trailing_nl: bool = False + trailing_form_feed: bool = False class SpaceHint(NamedTuple): original_fragment_index: int @@ -114,8 +117,8 @@ class CurrentLine: url: str | None = None, ): ... def trim_trailing_spaces(self) -> None: ... - def manual_break(self, align: Align, trailing_nl: bool = False): ... - def automatic_break_possible(self): ... + def manual_break(self, align: Align, trailing_nl: bool = False, trailing_form_feed: bool = False) -> TextLine: ... + def automatic_break_possible(self) -> bool: ... def automatic_break(self, align: Align): ... class MultiLineBreak: diff --git a/stubs/fpdf2/fpdf/output.pyi b/stubs/fpdf2/fpdf/output.pyi index 03b078a7f6b8..575d4d5d8338 100644 --- a/stubs/fpdf2/fpdf/output.pyi +++ b/stubs/fpdf2/fpdf/output.pyi @@ -5,6 +5,8 @@ from typing_extensions import Final from .annotations import AnnotationDict from .encryption import StandardSecurityHandler +from .fpdf import FPDF +from .image_datastructures import RasterImageInfo from .syntax import Name, PDFArray, PDFContentStream, PDFObject, PDFString LOGGER: Logger @@ -172,12 +174,23 @@ class PDFXrefAndTrailer(ContentWithoutID): def serialize(self, _security_handler: StandardSecurityHandler | None = None) -> str: ... class OutputProducer: - fpdf: Incomplete + fpdf: FPDF pdf_objs: list[Incomplete] obj_id: int offsets: dict[Incomplete, Incomplete] trace_labels_per_obj_id: dict[Incomplete, Incomplete] sections_size_per_trace_label: defaultdict[Incomplete, int] buffer: bytearray - def __init__(self, fpdf) -> None: ... + def __init__(self, fpdf: FPDF) -> None: ... def bufferize(self) -> bytearray: ... + +def stream_content_for_raster_image( + info: RasterImageInfo, + x: float, + y: float, + w: float, + h: float, + keep_aspect_ratio: bool = False, + scale: float = 1, + pdf_height_to_flip: float | None = None, +) -> str: ... diff --git a/stubs/fpdf2/fpdf/svg.pyi b/stubs/fpdf2/fpdf/svg.pyi index 82f18d4a9238..815c38a41c3d 100644 --- a/stubs/fpdf2/fpdf/svg.pyi +++ b/stubs/fpdf2/fpdf/svg.pyi @@ -1,10 +1,16 @@ -from _typeshed import Incomplete +from _typeshed import Incomplete, Unused from collections.abc import Callable +from logging import Logger from re import Pattern - -from fpdf.drawing import PaintedPath +from typing import NamedTuple, overload +from typing_extensions import Literal from ._fonttools_shims import BasePen, _TTGlyphSet +from .drawing import ClippingPath, PaintedPath +from .fpdf import FPDF +from .image_datastructures import ImageCache + +LOGGER: Logger __pdoc__: dict[str, bool] @@ -40,20 +46,40 @@ def parse_style(svg_element) -> None: ... def apply_styles(stylable, svg_element) -> None: ... class ShapeBuilder: + @overload @staticmethod - def new_path(tag): ... + def new_path(tag, clipping_path: Literal[True]) -> ClippingPath: ... + @overload + @staticmethod + def new_path(tag, clipping_path: Literal[False] = False) -> PaintedPath: ... + @overload + @classmethod + def rect(cls, tag, clipping_path: Literal[True]) -> ClippingPath: ... + @overload @classmethod - def rect(cls, tag): ... + def rect(cls, tag, clipping_path: Literal[False] = False) -> PaintedPath: ... + @overload @classmethod - def circle(cls, tag): ... + def circle(cls, tag, clipping_path: Literal[True]) -> ClippingPath: ... + @overload @classmethod - def ellipse(cls, tag): ... + def circle(cls, tag, clipping_path: Literal[False] = False) -> PaintedPath: ... + @overload @classmethod - def line(cls, tag): ... + def ellipse(cls, tag, clipping_path: Literal[True]) -> ClippingPath: ... + @overload @classmethod - def polyline(cls, tag): ... + def ellipse(cls, tag, clipping_path: Literal[False] = False) -> PaintedPath: ... @classmethod - def polygon(cls, tag): ... + def line(cls, tag) -> PaintedPath: ... + @classmethod + def polyline(cls, tag) -> PaintedPath: ... + @overload + @classmethod + def polygon(cls, tag, clipping_path: Literal[True]) -> ClippingPath: ... + @overload + @classmethod + def polygon(cls, tag, clipping_path: Literal[False] = False) -> PaintedPath: ... def convert_transforms(tfstr): ... @@ -67,14 +93,17 @@ class PathPen(BasePen): def svg_path_converter(pdf_path: PaintedPath, svg_path: str) -> None: ... class SVGObject: + image_cache: ImageCache | None + @classmethod def from_file(cls, filename, *args, encoding: str = "utf-8", **kwargs): ... cross_references: Incomplete - def __init__(self, svg_text) -> None: ... + def __init__(self, svg_text, image_cache: ImageCache | None = None) -> None: ... preserve_ar: Incomplete width: Incomplete height: Incomplete viewbox: Incomplete + def update_xref(self, key: str | None, referenced) -> None: ... def extract_shape_info(self, root_tag) -> None: ... base_group: Incomplete def convert_graphics(self, root_tag) -> None: ... @@ -83,9 +112,29 @@ class SVGObject: self, scale, width, height, align_viewbox: bool = True, ignore_svg_top_attrs: bool = False ): ... def draw_to_page( - self, pdf, x: Incomplete | None = None, y: Incomplete | None = None, debug_stream: Incomplete | None = None + self, pdf: FPDF, x: Incomplete | None = None, y: Incomplete | None = None, debug_stream: Incomplete | None = None ) -> None: ... def handle_defs(self, defs) -> None: ... def build_xref(self, xref): ... def build_group(self, group, pdf_group: Incomplete | None = None): ... def build_path(self, path): ... + def build_shape(self, shape): ... + def build_clipping_path(self, shape, clip_id): ... + def apply_clipping_path(self, stylable, svg_element) -> None: ... + def build_image(self, image) -> SVGImage: ... + +class SVGImage(NamedTuple): + href: str + x: float + y: float + width: float + height: float + svg_obj: SVGObject + + def __deepcopy__(self, _memo: Unused) -> SVGImage: ... + def render( + self, _gsd_registry: Unused, _style: Unused, last_item, initial_point + ) -> tuple[Incomplete, Incomplete, Incomplete]: ... + def render_debug( + self, gsd_registry: Unused, style: Unused, last_item, initial_point, debug_stream, _pfx: Unused + ) -> tuple[Incomplete, Incomplete, Incomplete]: ... diff --git a/stubs/fpdf2/fpdf/table.pyi b/stubs/fpdf2/fpdf/table.pyi index 17579ca735e9..9dedab1bef0e 100644 --- a/stubs/fpdf2/fpdf/table.pyi +++ b/stubs/fpdf2/fpdf/table.pyi @@ -14,13 +14,6 @@ from .util import Padding DEFAULT_HEADINGS_STYLE: FontFace -def draw_box_borders(pdf: FPDF, x1, y1, x2, y2, border: str | Literal[0, 1], fill_color: Incomplete | None = None) -> None: ... -@dataclass(frozen=True) -class RowLayoutInfo: - height: int - triggers_page_jump: bool - rendered_height: dict[Incomplete, Incomplete] - class Table: rows: list[Row] @@ -48,14 +41,14 @@ class Table: outer_border_width: float | None = None, num_heading_rows: int = 1, ) -> None: ... - def row(self, cells: Iterable[str] = ()) -> Row: ... + def row(self, cells: Iterable[str] = (), style: FontFace | None = None) -> Row: ... def render(self) -> None: ... def get_cell_border(self, i, j) -> str | Literal[0, 1]: ... class Row: cells: list[Cell] style: FontFace - def __init__(self, fpdf: FPDF) -> None: ... + def __init__(self, table: Table, style: FontFace | None = None) -> None: ... @property def cols_count(self) -> int: ... @property @@ -86,3 +79,11 @@ class Cell: link: str | int | None def write(self, text, align: Incomplete | None = None): ... + +@dataclass(frozen=True) +class RowLayoutInfo: + height: int + triggers_page_jump: bool + rendered_height: dict[Incomplete, Incomplete] + +def draw_box_borders(pdf: FPDF, x1, y1, x2, y2, border: str | Literal[0, 1], fill_color: Incomplete | None = None) -> None: ... diff --git a/stubs/fpdf2/fpdf/text_region.pyi b/stubs/fpdf2/fpdf/text_region.pyi index 46aa47da8177..bbdf463b39c9 100644 --- a/stubs/fpdf2/fpdf/text_region.pyi +++ b/stubs/fpdf2/fpdf/text_region.pyi @@ -1,8 +1,10 @@ from _typeshed import Incomplete from collections.abc import Sequence from typing import NamedTuple +from typing_extensions import Self from .enums import Align, WrapMode +from .image_datastructures import RasterImageInfo, VectorImageInfo, _AlignLiteral class Extents(NamedTuple): left: float @@ -45,9 +47,43 @@ class Paragraph: def ln(self, h: float | None = None) -> None: ... def build_lines(self, print_sh: bool) -> list[LineWrapper]: ... +class ImageParagraph: + region: Incomplete + name: Incomplete + align: Align | None + width: float | None + height: float | None + fill_width: bool + keep_aspect_ratio: bool + top_margin: float + bottom_margin: float + link: Incomplete | None + title: Incomplete | None + alt_text: Incomplete | None + img: Incomplete | None + info: Incomplete | None + + def __init__( + self, + region, + name, + align: Align | _AlignLiteral | None = None, + width: float | None = None, + height: float | None = None, + fill_width: bool = False, + keep_aspect_ratio: bool = False, + top_margin: float = 0, + bottom_margin: float = 0, + link: Incomplete | None = None, + title: Incomplete | None = None, + alt_text: Incomplete | None = None, + ) -> None: ... + def build_line(self) -> Self: ... + def render(self, col_left: float, col_width: float, max_height: float) -> VectorImageInfo | RasterImageInfo: ... + class ParagraphCollectorMixin: pdf: Incomplete - text_align: Align | str = "LEFT" + text_align: Align line_height: Incomplete print_sh: Incomplete wrapmode: Incomplete @@ -57,11 +93,13 @@ class ParagraphCollectorMixin: pdf, *args, text: str | None = None, - text_align: str = "LEFT", + text_align: Align | _AlignLiteral = "LEFT", line_height: float = 1.0, print_sh: bool = False, skip_leading_spaces: bool = False, wrapmode: WrapMode | None = None, + img: Incomplete | None = None, + img_fill_width: bool = False, **kwargs, ) -> None: ... def __enter__(self): ... @@ -78,6 +116,20 @@ class ParagraphCollectorMixin: wrapmode: WrapMode | None = None, ): ... def end_paragraph(self) -> None: ... + def image( + self, + name, + align: Align | _AlignLiteral | None = None, + width: float | None = None, + height: float | None = None, + fill_width: bool = False, + keep_aspect_ratio: bool = False, + top_margin: float = 0, + bottom_margin: float = 0, + link: Incomplete | None = None, + title: Incomplete | None = None, + alt_text: Incomplete | None = None, + ) -> None: ... class TextRegion(ParagraphCollectorMixin): def current_x_extents(self, y, height) -> None: ... @@ -93,6 +145,7 @@ class TextColumnarMixin: class TextColumns(TextRegion, TextColumnarMixin): balance: Incomplete def __init__(self, pdf, *args, ncols: int = 1, gutter: float = 10, balance: bool = False, **kwargs) -> None: ... - def __enter__(self): ... + def __enter__(self) -> Self: ... + def new_column(self) -> None: ... def render(self) -> None: ... def current_x_extents(self, y, height): ...