+
    f0i2m                     0  a  R6 t>0 t ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIHt ^ RIH	t	H
t
HtHtHtHtHtHtHtHt ^RIHtHtHtHtHtHt ^RIHt ^RIHt ^RIHt ]P@                  ! ]!4      t"^t#^t$Rt%^t&R	t'] ^ k R
t(] ^k RRRRRRRRRRRRRR/t)R R lt*R R lt+R	]! ^4      R]! ^4      R
]! ^ 4      R]! ^4      /t,R	]! R4      R]! R4      R
]! R 4      R]! R!4      /t-R7R" R# llt. ! R$ R%4      t/ ! R& R'4      t0 ! R( R)4      t1R8R* R+ llt2]Pf                  ! ]0Ph                  4      Pj                  Pm                  4       t7]Pf                  ! ]14      Pj                  Pm                  4       t8R, R- lt9R9R. R/ llt:]#3R0 R1 llt;]#]$3R2 R3 llt<R:R4 R5 llt=R# );    N)
itemgetter)
AnyCallableDict	GeneratorListMatchOptionalPatternTupleUnion)T_bboxT_dirT_numT_obj
T_obj_iter
T_obj_list)cluster_objects)to_list)objects_to_bboxg      @ttbltru   ﬀffu   ﬃffiu   ﬄfflu   ﬁfiu   ﬂflu   ﬆstu   ﬅc                T    V ^8  d   QhR\         R\        \        .\        3,          /# )   line_dirreturn)r   r   r   r   )formats   "[/Users/agent/.openclaw/workspace/venv/lib/python3.14/site-packages/pdfplumber/utils/text.py__annotate__r%   -   s%      5 Xugun-E     c                 ,    R R RR RR RR /V ,          # )r   c                     V R ,          # )top xs   &r$   <lambda>&get_line_cluster_key.<locals>.<lambda>/   s    5r&   bttc                     V R ,          ) # )bottomr*   r+   s   &r$   r-   r.   0   s
    !H+r&   r   c                     V R ,          # x0r*   r+   s   &r$   r-   r.   1   s    4r&   rtlc                     V R ,          ) # )x1r*   r+   s   &r$   r-   r.   2   s
    !D'r&   r*   )r!   s   &r$   get_line_cluster_keyr8   -   s.    !% !	
  r&   c                v    V ^8  d   QhR\         R\        \        .\        \        \        3,          3,          /# )r    char_dirr"   )r   r   r   r   r   )r#   s   "r$   r%   r%   6   s/       (E7E%,<O3O*P r&   c                 ,    R R RR RR RR /V ,          # )r   c                 &    V R ,          V R,          3# )r)   r1   r*   r+   s   &r$   r-   #get_char_sort_key.<locals>.<lambda>8   s    !E(AhK0r&   r/   c                 F    V R ,          V R,          ,           ) V R ,          ) 3# )r)   heightr*   r+   s   &r$   r-   r=   9   s    AeHq{23ahY?r&   r   c                 &    V R ,          V R ,          3# r3   r*   r+   s   &r$   r-   r=   :   s    !D'1T7+r&   r5   c                 *    V R ,          ) V R,          ) 3# )r7   r4   r*   r+   s   &r$   r-   r=   ;   s    1T7(QtWH-r&   r*   )r:   s   &r$   get_char_sort_keyrB   6   s.    0?+-	
  r&   r/   r5   r)   r1   r4   r7   c                @    V ^8  d   QhR\         R\         R\        RR/# )r    r!   r:   suffixr"   N)r   str)r#   s   "r$   r%   r%   N   s(     
 
% 
5 
# 
t 
r&   c           
         \        \        P                  4       4      pW9  d   \        R V RV RV  24      hW9  d   \        RV RV RV 24      h\        V 4      \        V4      8X  d   \        R V RV  RV RV 24      hR# )r!   z must be one of z, not r:   =z is incompatible with char_dirN)setPOSITION_KEYSkeys
ValueError)r!   r:   rD   
valid_dirss   &&& r$   validate_directionsrM   N   s    ]'')*J!vh.zl&
K
 	
 !vh.zl&
K
 	
 8}H%vhaz *"81XJ0
 	
 &r&   c                      a  ] tR t^_t o RtV 3R lR ltV 3R lR ltRV 3R lR lltRV 3R lR	 lltRV 3R
 lR llt	Rt
V tR# )TextMapz
A TextMap maps each unicode character in the text to an individual `char`
object (or, in the case of layout-implied whitespace, `None`).
c                f   < V ^8  d   QhRS[ S[S[S[S[,          3,          ,          RS[RS[RR/# )r    tuplesline_dir_renderchar_dir_renderr"   N)r   r   rE   r
   r   r   )r#   __classdict__s   "r$   r%   TextMap.__annotate__e   sF     
* 
*U3/01
* 
* 	
*
 

*r&   c                l    \        W#R 4       Wn        W n        W0n        V P	                  4       V n        R# )_renderN)rM   rQ   rR   rS   	to_string	as_string)selfrQ   rR   rS   s   &&&&r$   __init__TextMap.__init__e   s-     	OiH..)r&   c                    < V ^8  d   QhRS[ /# )r    r"   )rE   )r#   rT   s   "r$   r%   rU   q   s     ( (3 (r&   c           	        a V P                   pV P                  pR P                  \        \	        ^ 4      V P
                  4      4      pVR8X  d
   VR8X  d   V# VP                  R4      oVR9   d   \        \        S4      4      oVR8X  d+   S Uu. uF  pR P                  \        V4      4      NK  	  upoVR	9   d   \        \        \        S4      4      pVR8X  d2   S Uu. uF#  pRV\        V4      ,
          ,          V,           NK%  	  upoM/S Uu. uF"  qDRV\        V4      ,
          ,          ,           NK$  	  upoRP                  V3R l\        V4       4       4      # RP                  S4      # u upi u upi u upi )
 r   r   
r/   r5    c              3   \   <a"   T F   oR P                  V3R lS 4       4      x  K"  	  R# 5i)r_   c              3   4   <"   T F  qS,          x  K  	  R # 5iNr*   ).0lineis   & r$   	<genexpr>.TextMap.to_string.<locals>.<genexpr>.<genexpr>   s     6GGs   Njoin)re   rg   liness   &@r$   rh   $TextMap.to_string.<locals>.<genexpr>   s'      !@V1BGG6666@Vs   (,r/   r5   )r5   r   )rS   rR   rk   mapr   rQ   splitlistreversedmaxlenrange)rZ   cdldbaserf   max_line_lengthrl   s   &     @r$   rX   TextMap.to_stringq   s[   !!!!wws:a=$++67;2;KJJt$E^#Xe_-U{=BCUT$0UC^#"%c#uo"6;QVQV#d) ;<DDQVE
 RWQVT'B CDDQVE yy !@Eo@V!   yy''! D
s   #E1 )E6(E;c                ^   < V ^8  d   QhRS[ S[,          RS[RS[RS[RS[S[S[3,          /# )r    m
main_groupreturn_groupsreturn_charsr"   )r	   rE   intboolr   r   )r#   rT   s   "r$   r%   rU      sI      :  	
  
c3hr&   c           
     B   V P                   VP                  V4      VP                  V4       pV UUu. uF  w  rgVf   K  VNK  	  ppp\        V4      w  rrRVP	                  V4      RV	RV
RVRV/pV'       d   VP                  4       VR&   V'       d   WR&   V# u uppi )Ntextr4   r)   r7   r1   groupschars)rQ   startendr   groupr   )rZ   r|   r}   r~   r   subsetr   cr   r4   r)   r7   r1   results   &&&&&         r$   match_to_dictTextMap.match_to_dict   s     QWWZ01553DE$*<FyaF<-e4 AGGJ'"3"f
  xxzF8#7O# =s   B Bc                   < V ^8  d   QhRS[ S[S[S[,          3,          RS[RS[RS[RS[RS[RS[S[S[S[3,          ,          /# )r    patternregexcaser~   r   r}   r"   )r   rE   r   r   r   r   r   r   )r#   rT   s   "r$   r%   rU      sl     &
 &
sGCL()&
 &
 	&

 &
 &
 &
 
d38n	&
r&   c           
       a \        V\        4      '       d&   VR J d   \        R4      hVR J d   \        R4      hTpMJVR J d   \        P                  ! V4      pVR J d   \        P
                  M^ p\        P                  ! W4      p\        P                  ! WpP                  4      p	\        V3R lV	4      p
V
 Uu. uF  pV P                  VVVSR7      NK  	  up# u upi )FzACannot pass a compiled search pattern *and* regex=False together.z@Cannot pass a compiled search pattern *and* case=False together.c                 T   < \        V P                  S4      P                  4       4      # rd   )r   r   strip)r|   r}   s   &r$   r-    TextMap.search.<locals>.<lambda>   s    D)<)B)B)D$Er&   )r~   r   r}   )
isinstancer   rK   reescapeIcompilefinditerrY   filterr   )rZ   r   r   r   r~   r   r}   compiledflagsgenfilteredr|   s   &&&&&&f     r$   searchTextMap.search   s     gw''~ W  u} V  H~))G, EMBDDqEzz'1Hkk(NN3 EsK 
  +)%	   
 	
 
s   ;Cc          	      R   < V ^8  d   QhRS[ RS[ RS[S[S[S[3,          ,          /# )r    r   r   r"   )r   r   r   rE   r   )r#   rT   s   "r$   r%   rU      s2     
 

04
	d38n	
r&   c                F    V'       d   RpMRpV P                  V^VRR7      # )a6  
`strip` is analogous to Python's `str.strip()` method, and returns
`text` attributes without their surrounding whitespace. Only
relevant when the relevant TextMap is created with `layout` = True

Setting `return_chars` to False will exclude the individual
character objects from the returned text-line dicts.
z *([^\n]+?) *(\n|$)z([^\n]+)F)r}   r   r~   )r   )rZ   r   r   pats   &&& r$   extract_text_linesTextMap.extract_text_lines   s0     (CC{{AL  
 	
r&   )rY   rS   rR   rQ   N)r   TT)TTTTr   )TT)__name__
__module____qualname____firstlineno____doc__r[   rX   r   r   r   __static_attributes____classdictcell__rT   s   @r$   rO   rO   _   sC     

* 
*( (@ 6&
 &
P
 
 
r&   rO   c                   t   a  ] tR t^t o RtV 3R lR ltR^ ^ ^ ^ R
]]^ ^ ]]	]
RRRRRRR3V 3R lR lltR	tV tR# )WordMapz
A WordMap maps words->chars.
c                J   < V ^8  d   QhRS[ S[S[S[3,          ,          RR/# )r    rQ   r"   N)r   r   r   r   )r#   rT   s   "r$   r%   WordMap.__annotate__   s*      tE%*;$<= $ r&   c                    Wn         R # rd   rQ   )rZ   rQ   s   &&r$   r[   WordMap.__init__   s    r&   FNTc          *         < V ^8  d   Qh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[S[,          RS[S[,          RS[S[,          RS[S[,          RS[ RS[ RS[ RS[/# )r    layoutlayout_widthlayout_heightlayout_width_charslayout_height_charslayout_bbox	x_density	y_densityx_shifty_shifty_tolerancer!   r:   line_dir_rotatedchar_dir_rotatedrS   rR   use_text_flow	presortedexpand_ligaturesr"   )r   r   r   r   r   r
   rO   )r#   rT   s   "r$   r%   r      s    s
 s
s
 s
 	s

  s
 !s
 s
 s
 s
 s
 s
 s
 s
 s
 #5/s
  #5/!s
" "%#s
$ "%%s
& 's
( )s
* +s
, 
-s
r&   c                
  a2a3 . p\        V P                  4      '       g#   \        TT;'       g    TT;'       g    TR7      # V'       d   \        M/ pV'       dx   V'       d   V'       d   \	        R4      hM\        \        W',          4      4      pV'       d   V'       d   \	        R4      hM\        \        W8,          4      4      pR.V,          pM. p^ p\        V4      o3\        V4      o2\        V,          p\        V,          p\        V,          ! V4      p\        V,          ! V4      pV'       g	   V'       d   V P                  M\        V P                  V33R lR7      p\        TV33R lTT;'       g    TR7      p\        V4       EF  w  pp V'       dC   V! V ^ ,          ^ ,          4      p!V!VV
,           ,
          p"VR9   d   RM^p#V"V#,          V,          p$M^ p$\        \        V^ 8  4      \        V$4      V,
          4      p%\        V%4       FC  p\        V4      '       d   VR,          ^ ,          R	8X  d
   VV,          pVP!                  R4       KE  	  VV%,          p^ p&V'       g	   V'       d   T M\        V V23R
 lR7      p'V' F  w  p(p)V'       d5   V! V(4      p*V*VV	,           ,
          p+VR9   d   RM^p#V+V#,          V,          p,M^ p,\        \#        ^V&4      \        V,4      V&,
          4      p-VR.V-,          ,          pV&V-,          p&V) FH  p.VP%                  V.R,          V.R,          4      p/V/ F  p0VP!                  V0V.34       V&^,          p&K!  	  KJ  	  K  	  V'       g   EK  VR.VV&,
          ,          ,          pEK  	  V'       dW   VV^,           ,
          p1\        V14       F$  pV^ 8  d
   VV,          pVP!                  R4       K&  	  VR,          R8X  d   VRR p\        TT;'       g    TT;'       g    TR7      # )a  
Given a list of (word, chars) tuples (i.e., a WordMap), return a list of
(char-text, char) tuples (i.e., a TextMap) that can be used to mimic
the structural layout of the text on the page(s), using the following
approach for top-to-bottom, left-to-right text:

- Sort the words by (top, x0) if not already sorted.

- Cluster the words by top (taking `y_tolerance` into account), and
  iterate through them.

- For each cluster, divide (top - y_shift) by `y_density` to calculate
  the minimum number of newlines that should come before this cluster.
  Append that number of newlines *minus* the number of newlines already
  appended, with a minimum of one.

- Then for each cluster, iterate through each word in it. Divide each
  word's x0, minus `x_shift`, by `x_density` to calculate the minimum
  number of characters that should come before this cluster.  Append that
  number of spaces *minus* the number of characters and spaces already
  appended, with a minimum of one. Then append the word's text.

- At the termination of each line, add more spaces if necessary to
  mimic `layout_width`.

- Finally, add newlines to the end if necessary to mimic to
  `layout_height`.

For other line/character directions (e.g., bottom-to-top,
right-to-left), these steps are adjusted.
rR   rS   z;`layout_width` and `layout_width_chars` cannot both be set.z=`layout_height` and `layout_height_chars` cannot both be set.Nc                 "   < S! V ^ ,          4      # r   r*   r,   line_cluster_keys   &r$   r-   $WordMap.to_textmap.<locals>.<lambda>U  s    3CAaD3Ir&   keyc                 "   < S! V ^ ,          4      # r   r*   r   s   &r$   r-   r   Z  s    &qt,r&   )preserve_orderr`   c                 "   < S! V ^ ,          4      # r   r*   )r,   char_sort_keys   &r$   r-   r   z  s    }QqT7Jr&   r   )ra   Nrn   )r`   N)rt   rQ   rO   	LIGATURESrK   r   roundr8   rB   rI   BBOX_ORIGIN_KEYSsortedr   	enumeraters   ru   appendminget)4rZ   r   r   r   r   r   r   r   r   r   r   r   r!   r:   r   r   rS   rR   r   r   r   _textmap
expansions
blank_linenum_newlinesline_position_keychar_position_keyy_originx_originwords_sorted_line_dirtuples_by_linerg   line_tuplesline_position
y_dist_rawadjy_distnum_newlines_prependline_lenline_tuples_sortedwordr   char_position
x_dist_rawx_distnum_spaces_prependr   lettersletternum_newlines_appendr   r   s4   &&&&&&&&&&&&&&&&&&&&&                             @@r$   
to_textmapWordMap.to_textmap   s   l 794;; / ; ;8 / ; ;8  #3Y
!$U   
 &)|/G)H%I"" $W  !
 '*%0I*J&K#%);;JJ/9)(3)(3)(3#H-k:#H-k: M KK)IJ 	 )!,$55	
 (7NA{ 1+a.2C D*h.@A
$6bA#c)I5#&AE
f,	$  /08}}Q4(?
*H- 1
 00LH  K-JK   2e$5d$;M!.(W2D!EJ (N :"C'#-	9FF%(Q)95=8;S%T"[M,>>>..A(nnQvY&	BG") 4 A #*   2( v[M-?(-JKKg 8l "59I"J./q5
*H- 0 ||+#CR=+77x+77x
 	
r&   r   )r   r   r   r   )r   r   r   r   r   r[   DEFAULT_X_DENSITYDEFAULT_Y_DENSITYDEFAULT_Y_TOLERANCEDEFAULT_LINE_DIRDEFAULT_CHAR_DIRr   r   r   r   s   @r$   r   r      sd      
  "##$*,,0**,0,0+/+/#!%+s
 s
 s
r&   r   c                      a  ] tR tRt o ]]RRRRRR]]RRRRR3V 3R lR lltV 3R lR lt	V 3R	 lR
 lt
V 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltV 3R lR ltRV 3R lR lltRtV tR# )WordExtractori  NFTc                   < V ^8  d   QhRS[ RS[ RS[S[S[R3,          RS[S[S[R3,          RS[RS[RS[R	S[R
S[RS[RS[S[,          RS[S[,          RS[S[S[,          ,          RS[S[S[3,          RS[/# )r    x_tolerancer   x_tolerance_ratioNy_tolerance_ratiokeep_blank_charsr   vertical_ttbhorizontal_ltrr!   r:   r   r   extra_attrssplit_at_punctuationr   )	r   r   r   floatr   r   r
   r   rE   )r#   rT   s   "r$   r%   WordExtractor.__annotate__  s     4@ 4@4@ 4@ !eT!12	4@
 !eT!124@ 4@ 4@ 4@ 4@ 4@ 4@ #5/4@ #5/4@ d3i(4@ $D#I.4@  !4@r&   c                P   Wn         W n        W0n        W@n        WPn        W`n        Wn        Wpn        VR J d   \        P                  R4       VR J d   \        P                  R4       Wn
        Wn        T;'       g    T
V n        T;'       g    T	V n        \        V P                  V P                  4       \        V P                  V P                  R4       Vf   . MTV n        VRJ d   \         P"                  MT;'       g    RV n        V'       d   \&        V n        R# / V n        R# )FzNvertical_ttb is deprecated and will be removed; use line_dir/char_dir instead.zPhorizontal_ltr is deprecated and will be removed; use line_dir/char_dir instead._rotatedNTr_   )r  r   r  r  r  r   r  r  loggerwarningr!   r:   r   r   rM   r  stringpunctuationr	  r   r   )rZ   r  r   r  r  r  r   r  r  r!   r:   r   r   r  r	  r   s   &&&&&&&&&&&&&&&&r$   r[   WordExtractor.__init__  s   $ '&!2!2 0*,(5 NN2 U"NN2 !  0 < <H 0 < <HDMM4==9D1143H3H*U!,!42+
 $t+ &,," 	! (8)Rr&   c                &   < V ^8  d   QhRS[ RS[/# )r    uprightr"   )r   r   )r#   rT   s   "r$   r%   r    s     
C 
CC 
CE 
Cr&   c                    V'       g   V P                   '       g   R # V'       d   V P                  '       g   R# V'       d   V P                  # V P                  # rn   )r  r  r:   r   )rZ   r  s   &&r$   get_char_dirWordExtractor.get_char_dir  s=     t000T000 't}}BT-B-BBr&   c                &   < V ^8  d   QhRS[ RS[/# )r    ordered_charsr"   )r   r   )r#   rT   s   "r$   r%   r    s        r&   c                |  a  \        V4      w  r#rEV^ ,          R,          V^ ,          R,          ,
          pV^ ,          R,          pS P                  V4      pRRP                  V 3R lV 4       4      RVRVRVRW6,           R	VRVR
WS,
          RWB,
          RV/
p	S P                   F  p
V^ ,          V
,          W&   K  	  V	# )r   doctopr)   r  r   r_   c              3   x   <"   T F/  pSP                   P                  VR ,          VR ,          4      x  K1  	  R# 5ir   N)r   r   )re   r   rZ   s   & r$   rh   ,WordExtractor.merge_chars.<locals>.<genexpr>  s0      CPa##AfIqy99=s   7:r4   r7   r1   r?   width	direction)r   r  rk   r  )rZ   r  r4   r)   r7   r1   
doctop_adjr  r:   r   r   s   f&         r$   merge_charsWordExtractor.merge_chars  s    -m<"1%h/-2B52II
"9-$$W- BGG CP  ""3c&fwflRW
 ##C%a(-DI $ r&   c                >   < V ^8  d   QhRS[ RS[ RS[RS[RS[RS[/# )r    	prev_char	curr_charr   r  r   r"   )r   r   r   r   )r#   rT   s   "r$   r%   r    sO     K
 K
K
 K
 	K

 K
 K
 
K
r&   c                   VR9   dY   TpTpVR,          pVR,          p	VR8X  d   VR,          p
VR,          pVR,          pMvVR,          ) p
VR,          ) pVR,          ) pMWTpTpVR,          pVR,          p	VR8X  d   VR,          p
VR,          pVR,          pMVR,          ) p
VR,          ) pVR,          ) p\        W8  ;'       g(    WV,           8  ;'       g    \        W,
          4      V8  4      # )a  This method takes several factors into account to determine if
`curr_char` represents the beginning of a new word:

- Whether the text is "upright" (i.e., non-rotated)
- Whether the user has specified that horizontal text runs
  left-to-right (default) or right-to-left, as represented by
  self.horizontal_ltr
- Whether the user has specified that vertical text the text runs
  top-to-bottom (default) or bottom-to-top, as represented by
  self.vertical_ttb
- The x0, top, x1, and bottom attributes of prev_char and
  curr_char
- The self.x_tolerance and self.y_tolerance settings. Note: In
  this case, x/y refer to those directions for non-rotated text.
  For vertical text, they are flipped. A more accurate terminology
  might be "*intra*line character distance tolerance" and
  "*inter*line character distance tolerance"

An important note: The *intra*line distance is measured from the
*end* of the previous character to the *beginning* of the current
character, while the *inter*line distance is measured from the
*top* of the previous character to the *top* of the next
character. The reasons for this are partly repository-historical,
and partly logical, as successive text lines' bounding boxes often
overlap slightly (and we don't want that overlap to be interpreted
as the two lines being the same line).

The upright-ness of the character determines the attributes to
compare, while horizontal_ltr/vertical_ttb determine the direction
of the comparison.
r   r)   r4   r7   r   r1   )r   r5   )r   abs)rZ   r%  r&  r   r  r   r,   yaycyaxbxcxs   &&&&&&       r$   char_begins_new_word"WordExtractor.char_begins_new_word  s   R &AA5!B5!BE!t_t_t_o%o%o% AA4B4BE!u%x(u%))&&))W    !V    27|a
 	
r&   c          	      B   < V ^8  d   QhRS[ RS[RS[S[RR3,          /# )r    r  r   r"   N)r   r   r   r   )r#   rT   s   "r$   r%   r  Q  s5     . .!. . 
:tT)	*	.r&   c           
   #    a
"   . o
R  V
3R llpV P                   pV P                  pV P                  pV P                  pV F  pVR,          p	V P                  '       g)   V	P                  4       '       d   V! R4       Rj  xL
  KF  WP                  9   d#   V! V4       Rj  xL
  V! R4       Rj  xL
  Kx  S
'       dl   T P                  S
R,          TTVf   TMVS
R,          R,          ,          Vf   TMVS
R,          R,          ,          R7      '       d   V! V4       Rj  xL
  K  S
P                  V4       K  	  S
'       d   S
x  R# R#  L L L L15i)c                b    V ^8  d   QhR\         \        ,          R\        \        RR3,          /# )r    new_charr"   N)r
   r   r   r   )r#   s   "r$   r%   7WordExtractor.iter_chars_to_words.<locals>.__annotate__X  s0     	B 	Buo	Bz4-.	Br&   c              3   >   <"   S'       d   Sx  V f   . oR # V .oR # 5ird   r*   )r4  current_words   &r$   start_next_word:WordExtractor.iter_chars_to_words.<locals>.start_next_wordX  s!     
 ""!)!12LzLs   r   Nsize)r  r   r   )	r  r  r   r  r  isspacer	  r/  r   )rZ   r  r   r8  xtxtrytytrcharr   r7  s   &&&       @r$   iter_chars_to_words!WordExtractor.iter_chars_to_wordsQ  s@    
 $&	B 	B $$$$!D<D(((T\\^^*4000222*4000*4000$";";R #&;RC,r:J6:R4R#&;RC,r:J6:R4R #< # # +4000 ##D)) ".  ' 1 10 1sa   A1E5E E!E"E#E2E3EAEE%E&"E		EEEEc                R   < V ^8  d   QhRS[ RS[S[S[S[3,          RR3,          /# r    r   r"   N)r   r   r   r   r   )r#   rT   s   "r$   r%   r    s3     + ++	5U*+T47	8+r&   c              #  Z  "   \        V4      pV^ ,          R,          pV'       d   V P                  MV P                  pV P                  V4      p\	        V4      p\        V4      p\        TTVR9   d   V P                  MV P                  4      pV F  p\        WR7      p	W3x  K  	  R# 5i)r   r  r   Nr   r/   )
rq   r!   r   r  r8   rB   r   r   r  r   )
rZ   r   r  r!   r:   r   r   subclustersscchars_sorteds
   &&        r$   iter_chars_to_lines!WordExtractor.iter_chars_to_lines  s      U(9%$+4==1F1F$$W-/9)(3 &!)^!;TAQAQ
 B!"8L** s   B)B+c                R   < V ^8  d   QhRS[ RS[S[S[S[3,          RR3,          /# rD  )r   r   r   r   r   )r#   rT   s   "r$   r%   r    s7     E EE	5
*+T47	8Er&   c              #  P  "   \        R .V P                  O5!  p\        P                  ! W4      pV Fn  w  rEV P                  '       d   WPP
                  3.MV P                  V4      pV F2  w  rxV P                  Wx4       F  p	V P                  V	4      V	3x  K  	  K4  	  Kp  	  R# 5i)r  N)	r   r  	itertoolsgroupbyr   r:   rJ  rA  r"  )
rZ   r   grouping_keygrouped_charskeyvals
char_groupline_groups
line_charsr   
word_charss
   &&        r$   iter_extract_tuples!WordExtractor.iter_extract_tuples  s      ")?d.>.>?!))%>#0G %%% mm,---j9 
 *5%
"&":"::"QJ++J7DD #R *5 $1s   B$B&c                &   < V ^8  d   QhRS[ RS[/# )r    r   r"   )r   r   )r#   rT   s   "r$   r%   r    s     > >Z >G >r&   c                H    \        \        V P                  V4      4      4      # rd   )r   rq   rW  )rZ   r   s   &&r$   extract_wordmapWordExtractor.extract_wordmap  s    tD44U;<==r&   c                ,   < V ^8  d   QhRS[ RS[RS[ /# )r    r   r   r"   )r   r   )r#   rT   s   "r$   r%   r    s*     	V 	V	V/3	V		Vr&   c                    V'       d"   \        R  V P                  V4       4       4      # \        R V P                  V4       4       4      # )c              3   6   "   T F  w  r/ VCR V/Cx  K  	  R# 5i)r   Nr*   re   r   rV  s   &  r$   rh   .WordExtractor.extract_words.<locals>.<genexpr>  s&      (G$D .4-*-(Gs   c              3   *   "   T F	  w  rVx  K  	  R # 5ird   r*   r`  s   &  r$   rh   ra    s     U5T!15Ts   )rq   rW  )rZ   r   r   s   &&&r$   extract_wordsWordExtractor.extract_words  sJ      (,(@(@(G  
 UT5M5Me5TUUUr&   )r:   r   r   r  r  r  r!   r   r	  r   r  r  r  r   r  F)r   r   r   r   DEFAULT_X_TOLERANCEr   r   r   r[   r  r"  r/  rA  rJ  rW  r[  rc  r   r   r   s   @r$   r   r     s      105959!&#!#**,0,0+/16!%!4@ 4@l
C 
C 4K
 K
Z. .`+ +.E E > >	V 	V 	Vr&   r   c                H    V ^8  d   QhR\         R\        R\        R\         /# )r    r   r   kwargsr"   )r   r   r   )r#   s   "r$   r%   r%     s2     F FF%)F=@FFr&   c                 6    \        R/ VB P                  W4      # )Nr*   )r   rc  )r   r   rh  s   &&,r$   rc  rc    s     "6"00EEr&   c                <    V ^8  d   QhR\         R\        R\        /# )r    r   rh  r"   )r   r   rO   )r#   s   "r$   r%   r%     s!      J # ' r&   c           
      p   TP                  R RRVP                  R4      ;'       g    \        V 4      /4       \        R/ \         Uu/ uF  q"V9   g   K  W!V,          bK  	  upB pVP                  V 4      pVP                  ! R/ \         Uu/ uF  q"V9   g   K  W!V,          bK  	  upB pV# u upi u upi )r   Tr   r*   )updater   r   r   WORD_EXTRACTOR_KWARGSr[  r   TEXTMAP_KWARGS)r   rh  k	extractorwordmaptextmaps   &,    r$   chars_to_textmaprs    s    
MM6::m4NN8N	
  !6
F!6Av+<1Qi<!6
FI ''.G   !/
?A;<1Qi<
?G N G @s   B.B.B3B3c          
          V ^8  d   QhR\         R\        \        ,          R\        \        ,          R\        R\        /# )r    r   rR   rS   rh  r"   )r   r
   r   r   rE   )r#   s   "r$   r%   r%     sB     - --e_- e_- 	-
 	-r&   c           
         \        V 4      p \        V 4      ^ 8X  d   R# VP                  R4      '       d!   / VCRVRV/Cp\        V 3/ VB P                  # \        R/ \         Uu/ uF  qUV9   g   K  WSV,          bK  	  upB pVP                  V 4      pT;'       g    VP                  pT;'       g    VP                  p\        VP                  4      pVP                  R\        4      p	VP                  R\        4      p
\        TTVR9   d   T
MT	4      p\        RP                  R V 4       4       Uu. uF  pVR	3NK	  	  upVVR
7      P                  # u upi u upi )r   r_   r   rR   rS   r  r   r`   c              3   R   "   T F  pR P                  R V 4       4      x  K  	  R# 5i)ra   c              3   2   "   T F  qR ,          x  K  	  R# 5ir  r*   )re   r   s   & r$   rh   )extract_text.<locals>.<genexpr>.<genexpr>  s     &EF||s   Nrj   )re   rf   s   & r$   rh   extract_text.<locals>.<genexpr>  s$     XRW$chh&E&EEERWs   %'Nr   r*   rF  )r   rt   r   rs  rY   r   rm  rc  r!   r:   r8   rf  r   r   rO   rk   )r   rR   rS   rh  textmap_kwargsro  rp  wordsr   r  r   rl   r@  s   &&&,         r$   extract_textr|    sy    ENE
5zQzz(

 /3DoV
  88BBB! 
%:J%:6k|q)|%:J
	 ''.)??Y-?-?)??Y-?-?/	0B0BCjj0CDjj0CD*n<K+
  IIXRWXX Y  tX ,+	
 )		% K&s   $E1E6Ec                <    V ^8  d   QhR\         R\        R\        /# )r    rU  	tolerancer"   r   r   rE   )r#   s   "r$   r%   r%     s&       	r&   c                     R pRp\        V \        R4      R7       F<  pVe   VR,          W1,           8  d
   VR,          pVR,          pW$R,          ,          pK>  	  V# )r_   Nr4   r   ra   r7   r   )r   r   )rU  r~  colllast_x1r@  s   &&   r$   collate_liner    s]     DGzz$'78d4jG4G&HCKDt*V	 9
 Kr&   c                H    V ^8  d   QhR\         R\        R\        R\        /# )r    r   r  r   r"   r  )r#   s   "r$   r%   r%     s6     F FFF F 		Fr&   c                 f   a \        V \        R 4      V4      pRP                  V3R lV 4       4      # )r  r`   c              3   <   <"   T F  p\        VS4      x  K  	  R # 5ird   )r  )re   r   r  s   & r$   rh   &extract_text_simple.<locals>.<genexpr>  s     E9a\![119s   )r   r   rk   )r   r  r   	clustereds   &f& r$   extract_text_simpler    s-    
  z(';[II99E9EEEr&   c          	      x    V ^8  d   QhR\         R\        R\        \        \        R3,          ,          R\         /# )r    r   r~  r  .r"   )r   r   r
   r   rE   )r#   s   "r$   r%   r%     s=     , ,,, %S/*, 	,r&   c                   aaa \        . ROT;'       g    \        4       O5!  o\        RR4      oR VVV3R llpV! V 4      p\        W@P                  R7      # )u   
Removes duplicate chars — those sharing the same text and positioning
(within `tolerance`) as other characters in the set. Use extra_args to
be more restrictive with the properties shared by the matching chars.
r  r4   c                L    V ^8  d   QhR\         R\        \        RR3,          /# rD  )r   r   r   )r#   s   "r$   r%   "dedupe_chars.<locals>.__annotate__'  s&     	< 	<* 	<5$;L1M 	<r&   c              3     <"   \        V SR 7      p\        P                  ! VSR 7       F^  w  r#\        \	        V4      \        R4      S4       F6  p\        V\        R4      S4       F  p\        VSR 7      ^ ,          x  K  	  K8  	  K`  	  R# 5i)r   r  r4   N)r   rN  rO  r   rq   r   )	r   sorted_charsgrp	grp_chars	y_cluster	x_clusterr   pos_keyr~  s	   &     r$   yield_unique_chars(dedupe_chars.<locals>.yield_unique_chars'  s|     e-'//#FNC,YH!5y	 "1z$/"I !8;;" Gs   B
Br   )r  r   )r   tupler   index)r   r~  r  r  dedupedr   r  s   &f&  @@r$   dedupe_charsr    sS     
E)
E[-C-CEG
EC4(G	< 	< !'G'{{++r&   c                h    V ^8  d   Qh/ ^ \         9   d
   \        ;R&   ^\         9   d
   \        ;R&   # )r    r   r   )__conditional_annotations__r   )r#   s   "r$   r%   r%      s*    <   % = >   % ? r&   )r_   re  )NN)   )fontnamer:  )?r  inspectrN  loggingr   r  operatorr   typingr   r   r   r   r   r	   r
   r   r   r   _typingr   r   r   r   r   r   
clusteringr   genericr   geometryr   	getLoggerr   r  rf  r   r   r   r   r   r   r8   rB   r   rI   rM   rO   r   r   rc  	signaturer   
parametersrJ   rn  rm  rs  r|  r  r  r  r%   )r  s   @r$   <module>r     s      	     J I '  %			8	$         
4	5	5	4	4	4	4	 
:a=	:a=	:a=	:a=	  
:e	:h	:d	:d	
"G
 G
T{
 {
|MV MV`F ""7#5#56AAFFH))-8CCHHJ $-d +  -,F, ,r&   