Spaces:
Runtime error
Runtime error
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |