1from typing import Any, Union 
    2 
    3from ._base import FloatObject, NumberObject 
    4from ._data_structures import ArrayObject 
    5 
    6 
    7class RectangleObject(ArrayObject): 
    8    """ 
    9    This class is used to represent *page boxes* in pypdf. 
    10 
    11    These boxes include: 
    12 
    13    * :attr:`artbox <pypdf._page.PageObject.artbox>` 
    14    * :attr:`bleedbox <pypdf._page.PageObject.bleedbox>` 
    15    * :attr:`cropbox <pypdf._page.PageObject.cropbox>` 
    16    * :attr:`mediabox <pypdf._page.PageObject.mediabox>` 
    17    * :attr:`trimbox <pypdf._page.PageObject.trimbox>` 
    18    """ 
    19 
    20    def __init__( 
    21        self, arr: Union["RectangleObject", tuple[float, float, float, float]] 
    22    ) -> None: 
    23        # must have four points 
    24        assert len(arr) == 4 
    25        # automatically convert arr[x] into NumberObject(arr[x]) if necessary 
    26        ArrayObject.__init__(self, [self._ensure_is_number(x) for x in arr]) 
    27 
    28    def _ensure_is_number(self, value: Any) -> Union[FloatObject, NumberObject]: 
    29        if not isinstance(value, (FloatObject, NumberObject)): 
    30            value = FloatObject(value) 
    31        return value 
    32 
    33    def scale(self, sx: float, sy: float) -> "RectangleObject": 
    34        return RectangleObject( 
    35            ( 
    36                float(self.left) * sx, 
    37                float(self.bottom) * sy, 
    38                float(self.right) * sx, 
    39                float(self.top) * sy, 
    40            ) 
    41        ) 
    42 
    43    def __repr__(self) -> str: 
    44        return f"RectangleObject({list(self)!r})" 
    45 
    46    @property 
    47    def left(self) -> FloatObject: 
    48        return self[0] 
    49 
    50    @left.setter 
    51    def left(self, f: float) -> None: 
    52        self[0] = FloatObject(f) 
    53 
    54    @property 
    55    def bottom(self) -> FloatObject: 
    56        return self[1] 
    57 
    58    @bottom.setter 
    59    def bottom(self, f: float) -> None: 
    60        self[1] = FloatObject(f) 
    61 
    62    @property 
    63    def right(self) -> FloatObject: 
    64        return self[2] 
    65 
    66    @right.setter 
    67    def right(self, f: float) -> None: 
    68        self[2] = FloatObject(f) 
    69 
    70    @property 
    71    def top(self) -> FloatObject: 
    72        return self[3] 
    73 
    74    @top.setter 
    75    def top(self, f: float) -> None: 
    76        self[3] = FloatObject(f) 
    77 
    78    @property 
    79    def lower_left(self) -> tuple[float, float]: 
    80        """ 
    81        Property to read and modify the lower left coordinate of this box 
    82        in (x,y) form. 
    83        """ 
    84        return self.left, self.bottom 
    85 
    86    @lower_left.setter 
    87    def lower_left(self, value: tuple[float, float]) -> None: 
    88        self[0], self[1] = (self._ensure_is_number(x) for x in value) 
    89 
    90    @property 
    91    def lower_right(self) -> tuple[float, float]: 
    92        """ 
    93        Property to read and modify the lower right coordinate of this box 
    94        in (x,y) form. 
    95        """ 
    96        return self.right, self.bottom 
    97 
    98    @lower_right.setter 
    99    def lower_right(self, value: tuple[float, float]) -> None: 
    100        self[2], self[1] = (self._ensure_is_number(x) for x in value) 
    101 
    102    @property 
    103    def upper_left(self) -> tuple[float, float]: 
    104        """ 
    105        Property to read and modify the upper left coordinate of this box 
    106        in (x,y) form. 
    107        """ 
    108        return self.left, self.top 
    109 
    110    @upper_left.setter 
    111    def upper_left(self, value: tuple[float, float]) -> None: 
    112        self[0], self[3] = (self._ensure_is_number(x) for x in value) 
    113 
    114    @property 
    115    def upper_right(self) -> tuple[float, float]: 
    116        """ 
    117        Property to read and modify the upper right coordinate of this box 
    118        in (x,y) form. 
    119        """ 
    120        return self.right, self.top 
    121 
    122    @upper_right.setter 
    123    def upper_right(self, value: tuple[float, float]) -> None: 
    124        self[2], self[3] = (self._ensure_is_number(x) for x in value) 
    125 
    126    @property 
    127    def width(self) -> float: 
    128        return self.right - self.left 
    129 
    130    @property 
    131    def height(self) -> float: 
    132        return self.top - self.bottom