From 4f94a0e14020d63344a3d318bdefc33206b2547f Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Thu, 10 Oct 2024 16:49:39 +0200 Subject: [PATCH] Bump fpdf2 to 2.8.1 (#12753) Closes: #12738 --- stubs/fpdf2/@tests/stubtest_allowlist.txt | 6 +- stubs/fpdf2/METADATA.toml | 2 +- stubs/fpdf2/fpdf/__init__.pyi | 3 +- stubs/fpdf2/fpdf/drawing.pyi | 8 +- stubs/fpdf2/fpdf/enums.pyi | 6 +- stubs/fpdf2/fpdf/fonts.pyi | 38 ++++- stubs/fpdf2/fpdf/fpdf.pyi | 108 +++++++++----- stubs/fpdf2/fpdf/html.pyi | 47 +++--- stubs/fpdf2/fpdf/image_datastructures.pyi | 5 +- stubs/fpdf2/fpdf/line_break.pyi | 6 +- stubs/fpdf2/fpdf/table.pyi | 2 +- stubs/fpdf2/fpdf/template.pyi | 6 +- stubs/fpdf2/fpdf/text_region.pyi | 24 ++- stubs/fpdf2/fpdf/unicode_script.pyi | 172 ++++++++++++++++++++++ 14 files changed, 346 insertions(+), 87 deletions(-) create mode 100644 stubs/fpdf2/fpdf/unicode_script.pyi diff --git a/stubs/fpdf2/@tests/stubtest_allowlist.txt b/stubs/fpdf2/@tests/stubtest_allowlist.txt index ea1b8ded9..3453af1c7 100644 --- a/stubs/fpdf2/@tests/stubtest_allowlist.txt +++ b/stubs/fpdf2/@tests/stubtest_allowlist.txt @@ -8,7 +8,5 @@ fpdf._fonttools_shims # Only present if harfbuzz is installed fpdf.fonts.HarfBuzzFont -# Checking the following function crashes stubtest 0.991, but seems to be -# fixed in later versions. -fpdf.FPDF.set_encryption -fpdf.fpdf.FPDF.set_encryption +# Stubtest wants us to use Literals, but that is unreasonable. +fpdf.unicode_script.UNICODE_RANGE_TO_SCRIPT diff --git a/stubs/fpdf2/METADATA.toml b/stubs/fpdf2/METADATA.toml index eb033d741..a86dce92a 100644 --- a/stubs/fpdf2/METADATA.toml +++ b/stubs/fpdf2/METADATA.toml @@ -1,4 +1,4 @@ -version = "2.7.9" +version = "2.8.1" upstream_repository = "https://github.com/PyFPDF/fpdf2" requires = ["Pillow>=10.3.0"] diff --git a/stubs/fpdf2/fpdf/__init__.pyi b/stubs/fpdf2/fpdf/__init__.pyi index 134f8df26..b6d360183 100644 --- a/stubs/fpdf2/fpdf/__init__.pyi +++ b/stubs/fpdf2/fpdf/__init__.pyi @@ -1,7 +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 .fonts import FontFace as FontFace, TextStyle as TextStyle 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 @@ -25,6 +25,7 @@ __all__ = [ "Template", "FlexTemplate", "TitleStyle", + "TextStyle", "ViewerPreferences", "HTMLMixin", "HTML2FPDF", diff --git a/stubs/fpdf2/fpdf/drawing.pyi b/stubs/fpdf2/fpdf/drawing.pyi index f9a426344..648523c5c 100644 --- a/stubs/fpdf2/fpdf/drawing.pyi +++ b/stubs/fpdf2/fpdf/drawing.pyi @@ -75,9 +75,13 @@ 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: ... +def convert_to_device_color(r: DeviceCMYK) -> DeviceCMYK: ... @overload -def convert_to_device_color(r: DeviceRGB, g: int = -1, b: int = -1) -> DeviceRGB: ... +def convert_to_device_color(r: DeviceGray) -> DeviceGray: ... +@overload +def convert_to_device_color(r: DeviceRGB) -> DeviceRGB: ... +@overload +def convert_to_device_color(r: str) -> DeviceRGB: ... @overload def convert_to_device_color(r: int, g: Literal[-1] = -1, b: Literal[-1] = -1) -> DeviceGray: ... @overload diff --git a/stubs/fpdf2/fpdf/enums.pyi b/stubs/fpdf2/fpdf/enums.pyi index d08f6ac20..e8a66b855 100644 --- a/stubs/fpdf2/fpdf/enums.pyi +++ b/stubs/fpdf2/fpdf/enums.pyi @@ -1,6 +1,6 @@ from enum import Enum, Flag, IntEnum, IntFlag from typing import Literal -from typing_extensions import Self +from typing_extensions import Self, TypeAlias from .syntax import Name @@ -38,6 +38,8 @@ class Align(CoerciveEnum): R = "RIGHT" J = "JUSTIFY" +_Align: TypeAlias = Align | Literal["CENTER", "X_CENTER", "LEFT", "RIGHT", "JUSTIFY"] # noqa: Y047 + class VAlign(CoerciveEnum): M = "MIDDLE" T = "TOP" @@ -51,6 +53,8 @@ class TextEmphasis(CoerciveIntFlag): @property def style(self) -> str: ... + def add(self, value: TextEmphasis) -> TextEmphasis: ... + def remove(self, value: TextEmphasis) -> TextEmphasis: ... class MethodReturnValue(CoerciveIntFlag): PAGE_BREAK = 1 diff --git a/stubs/fpdf2/fpdf/fonts.pyi b/stubs/fpdf2/fpdf/fonts.pyi index f4e7722d8..eb8c93478 100644 --- a/stubs/fpdf2/fpdf/fonts.pyi +++ b/stubs/fpdf2/fpdf/fonts.pyi @@ -2,8 +2,8 @@ import dataclasses from _typeshed import Incomplete from collections.abc import Generator from dataclasses import dataclass -from typing import overload -from typing_extensions import Self +from typing import Final, overload +from typing_extensions import Self, deprecated from .drawing import DeviceGray, DeviceRGB, Number from .enums import TextEmphasis @@ -39,6 +39,40 @@ class FontFace: @staticmethod def combine(default_style: FontFace | None, override_style: FontFace | None) -> FontFace: ... +class TextStyle(FontFace): + t_margin: int + l_margin: int + b_margin: int + def __init__( + self, + font_family: str | None = None, + font_style: str | None = None, + font_size_pt: int | None = None, + color: int | tuple[int, int, int] | None = None, + fill_color: int | tuple[int, int, int] | None = None, + underline: bool = False, + t_margin: int | None = None, + l_margin: int | None = None, + b_margin: int | None = None, + ): ... + def replace( # type: ignore[override] + self, + /, + font_family: str | None = None, + emphasis: TextEmphasis | None = None, + font_size_pt: int | None = None, + color: int | tuple[int, int, int] | None = None, + fill_color: int | tuple[int, int, int] | None = None, + t_margin: int | None = None, + l_margin: int | None = None, + b_margin: int | None = None, + ) -> TextStyle: ... + +@deprecated("fpdf.TitleStyle is deprecated since 2.7.10. It has been replaced by fpdf.TextStyle.") +class TitleStyle(TextStyle): ... + +__pdoc__: Final[dict[str, bool]] + class _FontMixin: i: int type: str diff --git a/stubs/fpdf2/fpdf/fpdf.pyi b/stubs/fpdf2/fpdf/fpdf.pyi index fb1430b5a..1508aad89 100644 --- a/stubs/fpdf2/fpdf/fpdf.pyi +++ b/stubs/fpdf2/fpdf/fpdf.pyi @@ -14,28 +14,33 @@ from PIL import Image from .annotations import AnnotationDict, PDFEmbeddedFile from .drawing import DeviceGray, DeviceRGB, DrawingContext, PaintedPath from .enums import ( + AccessPermission, Align, AnnotationFlag, AnnotationName, Corner, + EncryptionMethod, FileAttachmentAnnotationName, MethodReturnValue, PageLayout, + PageMode, PathPaintRule, RenderStyle, TableBordersLayout, TableCellFillMode, TableHeadingsDisplay, TextDirection, + TextEmphasis, TextMarkupType, TextMode as TextMode, VAlign, WrapMode as WrapMode, XPos as XPos, YPos as YPos, + _Align, ) from .errors import FPDFException as FPDFException -from .fonts import FontFace +from .fonts import FontFace, TextStyle, TitleStyle as TitleStyle from .graphics_state import GraphicsStateMixin from .html import HTML2FPDF from .image_datastructures import ( @@ -73,23 +78,6 @@ _FontStyles: TypeAlias = Literal["", "B", "I", "U", "BU", "UB", "BI", "IB", "IU" FPDF_VERSION: Final[str] PAGE_FORMATS: dict[_Format, tuple[float, float]] -class TitleStyle(FontFace): - t_margin: int | None - l_margin: int | None - b_margin: int | None - - def __init__( - self, - font_family: str | None = None, - font_style: str | None = None, - font_size_pt: int | None = None, - color: int | tuple[int, int, int] | None = None, - underline: bool = False, - t_margin: int | None = None, - l_margin: int | None = None, - b_margin: int | None = None, - ) -> None: ... - class ToCPlaceholder(NamedTuple): render_function: Callable[[FPDF, Any], object] start_page: int @@ -105,6 +93,7 @@ class FPDF(GraphicsStateMixin): MARKDOWN_BOLD_MARKER: ClassVar[str] MARKDOWN_ITALICS_MARKER: ClassVar[str] MARKDOWN_UNDERLINE_MARKER: ClassVar[str] + MARKDOWN_ESCAPE_CHARACTER: ClassVar[str] MARKDOWN_LINK_REGEX: ClassVar[Pattern[str]] MARKDOWN_LINK_COLOR: ClassVar[Incomplete | None] MARKDOWN_LINK_UNDERLINE: ClassVar[bool] @@ -114,9 +103,11 @@ class FPDF(GraphicsStateMixin): page: int pages: dict[int, PDFPage] fonts: dict[str, _Font] + fonts_used_per_page_number: dict[int, set[int]] links: dict[int, DestinationXYZ] embedded_files: list[PDFEmbeddedFile] image_cache: ImageCache + images_used_per_page_number: dict[int, set[int]] in_footer: bool str_alias_nb_pages: str @@ -128,7 +119,7 @@ class FPDF(GraphicsStateMixin): oversized_images: Incomplete | None oversized_images_ratio: float struct_builder: StructureTreeBuilder - section_title_styles: dict[int, Incomplete] + section_title_styles: dict[int, TextStyle] core_fonts: dict[str, str] core_fonts_encoding: str @@ -149,6 +140,7 @@ class FPDF(GraphicsStateMixin): compress: bool pdf_version: str creation_date: datetime.datetime + graphics_style_names_per_page_number: dict[int, set[str]] buffer: bytearray | None @@ -166,21 +158,22 @@ class FPDF(GraphicsStateMixin): format: _Format | tuple[float, float] = "A4", font_cache_dir: Literal["DEPRECATED"] = "DEPRECATED", ) -> None: ... - # The following definition crashes stubtest 1.1.1. - # def set_encryption( - # self, - # owner_password: str, - # user_password: str | None = None, - # encryption_method: EncryptionMethod | str = ..., - # permissions: AccessPermission = ..., - # encrypt_metadata: bool = False, - # ) -> None: ... + def set_encryption( + self, + owner_password: str, + user_password: str | None = None, + encryption_method: EncryptionMethod | str = ..., + permissions: AccessPermission = ..., + encrypt_metadata: bool = False, + ) -> None: ... # args and kwargs are passed to HTML2FPDF_CLASS constructor. def write_html(self, text: str, *args: Any, **kwargs: Any) -> None: ... @property + def emphasis(self) -> TextEmphasis: ... + @property def is_ttf_font(self) -> bool: ... @property - def page_mode(self): ... + def page_mode(self) -> PageMode: ... @property def epw(self) -> float: ... @property @@ -280,7 +273,7 @@ class FPDF(GraphicsStateMixin): corner_radius: float = 0, ) -> None: ... def ellipse(self, x: float, y: float, w: float, h: float, style: RenderStyle | str | None = None) -> None: ... - def circle(self, x: float, y: float, r, style: RenderStyle | str | None = None) -> None: ... + def circle(self, x: float, y: float, radius: float, style: RenderStyle | str | None = None) -> None: ... def regular_polygon( self, x: float, @@ -326,6 +319,12 @@ class FPDF(GraphicsStateMixin): clockwise: bool = False, style: RenderStyle | str | None = None, ) -> None: ... + def bezier( + self, + point_list: Sequence[tuple[int, int]], + closed: bool = False, + style: RenderStyle | Literal["D", "F", "DF", "FD"] | None = None, + ) -> None: ... def add_font( self, family: str | None = None, @@ -429,15 +428,45 @@ class FPDF(GraphicsStateMixin): def mirror(self, origin, angle) -> Generator[None]: ... def local_context( self, + *, font_family: Incomplete | None = None, font_style: Incomplete | None = None, - font_size: Incomplete | None = None, + font_size_pt: Incomplete | None = None, line_width: Incomplete | None = None, draw_color: Incomplete | None = None, fill_color: Incomplete | None = None, text_color: Incomplete | None = None, dash_pattern: Incomplete | None = None, - **kwargs, + font_size=..., # semi-deprecated, prefer font_size_pt + char_vpos=..., + char_spacing=..., + current_font=..., + denom_lift=..., + denom_scale=..., + font_stretching=..., + nom_lift=..., + nom_scale=..., + sub_lift=..., + sub_scale=..., + sup_lift=..., + sup_scale=..., + text_mode=..., + text_shaping=..., + underline=..., + paint_rule=..., + allow_transparency=..., + auto_close=..., + intersection_rule=..., + fill_opacity=..., + stroke_color=..., + stroke_opacity=..., + blend_mode=..., + stroke_width=..., + stroke_cap_style=..., + stroke_join_style=..., + stroke_miter_limit=..., + stroke_dash_pattern=..., + stroke_dash_phase=..., ) -> _GeneratorContextManager[None]: ... @property def accept_page_break(self) -> bool: ... @@ -513,6 +542,7 @@ class FPDF(GraphicsStateMixin): dims: tuple[float, float] | None = None, keep_aspect_ratio: bool = False, ) -> RasterImageInfo | VectorImageInfo: ... + def x_by_align(self, x: _Align, w: int, h: int, img_info: ImageInfo, keep_aspect_ratio: bool) -> int: ... @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 @@ -558,13 +588,13 @@ class FPDF(GraphicsStateMixin): def insert_toc_placeholder(self, render_toc_function, pages: int = 1) -> None: ... def set_section_title_styles( self, - level0: TitleStyle, - level1: TitleStyle | None = None, - level2: TitleStyle | None = None, - level3: TitleStyle | None = None, - level4: TitleStyle | None = None, - level5: TitleStyle | None = None, - level6: TitleStyle | None = None, + level0: TextStyle, + level1: TextStyle | None = None, + level2: TextStyle | None = None, + level3: TextStyle | None = None, + level4: TextStyle | None = None, + level5: TextStyle | None = None, + level6: TextStyle | None = None, ) -> None: ... def start_section(self, name: str, level: int = 0, strict: bool = True) -> None: ... def use_font_face(self, font_face: FontFace) -> _GeneratorContextManager[None]: ... diff --git a/stubs/fpdf2/fpdf/html.pyi b/stubs/fpdf2/fpdf/html.pyi index 21e794441..443968afc 100644 --- a/stubs/fpdf2/fpdf/html.pyi +++ b/stubs/fpdf2/fpdf/html.pyi @@ -1,12 +1,13 @@ -from _typeshed import Incomplete, SupportsItemAccess, SupportsKeysAndGetItem, Unused +from _typeshed import Incomplete, SupportsKeysAndGetItem from collections.abc import Callable, Iterable, Mapping from html.parser import HTMLParser from logging import Logger -from typing import ClassVar, Final, Literal, TypedDict, type_check_only +from typing import ClassVar, Final, Literal from typing_extensions import TypeAlias from fpdf import FPDF +from .enums import TextEmphasis from .fonts import FontFace from .table import Row, Table @@ -20,17 +21,13 @@ BULLET_WIN1252: Final[str] DEGREE_WIN1252: Final[str] HEADING_TAGS: Final[tuple[str, ...]] DEFAULT_TAG_STYLES: Final[dict[str, FontFace]] -DEFAULT_TAG_INDENTS: Final[dict[str, int]] +INLINE_TAGS: Final[tuple[str, ...]] +BLOCK_TAGS: Final[tuple[str, ...]] COLOR_DICT: Final[dict[str, str]] def color_as_decimal(color: str | None = "#000000") -> tuple[int, int, int] | None: ... -def parse_style(elem_attrs: SupportsItemAccess[str, str]) -> None: ... -@type_check_only -class _Emphasis(TypedDict): - b: bool - i: bool - u: bool +def parse_css_style(style_attr: str) -> dict[str, str]: ... class HTML2FPDF(HTMLParser): HTML_UNCLOSED_TAGS: ClassVar[tuple[str, ...]] @@ -41,20 +38,23 @@ class HTML2FPDF(HTMLParser): ul_bullet_char: str li_prefix_color: tuple[int, int, int] warn_on_tags_not_matching: bool - emphasis: _Emphasis - font_size: float + + font_family: str + font_size_pt: float + font_emphasis: TextEmphasis + font_color: tuple[int, int, int] + + style_stack: list[FontFace] + h: float follows_trailing_space: bool follows_heading: bool href: str align: str - style_stack: list[FontFace] indent: int + line_height_stack: list[Incomplete] ol_type: list[_OLType] bullet: list[Incomplete] - font_color: tuple[int, int, int] heading_level: Incomplete | None - heading_above: float - heading_below: float table_line_separators: bool table: Table | None table_row: Row | None @@ -63,32 +63,25 @@ class HTML2FPDF(HTMLParser): tag_indents: dict[str, int] tag_styles: dict[str, FontFace] - # Not initialized in __init__: - font_family: str - h: float - def __init__( self, pdf: FPDF, image_map: Callable[[str], str] | None = None, - li_tag_indent: int = 5, - dd_tag_indent: int = 10, + li_tag_indent: int | None = None, + dd_tag_indent: int | None = None, table_line_separators: bool = False, ul_bullet_char: str = "\x95", li_prefix_color: tuple[int, int, int] = (190, 0, 0), heading_sizes: SupportsKeysAndGetItem[str, int] | Iterable[tuple[str, int]] | None = None, - pre_code_font: str = ..., + pre_code_font: str | None = None, warn_on_tags_not_matching: bool = True, tag_indents: dict[str, int] | None = None, tag_styles: Mapping[str, FontFace] | None = None, - **_: Unused, - ): ... + font_family: str = "times", + ) -> None: ... def handle_data(self, data) -> None: ... def handle_starttag(self, tag, attrs) -> None: ... def handle_endtag(self, tag) -> None: ... - def set_font(self, family: str | None = None, size: float | None = None, set_default: bool = False) -> None: ... - def set_style(self, tag: Incomplete | None = None, enable: bool = False) -> None: ... - def set_text_color(self, r: Incomplete | None = None, g: int = 0, b: int = 0) -> None: ... def put_link(self, text) -> None: ... def render_toc(self, pdf, outline) -> None: ... def error(self, message: str) -> None: ... diff --git a/stubs/fpdf2/fpdf/image_datastructures.pyi b/stubs/fpdf2/fpdf/image_datastructures.pyi index b81fb5865..24f3dd65b 100644 --- a/stubs/fpdf2/fpdf/image_datastructures.pyi +++ b/stubs/fpdf2/fpdf/image_datastructures.pyi @@ -4,7 +4,6 @@ from typing import Any, Literal from typing_extensions import TypeAlias from fpdf.enums import Align -from fpdf.fpdf import FPDF from .image_parsing import _ImageFilter @@ -31,7 +30,7 @@ _AlignLiteral: TypeAlias = Literal[ "r", "j", ] -_TextAlign: TypeAlias = Align | _AlignLiteral +_TextAlign: TypeAlias = Align | _AlignLiteral # noqa: Y047 class ImageInfo(dict[str, Any]): @property @@ -43,8 +42,6 @@ class ImageInfo(dict[str, Any]): @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: _TextAlign, 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]: ... diff --git a/stubs/fpdf2/fpdf/line_break.pyi b/stubs/fpdf2/fpdf/line_break.pyi index d17af4255..d71917cd0 100644 --- a/stubs/fpdf2/fpdf/line_break.pyi +++ b/stubs/fpdf2/fpdf/line_break.pyi @@ -7,6 +7,8 @@ from .enums import Align, TextDirection, WrapMode SOFT_HYPHEN: Final[str] HYPHEN: Final[str] SPACE: Final[str] +BREAKING_SPACE_SYMBOLS: Final[list[str]] +BREAKING_SPACE_SYMBOLS_STR: Final[str] NBSP: Final[str] NEWLINE: Final[str] FORM_FEED: Final[str] @@ -128,7 +130,7 @@ class CurrentLine: def trim_trailing_spaces(self) -> None: ... 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): ... + def automatic_break(self, align: Align) -> tuple[Incomplete, Incomplete, TextLine]: ... class MultiLineBreak: fragments: Sequence[Fragment] @@ -153,4 +155,4 @@ class MultiLineBreak: line_height: float = 1.0, skip_leading_spaces: bool = False, ) -> None: ... - def get_line(self): ... + def get_line(self) -> TextLine: ... diff --git a/stubs/fpdf2/fpdf/table.pyi b/stubs/fpdf2/fpdf/table.pyi index a3430949d..c000e828f 100644 --- a/stubs/fpdf2/fpdf/table.pyi +++ b/stubs/fpdf2/fpdf/table.pyi @@ -105,7 +105,7 @@ class Cell: class RowLayoutInfo: height: int pagebreak_height: float - rendered_height: dict[Incomplete, Incomplete] + rendered_heights: dict[Incomplete, Incomplete] merged_heights: list[Incomplete] @dataclass(frozen=True) diff --git a/stubs/fpdf2/fpdf/template.pyi b/stubs/fpdf2/fpdf/template.pyi index 12addfb78..e795850c5 100644 --- a/stubs/fpdf2/fpdf/template.pyi +++ b/stubs/fpdf2/fpdf/template.pyi @@ -1,4 +1,5 @@ from _typeshed import Incomplete +from os import PathLike from typing import Any __author__: str @@ -14,7 +15,10 @@ class FlexTemplate: elements: Any keys: Any def load_elements(self, elements) -> None: ... - def parse_csv(self, infile, delimiter: str = ",", decimal_sep: str = ".", encoding: Incomplete | None = None): ... + def parse_json(self, infile: PathLike[Any], encoding: str = "utf-8") -> None: ... + def parse_csv( + self, infile: PathLike[Any], delimiter: str = ",", decimal_sep: str = ".", encoding: str | None = None + ) -> None: ... def __setitem__(self, name, value) -> None: ... set: Any def __contains__(self, name): ... diff --git a/stubs/fpdf2/fpdf/text_region.pyi b/stubs/fpdf2/fpdf/text_region.pyi index a9d4c2920..6cc4396a3 100644 --- a/stubs/fpdf2/fpdf/text_region.pyi +++ b/stubs/fpdf2/fpdf/text_region.pyi @@ -5,6 +5,7 @@ from typing_extensions import Self from .enums import Align, WrapMode from .image_datastructures import RasterImageInfo, VectorImageInfo, _TextAlign +from .line_break import Fragment, TextLine class Extents(NamedTuple): left: float @@ -22,14 +23,24 @@ class LineWrapper(NamedTuple): first_line: bool = False last_line: bool = False +class Bullet: + fragments: Sequence[Fragment] + text_line: TextLine + r_margin: float + rendered_flag: bool + def __init__(self, bullet_fragments: Sequence[Fragment], text_line: TextLine, bullet_r_margin: float) -> None: ... + def get_fragments_width(self) -> float: ... + class Paragraph: pdf: Incomplete text_align: Align line_height: Incomplete top_margin: Incomplete bottom_margin: Incomplete - skip_leading_spaces: Incomplete + indent: float + skip_leading_spaces: bool wrapmode: Incomplete + bullet: Bullet | None def __init__( self, @@ -38,12 +49,18 @@ class Paragraph: line_height: Incomplete | None = None, top_margin: float = 0, bottom_margin: float = 0, + indent: float = 0, + bullet_r_margin: float | None = None, + bullet_string: str = "", skip_leading_spaces: bool = False, wrapmode: WrapMode | None = None, ) -> None: ... def __enter__(self): ... def __exit__(self, exc_type, exc_value, traceback) -> None: ... def write(self, text: str, link: Incomplete | None = None): ... + def generate_bullet_frags_and_tl( + self, bullet_string: str, bullet_r_margin: float + ) -> tuple[tuple[Fragment, ...], TextLine] | None: ... def ln(self, h: float | None = None) -> None: ... def build_lines(self, print_sh: bool) -> list[LineWrapper]: ... @@ -113,8 +130,11 @@ class ParagraphCollectorMixin: skip_leading_spaces: bool = False, top_margin: int = 0, bottom_margin: int = 0, + indent: int = 0, + bullet_string: str = "", + bullet_r_margin: float | None = None, wrapmode: WrapMode | None = None, - ): ... + ) -> Paragraph: ... def end_paragraph(self) -> None: ... def image( self, diff --git a/stubs/fpdf2/fpdf/unicode_script.pyi b/stubs/fpdf2/fpdf/unicode_script.pyi new file mode 100644 index 000000000..49e56f2d2 --- /dev/null +++ b/stubs/fpdf2/fpdf/unicode_script.pyi @@ -0,0 +1,172 @@ +from enum import IntEnum +from typing import Final + +class UnicodeScript(IntEnum): + COMMON = 0 + LATIN = 1 + GREEK = 2 + CYRILLIC = 3 + ARMENIAN = 4 + HEBREW = 5 + ARABIC = 6 + SYRIAC = 7 + THAANA = 8 + DEVANAGARI = 9 + BENGALI = 10 + GURMUKHI = 11 + GUJARATI = 12 + ORIYA = 13 + TAMIL = 14 + TELUGU = 15 + KANNADA = 16 + MALAYALAM = 17 + SINHALA = 18 + THAI = 19 + LAO = 20 + TIBETAN = 21 + MYANMAR = 22 + GEORGIAN = 23 + HANGUL = 24 + ETHIOPIC = 25 + CHEROKEE = 26 + CANADIAN_ABORIGINAL = 27 + OGHAM = 28 + RUNIC = 29 + KHMER = 30 + MONGOLIAN = 31 + HIRAGANA = 32 + KATAKANA = 33 + BOPOMOFO = 34 + HAN = 35 + YI = 36 + OLD_ITALIC = 37 + GOTHIC = 38 + DESERET = 39 + INHERITED = 40 + TAGALOG = 41 + HANUNOO = 42 + BUHID = 43 + TAGBANWA = 44 + LIMBU = 45 + TAI_LE = 46 + LINEAR_B = 47 + UGARITIC = 48 + SHAVIAN = 49 + OSMANYA = 50 + CYPRIOT = 51 + BRAILLE = 52 + BUGINESE = 53 + COPTIC = 54 + NEW_TAI_LUE = 55 + GLAGOLITIC = 56 + TIFINAGH = 57 + SYLOTI_NAGRI = 58 + OLD_PERSIAN = 59 + KHAROSHTHI = 60 + BALINESE = 61 + CUNEIFORM = 62 + PHOENICIAN = 63 + PHAGS_PA = 64 + NKO = 65 + SUNDANESE = 66 + LEPCHA = 67 + OL_CHIKI = 68 + VAI = 69 + SAURASHTRA = 70 + KAYAH_LI = 71 + REJANG = 72 + LYCIAN = 73 + CARIAN = 74 + LYDIAN = 75 + CHAM = 76 + TAI_THAM = 77 + TAI_VIET = 78 + AVESTAN = 79 + EGYPTIAN_HIEROGLYPHS = 80 + SAMARITAN = 81 + LISU = 82 + BAMUM = 83 + JAVANESE = 84 + MEETEI_MAYEK = 85 + IMPERIAL_ARAMAIC = 86 + OLD_SOUTH_ARABIAN = 87 + INSCRIPTIONAL_PARTHIAN = 88 + INSCRIPTIONAL_PAHLAVI = 89 + OLD_TURKIC = 90 + KAITHI = 91 + BATAK = 92 + BRAHMI = 93 + MANDAIC = 94 + CHAKMA = 95 + MEROITIC_CURSIVE = 96 + MEROITIC_HIEROGLYPHS = 97 + MIAO = 98 + SHARADA = 99 + SORA_SOMPENG = 100 + TAKRI = 101 + CAUCASIAN_ALBANIAN = 102 + BASSA_VAH = 103 + DUPLOYAN = 104 + ELBASAN = 105 + GRANTHA = 106 + PAHAWH_HMONG = 107 + KHOJKI = 108 + LINEAR_A = 109 + MAHAJANI = 110 + MANICHAEAN = 111 + MENDE_KIKAKUI = 112 + MODI = 113 + MRO = 114 + OLD_NORTH_ARABIAN = 115 + NABATAEAN = 116 + PALMYRENE = 117 + PAU_CIN_HAU = 118 + OLD_PERMIC = 119 + PSALTER_PAHLAVI = 120 + SIDDHAM = 121 + KHUDAWADI = 122 + TIRHUTA = 123 + WARANG_CITI = 124 + AHOM = 125 + ANATOLIAN_HIEROGLYPHS = 126 + HATRAN = 127 + MULTANI = 128 + OLD_HUNGARIAN = 129 + SIGNWRITING = 130 + ADLAM = 131 + BHAIKSUKI = 132 + MARCHEN = 133 + NEWA = 134 + OSAGE = 135 + TANGUT = 136 + MASARAM_GONDI = 137 + NUSHU = 138 + SOYOMBO = 139 + ZANABAZAR_SQUARE = 140 + DOGRA = 141 + GUNJALA_GONDI = 142 + MAKASAR = 143 + MEDEFAIDRIN = 144 + HANIFI_ROHINGYA = 145 + SOGDIAN = 146 + OLD_SOGDIAN = 147 + ELYMAIC = 148 + NANDINAGARI = 149 + NYIAKENG_PUACHUE_HMONG = 150 + WANCHO = 151 + CHORASMIAN = 152 + DIVES_AKURU = 153 + KHITAN_SMALL_SCRIPT = 154 + YEZIDI = 155 + CYPRO_MINOAN = 156 + OLD_UYGHUR = 157 + TANGSA = 158 + TOTO = 159 + VITHKUQI = 160 + KAWI = 161 + NAG_MUNDARI = 162 + UNKNOWN = 999 + +UNICODE_RANGE_TO_SCRIPT: Final[tuple[tuple[int, int, int]]] + +def get_unicode_script(char: str) -> UnicodeScript: ...