o
    &zh`D                  
   @   sb  d Z ddlZddlZddlmZ ddlmZ ddlmZm	Z	 ddl
mZ ddlmZ g dZeeZG d	d
 d
eZG dd deZG dd dZG dd dejZG dd dejZejejejejejejiZeddG dd deZdededededef
ddZdededededef
dd Z eddG d!d" d"eZ!eddG d#d$ d$eZ"dS )%z!Layout utilities (to be expanded)    N)	dataclass)Fraction)OptionalUnion)ConfigurableMixin)ConfigurationError)LayoutErrorBoxSpecificationErrorBoxConstraintsAxisAlignmentMarginsInnerScalingSimpleBoxLayoutRulePositioningc                       s&   e Zd ZdZdef fddZ  ZS )r   z+Indicates an error in a layout computation.msgc                    s   || _ t j|g|R   d S N)r   super__init__)selfr   args	__class__ S/var/www/html/kangema/venv/lib/python3.10/site-packages/pyhanko/pdf_utils/layout.pyr      s   zLayoutError.__init__)__name__
__module____qualname____doc__strr   __classcell__r   r   r   r   r      s    r   c                       s,   e Zd ZdZddee f fddZ  ZS )r	   z4Raised when a box constraint is over/underspecified.Nr   c                    s   t  j|pdd d S )Nz%box constraint is over/underspecified)r   )r   r   )r   r   r   r   r   r   %   s   zBoxSpecificationError.__init__r   )r   r   r   r   r   r   r   r   r   r   r   r   r	   "   s     r	   c                   @   s  e Zd ZU dZee ed< ee ed< ee ed< eed< 			dde	ee
df de	ee
df d	ee fd
dZdd ZedefddZejdd ZedefddZedefddZejdd ZedefddZedefddZedefddZdS )r
   a)  Represents a box of potentially variable width and height.
    Among other uses, this can be leveraged to produce a variably sized
    box with a fixed aspect ratio.

    If width/height are not defined yet, they can be set by assigning to the
    :attr:`width` and :attr:`height` attributes.
    _width_height_ar_fully_specifiedNwidthheightaspect_ratioc                 C   s   |d urt |nd }|d urt |nd }|| _|| _d}d | _|d u r-|d u r-|d u r-d S |d urD|d urD|d ur;tt||| _d}n"|d urf|| _|d urYt t|| | _n|d urft t|| | _|| _d S )NFT)intr    r!   r"   r	   r   roundr#   )r   r$   r%   r&   	int_width
int_heightfully_specifiedr   r   r   r   7   s(   
zBoxConstraints.__init__c                 C   s   | j d ur| jd urt| j | j| _d| _d S | jd urB| jd ur/t| j| j | _ d| _d S | j d urDt| j | j | _d| _d S d S d S )NT)r    r!   r   r"   r#   r'   r   r   r   r   _recalculateU   s   





zBoxConstraints._recalculatereturnc                 C      | j dur| j S t)z
        :return:
            The width of the box.
        :raises BoxSpecificationError:
            if the box's width could not be determined.
        N)r    r	   r,   r   r   r   r$   a      
zBoxConstraints.widthc                 C       | j d u r|| _ |   d S tr   )r    r-   r	   r   r$   r   r   r   r$   n      
c                 C   
   | j duS )z
        :return:
            ``True`` if the box currently has a well-defined width,
            ``False`` otherwise.
        N)r    r,   r   r   r   width_definedv      
zBoxConstraints.width_definedc                 C   r/   )z
        :return:
            The height of the box.
        :raises BoxSpecificationError:
            if the box's height could not be determined.
        N)r!   r	   r,   r   r   r   r%      r0   zBoxConstraints.heightc                 C   r1   r   )r!   r-   r	   r   r%   r   r   r   r%      r3   c                 C   r4   )z
        :return:
            ``True`` if the box currently has a well-defined height,
            ``False`` otherwise.
        N)r!   r,   r   r   r   height_defined   r6   zBoxConstraints.height_definedc                 C   r/   )z
        :return:
            The aspect ratio of the box.
        :raises BoxSpecificationError:
            if the box's aspect ratio could not be determined.
        N)r"   r	   r,   r   r   r   r&      r0   zBoxConstraints.aspect_ratioc                 C   r4   )z
        :return:
            ``True`` if the box currently has a well-defined aspect ratio,
            ``False`` otherwise.
        N)r"   r,   r   r   r   aspect_ratio_defined   r6   z#BoxConstraints.aspect_ratio_defined)NNN)r   r   r   r   r   r'   __annotations__r   boolr   floatr   r-   propertyr$   setterr5   r%   r8   r&   r9   r   r   r   r   r
   )   sB   
 


r
   c                   @   sN   e Zd ZdZe Z	 e Z	 e Z	 e Z		 e
dedd fddZdS )r   z(Class representing a scaling convention.
config_strr.   c                 C   s@   zt jt jt jt jd|  W S  ty   td| dw )a   
        Convert from a configuration string.

        :param config_str:
            A string: 'none', 'stretch-fill', 'stretch-to-fit', 'shrink-to-fit'
        :return:
            An :class:`.InnerScaling` value.
        :raise ConfigurationError: on unexpected string inputs.
        )nonezstretch-fillzstretch-to-fitzshrink-to-fit'zs' is not a valid inner scaling setting; valid values are 'none', 'stretch-fill', 'stretch-to-fit', 'shrink-to-fit'.)r   
NO_SCALINGSTRETCH_FILLSTRETCH_TO_FITSHRINK_TO_FITlowerKeyErrorr   )clsr?   r   r   r   from_config   s   
zInnerScaling.from_configN)r   r   r   r   enumautorB   rC   rD   rE   classmethodr   rI   r   r   r   r   r      s    r   c                   @   s|   e Zd ZdZe Z	 e Z	 e Z	 e	de
dd fddZe	de
dd fddZedd	 Zd
ededefddZdS )r   z;Class representing one-dimensional alignment along an axis.	align_strr.   c                 C   <   zt jt jt jd|  W S  ty   td| dw )a  
        Convert from a horizontal alignment config string.

        :param align_str:
            A string: 'left', 'mid' or 'right'.
        :return:
            An :class:`.AxisAlignment` value.
        :raise ConfigurationError: on unexpected string inputs.
        )leftmidrightrA   zO' is not a valid horizontal alignment; valid values are 'left', 'mid', 'right'.r   	ALIGN_MIN	ALIGN_MID	ALIGN_MAXrF   rG   r   rH   rM   r   r   r   from_x_align      
zAxisAlignment.from_x_alignc                 C   rN   )a  
        Convert from a vertical alignment config string.

        :param align_str:
            A string: 'bottom', 'mid' or 'top'.
        :return:
            An :class:`.AxisAlignment` value.
        :raise ConfigurationError: on unexpected string inputs.
        )bottomrP   toprA   zM' is not a valid vertical alignment; valid values are 'bottom', 'mid', 'top'.rR   rV   r   r   r   from_y_align  rX   zAxisAlignment.from_y_alignc                 C   s   t |  S r   )_alignment_oppositesr,   r   r   r   flipped#  s   zAxisAlignment.flippedcontainer_len	inner_lenc                 C   s   t d|||}| tjkr|| | S | tjkr|S ||kr2td| d| d| d| d	 |S | tjkrA|| d }|| S t)NlengthzContent box width/height z  is too wide for container size z with margins (, z); post_margin will be ignored   )	r   	effectiver   rU   rS   loggerwarningrT   	TypeError)r   r^   r_   
pre_marginpost_margineffective_max_leninner_offsetr   r   r   align'  s,   


zAxisAlignment.alignN)r   r   r   r   rJ   rK   rS   rT   rU   rL   r   rW   r[   r=   r]   r'   rk   r   r   r   r   r      s*    
r   T)frozenc                   @   sB   e Zd ZU dZeed< 	 eed< 	 eed< 	 eed< 	 dd ZdS )	r   zP
    Class describing the position and scaling of an object in a container.
    x_posy_posx_scaley_scalec                 C   s   d| j | j| j| jf S )z
        Convenience method to convert this :class:`.Positioning` into a PDF
        ``cm`` operator.

        :return:
            A byte string representing the ``cm`` operator corresponding
            to this :class:`.Positioning`.
        s   %g 0 0 %g %g %g cm)ro   rp   rm   rn   r,   r   r   r   as_cm^  s   	zPositioning.as_cmN)r   r   r   r   r'   r:   r<   rq   r   r   r   r   r   L  s   
 r   	alignmentcontainer_boxinner_nat_widthrg   rh   c                 C   *   |j r| |j|||S || | |_|S r   )r5   rk   r$   )rr   rs   rt   rg   rh   r   r   r   
_aln_widtho     
rv   inner_nat_heightc                 C   ru   r   )r8   rk   r%   )rr   rs   rx   rg   rh   r   r   r   _aln_height  rw   ry   c                       s~   e Zd ZU dZdZeed< dZeed< dZeed< dZ	eed< e
dd Zed	d
 Zdd Zdd Ze
 fddZ  ZS )r   z"Class describing a set of margins.r   rO   rQ   rZ   rY   c                 C   s   t ||||S )z
        Return a set of uniform margins.

        :param num:
            The uniform margin to apply to all four sides.
        :return:
            ``Margins(num, num, num, num)``
        )r   )rH   numr   r   r   uniform  s   
zMargins.uniformc              
   C   s:   || | }|dk rt d| d| d|  d| d	|S )z4Internal helper method to compute effective margins.r   z	Margins (ra   z) too wide for container  .)r   )dim_namer^   preposteffr   r   r   rc     s   zMargins.effectivec                 C      t d|| j| jS )a&  
        Compute width without margins.

        :param width:
            The container width.
        :return:
            The width after subtracting the left and right margins.
        :raises LayoutError:
            if the container width is too short to accommodate the margins.
        r$   )r   rc   rO   rQ   r2   r   r   r   effective_width     zMargins.effective_widthc                 C   r   )a+  
        Compute height without margins.

        :param height:
            The container height.
        :return:
            The height after subtracting the top and bottom margins.
        :raises LayoutError:
            if the container height is too short to accommodate the margins.
        r%   )r   rc   rY   rZ   r7   r   r   r   effective_height  r   zMargins.effective_heightc                    s$   t |trttd|}t |S )N)rO   rQ   rZ   rY   )
isinstancelistdictzipr   rI   )rH   config_dictr   r   r   rI     s
   
zMargins.from_config)r   r   r   r   rO   r'   r:   rQ   rZ   rY   rL   r{   staticmethodrc   r   r   rI   r   r   r   r   r   r     s   
 


r   c                   @   s~   e Zd ZU dZeed< 	 eed< 	 e Zeed< 	 ej	Z
eed< 	 edd Zded	d fd
dZdededed	efddZdS )r   zk
    Class describing alignment, scaling and margin rules for a box
    positioned inside another box.
    x_aligny_alignmarginsinner_content_scalingc                 C   s~   | dtj}t|trt|}||d< | dtj}t|tr&t|}||d< | dd }|d ur=t||d< d S d S )Nr   r   r   )	getr   rT   r   r   rW   r[   r   rI   )rH   r   r   r   scalingr   r   r   process_entries  s   



z#SimpleBoxLayoutRule.process_entriesnew_marginsr.   c                 C   s   t | j| j|| jdS )N)r   r   r   r   )r   r   r   r   )r   r   r   r   r   substitute_margins  s   z&SimpleBoxLayoutRule.substitute_marginsrs   rt   rx   c                 C   s   | j }| j}d }}|tjkrO|jrO|jrO||j}||j	}	|dkr)|| nd}|dkr3|	| nd}|tj
krBt|| }}n|tjkrOt||d }}t| j||| |j|j}
t| j||| |j|j}t|
|||dS )a  
        Position and possibly scale a box within a container, according
        to this layout rule.

        :param container_box:
            :class:`.BoxConstraints` describing the container.
        :param inner_nat_width:
            The inner box's natural width.
        :param inner_nat_height:
            The inner box's natural height.
        :return:
            A :class:`.Positioning` describing the scaling & position of the
            lower left corner of the inner box.
           r   )rm   rn   ro   rp   )r   r   r   rB   r5   r8   r   r$   r   r%   rD   minrE   rv   r   rO   rQ   ry   r   rY   rZ   r   )r   rs   rt   rx   r   r   ro   rp   	eff_width
eff_heightrm   rn   r   r   r   fit  sF   


zSimpleBoxLayoutRule.fitN)r   r   r   r   r   r:   r   r   r   rE   r   rL   r   r   r
   r'   r   r   r   r   r   r   r     s,   
 
r   )#r   rJ   loggingdataclassesr   	fractionsr   typingr   r   pyhanko.config.apir   pyhanko.config.errorsr   __all__	getLoggerr   rd   
ValueErrorr   r	   r
   Enumr   r   rT   rS   rU   r\   r   r'   rv   ry   r   r   r   r   r   r   <module>   s`    
 /c"

F