
    kh>                     ~    d Z ddlmZ ddlmZ ddlmZ ddlmZ ddl	m
Z
mZ ddlmZ  G d	 d
      Z G d de      Zy)a  Module to determine stream table borders.

Though no exact borders exist for stream table, it's better to simplify table structure by
aligning borders as more as possible. Taking vertical borders for example, it can be moved 
in a valid range in horizontal direction, but restricted by top and bottom borders in vertical 
direction. It's also true for horizontal borders.

Accordingly, introduce ``Border`` object, which has the following attributes:

* Valid range, e.g. ``(100, 250)``;
* Boundary borders, e.g. ``(top_border, bottom_border)`` for v-border,
  or ``(left_border, right_border)`` for h-border.

The target is to finalize the position in valid range, e.g. ``x=125`` for v-border with valid range 
``(120, 250)``. Then it's y-direction is determined by its boundary borders, where the y-coordinates 
are finalized in same logic. Finally, this border is fixed since both x- and y- directions are 
determined.

.. note::
    Consider horizontal and vertical borders only.
    )defaultdict   )Shapes)Stroke)	constants)RectType	rgb_value)BaseCollectionc                       e Zd ZdZddededefdZed        Zed        Z	ed	        Z
ed
        Zed        Zed        ZdefdZddefdZddefdZd ZdefdZdefdZd Zy)BorderzBorder for stream table.Nborder_rangeborders	referencec                     |j                         | _        d| _        || _        | j	                  |       | j                  |       d| _        t        j                  | _	        d| _
        y)a  Border for stream table.
        
        Args:
            border_type (str): border orientation/position, e.g. 'hi' represents horizontal inner border.
                * ``h/v``       - horizontal/vertical border;
                * ``t/b/l/r/i`` - outer border (top/bottom/left/right), or inner border
            border_range (tuple): Valid range, e.g. ``(x0, x1)`` for vertical border.
            borders (tuple): Boundary borders in ``Border`` type, e.g. 
                * top and bottom horizontal borders for current vertical border; 
                * left and right vertical borders for current horizontal border. 
            reference (bool): Reference border will not convert to real table border.
        FNr   )upperborder_type	finalizedis_referenceset_border_rangeset_boundary_borders_valuer   HIDDEN_W_BORDERwidthcolor)selfr   r   r   r   s        Q/var/www/teggl/fontify/venv/lib/python3.12/site-packages/pdf2docx/table/Border.py__init__zBorder.__init__$   sg     ',,.  & 	l+ 	!!'*  ..

    c                     d| j                   v S )NHr   r   s    r   is_horizontalzBorder.is_horizontalL   s    $'4+;+;$;;r   c                     d| j                   v S )NVr!   r"   s    r   is_verticalzBorder.is_verticalO   s    "%)9)9"99r   c                     d| j                   v S )NTr!   r"   s    r   is_topzBorder.is_topR   s     D$4$444r   c                     d| j                   v S )NBr!   r"   s    r   	is_bottomzBorder.is_bottomU   s     #t'7'7 77r   c                    | j                   r| j                  S | j                  | j                  z   dz  }| j                  rt        | j                  dz
  |      S | j                  rt        | j                  dz   |      S |S )zFinalized position, e.g. y-coordinate of horizontal border. 

        Average value if not finalized, but close to the table side for top and bottom 
        boundary borders.
               @   )r   r   LRangeURanger)   maxr,   min)r   avgs     r   valuezBorder.valueX   si     >>;;;;t{{*C/C{{4;;q=#..4;;q=#..
r   c                 "   | j                   rB| j                  j                  | j                  | j                  j                  | j                  fS | j                  | j                  j                  | j                  | j                  j                  fS )zCenter line of this border.)r#   _LBorderr5   _UBorderr"   s    r   
centerlinezBorder.centerlinej   sc     MM''T]]5H5H$**UUJJ 3 3TZZATATUUr   r5   c                     | j                   t        j                  z
  |cxk  xr  | j                  t        j                  z   k  S c S )zWhether the given position locates in the valid border range.

            Args:
                value (float): Target position.
            
            Returns:
                bool: Valid position or not.
        )r0   r   
MINOR_DISTr1   r   r5   s     r   is_validzBorder.is_valids   s8     I000U`t{{9K_K_?_````r   c                 <    |r|\  }}nd\  }}|| _         || _        | S )zSet border valid ranges.

        Args:
            border_range (tuple, optional): Lower/upper range to set. Defaults to None.

        Returns:
            Border: self
        )ii'  )r0   r1   )r   r   x0x1s       r   r   zBorder.set_border_range   s,     !FB FBr   c                 <    |r|\  }}nd\  }}|| _         || _        | S )zSet boundary borders.

        Args:
            borders (tuple, optional): Lower/upper boundary borders to set. Defaults to None.

        Returns:
            Border: self
        )NNr7   r8   )r   r   lower_borderupper_borders       r   r   zBorder.set_boundary_borders   s.     )0&L,)3&L,++r   c                 2    | j                   | j                  fS )zhGet boundary borders.

        Returns:
            tuple: ``(lower b-border, upper b-border)``
        rB   r"   s    r   get_boundary_borderszBorder.get_boundary_borders   s     t}}--r   c                 j    | j                   s| j                  |      sy|| _        d| _         d| _        y)zhFinalize border with given position.

        Args:
            value (float): Target position.
        FT)r   r=   r   r   r<   s     r   finalize_by_valuezBorder.finalize_by_value   s1     >>u!5e!r   strokec                 4   | j                   r%|j                  |j                  }}|j                  }n$|j                  |j                  }}|j                  }| j                  |      sy|| j                  j                  kD  r|| j                  j                  k  ry| j                  |      r7|j                  | _        |j                  | _        t        j                  |_        | j                  j                  |       | j                  j                  |       y)ak  Finalize border with specified stroke shape, which is generally a showing border-like shape.

        Args:
            stroke (Stroke): Target stroke to finalize this border.

        .. note::
            * The boundary borders may also be affected by this stroke shape.
            * The border-like stroke may be an underline or strike-through.      
        N)r#   r?   r@   y0y1r=   r7   r1   r8   r0   rH   r   r   r   BORDERtype)r   rI   low_pos	upper_posr5   s        r   finalize_by_strokezBorder.finalize_by_stroke   s     !'FIIYGIIE "(FIIYGIIE }}U#V T]])))i$--:N:N.NPV !!%(DJDJ"//FK 	''0''	2r   c                     | j                   ryt        | j                  | j                  d      j	                  | j
                        }t        j                  |_        |S )zConvert to border stroke.N)r   r   )	r   r   r   r   update_bboxr9   r   rM   rN   )r   rI   s     r   	to_strokezBorder.to_stroke   sH     T$**tzzBCOOPTP_P_`oor   )hiNNFN)__name__
__module____qualname____doc__tupleboolr   propertyr#   r&   r)   r,   r5   r9   floatr=   r   r   rF   rH   r   rQ   rT    r   r   r   r   !   s    "%e %% %`d %P ; ;9 94 47 7 " V V
aU 
aE $5 $.e  &3 &3Rr   r   c                   H    e Zd ZdZdedefdZdefdZedefd       Z	d Z
y	)
Bordersz#Collection of ``Border`` instances.strokesfillsc                    | j                          | j                  |       g }|D ]  }|j                  s|j                  t	        d      k(  r(|j
                  \  }}}}|j                  t               j                  ||||f      t               j                  ||||f      t               j                  ||||f      t               j                  ||||f      g        | j                  |       t        t        d | j                              }	t        t        d |	            }
| j                  |
       t        t        d |	            }| j                  |       y)a  Finalize the position of all borders.
        
        Args:
            strokes (Shapes): A group of explicit border strokes.
            fills (Shapes): A group of explicit cell shadings.

        .. note::
            A border is finalized in priority below:
            
            * Follow explicit stroke/border.
            * Follow explicit fill/shading.
            * Align h-borders or v-borders as more as possible to simplify the table structure.            
        )   re   re   c                 8    | j                   xs | j                   S rV   )r   r   borders    r   <lambda>z"Borders.finalize.<locals>.<lambda>  s    &2B2B2YfFYFY-Z r   c                 T    | j                   xr | j                  xs | j                   S rV   )r#   r)   r,   rg   s    r   ri   z"Borders.finalize.<locals>.<lambda>  s)    6// <:&*:*:; r   c                     | j                   S rV   r&   rg   s    r   ri   z"Borders.finalize.<locals>.<lambda>$      v/A/A r   N)_add_full_dummy_borders_finalize_by_strokesis_determinedr   r	   bboxextendr   rS   listfilter
_instances_finalize_by_layout)r   rb   rc   tmp_strokesfillr?   rK   r@   rL   r   	h_borders	v_borderss               r   finalizezBorders.finalize   sS    	$$& 	!!'*  
	D!!TZZ9W3E%Ex!YYNBB$$b"b"%56$$b"b"%56$$b"b"%56$$b"b"%56	  
	 	!!+.
 vZ\`\k\klm
 <=DF G	 	  +  A7KL	  +r   c                     |D ]K  }|j                   r| j                  D ]-  }|j                  |j                  k7  r|j	                  |       / M y)z%Finalize borders by explicit strokes.N)rp   ru   
horizontalr#   rQ   )r   rb   rI   rh   s       r   ro   zBorders._finalize_by_strokes(  sS     	2F##X// 2$$(<(<<h))&1	2	2r   r   c           	      :   t               }| D ]8  }|j                  |j                         |j                  |j                         : t	        |      }|j                          g }t        t        |      dz
        D ]M  }||   ||dz      z   dz  }| D cg c]  }t        |j                  |             }}|j                  ||f       O |j                  d d       t        |       }dg|z  }|D ]  \  }}	t        |      |k(  r yt        t        ||	      D 
cg c]
  \  }
}|
|z   c}}
      }|rDt        ||	      D 
cg c]
  \  }
}|
|z    }}
}t        | |	      D ]"  \  }}|s	|j                  t        |             $  yc c}w c c}}
w c c}}
w )a6  Finalize the position of all borders: 
        align borders as more as possible to simplify the table structure.

        Taking finalizing vertical borders for example:

        * initialize a list of x-coordinates, ``[x0, x1, x2, ...]``, with the interval points of each border
        * every two adjacent x-coordinates forms an interval for checking, ``[x0, x1]``, ``[x1, x2]``, ...
        * for each interval, count the intersection status of center point, ``x=(x0+x1)/2.0``, with all borders
        * sort center point with the count of intersections in decent order
        * finalize borders with x-coordinate of center points in sorting order consequently
        * terminate the process when all borders are finalized
        
        Args:
            borders (list): A list of ``Border`` instances.
        re   r.   c                     t        | d         S )Nre   )sum)items    r   ri   z-Borders._finalize_by_layout.<locals>.<lambda>V  s    s47| r   T)keyreverser   N)setaddr0   r1   rs   sortrangelenintr=   appendr   ziprH   )r   x_pointsrh   x_statusixsnumcurrent_statusstatusc1c2
duplicatedborder_statuss                 r   rv   zBorders._finalize_by_layout4  s   $ 5 	(FLL'LL'	( > s8}Q' 	#A!Xac]*C/A7>?VV__Q'(?A?OOQqE"	# 	3TB 'ls! 	CIAv>"c)5
 ^V1LM2beMNJ8 25^V1LM2beMNM *-Wf)= C% &":":3q6"BC	C @  N Ns   !FFFc                 f   t        t        d | j                              }t        t        d | j                              }t        t               }t	               }|D ]I  }|j
                  |j                  f}|j                  |       ||j                     j                  |       K |j                  d        t        t        |      dz
        D ]  }||   ||dz      }	}|j                         \  }
}|	j                         \  }}|
|k7  r||k7  rAt        |
j
                  |j
                        }t        |j                  |j                        }|j                  ||	fg       }|D ]D  }||v r|d   |kD  s|d   |k  rt!        d|||	fd	      }| j                  j                  |       F  y
)a  Add reference borders to build full lattices.
        
        The original borders extracted from contents may be not able to represent the real 
        structure. Then, the reference borders has a chance to be finalized by explicit stroke 
        or fillings::

           +-------+---------+----------+
           +-------+---------+          +  <- shading in the first row, but not represented
           +-------+---------+          +  <- empty in these cells, so no borders extracted
           +-------+---------+----------+

        Add two dummy borders to form full lattices::

           +-------+---------+----------+
           +-------+---------+~~~~~~~~~~+  <- dummy borders
           +-------+---------+~~~~~~~~~~+
           +-------+---------+----------+
        c                     | j                   S rV   )r#   rg   s    r   ri   z1Borders._add_full_dummy_borders.<locals>.<lambda>  s    v/C/C r   c                     | j                   S rV   rl   rg   s    r   ri   z1Borders._add_full_dummy_borders.<locals>.<lambda>  rm   r   c                     | j                   S rV   )r5   rg   s    r   ri   z1Borders._add_full_dummy_borders.<locals>.<lambda>  s
    &,, r   )r   re   r   HIT)r   N)rs   rt   ru   r   r   r0   r1   r   rF   r   r   r   r   r2   r3   getr   )r   ry   rz   raw_borders_maph_range_setrh   h_ranger   leftrightleft_l_borderleft_u_borderright_l_borderright_u_borderlower_boundupper_boundraw_bordersh_borders                     r   rn   zBorders._add_full_dummy_bordersm  s   &  CT__UV	 A4??ST	 &d+e 	IF}}fmm4GOOG$F778??H	I 	67s9~a'( 	1A#A,	!A#%D+/+D+D+F(M=-2-G-G-I*NN n,1NPX m22N4I4IJKm22N4I4IJK *--tElB?K& 1k)8 1:k)WQZ-CX!$$$O&&x01	1r   N)rW   rX   rY   rZ   r   r{   rs   ro   staticmethodrv   rn   r_   r   r   ra   ra      sI    -2,v 2,V 2,j	24 	2 5CD 5C 5Cp61r   ra   N)rZ   collectionsr   shape.Shapesr   shape.Shaper   commonr   common.sharer   r	   common.Collectionr
   r   ra   r_   r   r   <module>r      s9   , $ !    . .L L^s1n s1r   