aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py')
-rw-r--r--.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py275
1 files changed, 275 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py
new file mode 100644
index 00000000..bb46dd90
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PyPDF2/generic/_annotations.py
@@ -0,0 +1,275 @@
+from typing import Optional, Tuple, Union
+
+from ._base import (
+ BooleanObject,
+ FloatObject,
+ NameObject,
+ NumberObject,
+ TextStringObject,
+)
+from ._data_structures import ArrayObject, DictionaryObject
+from ._fit import DEFAULT_FIT, Fit
+from ._rectangle import RectangleObject
+from ._utils import hex_to_rgb
+
+
+class AnnotationBuilder:
+ """
+ The AnnotationBuilder creates dictionaries representing PDF annotations.
+
+ Those dictionaries can be modified before they are added to a PdfWriter
+ instance via `writer.add_annotation`.
+
+ See `adding PDF annotations <../user/adding-pdf-annotations.html>`_ for
+ it's usage combined with PdfWriter.
+ """
+
+ from ..types import FitType, ZoomArgType
+
+ @staticmethod
+ def text(
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ text: str,
+ open: bool = False,
+ flags: int = 0,
+ ) -> DictionaryObject:
+ """
+ Add text annotation.
+
+ :param Tuple[int, int, int, int] rect:
+ or array of four integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``
+ :param bool open:
+ :param int flags:
+ """
+ # TABLE 8.23 Additional entries specific to a text annotation
+ text_obj = DictionaryObject(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Text"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Contents"): TextStringObject(text),
+ NameObject("/Open"): BooleanObject(open),
+ NameObject("/Flags"): NumberObject(flags),
+ }
+ )
+ return text_obj
+
+ @staticmethod
+ def free_text(
+ text: str,
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ font: str = "Helvetica",
+ bold: bool = False,
+ italic: bool = False,
+ font_size: str = "14pt",
+ font_color: str = "000000",
+ border_color: str = "000000",
+ background_color: str = "ffffff",
+ ) -> DictionaryObject:
+ """
+ Add text in a rectangle to a page.
+
+ :param str text: Text to be added
+ :param RectangleObject rect: or array of four integers
+ specifying the clickable rectangular area ``[xLL, yLL, xUR, yUR]``
+ :param str font: Name of the Font, e.g. 'Helvetica'
+ :param bool bold: Print the text in bold
+ :param bool italic: Print the text in italic
+ :param str font_size: How big the text will be, e.g. '14pt'
+ :param str font_color: Hex-string for the color
+ :param str border_color: Hex-string for the border color
+ :param str background_color: Hex-string for the background of the annotation
+ """
+ font_str = "font: "
+ if bold is True:
+ font_str = font_str + "bold "
+ if italic is True:
+ font_str = font_str + "italic "
+ font_str = font_str + font + " " + font_size
+ font_str = font_str + ";text-align:left;color:#" + font_color
+
+ bg_color_str = ""
+ for st in hex_to_rgb(border_color):
+ bg_color_str = bg_color_str + str(st) + " "
+ bg_color_str = bg_color_str + "rg"
+
+ free_text = DictionaryObject()
+ free_text.update(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/FreeText"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Contents"): TextStringObject(text),
+ # font size color
+ NameObject("/DS"): TextStringObject(font_str),
+ # border color
+ NameObject("/DA"): TextStringObject(bg_color_str),
+ # background color
+ NameObject("/C"): ArrayObject(
+ [FloatObject(n) for n in hex_to_rgb(background_color)]
+ ),
+ }
+ )
+ return free_text
+
+ @staticmethod
+ def line(
+ p1: Tuple[float, float],
+ p2: Tuple[float, float],
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ text: str = "",
+ title_bar: str = "",
+ ) -> DictionaryObject:
+ """
+ Draw a line on the PDF.
+
+ :param Tuple[float, float] p1: First point
+ :param Tuple[float, float] p2: Second point
+ :param RectangleObject rect: or array of four
+ integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``
+ :param str text: Text to be displayed as the line annotation
+ :param str title_bar: Text to be displayed in the title bar of the
+ annotation; by convention this is the name of the author
+ """
+ line_obj = DictionaryObject(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Line"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/T"): TextStringObject(title_bar),
+ NameObject("/L"): ArrayObject(
+ [
+ FloatObject(p1[0]),
+ FloatObject(p1[1]),
+ FloatObject(p2[0]),
+ FloatObject(p2[1]),
+ ]
+ ),
+ NameObject("/LE"): ArrayObject(
+ [
+ NameObject(None),
+ NameObject(None),
+ ]
+ ),
+ NameObject("/IC"): ArrayObject(
+ [
+ FloatObject(0.5),
+ FloatObject(0.5),
+ FloatObject(0.5),
+ ]
+ ),
+ NameObject("/Contents"): TextStringObject(text),
+ }
+ )
+ return line_obj
+
+ @staticmethod
+ def rectangle(
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ interiour_color: Optional[str] = None,
+ ) -> DictionaryObject:
+ """
+ Draw a rectangle on the PDF.
+
+ :param RectangleObject rect: or array of four
+ integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``
+ """
+ square_obj = DictionaryObject(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Square"),
+ NameObject("/Rect"): RectangleObject(rect),
+ }
+ )
+
+ if interiour_color:
+ square_obj[NameObject("/IC")] = ArrayObject(
+ [FloatObject(n) for n in hex_to_rgb(interiour_color)]
+ )
+
+ return square_obj
+
+ @staticmethod
+ def link(
+ rect: Union[RectangleObject, Tuple[float, float, float, float]],
+ border: Optional[ArrayObject] = None,
+ url: Optional[str] = None,
+ target_page_index: Optional[int] = None,
+ fit: Fit = DEFAULT_FIT,
+ ) -> DictionaryObject:
+ """
+ Add a link to the document.
+
+ The link can either be an external link or an internal link.
+
+ An external link requires the URL parameter.
+ An internal link requires the target_page_index, fit, and fit args.
+
+
+ :param RectangleObject rect: or array of four
+ integers specifying the clickable rectangular area
+ ``[xLL, yLL, xUR, yUR]``
+ :param border: if provided, an array describing border-drawing
+ properties. See the PDF spec for details. No border will be
+ drawn if this argument is omitted.
+ - horizontal corner radius,
+ - vertical corner radius, and
+ - border width
+ - Optionally: Dash
+ :param str url: Link to a website (if you want to make an external link)
+ :param int target_page_index: index of the page to which the link should go
+ (if you want to make an internal link)
+ :param Fit fit: Page fit or 'zoom' option.
+ """
+ from ..types import BorderArrayType
+
+ is_external = url is not None
+ is_internal = target_page_index is not None
+ if not is_external and not is_internal:
+ raise ValueError(
+ "Either 'url' or 'target_page_index' have to be provided. Both were None."
+ )
+ if is_external and is_internal:
+ raise ValueError(
+ f"Either 'url' or 'target_page_index' have to be provided. url={url}, target_page_index={target_page_index}"
+ )
+
+ border_arr: BorderArrayType
+ if border is not None:
+ border_arr = [NameObject(n) for n in border[:3]]
+ if len(border) == 4:
+ dash_pattern = ArrayObject([NameObject(n) for n in border[3]])
+ border_arr.append(dash_pattern)
+ else:
+ border_arr = [NumberObject(0)] * 3
+
+ link_obj = DictionaryObject(
+ {
+ NameObject("/Type"): NameObject("/Annot"),
+ NameObject("/Subtype"): NameObject("/Link"),
+ NameObject("/Rect"): RectangleObject(rect),
+ NameObject("/Border"): ArrayObject(border_arr),
+ }
+ )
+ if is_external:
+ link_obj[NameObject("/A")] = DictionaryObject(
+ {
+ NameObject("/S"): NameObject("/URI"),
+ NameObject("/Type"): NameObject("/Action"),
+ NameObject("/URI"): TextStringObject(url),
+ }
+ )
+ if is_internal:
+ # This needs to be updated later!
+ dest_deferred = DictionaryObject(
+ {
+ "target_page_index": NumberObject(target_page_index),
+ "fit": NameObject(fit.fit_type),
+ "fit_args": fit.fit_args,
+ }
+ )
+ link_obj[NameObject("/Dest")] = dest_deferred
+ return link_obj