
    $pj;                       S r SSKJr  SSKrSSKrSSKJr  SSKJr  SSK	J
r
JrJr  SS/rS	S
KJr  S	SKJrJrJrJrJrJrJrJrJrJrJrJrJrJr  \
(       a  SSKJ r   \RB                  S:  =(       a	    \"" \S5      r#Sr$ " S S\5      r%\" SS9S"S j5       r&\" SS9S#S j5       r'\" SS9S#S j5       r(\" SS9S#S j5       r)\" SS9S#S j5       r* " S S\5      r+\" SS9S$S j5       r,            S%S jr-  S&       S'S jjr.  S&       S(S jjr/S)S jr0S*S  jr1  S&       S'S! jjr2\#(       a  \.r3g\/r3g)+z
Grapheme cluster segmentation following Unicode Standard Annex #29.

This module provides pure-Python implementation of the grapheme cluster boundary algorithm as
defined in UAX #29: Unicode Text Segmentation.

https://www.unicode.org/reports/tr29/
    )annotationsN)IntEnum)	lru_cache)TYPE_CHECKINGOptional
NamedTuplezwcwidth.bisearchzwcwidth.table_grapheme   )bisearch)
GRAPHEME_L
GRAPHEME_T
GRAPHEME_VGRAPHEME_LVINCB_EXTENDINCB_LINKERGRAPHEME_LVTINCB_CONSONANTGRAPHEME_EXTENDGRAPHEME_CONTROLGRAPHEME_PREPENDGRAPHEME_SPACINGMARKEXTENDED_PICTOGRAPHICGRAPHEME_REGIONAL_INDICATOR)Iterator)      iter_graphemes    c                  P    \ rS rSrSrSrSrSrSrSr	Sr
S	rS
rSrSrSrSrSrSrSrg)GCB8   z'Grapheme Cluster Break property values.r   r	      r                  	   
             N)__name__
__module____qualname____firstlineno____doc__OTHERCRLFCONTROLEXTENDZWJREGIONAL_INDICATORPREPENDSPACING_MARKLVTLVLVT__static_attributes__r,       L/var/www/html/pdf-tiff/venv/lib/python3.13/site-packages/wcwidth/grapheme.pyr   r   8   sL    1E	
B	
BGF
CGL	A
A
A	B
CrA   r   i   )maxsizec                   U S:X  a  [         R                  $ U S:X  a  [         R                  $ U S:X  a  [         R                  $ [	        U [
        5      (       a  [         R                  $ [	        U [        5      (       a  [         R                  $ [	        U [        5      (       a  [         R                  $ [	        U [        5      (       a  [         R                  $ [	        U [        5      (       a  [         R                  $ [	        U [        5      (       a  [         R                   $ [	        U ["        5      (       a  [         R$                  $ [	        U [&        5      (       a  [         R(                  $ [	        U [*        5      (       a  [         R,                  $ [	        U [.        5      (       a  [         R0                  $ [         R2                  $ )z;Return the Grapheme_Cluster_Break property for a codepoint.r+   r(   i   )r   r3   r4   r7   	_bisearchr   r5   r   r6   r   r8   r   r9   r   r:   r   r;   r   r<   r   r=   r   r>   r   r?   r2   ucss    rB   _grapheme_cluster_breakrH   N   s'   
 f}vv
f}vv
f}ww&''{{o&&zz122%%%&''{{*++j!!uuj!!uuj!!uuk""vvl##ww99rA   c                4    [        [        U [        5      5      $ )z6Check if codepoint has Extended_Pictographic property.)boolrE   r   rF   s    rB   _is_extended_pictographicrK   q   s     	#4566rA   c                4    [        [        U [        5      5      $ )z,Check if codepoint has InCB=Linker property.)rJ   rE   r   rF   s    rB   _is_incb_linkerrM   w        	#{+,,rA   c                4    [        [        U [        5      5      $ )z/Check if codepoint has InCB=Consonant property.)rJ   rE   r   rF   s    rB   _is_incb_consonantrP   }   s     	#~.//rA   c                4    [        [        U [        5      5      $ )z,Check if codepoint has InCB=Extend property.)rJ   rE   r   rF   s    rB   _is_incb_extendrR      rN   rA   c                  .    \ rS rSr% SrS\S'   S\S'   Srg)	BreakResult   z*Result of grapheme cluster break decision.rJ   should_breakintri_countr,   N)r-   r.   r/   r0   r1   __annotations__r@   r,   rA   rB   rT   rT      s    4MrA   rT   c                   U [         R                  :X  a  U[         R                  :X  a
  [        SSS9$ U [         R                  [         R                  [         R                  4;   a
  [        SSS9$ U[         R                  [         R                  [         R                  4;   a
  [        SSS9$ U [         R
                  :X  aL  U[         R
                  [         R                  [         R                  [         R                  4;   a
  [        SSS9$ U [         R                  [         R                  4;   a.  U[         R                  [         R                  4;   a
  [        SSS9$ U [         R                  [         R                  4;   a  U[         R                  :X  a
  [        SSS9$ U[         R                  :X  a
  [        SSS9$ U[         R                  :X  a
  [        SSS9$ U [         R                  :X  a
  [        SSS9$ g)z
Check simple GCB-pair-based break rules (cacheable).

Returns BreakResult for rules that can be determined from GCB properties alone, or None if
complex lookback rules (GB9c, GB11) need to be checked.
Fr   rV   rX   TN)r   r3   r4   rT   r5   r;   r<   r>   r?   r=   r6   r:   r9   )prev_gcbcurr_gcbs     rB   _simple_break_checkr^      st    366h#&&0:: CKK00q99 CKK00q99 355X#%%)HH:: CFFCEE?"xCEE355>'A:: CGGSUU##CEE(9:: 3:::: 3###:: 3;;:: rA   c                Z   [        X5      nUb  U$ U[        R                  :X  a
  [        SSS9$ [	        X#   5      n[        U5      (       as  SnUS-
  nUS:  af  [	        X(   5      n	[        U	5      (       a  SnUS-  nO9[        U	5      (       a  US-  nO#[        U	5      (       a  U(       a
  [        SSS9$ O	OUS:  a  Mf  U [        R                  :X  ap  [        U5      (       a`  US-
  nUS:  aU  [	        X(   5      n	[        U	5      n
U
[        R                  :X  a  US-  nO[        U	5      (       a
  [        SSS9$ OUS:  a  MU  U [        R                  :X  a4  U[        R                  :X  a   US-  S:X  a  [        SUS-   S9$ [        SSS9$ U[        R                  :X  a  SOSn[        SUS9$ )z
Determine if there should be a grapheme cluster break between prev and curr.

Implements UAX #29 grapheme cluster boundary rules.
Fr   r[   r	   Tr!   )r^   r   r7   rT   ordrP   rM   rR   rK   rH   r6   r8   )r\   r]   textcurr_idxrX   resultcurr_ucs
has_linkeriprev_ucs	prev_props              rB   _should_breakri      s    !4F 377::
 4>"H(##
qL1f47|Hx((!
Q **Q#H--&EAFF 1f 3778BBqL1f47|H/9ICJJ&Q*844"BB 1f 3)))h#:P:P.Pa<1EHqLIIq99  6 66qAHD8<<rA   c              #     #    U (       d  g[        U 5      nUc  UnX:  d  X:  a  g[        X#5      nXU n[        R                  " U5       H  nXER                  UR
                   v   M     g7f)%  
Iterate over grapheme clusters using :func:`unicodedata.iter_graphemes`.

Grapheme clusters are "user-perceived characters" - what a user would
consider a single character, which may consist of multiple Unicode
codepoints (e.g., a base character with combining marks, emoji sequences).

:param unistr: The Unicode string to segment.
:param start: Starting index (default 0).
:param end: Ending index (default len(unistr)).
:yields: Grapheme cluster substrings.

Example::

    >>> list(iter_graphemes('cafe\u0301'))
    ['c', 'a', 'f', 'e\u0301']
    >>> list(iter_graphemes('ok\U0001F468\u200D\U0001F469\u200D\U0001F467'))
    ['o', 'k', '\U0001F468\u200D\U0001F469\u200D\U0001F467']
    >>> list(iter_graphemes('ok\U0001F1FA\U0001F1F8'))
    ['o', 'k', '\U0001F1FA\U0001F1F8']

.. versionadded:: 0.3.0
N)lenminunicodedatar   startend)unistrro   rp   lengthfull_segmentsegs         rB   _iter_graphemes_stdlibru     sh     8 [F
{|u
c
C$L)),799SWW-- 8s   A+A-c              #    #    U (       d  g[        U 5      nUc  UnX:  d  X:  a  g[        X#5      nUnSn[        [        X   5      5      nU[        R
                  :X  a  Sn[        US-   U5       HM  n[        [        X   5      5      n[        XhXU5      n	U	R                  nU	R                  (       a  XU v   UnUnMO     XU v   g7f)rk   Nr   r	   )
rl   rm   rH   r`   r   r8   rangeri   rX   rV   )
rq   ro   rp   rr   cluster_startrX   r\   idxr]   rc   s
             rB   _iter_graphemes_pythonrz   2  s     8 [F
{|u
c
C MH 's6='9:H 3)))UQY$*3v{+;<x6I??s++M % s
##s   CCc                   [        XS-
     5      nUS:X  a  US:  a  XS-
     S:X  a  US-
  $ US:  aR  US:  aG  US:  aA  [        XS-
     5      nUS:  a+  [        U5      [        R                  :X  a  [	        XS-
  5      $ US-
  $ US-
  nUS:  aa  X-
  [
        :  aU  [        X   5      nSUs=::  a  S:  a  O  OO7[        U5      [        R                  :X  a  OUS-  nUS:  a  X-
  [
        :  a  MU  Un[        [        X   5      5      nU[        R                  :X  a  SOSn[        US-   U5       HG  n	[        [        X	   5      5      n
[        XzX	U5      nUR                  nUR                  (       a  U	nU
nMI     U$ )ac  
Find the start of the grapheme cluster containing the character before pos.

Scans backwards from pos to find a safe starting point, then iterates forward using standard
break rules to find the actual cluster boundary.

:param text: The Unicode string.
:param pos: Position to search before (exclusive).
:returns: Start position of the grapheme cluster.
r	   r(   r!      r   r   )r`   rH   r   r9   _find_cluster_startMAX_GRAPHEME_SCANr5   r8   rw   ri   rX   rV   )ra   pos	target_cpprev_cp
safe_startcprx   left_gcbrX   rf   	right_gcbrc   s               rB   r~   r~   v  s    DqM"I DSAX$Qw-4*?Qw 4!8	T)$Qw-(G$#:7#Cs{{#R*4q99Qw qJ
q.c.2CC!"2"2&#++5a
 q.c.2CC M&s4+;'<=H 6 66qAH:>3'+CL9	xDXF??M ( rA   c           	     N    US::  a  g[        U [        U[        U 5      5      5      $ )a  
Find the grapheme cluster boundary immediately before a position.

:param unistr: The Unicode string to search.
:param pos: Position in the string (0 < pos <= len(unistr)).
:returns: Start index of the grapheme cluster containing the character at pos-1.

Example::

    >>> grapheme_boundary_before('Hello \U0001F44B\U0001F3FB', 8)
    6
    >>> grapheme_boundary_before('a\r\nb', 3)
    1

.. versionadded:: 0.3.6
r   )r~   rm   rl   )rq   r   s     rB   grapheme_boundary_beforer     s&    " axvs3F'<==rA   c              #     #    U (       d  g[        U 5      nUc  UO
[        X#5      n[        US5      nX:  d  X:  a  gUnXA:  a!  [        X5      nXQ:  a  gXU v   UnXA:  a  M   gg7f)ay  
Iterate over grapheme clusters in reverse order (last to first).

:param unistr: The Unicode string to segment.
:param start: Starting index (default 0).
:param end: Ending index (default len(unistr)).
:yields: Grapheme cluster substrings in reverse order.

Example::

    >>> list(iter_graphemes_reverse('cafe\u0301'))
    ['e\u0301', 'f', 'a', 'c']

.. versionadded:: 0.3.6
Nr   )rl   rm   maxr~   )rq   ro   rp   rr   r   rx   s         rB   iter_graphemes_reverser     sq     ( [FK&S%5CqME|u
C
++F8 3'' +s   A A&$A&)rG   rW   returnr   )rG   rW   r   rJ   )r\   r   r]   r   r   zOptional[BreakResult])r\   r   r]   r   ra   strrb   rW   rX   rW   r   rT   )r   N)rq   r   ro   rW   rp   zOptional[int]r   Iterator[str])rq   r   ro   rW   rp   z
int | Noner   r   )ra   r   r   rW   r   rW   )rq   r   r   rW   r   rW   )4r1   
__future__r   sysrn   enumr   	functoolsr   typingr   r   r   __lazy_modules__r
   rE   table_graphemer   r   r   r   r   r   r   r   r   r   r   r   r   r   collections.abcr   version_infohasattr_HAS_PYTHON315_ITER_GRAPHEMESr   r   rH   rK   rM   rP   rR   rT   r^   ri   ru   rz   r~   r   r   r   r,   rA   rB   <module>r      s1   #     6 6  
 ,: : : : (  /-.   ' , 4 D 47 7
 4- -
 40 0
 4- -
*  4- -`@=@=@= @= 	@=
 @= @=J +.+.+. 
+. 	+.` A$A$A$ 
A$ 	A$H1h>0 &&& 
& 	&V < 	 rA   