U
    :vhk                     @   s  d dl Z d dlmZmZmZmZ ddlmZ ddlm	Z	m
Z
mZ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 deZG dd dZeddZG dd deZG dd dZG dd dZG dd dZG dd dZG dd deZG dd dZG dd deeZdS )    N)
NamedTupleSequenceListNewType   )FPDFException)AlignXPosYPosWrapMode)VectorImageInfo)preload_image)MultiLineBreak	FORM_FEED)get_scale_factorc                   @   s   e Zd ZU eed< eed< dS )ExtentsleftrightN)__name__
__module____qualname__float__annotations__ r   r   4/tmp/pip-unpacked-wheel-dvf6lv8i/fpdf/text_region.pyr      s   
r   c                       s8   e Zd ZdZ fddZdd Zdd Zdd	 Z  ZS )
TextRegionMixinz>Mix-in to be added to FPDF() in order to support text regions.c                    s   |    t j|| d S N)clear_text_regionsuper__init__)selfargskwargs	__class__r   r   r      s    zTextRegionMixin.__init__c                 C   s
   || _ d S r   Z%_TextRegionMixin__current_text_regionr    regionr   r   r   register_text_region   s    z$TextRegionMixin.register_text_regionc                 C   s
   | j |kS r   r%   r&   r   r   r   is_current_text_region   s    z&TextRegionMixin.is_current_text_regionc                 C   s
   d | _ d S r   r%   r    r   r   r   r   "   s    z!TextRegionMixin.clear_text_region)	r   r   r   __doc__r   r(   r)   r   __classcell__r   r   r#   r   r      s
   r   	Paragraphc                   @   s:   e Zd ZU dZeed< eed< dZeed< dZ	eed< dS )LineWrapperzConnects each TextLine with the Paragraph it was written to.
    This allows to access paragraph specific attributes like
    top/bottom margins when rendering the line.
    line	paragraphF
first_line	last_lineN)
r   r   r   r+   r   r   r-   r1   boolr2   r   r   r   r   r.   *   s
   
r.   c                   @   s   e Zd Zdd Zdd ZdS )Bulletc                 C   s   || _ || _|| _d| _d S )NF)	fragments	text_liner_marginrendered_flag)r    bullet_fragmentsr6   bullet_r_marginr   r   r   r   7   s    zBullet.__init__c                 C   s    d}| j D ]}|| 7 }q
|S Nr   )r5   	get_width)r    fragments_widthfragr   r   r   get_fragments_widthB   s    
zBullet.get_fragments_widthN)r   r   r   r   r?   r   r   r   r   r4   6   s   r4   c                
   @   s|   e Zd ZdeeeeeeedddZdd	 Zd
d Z	dd Z
dedddZeedddZdddZee dddZdS )r-   Nr    F)
top_marginbottom_marginindentbullet_stringskip_leading_spaceswrapmodefirst_line_indentc                 C   s   || _ |j| _|rFt|}|tjtjtjtjfkrFtd|j	 d|| _
|d kr^|j| _n|| _|| _|| _|| _|	| _|
d kr| j j| _nt|
| _g | _|d krdtd | jj }|rt| |||f | _nd | _|| _d S )NAText_align must be 'LEFT', 'CENTER', 'RIGHT', or 'JUSTIFY', not ''.   mm)_regionpdfr   coerceLCRJ
ValueErrorvalue
text_alignline_heightrA   rB   rC   rE   rF   r   _text_fragmentsr   kr4   generate_bullet_frags_and_tlbulletrG   )r    r'   rU   rV   rA   rB   rC   r:   rD   rE   rF   rG   r   r   r   r   J   s:    


zParagraph.__init__c                 C   sB   d| j  d| j d| j d| j d| j d| j dt| j dS )	NzParagraph(text_align=z, line_height=z, top_margin=z, bottom_margin=z, skip_leading_spaces=z, wrapmode=z, #text_fragments=))rU   rV   rA   rB   rE   rF   lenrW   r*   r   r   r   __str__{   s    @zParagraph.__str__c                 C   s   | S r   r   r*   r   r   r   	__enter__   s    zParagraph.__enter__c                 C   s   | j   d S r   )rL   end_paragraphr    exc_type	exc_value	tracebackr   r   r   __exit__   s    zParagraph.__exit__textc                 C   sX   | j jstd| j |dd}| j j|dd}|rH|D ]
}||_q<| j| d S )N3No font set, you need to call set_font() beforehandr@   FZmarkdown)	rM   font_familyr   normalize_textreplace_preload_font_styleslinkrW   extend)r    rf   rn   Znormalized_stringr5   r>   r   r   r   write   s    zParagraph.write)rD   r:   c              	   C   s   |sd S | j |}| j js$td| j j|dd}d}|D ]}|| 7 }q<t|| jj| j j| j	| |  | j jf| j
p| jj
ptj| j| j| jp| jjd}| }||fS )Nrg   Fri   r   )	max_widthmarginsalignrF   rV   rE   )rM   rk   rj   r   rm   r<   r   rL   c_marginrC   rU   r   rO   rF   rV   rE   get_line)r    rD   r:   r9   r=   r>   Zbullet_line_breakZbullet_text_liner   r   r   rY      s.    z&Paragraph.generate_bullet_frags_and_tlc                 C   sZ   | j jstd|d kr&| j j| j }| j jdddd }||j |jd< | j	| d S )Nrg   
Fri   r   Zfont_size_pt)
rM   rj   r   Z	font_sizerV   rm   rX   Zgraphics_staterW   append)r    hfragmentr   r   r   ln   s    zParagraph.ln)returnc                 C   s   g }t | j| jj| jj| j | jjf| j| jp:| jjp:t	j
|| j| j| jpP| jjd	}g | _| }d}|d k	r|t|| |d d}| }qh|r|d }t|j| |jdd}||d< |S )N)rq   rr   rG   rs   print_shrF   rV   rE   T)r1   F)r1   r2   )r   rW   rL   r<   rM   rt   rC   rG   rU   r   rO   rF   rV   rE   ru   rw   r.   r/   r1   )r    r|   
text_linesZmulti_line_breakr6   r1   lastr   r   r   build_lines   s<    
   zParagraph.build_lines)
NNr   r   r   Nr@   FNr   )N)N)r   r   r   r   strr3   r   r   r]   r^   rd   rp   rY   rz   r   r.   r   r   r   r   r   r-   I   s4             1
	c                
   @   s0   e Zd ZdeeedddZdd Zd	d
 ZdS )ImageParagraphNFr   widthheight
fill_widthc                 C   s   || _ || _|r@t|}|tjtjtjfkr@td|j d|| _	|| _
|| _|| _|| _|| _|	| _|
| _|| _|| _d  | _| _d S )Nz1Align must be 'LEFT', 'CENTER', or 'RIGHT', not 'rI   )r'   namer   rN   rO   rP   rQ   rS   rT   rs   r   r   r   keep_aspect_ratiorA   rB   rn   titlealt_textimginfo)r    r'   r   rs   r   r   r   r   rA   rB   rn   r   r   r   r   r   r      s&    
zImageParagraph.__init__c                 C   s"   t | jjj| j\| _| _| _| S r   )r   r'   rM   Zimage_cacher   r   r   r*   r   r   r   
build_line   s
     zImageParagraph.build_linec           
      C   s@  | j stdt| jt}| jr(| j}n| jd | jjj }| j	rJ| j	}n,| jd | jjj }||ksl| j
rr|}n|}| js|| | }||krd S |}	| jr| jtjkr|	|| 7 }	n| jtjkr|	|| d 7 }	|r| jjj| j| j | j|	d ||| j| j| j| jdS | jjj| j| j | j|	d ||| j| j| jd | jdS )Nz;ImageParagraph.build_line() must be called before render().rx   wrJ   )r   svgr   xyr   rx   rn   r   r   r   )r   r   r   r   r   r   rx   rn   r   r   Zdimsr   )r   RuntimeError
isinstancer   r   r   r'   rM   rX   r   r   rs   r   rQ   rP   Z_vector_imager   rn   r   r   r   Z_raster_image)
r    col_left	col_width
max_heightZis_svgrx   Znative_hr   Znative_wr   r   r   r   render   sh    zImageParagraph.render)
NNNFFr   r   NNN)r   r   r   r   r3   r   r   r   r   r   r   r   r      s"             #r   c                
       s   e Zd Zdddddddddeeeed fddZd	d
 Zdd Zdd Z	de
dddZdddZd eedddZdd Zd!eeedddZ  ZS )"ParagraphCollectorMixinNLEFTg      ?F)rf   rU   rV   r|   rE   rF   r   img_fill_width)rV   r|   rE   rF   c                   s   || _ t|| _| jtjtjtjtjfkr@td| jj	 d|| _
|| _t|| _|| _g | _d | _t j|f|
| |r| | |r| j||	d d S )NrH   rI   )r   )rM   r   rN   rU   rO   rP   rQ   rR   rS   rT   rV   r|   r   rF   rE   _paragraphs_active_paragraphr   r   rp   image)r    rM   rf   rU   rV   r|   rE   rF   r   r   r!   r"   r#   r   r   r   =  s"    
z ParagraphCollectorMixin.__init__c                 C   sL   | j | r td| jj d| j j| _| j   d| j _| j |  | S )NzUnable to enter the same z context recursively.r   )	rM   r)   r   r$   r   page_pageZ_push_local_stackr(   r*   r   r   r   r^   ]  s    

z!ParagraphCollectorMixin.__enter__c                 C   s*   | j   | j| j _| j   |   d S r   )rM   r   r   r   Z_pop_local_stackr   r`   r   r   r   rd   h  s    


z ParagraphCollectorMixin.__exit__c                 C   sD   | j dkrtd| j d kr@t| | j| jd}| j| d| _ d S )NEXPLICITzaConflicts with active paragraph. Either close the current paragraph or write your text inside it.)r'   rU   rE   AUTOr   r   r-   rU   rE   r   rw   )r    pr   r   r   _check_paragraphn  s    

z(ParagraphCollectorMixin._check_paragraphre   c                 C   s   |    | jd | d S Nr}   )r   r   rp   )r    rf   rn   r   r   r   rp   |  s    zParagraphCollectorMixin.writec                 C   s   |    | jd | d S r   )r   r   rz   )r    rx   r   r   r   rz     s    zParagraphCollectorMixin.lnr   r@   )rE   rF   c                 C   sR   | j dkrtdt| |p| j||p(| j|	||||
||d}| j| d| _ |S )a~  
        Args:
            text_align (Align, optional): the horizontal alignment of the paragraph.
            line_height (float, optional): factor by which the line spacing will be different from the font height. (Default: by region)
            top_margin (float, optional):  how much spacing is added above the paragraph.
                No spacing will be added at the top of the paragraph if the current y position is at (or above) the
                top margin of the page. (Default: 0.0)
            bottom_margin (float, optional): those two values determine how much spacing is added below the paragraph.
                No spacing will be added at the bottom if it would result in overstepping the bottom margin of the page. (Default: 0.0)
            indent (float, optional): determines the indentation of the paragraph. (Default: 0.0)
            bullet_string (str, optional): determines the fragments and text lines of the bullet. (Default: "")
            bullet_r_margin (float, optional): determines the spacing between the bullet and the bulleted line
            skip_leading_spaces (float, optional): removes all space characters at the beginning of each line. (Default: False)
            wrapmode (WrapMode): determines the way text wrapping is handled. (Default: None)
            first_line_indent (float, optional): left spacing before first line of text in paragraph.
        r   Unable to nest paragraphs.)r'   rU   rV   rE   rF   rA   rB   rC   rG   rD   r:   r   )r    rU   rV   rE   rA   rB   rC   rD   r:   rF   rG   r   r   r   r   r0     s$    
z!ParagraphCollectorMixin.paragraphc                 C   s   | j stdd | _ d S )NzNo active paragraph to end.)r   r   r*   r   r   r   r_     s    z%ParagraphCollectorMixin.end_paragraphr   c                 C   sP   | j dkrtd| j r |   t| |||||||||	|
|d}| j| d S )Nr   r   )
rs   r   r   r   r   rA   rB   rn   r   r   )r   r   r_   r   r   rw   )r    r   rs   r   r   r   r   rA   rB   rn   r   r   r   r   r   r   r     s&    
zParagraphCollectorMixin.image)N)N)
NNFr   r   r   r@   NNr   )
NNNFFr   r   NNN)r   r   r   r   r3   r   r   r^   rd   r   r   rp   rz   r0   r_   r   r,   r   r   r#   r   r   <  sb    
          0	          r   c                   @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )
TextRegionz3Abstract base class for all text region subclasses.c                 C   s
   t  dS )aZ  
        Return the horizontal extents of the current line.
        Columnar regions simply return the boundaries of the column.
        Regions with non-vertical boundaries need to check how the largest
        font-height in the current line actually fits in there.
        For that reason we include the current y and the line height.
        NNotImplementedError)r    r   r   r   r   r   current_x_extents  s    zTextRegion.current_x_extentsc                 C   s   |j r(| jj| jjkr(| j j|j 7  _| | jjd\}}| jj| jj }|| jj }|||| |}|r|j}|r| jj| |k r| j j|7  _|S r;   )	rA   rM   r   t_marginr   rx   b_marginr   rB   )r    r0   r   	col_rightbottomr   renderedmarginr   r   r   _render_image_paragraph  s    z"TextRegion._render_image_paragraphc              	   C   sB  |sdS || j _d}d }d}|D ]
}t|trL| |rD|d7 }n q.q |j}d}	|j}
|
j}|jD ]}|j	rhd}	 q|qh|	r|j
r|s|
jr| j j| j jkr| j  j|
j7  _| j j|j |kr|} q.|}|j}| | j jd\}}| j j|k s| j j|kr|| j _| j  j|
j7  _|r|js| |j }| j  j|8  _| j j|j|jjdtjtjdd d|_| j  j|7  _| j  j|j7  _| j j||jdtjtjdd | j  j|j8  _| j  j|
j8  _|jr|
j}|r|	r| j j| |k r| j  j|
j7  _|d7 }|jr  q.q |r>|d |= |S )Nr   r   FT)rx   ZborderZnew_xnew_yfill)rM   r   r   r   r   r/   r0   rZ   r5   
charactersr1   rA   r   r   r   r   rC   r8   r?   r7   Z_render_styled_text_liner6   r	   r   r
   ZTOPZNEXTr2   rB   Ztrailing_form_feed)r    r~   topr   Zprev_line_heightlast_line_heightZrendered_linesZ
tl_wrapperr6   Ztext_renderedZcur_paragraphZ
cur_bulletr>   r   r   Zbullet_indent_shiftr   r   r   r   _render_column_lines  s    





zTextRegion._render_column_linesc                 C   sN   g }| j D ]>}t|tr,| }|| q
|| j}|s>q
|| q
|S r   )r   r   r   r   rw   r   r|   ro   )r    r~   r0   r/   Z	cur_linesr   r   r   collect_linesE  s    

zTextRegion.collect_linesc                 C   s
   t  d S r   r   r*   r   r   r   r   R  s    zTextRegion.renderc                 C   s@   |  | jj|\}}| jj|kr4| jj|k r4| jj}|| }|S r   )r   rM   r   r   )r    r   startendresr   r   r   r<   U  s
    zTextRegion.get_widthN)
r   r   r   r+   r   r   r   r   r   r<   r   r   r   r   r     s   
Nr   c                       s0   e Zd ZdZddd fdd
Zdd Z  ZS )TextColumnarMixinz*Enable a TextRegion to perform page breaksN)l_marginr7   c                   sX   t  j|| |d kr|jn|| _| j}|d kr6|jn|| _|j| j }| || d S r   )r   r   r   r7   r   _set_left_right)r    rM   r   r7   r!   r"   r   r   r#   r   r   r   `  s    zTextColumnarMixin.__init__c                 C   sf   |d kr| j jn|}|d kr,| j j| j j n|}||krVt| jj d| d| dt||| _d S )Nz(): Right limit (z) lower than left limit (z).)	rM   r   r   r7   r   r$   r   r   extents)r    r   r   r   r   r   r   h  s    z!TextColumnarMixin._set_left_right)r   r   r   r+   r   r   r,   r   r   r#   r   r   ]  s   r   c                       s\   e Zd Zddddeeed fddZ fddZd	d
 Zdd Z	dd Z
dd Z  ZS )TextColumnsr   
   F)ncolsgutterbalancec                   s   t  j|f|| d| _|| _|| _| jj| jj }||d |  | }| jj}	t|	|	| g| _	t
d|D ]&}
|	|| 7 }	| j	t|	|	|  qnt| jj| jj| _d S )Nr   r   )r   r   _cur_column_ncolsr   r   r   r   r   _colsrangerw   maxrM   r   r   _first_page_top)r    rM   r   r   r   r!   r"   Ztotal_wr   Zc_leftir#   r   r   r   t  s    	zTextColumns.__init__c                    s@   t    t| jj| jj| _| jr<d| _| j	| j j
| j_| S r;   )r   r^   r   rM   r   r   r   r   r   r   r   r   r*   r#   r   r   r^     s    
zTextColumns.__enter__c                 C   s&   | j r| j d t n
| t dS )z?End the current column and continue at the top of the next one.r}   N)r   rp   r   r*   r   r   r   
new_column  s    zTextColumns.new_columnc                 C   s^  d}| j j}| jr|}|sdS tdd |D }|| j }|| }	||	k rd}|| }tt|| j d }
|d jj	|
 }||kr|| }||kr|}d}t
| j| jD ]}|s dS || jkr|| _| dd\}}| j j|k s| j j|kr|| j _|r || jd kr | j j| j j }| |||}|r| j j| }||kr|}q|rZ|| j _dS )	z?Rendering a set of lines in one or several columns on one page.FNc                 s   s   | ]}|j jV  qd S r   )r/   r   ).0lr   r   r   	<genexpr>  s     z1TextColumns._render_page_lines.<locals>.<genexpr>Tg      ?r   r   )rM   r   r   sumr   mathceilr\   r/   r   r   r   r   r   rx   r   r   )r    r~   r   r   Z	balancingZnext_ypage_bottomZ
tot_heightZ
col_heightZavail_heightZlines_per_columnZmult_heightcr   r   r   r   r   r   r   _render_page_lines  sH    

zTextColumns._render_page_linesc                 C   s   | j s
d S |  }|sd S | jj| jj }t| jj| jj}| ||| |r~| j	| jj}|sdq~d| _
| || jj| qJd S r;   )r   r   rM   rx   r   r   r   r   r   Z_perform_page_break_if_need_ber   )r    r~   r   Zfirst_page_topZ
page_breakr   r   r   r     s    zTextColumns.renderc                 C   s   | j | j \}}||fS r   )r   r   )r    r   r   r   r   r   r   r   r     s    zTextColumns.current_x_extents)r   r   r   intr   r3   r   r^   r   r   r   r   r,   r   r   r#   r   r   s  s   1r   ) r   typingr   r   r   r   errorsr   enumsr   r	   r
   r   Zimage_datastructuresr   Zimage_parsingr   Z
line_breakr   r   utilr   r   r   r-   r.   r4   r   r   r   r   r   r   r   r   r   <module>   s*   
 h " 