about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py')
-rw-r--r--.venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py308
1 files changed, 308 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py b/.venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py
new file mode 100644
index 00000000..4db8dfdb
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pypdf/annotations/_markup_annotations.py
@@ -0,0 +1,308 @@
+import sys
+from abc import ABC
+from typing import Any, List, Optional, Tuple, Union
+
+from .._utils import deprecate_with_replacement
+from ..constants import AnnotationFlag
+from ..generic import ArrayObject, DictionaryObject
+from ..generic._base import (
+    BooleanObject,
+    FloatObject,
+    NameObject,
+    NumberObject,
+    TextStringObject,
+)
+from ..generic._rectangle import RectangleObject
+from ..generic._utils import hex_to_rgb
+from ._base import NO_FLAGS, AnnotationDictionary
+
+if sys.version_info[:2] >= (3, 10):
+    from typing import TypeAlias
+else:
+    # PEP 613 introduced typing.TypeAlias with Python 3.10
+    # For older Python versions, the backport typing_extensions is necessary:
+    from typing_extensions import TypeAlias
+
+
+Vertex: TypeAlias = Tuple[float, float]
+
+
+def _get_bounding_rectangle(vertices: List[Vertex]) -> RectangleObject:
+    x_min, y_min = vertices[0][0], vertices[0][1]
+    x_max, y_max = vertices[0][0], vertices[0][1]
+    for x, y in vertices:
+        x_min = min(x_min, x)
+        y_min = min(y_min, y)
+        x_max = max(x_max, x)
+        y_max = max(y_max, y)
+    rect = RectangleObject((x_min, y_min, x_max, y_max))
+    return rect
+
+
+class MarkupAnnotation(AnnotationDictionary, ABC):
+    """
+    Base class for all markup annotations.
+
+    Args:
+        title_bar: Text to be displayed in the title bar of the annotation;
+            by convention this is the name of the author
+    """
+
+    def __init__(self, *, title_bar: Optional[str] = None):
+        if title_bar is not None:
+            self[NameObject("T")] = TextStringObject(title_bar)
+
+
+class Text(MarkupAnnotation):
+    """
+    A text annotation.
+
+    Args:
+        rect: array of four integers ``[xLL, yLL, xUR, yUR]``
+            specifying the clickable rectangular area
+        text: The text that is added to the document
+        open:
+        flags:
+    """
+
+    def __init__(
+        self,
+        *,
+        rect: Union[RectangleObject, Tuple[float, float, float, float]],
+        text: str,
+        open: bool = False,
+        flags: int = NO_FLAGS,
+        **kwargs: Any,
+    ):
+        super().__init__(**kwargs)
+        self[NameObject("/Subtype")] = NameObject("/Text")
+        self[NameObject("/Rect")] = RectangleObject(rect)
+        self[NameObject("/Contents")] = TextStringObject(text)
+        self[NameObject("/Open")] = BooleanObject(open)
+        self[NameObject("/Flags")] = NumberObject(flags)
+
+
+class FreeText(MarkupAnnotation):
+    """A FreeText annotation"""
+
+    def __init__(
+        self,
+        *,
+        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: Optional[str] = "000000",
+        background_color: Optional[str] = "ffffff",
+        **kwargs: Any,
+    ):
+        super().__init__(**kwargs)
+        self[NameObject("/Subtype")] = NameObject("/FreeText")
+        self[NameObject("/Rect")] = RectangleObject(rect)
+
+        font_str = "font: "
+        if bold is True:
+            font_str = f"{font_str}bold "
+        if italic is True:
+            font_str = f"{font_str}italic "
+        font_str = f"{font_str}{font} {font_size}"
+        font_str = f"{font_str};text-align:left;color:#{font_color}"
+
+        default_appearance_string = ""
+        if border_color:
+            for st in hex_to_rgb(border_color):
+                default_appearance_string = f"{default_appearance_string}{st} "
+            default_appearance_string = f"{default_appearance_string}rg"
+
+        self.update(
+            {
+                NameObject("/Subtype"): NameObject("/FreeText"),
+                NameObject("/Rect"): RectangleObject(rect),
+                NameObject("/Contents"): TextStringObject(text),
+                # font size color
+                NameObject("/DS"): TextStringObject(font_str),
+                NameObject("/DA"): TextStringObject(default_appearance_string),
+            }
+        )
+        if border_color is None:
+            # Border Style
+            self[NameObject("/BS")] = DictionaryObject(
+                {
+                    # width of 0 means no border
+                    NameObject("/W"): NumberObject(0)
+                }
+            )
+        if background_color is not None:
+            self[NameObject("/C")] = ArrayObject(
+                [FloatObject(n) for n in hex_to_rgb(background_color)]
+            )
+
+
+class Line(MarkupAnnotation):
+    def __init__(
+        self,
+        p1: Vertex,
+        p2: Vertex,
+        rect: Union[RectangleObject, Tuple[float, float, float, float]],
+        text: str = "",
+        **kwargs: Any,
+    ):
+        super().__init__(**kwargs)
+        self.update(
+            {
+                NameObject("/Subtype"): NameObject("/Line"),
+                NameObject("/Rect"): RectangleObject(rect),
+                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),
+            }
+        )
+
+
+class PolyLine(MarkupAnnotation):
+    def __init__(
+        self,
+        vertices: List[Vertex],
+        **kwargs: Any,
+    ):
+        super().__init__(**kwargs)
+        if len(vertices) == 0:
+            raise ValueError("A polygon needs at least 1 vertex with two coordinates")
+        coord_list = []
+        for x, y in vertices:
+            coord_list.append(NumberObject(x))
+            coord_list.append(NumberObject(y))
+        self.update(
+            {
+                NameObject("/Subtype"): NameObject("/PolyLine"),
+                NameObject("/Vertices"): ArrayObject(coord_list),
+                NameObject("/Rect"): RectangleObject(_get_bounding_rectangle(vertices)),
+            }
+        )
+
+
+class Rectangle(MarkupAnnotation):
+    def __init__(
+        self,
+        rect: Union[RectangleObject, Tuple[float, float, float, float]],
+        *,
+        interior_color: Optional[str] = None,
+        **kwargs: Any,
+    ):
+        if "interiour_color" in kwargs:
+            deprecate_with_replacement("interiour_color", "interior_color", "6.0.0")
+            interior_color = kwargs["interiour_color"]
+            del kwargs["interiour_color"]
+        super().__init__(**kwargs)
+        self.update(
+            {
+                NameObject("/Type"): NameObject("/Annot"),
+                NameObject("/Subtype"): NameObject("/Square"),
+                NameObject("/Rect"): RectangleObject(rect),
+            }
+        )
+
+        if interior_color:
+            self[NameObject("/IC")] = ArrayObject(
+                [FloatObject(n) for n in hex_to_rgb(interior_color)]
+            )
+
+
+class Highlight(MarkupAnnotation):
+    def __init__(
+        self,
+        *,
+        rect: Union[RectangleObject, Tuple[float, float, float, float]],
+        quad_points: ArrayObject,
+        highlight_color: str = "ff0000",
+        printing: bool = False,
+        **kwargs: Any,
+    ):
+        super().__init__(**kwargs)
+        self.update(
+            {
+                NameObject("/Subtype"): NameObject("/Highlight"),
+                NameObject("/Rect"): RectangleObject(rect),
+                NameObject("/QuadPoints"): quad_points,
+                NameObject("/C"): ArrayObject(
+                    [FloatObject(n) for n in hex_to_rgb(highlight_color)]
+                ),
+            }
+        )
+        if printing:
+            self.flags = AnnotationFlag.PRINT
+
+
+class Ellipse(MarkupAnnotation):
+    def __init__(
+        self,
+        rect: Union[RectangleObject, Tuple[float, float, float, float]],
+        *,
+        interior_color: Optional[str] = None,
+        **kwargs: Any,
+    ):
+        if "interiour_color" in kwargs:
+            deprecate_with_replacement("interiour_color", "interior_color", "6.0.0")
+            interior_color = kwargs["interiour_color"]
+            del kwargs["interiour_color"]
+        super().__init__(**kwargs)
+
+        self.update(
+            {
+                NameObject("/Type"): NameObject("/Annot"),
+                NameObject("/Subtype"): NameObject("/Circle"),
+                NameObject("/Rect"): RectangleObject(rect),
+            }
+        )
+
+        if interior_color:
+            self[NameObject("/IC")] = ArrayObject(
+                [FloatObject(n) for n in hex_to_rgb(interior_color)]
+            )
+
+
+class Polygon(MarkupAnnotation):
+    def __init__(
+        self,
+        vertices: List[Tuple[float, float]],
+        **kwargs: Any,
+    ):
+        super().__init__(**kwargs)
+        if len(vertices) == 0:
+            raise ValueError("A polygon needs at least 1 vertex with two coordinates")
+
+        coord_list = []
+        for x, y in vertices:
+            coord_list.append(NumberObject(x))
+            coord_list.append(NumberObject(y))
+        self.update(
+            {
+                NameObject("/Type"): NameObject("/Annot"),
+                NameObject("/Subtype"): NameObject("/Polygon"),
+                NameObject("/Vertices"): ArrayObject(coord_list),
+                NameObject("/IT"): NameObject("/PolygonCloud"),
+                NameObject("/Rect"): RectangleObject(_get_bounding_rectangle(vertices)),
+            }
+        )