Update matching logic: AI scores all candidates, lower threshold, absolute amount, prompt improvements
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user