
    kh2                         d dl mZmZmZmZmZmZ d dlmZmZ d dl	m	Z	 d dl
ZddlmZmZ ddlmZmZmZmZmZmZmZ  G d d	e      Zy)
    )ListUnionDictr   AnyOptional)MutableSequenceIterable)copyN   )BaseCoordElementBaseLayoutElement)Interval	RectangleQuadrilateral	TextBlockALL_BASECOORD_ELEMENTSBASECOORD_ELEMENT_NAMEMAPBASECOORD_ELEMENT_INDEXMAPc                      e Zd ZdZd!dddee   defdZd Zd Z	d	 Z
d
 Zd Zd Zd Zd Zd Zd Zd Zd Zi dfdZd"ded    fdZi dfdZd Zd#dZd Zd Zd Zd Zdeeef   fdZdee    fdZ!d$de"jF                  fd Z$y)%LayoutaQ  
    The :obj:`Layout` class id designed for processing a list of layout elements
    on a page. It stores the layout elements in a list and the related `page_data`,
    and provides handy APIs for processing all the layout elements in batch. `

    Args:
        blocks (:obj:`list`):
            A list of layout element blocks
        page_data (Dict, optional):
            A dictionary storing the page (canvas) related information
            like `height`, `width`, etc. It should be passed in as a
            keyword argument to avoid any confusion.
            Defaults to None.
    N	page_datablocksr   c                *   |`t        |t              r|j                  j                  dk7  s7|j                  j                  dk(  rd}t	        |      d| d}t	        |      t        |t
              rt        |      }||ng | _        |xs i | _        y )Nr   zUPlease check the input: it should be lp.Layout([layout]) instead of lp.Layout(layout)zHBlocks should be a list of layout elements or empty (None), instead got z.
)	
isinstancer	   	__class____name__
ValueErrortuplelist_blocksr   )selfr   r   	error_msgs       X/var/www/teggl/fontify/venv/lib/python3.12/site-packages/layoutparser/elements/layout.py__init__zLayout.__init__1   s     ^68,1A1A1J1Jh1V ((H4s	 Y'' ggmfnnqr	Y''fe$&\F!'!3v"b    c                     | j                   |   }t        |t              r*| j                  | j                   |   | j                        S |S Nr   )r!   r   slicer   r   )r"   keyr   s      r$   __getitem__zLayout.__getitem__D   s?    c"c5!>>$,,s"3t~~>NNMr&   c                 "    || j                   |<   y Nr!   )r"   r*   newvalues      r$   __setitem__zLayout.__setitem__K   s    $Sr&   c                     | j                   |= y r-   r.   )r"   r*   s     r$   __delitem__zLayout.__delitem__N   s    LLr&   c                 ,    t        | j                        S r-   )lenr!   r"   s    r$   __len__zLayout.__len__Q   s    4<<  r&   c              #   6   K   | j                   D ]  }|  y wr-   r.   r"   eles     r$   __iter__zLayout.__iter__T   s     << 	CI	s   c           	          dj                  t        |       j                         D cg c]  \  }}| d|  c}}      }| j                  j                   d| dS c c}}w )Nz, =())joinvarsitemsr   r   )r"   r*   valinfo_strs       r$   __repr__zLayout.__repr__X   sZ    99T$Z=M=M=OPcQsenPQ..))*!H:Q77 Qs   A
c                     t        |t              r4| j                  |j                  k(  xr | j                  |j                  k(  S y)NF)r   r   r!   r   r"   others     r$   __eq__zLayout.__eq__\   s4    eV$<<5==0VT^^u5VVr&   c                    t        |t              r| j                  |j                  k(  r4| j                  | j                  |j                  z   | j                        S | j                  i k(  s|j                  i k(  rB| j                  | j                  |j                  z   | j                  xs |j                        S t        d| j                   d|j                   d      t        |t              r*| j                  | j                  |z   | j                        S t        d|j                  j                   d      )Nr   z(Incompatible page_data for two innputs: z vs .zInvalid input type for other )r   r   r   r   r!   r   r    r   rF   s     r$   __add__zLayout.__add__b   s   eV$~~0~~LL5==0DNN &   2%B)>~~LL5==0"nn? &  
 !>t~~>NdSXSbSbRccde  t$>>$,,"6$..>QQ/0H0H/IK r&   c                 <    | j                   j                  ||       y r-   )r!   insert)r"   r*   values      r$   rM   zLayout.insertx   s    C'r&   c                 b    | j                  t        | j                        | j                        S r(   )r   r
   r!   r   r5   s    r$   r
   zLayout.copy{   s"    ~~d4<<0DNN~KKr&   c                     | j                  | D cg c]  }|j                  |       c}| j                        S c c}w r(   )r   relative_tor   r"   rG   r9   s      r$   rQ   zLayout.relative_to~   s8    ~~/34S__U#4  
 	
4   ;c                     | j                  | D cg c]  }|j                  |       c}| j                        S c c}w r(   )r   condition_onr   rR   s      r$   rU   zLayout.condition_on   s:    ~~045Se$5  
 	
5rS   Fc           
          | j                  | D cg c]  }|j                  |||       c}| j                        S c c}w r(   r   is_inr   r"   rG   soft_margincenterr9   s        r$   rX   zLayout.is_in   s=    ~~>BCsSYYuk62Cnn  
 	
Cs   =returnc                     |s3| j                  t        | j                  ||      | j                        S | j                  j	                  ||       y)ap  Sort the list of blocks based on the given

        Args:
            key ([type], optional): key specifies a function of one argument that
            is used to extract a comparison key from each list element.
            Defaults to None.
            reverse (bool, optional): reverse is a boolean value. If set to True,
            then the list elements are sorted as if each comparison were reversed.
            Defaults to False.
            inplace (bool, optional): whether to perform the sort inplace. If set
            to False, it will return another object instance with _block sorted in
            the order. Defaults to False.

        Examples::
            >>> import layoutparser as lp
            >>> i = lp.Interval(4, 5, axis="y")
            >>> l = lp.Layout([i, i.shift(2)])
            >>> l.sort(key=lambda x: x.coordinates[1], reverse=True)

        )r*   reverser   N)r   sortedr!   r   sort)r"   r*   r^   inplaces       r$   r`   zLayout.sort   sL    * >>t||g>$.. "   LL#w7r&   c           
          | j                  | D cg c]  }|j                  |||      s| c}| j                        S c c}w )a:  
        Return a `Layout` object containing the elements that are in the `other` object.

        Args:
            other (:obj:`BaseCoordElement`):
                The block to filter the current elements.

        Returns:
            :obj:`Layout`:
                A new layout object after filtering.
        r   rW   rY   s        r$   	filter_byzLayout.filter_by   sA     ~~ JSCIIe[&$ISJnn  
 	
Js
   A A c                     | j                  | D cg c]  }|j                  |       c}| j                        S c c}w )a  
        Shift all layout elements by user specified amounts on x and y axis respectively. If shift_distance is one
        numeric value, the element will by shifted by the same specified amount on both x and y axis.

        Args:
            shift_distance (:obj:`numeric` or :obj:`Tuple(numeric)` or :obj:`List[numeric]`):
                The number of pixels used to shift the element.

        Returns:
            :obj:`Layout`:
                A new layout object with all the elements shifted in the specified values.
        r   )r   shiftr   )r"   shift_distancer9   s      r$   re   zLayout.shift   s:     ~~2673SYY~&74>>  
 	
7rS   c                     | j                  | D cg c]  }|j                  |||||       c}| j                        S c c}w )a  Pad all layout elements on the four sides of the polygon with the user-defined pixels. If
        safe_mode is set to True, the function will cut off the excess padding that falls on the negative
        side of the coordinates.

        Args:
            left (:obj:`int`, `optional`, defaults to 0): The number of pixels to pad on the upper side of the polygon.
            right (:obj:`int`, `optional`, defaults to 0): The number of pixels to pad on the lower side of the polygon.
            top (:obj:`int`, `optional`, defaults to 0): The number of pixels to pad on the left side of the polygon.
            bottom (:obj:`int`, `optional`, defaults to 0): The number of pixels to pad on the right side of the polygon.
            safe_mode (:obj:`bool`, `optional`, defaults to True): A bool value to toggle the safe_mode.

        Returns:
            :obj:`Layout`:
                A new layout object with all the elements padded in the specified values.
        r   )r   padr   )r"   leftrighttopbottom	safe_moder9   s          r$   rh   z
Layout.pad   sC      ~~EIJcSWWT5#vy9Jnn  
 	
Js   ?c                     | j                  | D cg c]  }|j                  |       c}| j                        S c c}w )a  
        Scale all layout element by a user specified amount on x and y axis respectively. If scale_factor is one
        numeric value, the element will by scaled by the same specified amount on both x and y axis.

        Args:
            scale_factor (:obj:`numeric` or :obj:`Tuple(numeric)` or :obj:`List[numeric]`): The amount for downscaling or upscaling the element.

        Returns:
            :obj:`Layout`:
                A new layout object with all the elements scaled in the specified values.
        r   )r   scaler   )r"   scale_factorr9   s      r$   ro   zLayout.scale   s:     ~~045SYY|$5  
 	
5rS   c                 J    | D cg c]  }|j                  |       c}S c c}w r-   )
crop_image)r"   imager9   s      r$   rr   zLayout.crop_image   s    156#u%666s    c                 Z    | D cg c]  }t        |d      s|j                   c}S c c}w )z
        Iterate through all the text blocks in the list and append their ocr'ed text results.

        Returns:
            :obj:`List[str]`: A list of text strings of the text blocks in the list of layout elements.
        text)hasattrru   r8   s     r$   	get_textszLayout.get_texts   s%     %)ASGC,@AAA   ((c                 Z    | D cg c]  }t        ||      st        ||       c}S c c}w )au  Given user-provided attribute name, check all the elements in the list and return the corresponding
        attribute values.

        Args:
            attr_name (:obj:`str`): The text string of certain attribute name.

        Returns:
            :obj:`List`:
                The list of the corresponding attribute value (if exist) of each element in the list.
        )rv   getattr)r"   	attr_namer9   s      r$   get_infozLayout.get_info   s(     48SC73	;RY'SSSrx   c                 b    | j                   | D cg c]  }|j                          c}dS c c}w )zGenerate a dict representation of the layout object with
        the page_data and all the blocks in its dict representation.

        Returns:
            :obj:`Dict`:
                The dictionary representation of the layout object.
        )r   r   )r   to_dictr8   s     r$   r~   zLayout.to_dict  s(     "^^QU7V#7VWW7Vs   ,c           	      t   d}d}| D ]@  }t        |t              rd}|j                  }n|}t        |t        |j
                           }B t        |   j
                  }|rg }| D ]  }t        |t              rHt        |      }|j                  j
                  |k7  rR t        |j                  d|              |_        n.|j
                  |k7  r t        |d|              }t              }|j                  |        |S | D cg c]'  }|j
                  |k7  r t        |d|              n|) }}|S c c}w )a6  Convert all elements into blocks of the same type based
        on the type casting rule::

            Interval < Rectangle < Quadrilateral < TextBlock

        Returns:
            List[BaseLayoutElement]:
                A list of base layout elements of the maximal compatible
                type
        FTto_)
r   r   blockmaxr   _namer   r
   rz   append)r"   has_textblockmax_coord_levelr9   r   target_coord_name
new_blockss          r$   get_homogeneous_blockszLayout.get_homogeneous_blocks  sb     
	C#y) $		!!;EKK!HO
	 3?CIIJ 	'c9-s)Cyy*;;$QGCII=N<O7P$Q$S	yy$55EgcS1B0C+DEG#E*C!!#&	'$   	  99 11 8s#4"5679J  s   ,D5c                     |r| j                         }n| }t        j                  |D cg c]  }|j                          c}      }|S c c}w )a  Convert the layout object into the dataframe.
        Warning: the page data won't be exported.

        Args:
            enforce_same_type (:obj:`bool`, optional):
                If true, it will convert all the contained blocks to
                the maximal compatible data type.
                Defaults to False.

        Returns:
            pd.DataFrame:
                The dataframe representation of layout object
        )r   pd	DataFramer~   )r"   enforce_same_typer   r9   dfs        r$   to_dataframezLayout.to_dataframeG  sC     002FF\\F;S3;;=;<	 <s   A	r-   )NFF)r   r   r   r   T)F)%r   
__module____qualname____doc__r   r   r   r%   r+   r0   r2   r6   r:   rD   rH   rK   rM   r
   rQ   rU   rX   r`   rc   re   rh   ro   rr   rw   r|   strr   r~   r   r   r   r   r    r&   r$   r   r   !   s    )4 )x~ )D )&%!8,(L



 (*% 
8hx>P 88 ,.e 
"
"
*
 7BTXc3h X0->(? 0dr|| r&   r   )typingr   r   r   r   r   collections.abcr   r	   r
   pandasr   baser   r   layout_elementsr   r   r   r   r   r   r   r   r   r&   r$   <module>r      s6    : 9 5   5  {_ {r&   