o
    
iH                     @  s   d dl mZ d dlZd dlZd dlmZmZmZ ddlm	Z	 ddl
mZ e	j	e	jB e	jB ZG dd deZG d	d
 d
ee ZG dd dee ZdS )    )annotationsN)AnyStrGeneric
NamedTuple   )	ImageFont)_Inkc                   @  s.   e Zd ZU ded< ded< ded< ded< dS )	_Linefloatxystranchorstr | bytestextN)__name__
__module____qualname____annotations__ r   r   K/home/ubuntu/SoloSpeech/.venv/lib/python3.10/site-packages/PIL/ImageText.pyr	      s
   
 r	   c                   @  s<   e Zd ZU g Zded< dZdZ		ddddZdddZdS )_Wrapzlist[AnyStr]linesr   Nr   Text[AnyStr]widthintheight
int | NonefontFont | NonereturnNonec                 C  s|  || _ || _|| _|| _| j j }t|trdnd}|}tt|tr$dnd|D ]}tt|tr3dnd|}	|	rg| |s@ ntt	|	D ] \}
}|
dkrS| |sS n|  j
t|7  _
|t|d  }qD|}|| }| j || jd |krz|}q(|r| |s n1t|}| }|t| | _| j || jd |kr|d u rd	}t| n
|}q(|r| | || j
d  | _d S )
N     z\s*\S+s   \s*\S+z
[^\S\n]*\ns
   [^\S\n]*\nr      zWord does not fit within line)r   r   r   r   
isinstancer   refindalladd_line	enumeratepositionlen	_get_bboxlstripoffset
ValueErrorremaining_text)selfr   r   r   r   
input_textemptystringlinewordnewlinesinew_lineoriginal_lengthmsgr   r   r   __init__   sP   

z_Wrap.__init__r4   r   boolc                 C  sx   | j |g }| jd ur(| jj|dd j}| j|| jd }|| | jkr(dS || _ |  jt|| j	 7  _d| _	dS )N)r      Fr   T)
r   r   r   _splitr   r,   r   r*   r+   r.   )r1   r4   r   last_line_ylast_line_heightr   r   r   r(   R   s   
z_Wrap.add_lineNN)
r   r   r   r   r   r   r   r   r    r!   )r4   r   r    r<   )	r   r   r   r   r   r*   r.   r;   r(   r   r   r   r   r      s   
 9r   c                   @  s   e Zd Z						d:d;ddZd<ddZd=d>ddZd?ddZ		d@dAd%d&ZdBd'd(Z	)		*	dCdDd2d3Z		d@dEd6d7Z
	)		*dFdGd8d9ZdS )HTextNRGB   r   r   r   r   moder   spacingr
   	direction
str | Nonefeatureslist[str] | Nonelanguager    r!   c                 C  sH   || _ |pt | _|| _|| _|| _|| _|| _d| _	d| _
d| _dS )a  
        :param text: String to be drawn.
        :param font: Either an :py:class:`~PIL.ImageFont.ImageFont` instance,
                     :py:class:`~PIL.ImageFont.FreeTypeFont` instance,
                     :py:class:`~PIL.ImageFont.TransposedFont` instance or ``None``. If
                     ``None``, the default font from :py:meth:`.ImageFont.load_default`
                     will be used.
        :param mode: The image mode this will be used with.
        :param spacing: The number of pixels between lines.
        :param direction: Direction of the text. It can be ``"rtl"`` (right to left),
                          ``"ltr"`` (left to right) or ``"ttb"`` (top to bottom).
                          Requires libraqm.
        :param features: A list of OpenType font features to be used during text
                         layout. This is usually used to turn on optional font features
                         that are not enabled by default, for example ``"dlig"`` or
                         ``"ss01"``, but can be also used to turn off default font
                         features, for example ``"-liga"`` to disable ligatures or
                         ``"-kern"`` to disable kerning.  To get all supported
                         features, see `OpenType docs`_.
                         Requires libraqm.
        :param language: Language of the text. Different languages may use
                         different glyph shapes or ligatures. This parameter tells
                         the font which language the text is in, and to apply the
                         correct substitutions as appropriate, if available.
                         It should be a `BCP 47 language code`_.
                         Requires libraqm.
        Fr   N)r   r   load_defaultr   rF   rG   rH   rJ   rL   embedded_colorstroke_widthstroke_fill)r1   r   r   rF   rG   rH   rJ   rL   r   r   r   r;   a   s   %
zText.__init__c                 C  s    | j dvrd}t|d| _dS )z?
        Use embedded color glyphs (COLR, CBDT, SBIX).
        )rD   RGBAz3Embedded color supported only in RGB and RGBA modesTN)rF   r/   rN   )r1   r:   r   r   r   embed_color   s   

zText.embed_colorr   r   fill_Ink | Nonec                 C  s   || _ || _dS )a  
        :param width: The width of the text stroke.
        :param fill: Color to use for the text stroke when drawing. If not given, will
                     default to the ``fill`` parameter from
                     :py:meth:`.ImageDraw.ImageDraw.text`.
        N)rO   rP   )r1   r   rS   r   r   r   stroke   s   
zText.strokec                 C  s   | j dv rdS | jrdS dS )N)1PIFrV   rQ   L)rF   rN   )r1   r   r   r   _get_fontmode   s
   
zText._get_fontmoder   r   r   scalingstr | tuple[str, int] | NoneText[AnyStr] | Nonec              	   C  s  t | jtjrd}t|| jdvrd}t||du r#t| ||}nt | jtjs0d}t||du r:d}t|t |trBd}n|\}}| j}t| |||}|dkr|j	sYdS t
|j}|j	r|t|dkrod	}t||d8 }| jj|d
}t| |||}|j	sb|| _nG|j	rd	}t|t
|j}|j	s||krd	}t||d7 }| jj|d
}|}	t| |||}|j	r|d8 }|| jjkr| jj|d
| _|	}|j	rt|j	| j| j| j| j| j| jd}
| j|
_| j|
_| j|
_nd}
t | jtrdnd}||j| _|
S )a  
        Wrap text to fit within a given width.

        :param width: The width to fit within.
        :param height: An optional height limit. Any text that does not fit within this
                       will be returned as a new :py:class:`.Text` object.
        :param scaling: An optional directive to scale the text, either "grow" as much
                        as possible within the given dimensions, or "shrink" until it
                        fits. It can also be a tuple of (direction, limit), with an
                        integer limit to stop scaling at.

        :returns: An :py:class:`.Text` object, or None.
        zTransposedFont not supported)NltrzOnly ltr direction supportedNz$'scaling' only supports FreeTypeFontz'scaling' requires 'height'r   shrinkzText could not be scaled)size)r   r   rF   rG   rH   rJ   rL   
   
)r%   r   r   TransposedFontr/   rH   r   FreeTypeFontr   r0   mathceilra   maxfont_variantfloorrC   rF   rG   rJ   rL   rN   rO   rP   r   joinr   )r1   r   r   r\   r:   wraplimitr   ra   	last_wrapr   newliner   r   r   rl      s   

	
z	Text.wrapc                 C  sR   t | jtrd| jv }nd| jv }|rd}t|| j| j|  | j| j| j	S )a  
        Returns length (in pixels with 1/64 precision) of text.

        This is the amount by which following text should be offset.
        Text bounding box may extend past the length in some fonts,
        e.g. when using italics or accents.

        The result is returned as a float; it is a whole number if using basic layout.

        Note that the sum of two lengths may not equal the length of a concatenated
        string due to kerning. If you need to adjust for kerning, include the following
        character and subtract its length.

        For example, instead of::

            hello = ImageText.Text("Hello", font).get_length()
            world = ImageText.Text("World", font).get_length()
            helloworld = ImageText.Text("HelloWorld", font).get_length()
            assert hello + world == helloworld

        use::

            hello = (
                ImageText.Text("HelloW", font).get_length() -
                ImageText.Text("W", font).get_length()
            )  # adjusted for kerning
            world = ImageText.Text("World", font).get_length()
            helloworld = ImageText.Text("HelloWorld", font).get_length()
            assert hello + world == helloworld

        or disable kerning with (requires libraqm)::

            hello = ImageText.Text("Hello", font, features=["-kern"]).get_length()
            world = ImageText.Text("World", font, features=["-kern"]).get_length()
            helloworld = ImageText.Text(
                "HelloWorld", font, features=["-kern"]
            ).get_length()
            assert hello + world == helloworld

        :return: Either width for horizontal text, or height for vertical text.
        rb   rc   z&can't measure length of multiline text)
r%   r   r   r/   r   	getlengthr[   rH   rJ   rL   )r1   	multiliner:   r   r   r   
get_length  s   *
zText.get_lengthr   r   leftxytuple[float, float]r   alignr   list[str] | list[bytes] | Nonelist[_Line]c              	     sl  |d u rj dkrdnd}nt|dkrd}t||d u r0tjtr*jdnjd}t|dkrDt|d	 |d ||d	 gS |d d
v rUj dkrUd}t|  j	
d d jjjd j j }|d }g }j dkr|d	 }	|D ]}
|t|	|||
 |	|7 }	q|S g }d	}|D ]}
j	|
 j jj}|| t||}q|d dkr|t|d | d 8 }n|d dkr|t|d | 8 }d}|D ]}
|d	 }	|d7 }|||  }|dv rn|dkr|	|d 7 }	n|dkr|	|7 }	nd}t||dkr|d	kr|t|d krt|
tr(|
dn|
d}t|dkr|d	 dkrB|	|d 8 }	n|d	 dkrM|	|8 }	 fdd|D }d|d  }|t| }d	}|D ]}|t|	||| |	|| |t|d   7 }	|d7 }qg||7 }q|d	 dkr|	|d 8 }	n|d	 dkr|	|8 }	|t|	|||
 ||7 }q|S )Nttbltlar$   z#anchor must be a 2 character stringrb   rc   r   r   tbz'anchor not supported for multiline textAr>   mg       @dr=   )rt   justifycenterrightz4align must be "left", "center", "right" or "justify"r        rc              	     s&   g | ]}j | jjjqS r   )r   rp   rH   rJ   rL   ).0r5   fontmoder1   r   r   
<listcomp>  s    zText._split.<locals>.<listcomp>l)rH   r+   r/   r%   r   r   splitr	   r[   r   getbboxrJ   rL   rO   rG   appendrp   rh   sum)r1   ru   r   rw   r   r:   line_spacingtoppartsrt   r4   widths	max_width
line_widthidxwidth_differencewordsword_widthsword_anchorr7   r5   r   r   r   r?   G  s   

	

L






zText._splitr   !tuple[float, float, float, float]c              	   C  s(   |p| j ||  | j| j| j| j|S )N)r   r   r[   rH   rJ   rL   rO   )r1   r   r   r   r   r   r   r,     s   
zText._get_bboxc           	      C  s   d}|  |||D ]L\}}}}| j||d}|d | |d | |d | |d | f}|du r3|}q	t|d |d t|d |d t|d |d t|d |d f}q	|dus\J |S )a  
        Returns bounding box (in pixels) of text.

        Use :py:meth:`get_length` to get the offset of following text with 1/64 pixel
        precision. The bounding box includes extra margins for some fonts, e.g. italics
        or accents.

        :param xy: The anchor coordinates of the text.
        :param anchor: The text anchor alignment. Determines the relative location of
                       the anchor to the text. The default alignment is top left,
                       specifically ``la`` for horizontal text and ``lt`` for
                       vertical text. See :ref:`text-anchors` for details.
        :param align: For multiline text, ``"left"``, ``"center"``, ``"right"`` or
                      ``"justify"`` determines the relative alignment of lines. Use the
                      ``anchor`` parameter to specify the alignment to ``xy``.

        :return: ``(left, top, right, bottom)`` bounding box
        N)r   r   r   r$   r>   )r?   r,   minrh   )	r1   ru   r   rw   bboxr   r   r   	bbox_liner   r   r   get_bbox  s"   



zText.get_bbox)NrD   rE   NNN)r   r   r   r   rF   r   rG   r
   rH   rI   rJ   rK   rL   rI   r    r!   )r    r!   )r   N)r   r
   rS   rT   r    r!   )r    r   rB   )r   r   r   r   r\   r]   r    r^   )r    r
   )rs   Nrt   N)
ru   rv   r   rI   rw   r   r   rx   r    ry   )r   r   r   r   r   rI   r    r   )rs   Nrt   )ru   rv   r   rI   rw   r   r    r   )r   r   r   r;   rR   rU   r[   rl   rr   r?   r,   r   r   r   r   r   rC   `   s4    
3	


_;}rC   )
__future__r   rf   r&   typingr   r   r   r"   r   _typingr   re   rd   Fontr	   r   rC   r   r   r   r   <module>   s    L