ó
    EñiUt ã            !       ó2  • S r SSKrSSKrSSKrSSKrSSKJr  SSKJr  SSK	J
r
  SSKrSSKrSSKJr  / r/ rSr\R"                  r\R&                  rS\R*                  -  \R,                  -  \R.                  -  \R0                  -  rS\R.                  -  \R4                  -  \R6                  -  \R0                  -  r\" \R<                  5      rS r S r!S	 r"S
\#4S jr$S r%S r&SpS jr' " S S\(5      r)/ SQr*/ SQr+\)" S5      r,Sr-Sr.Sr/Sr0Sr1Sr2Sr3Sr4\
" SSSS5      r5SSSSSS S S!.r6S
\74S" jr8 " S# S$5      r9 " S% S&5      r: " S' S(5      r;S)\7S
\74S* jr<\Rz                  " \:R|                  5      R~                  R�                  5       rA\Rz                  " \;5      R~                  R�                  5       rBS)\7S
\94S+ jrCS)\7S
\D4S, jrE\14S-\7S
\D4S. jjrFSqS)\7S
\74S/ jjrGS0 rHS
\74S1 jrIS
\74S2 jrJS
\74S3 jrK   SrS
\74S4 jjrLSsS
\74S5 jjrMS
\N4S6 jrOS
\74S7 jrPS8\D4S9 jrQS:\DS
\74S; jrR\-\-4S< jrSS=\D4S> jrT\.4S?\D4S@ jjrUSA rVS
\N4SB jrWS
\N4SC jrXSD rYSE rZ\04SF\[4SG jjr\SH r]\/4SF\[4SI jjr^StS
\N4SJ jjr_SK r`SL raS
\74SM jrb " SN SO5      rc " SP SQ\c5      rd " SR SS5      re " ST SU5      rf\ " SV SW5      5       rg " SX SY5      rh SuSZ jriSvS[ jrjS\ rkS] rlSS^S^SS\-SS\.SSS\/\0SSSSSSSSSS4S_\DS`\DSa\7Sb\7Sc\(Sd\(Se\(Sf\(Sg\(Sh\(Si\(Sj\(Sk\(Sl\(Sm\(Sn\(4 So jjrmg)waë  
Copyright (C) 2023 Artifex Software, Inc.

This file is part of PyMuPDF.

PyMuPDF is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.

PyMuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.

You should have received a copy of the GNU Affero General Public License
along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>

Alternative licensing terms are available from the licensor.
For commercial licensing, see <https://www.artifex.com/> or contact
Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
CA 94129, USA, for further information.

---------------------------------------------------------------------
Portions of this code have been ported from pdfplumber, see
https://pypi.org/project/pdfplumber/.

The ported code is under the following MIT license:

---------------------------------------------------------------------
The MIT License (MIT)

Copyright (c) 2015, Jeremy Singer-Vine

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------------------
Also see here: https://github.com/jsvine/pdfplumber/blob/stable/LICENSE.txt
---------------------------------------------------------------------

The porting mainly pertains to files "table.py" and relevant parts of
"utils/text.py" within pdfplumber's repository on Github.
With respect to "text.py", we have removed functions or features that are not
used by table processing. Examples are:

* the text search function
* simple text extraction
* text extraction by lines

Original pdfplumber code does neither detect, nor identify table headers.
This PyMuPDF port adds respective code to the 'Table' class as method '_get_header'.
This is implemented as new class TableHeader with the properties:
* bbox: A tuple for the header's bbox
* cells: A tuple for each bbox of a column header
* names: A list of strings with column header text
* external: A bool indicating whether the header is outside the table cells.

é    N)ÚSequence)Ú	dataclass)Ú
itemgetter)Úmupdfc                 ó†   •  U S   US   :¬  =(       a/    U S   US   :¬  =(       a    U S   US   :*  =(       a    U S   US   :*  $ )zBCheck whether rectangle 'inner' is fully inside rectangle 'outer'.é   r   é   é   © )ÚinnerÚouters     ÚJ/home/mande/repo/quber/.venv/lib/python3.13/site-packages/pymupdf/table.pyÚrect_in_rectr   s   s_   € ð	!Ø�!‰H˜˜a™Ñ ÷	!à�!‰H˜˜a™Ñ ÷	!ð �!‰H˜˜a™Ñ ÷	!ð �!‰H˜˜a™Ñ ðó    c                 ó.   ^• [        U4S jU  5       5      $ )zCCheck whether any of the chars in CHAR are inside rectangle 'rect'.c              3   ó¨   >#   • U  HG  n TS   US   :*  =(       a/    US   TS   :*  =(       a    TS    US   :*  =(       a    TS   US   :¬  v •  MI     g7f)	r   r   Úx0Úx1r	   Úy0r
   Úy1Nr   )Ú.0ÚcÚrects     €r   Ú	<genexpr>Ú chars_in_rect.<locals>.<genexpr>€   st   øé € ð ò ˆAð	Ø�‰G�q˜‘wÑ÷	àˆd‰G�t˜A‘wÑ÷	ð �‰G�q˜‘wÑ÷	ð �‰G�q˜‘wÑô		ò
 ùs   ƒAA©Úany)ÚCHARSr   s    `r   Úchars_in_rectr   ~   s   ø€ äô ñ óó ð r   c           	      óF  • [        S[        U S   US   5      [        U S   US   5      -
  5      n[        S[        U S   US   5      [        U S   US   5      -
  5      nX#-  nU(       d  gU S   U S   -
  U S   U S   -
  -  nUS   US   -
  US   US   -
  -  nXEU-   U-
  -  $ )z2Compute intersection over union of two rectangles.r   r	   r
   r   ©ÚmaxÚmin)Úr1Úr2ÚixÚiyÚintersectionÚarea1Úarea2s          r   Ú_iour+   Š   sÃ   € ä	ˆQ”�B�q‘E˜2˜a™5Ó!¤C¨¨1©¨r°!©uÓ$5Ñ5Ó	6€BÜ	ˆQ”�B�q‘E˜2˜a™5Ó!¤C¨¨1©¨r°!©uÓ$5Ñ5Ó	6€BØ‘7€LÞØØ�‰U�R˜‘U‰]˜r !™u r¨!¡u™}Ñ-€EØ�‰U�R˜‘U‰]˜r !™u r¨!¡u™}Ñ-€EØ 5™=¨<Ñ7Ñ8Ð8r   Úreturnc                 ó2   ^ ^• [        U U4S jU 5       5      $ )zMCheck whether any of the words in bbox are cut through by
horizontal line y.
c              3   óœ   >#   • U  HA  n[        UT5      (       d  M  UR                  Ts=:  =(       a    UR                  :  Os  v •  MC     g 7f©N)r   r   r   )r   ÚrÚbboxÚys     €€r   r   Ú%intersects_words_h.<locals>.<genexpr>š   s0   øé € ÐLª
 1´lÀ1Àd×6K‹ˆq�t‰t�a�‹˜!Ÿ$™$�‰ª
ùs
   ƒAœ0Ar   )r1   r2   Ú
word_rectss   `` r   Úintersects_words_hr5   –   s   ù€ ô ÕL©
ÓLÓLÐLr   c                 ór   • 0 n[         R                  R                  U R                  R                  X!5        U$ )zAExtract MuPDF table structure information from a given rectangle.)ÚpymupdfÚextraÚmake_table_dictÚthisÚ
m_internal)Útextpager   Ú
table_dicts      r   Úget_table_dict_from_rectr>   �   s+   € à€JÜ‡M�M×!Ñ! (§-¡-×":Ñ":¸JÔMØÐr   c           
      óØ  ^• / n[        X5      nUR                  S5      [        R                  :w  a  U$ [        R
                  " US   5      n[        US   S S9n[        US   S S9nUS   u  p‰/ n
U HI  u  p¼US	:”  a  M  [        X[U5      (       a  M   U
(       a  XºS
   -
  S:  a  XºS
'   M8  U
R                  U5        MK     [        S	[        [        U
5      S-
  S-  5      5      n	U Vs/ s H  oÝS   U	::  d  M  US	   PM     nnUR                  US
   S-   :”  a  UR                  UR                  5        [        [        U
5      S-
  5       GH
  n[        R
                  " UR                  X¯   UR                  X¯S-      5      n[        U Vs/ s H  n[        UU5      (       d  M  UPM     snS S9nU V^s/ s H!  m[!        U4S jU 5       5      (       a  M  TPM#     nn[        [        U5      S-
  5       HY  n[        R
                  " UU   X¯   UUS-      X¯S-      5      nUR"                  (       a  M?  UR                  [%        U5      5        M[     GM     U$ s  snf s  snf s  snf )z0Detect table structure within a given rectangle.Útyper1   Úxposc                 ó   • U S   $ ©Nr   r   ©Úxs    r   Ú<lambda>Ú&make_table_from_bbox.<locals>.<lambda>°   ó   € ¨q°ªtr   ©ÚkeyÚyposc                 ó   • U S   $ rC   r   )r2   s    r   rF   rG   ±   rH   r   Úmax_uncertainr   éÿÿÿÿr
   r	   gffffffÖ?r   c                 ó   • U R                   $ r/   )r   ©r0   s    r   rF   rG   Ó   s   € ÈqÏtÊtr   c              3   ót   >#   • U  H-  oR                   Ts=:  =(       a    UR                  :  Os  v •  M/     g 7fr/   ©r   r   )r   r0   rE   s     €r   r   Ú'make_table_from_bbox.<locals>.<genexpr>Ö   s#   øé € Ð0TÊ)ÀQ·±¸·³¸A¿D¹D·±Ê)ùs   ƒ58)r>   Úgetr   ÚFZ_STEXT_BLOCK_GRIDr7   ÚRectÚsortedr5   Úappendr"   ÚroundÚlenr   Úranger   r   r   Úis_emptyÚtuple)r<   r4   r   ÚcellsÚblockr1   rA   rK   ÚxmaxuÚymaxuÚnyposr2   ÚyuncrE   ÚnxposÚiÚrow_boxr0   Ú	row_wordsÚ	this_xposÚjÚcells                `        r   Úmake_table_from_bboxrk   ¤   s$  ø€ à€Eô % XÓ4€Eà‡y�y�ÓœE×5Ñ5Ó5ØˆÜ�<Š<˜˜f™Ó&€Dô �%˜‘-¡^Ñ4€DÜ�%˜‘-¡^Ñ4€Dð ˜Ñ)�L€Eð €EÛ‰ˆØ�!‹8ÙÜ˜d z×2Ñ2ÙÞ�a ™)‘m aÓ'Ø�"‹Ià�L‰L˜ŽOñ ô �”5œ#˜e›* q™.¨DÑ0Ó1Ó2€Eñ  Ó1š4�a Q¡4¨5¡=‹TˆQˆqŒT™4€EÐ1Ø‡w�w��r‘˜Q‘ÓØ�‰�T—W‘WÔô ”3�u“: ‘>×"ˆÜ—,’,˜tŸw™w¨©°$·'±'¸5ÀQÁ¹<ÓHˆäÙ"Ó?š
�1¤l°1°g×&>�Q™
Ñ?Á^ñ
ˆ	ñ !&ÔU¢˜1¬SÔ0TÉ)Ó0T×-T—Q¡ˆ	ÐUÜ”s˜9“~¨Ñ)Ö*ˆAÜ—<’< 	¨!¡¨e©h¸	À!ÀaÁ%Ñ8HÈ%ÐTUÑPUÉ,ÓWˆDØ—=—=‘=Ø—‘œU 4›[Ö)ô +ñ #ð €Lùò% 2ùò @ùò Vs$   Ã)IÃ9	IÆI"
Æ&I"
Æ8I'ÇI'c           	      óT  • SnU R                  5       S    GH  nUS   S:w  a  M  US   n US   US   :”  d$  US   US   :  d  US   US   :”  d  US   US   :  a  MG  US	    GH.  nUS   n US   US   :”  d$  US   US   :  d  US   US   :”  d  US   US   :  a  M<  U(       a  X2(       a  S
OS-  nUS   S:H  =(       d    US   S:H  nUS    GH½  n	U	S   n
 U
S   US   :”  d$  U
S   US   :  d  U
S   US   :”  d  U
S   US   :  a  M<  SnU	S    HU  nUS   n[        R                  " US   5      n[        Xá-  5      S[        U5      -  :”  a  X½-  nMD  U[        ;   d  MP  US-  nMW     U(       d  M¥  U(       d  X;-  nM²  SnSnU(       a  U	S   [
        -  (       a
  US-  nSU-   nU	S   [        -  (       a
  US-  nSU-   nU	S   [        R                  -  (       a
  US-  nSU-   nU	S   [        R                  -  (       a
  US-  nSU-   n[        U	S   5      S:”  a  UR                  5       n[        U5      =n(       a%  UR                  U5      (       a  USU*  U-   U-   nGM–  UR                  5       (       d  US-  nGM³  X?U-   U-   -  nGMÀ     GM1     GM‚     UR                  5       $ )a  Extract text from a rect-like 'cell' as plain or MD styled text.

This function should ultimately be used to extract text from a table cell.
Markdown output will only work correctly if extraction flag bit
TEXT_COLLECT_STYLES is set.

Args:
    textpage: A PyMuPDF TextPage object. Must have been created with
        TEXTFLAGS_TEXT | TEXT_COLLECT_STYLES.
    cell: A tuple (x0, y0, x1, y1) defining the cell's bbox.
    markdown: If True, return text formatted for Markdown.

Returns:
    A string with the text extracted from the cell.
Ú Úblocksr@   r   r1   r	   r   r
   Úlinesú<br>Ú
Údir)r   r   )r   r   ÚspansÚcharsr   g      à?Ú Ú
char_flagsz~~z**ÚflagsÚ_Ú`N)ÚextractRAWDICTr7   rV   ÚabsÚwhite_spacesÚTEXT_STRIKEOUTÚ	TEXT_BOLDÚTEXT_FONT_ITALICÚTEXT_FONT_MONOSPACEDrZ   ÚrstripÚendswithÚstrip)r<   rj   ÚmarkdownÚtextr_   Ú
block_bboxÚlineÚlbboxÚ
horizontalÚspanÚsbboxÚ	span_textÚcharÚ	this_charr1   ÚprefixÚsuffixÚlss                     r   Úextract_cellsr’   ß   sþ  € ð  €DØ×(Ñ(Ó*¨8Õ4ˆØ�‰=˜AÓÙØ˜6‘]ˆ
àØ˜!‰}˜t A™wÓ&Ø˜!‰}˜t A™wÓ&Ø˜!‰}˜t A™wÓ&Ø˜!‰}˜t A™wÓ&áØ˜'•NˆDØ˜‘LˆEàØ˜‘8˜d 1™gÓ%Ø˜‘8˜d 1™gÓ%Ø˜‘8˜d 1™gÓ%Ø˜‘8˜d 1™gÓ%áæØ¥(™°Ñ4�ð ˜e™¨Ñ.×G°$°u±+ÀÑ2GˆJà˜W��Ø˜V™�àØ˜Q‘x $ q¡'Ó)Ø˜Q‘x $ q¡'Ó)Ø˜Q‘x $ q¡'Ó)Ø˜Q‘x $ q¡'Ó)áð �	Ø  œM�DØ $ S¡	�IÜ"Ÿ<š<¨¨V©Ó5�DÜ˜4™;Ó'¨#´°D³	©/Ó9Ø!Ñ.š	Ø"¤lÕ2Ø! SÑ(š	ñ *ö !ÙæØÑ%�DÙà�Ø�Þ $ |Ñ"4´~×"EØ˜d‘N�FØ! F™]�FØ˜Ñ%¬	×1Ø˜d‘N�FØ! F™]�FØ˜‘=¤7×#;Ñ#;×;Ø˜c‘M�FØ  6™\�FØ˜‘=¤7×#?Ñ#?×?Ø˜c‘M�FØ  6™\�Fä�t˜G‘}Ó%¨Ó)Ø )× 0Ñ 0Ó 2�Iô ˜f›+Ð%�BÕ%¨4¯=©=¸×+@Ñ+@Ø  " ˜:¨	Ñ1°FÑ:“Dà$Ÿ?™?×,Ñ,Ø ™›à¨Ñ 2°VÑ ;Ñ;›ôk &ô# #ñ 5ðh �:‰:‹<Ðr   c                   ó   • \ rS rSrSrg)Ú
UnsetFloatiL  r   N©Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__static_attributes__r   r   r   r”   r”   L  ó   † Úr   r”   )Úsnap_toleranceÚsnap_x_toleranceÚsnap_y_toleranceÚjoin_toleranceÚjoin_x_toleranceÚjoin_y_toleranceÚedge_min_lengthÚmin_words_verticalÚmin_words_horizontalÚintersection_toleranceÚintersection_x_toleranceÚintersection_y_tolerance)ro   Úlines_strictr…   Úexplicitr
   r   g      @é   r   Útopr   ÚbottomÚffÚffiÚfflÚfiÚflÚst)u   ï¬€u   ï¬ƒu   ï¬„u   ï¬�u   ï¬‚u   ï¬†u   ï¬…c                 óÎ   • [        U [        5      (       a  U $ [        U [        5      (       a  [        U 5      $ [        U S5      (       a  U R	                  S5      nU$ [        U 5      $ )NÚto_dictÚrecords)Ú
isinstanceÚlistr   Úhasattrr´   )Ú
collectionÚress     r   Úto_listr»   x  sZ   € Ü�*œd×#Ñ#ØÐÜ	�J¤×	)Ñ	)Ü�JÓÐÜ	�˜Y×	'Ñ	'Ø× Ñ  Ó+ˆØˆ
ä�JÓÐr   c            	       óJ   • \ rS rSrSrSSS jjr   SS\S\S\S\4S	 jjr	S
r
g)ÚTextMapi„  zŠ
A TextMap maps each unicode character in the text to an individual `char`
object (or, in the case of layout-implied whitespace, `None`).
Nr,   c                 ób   • Xl         SR                  [        [        S5      U5      5      U l        g )Nrm   r   )ÚtuplesÚjoinÚmapr   Ú	as_string©Úselfr¿   s     r   Ú__init__ÚTextMap.__init__Š  s"   € ØŒØŸ™¤¤Z°£]°FÓ!;Ó<ˆ�r   Ú
main_groupÚreturn_groupsÚreturn_charsc                 ó6  • U R                   UR                  U5      UR                  U5       nU VVs/ s H  u  pgUc  M
  UPM     nnn[        U5      u  pšp¼UR	                  U5      U	U
UUS.nU(       a  UR                  5       US'   U(       a  X�S'   U$ s  snnf )N)r…   r   r«   r   r¬   Úgroupsrt   )r¿   ÚstartÚendÚobjects_to_bboxÚgrouprË   )rÄ   ÚmrÇ   rÈ   rÉ   Úsubsetr…   r   rt   r   r«   r   r¬   Úresults                 r   Úmatch_to_dictÚTextMap.match_to_dictŽ  s—   € ð —‘˜QŸW™W ZÓ0°1·5±5¸Ó3DÐEˆÙ$*Ô<¢F‘y˜¨a—¡FˆÑ<Ü-¨eÓ4Ñˆ�ð —G‘G˜JÓ'ØØØØñ
ˆö Ø Ÿx™x›zˆF�8ÑæØ#�7‰Oàˆùó# =s   ³	BÁ B)rÂ   r¿   r/   ©r,   N)r   TT)r–   r—   r˜   r™   Ú__doc__rÅ   ÚintÚboolÚdictrÓ   rš   r   r   r   r½   r½   „  sI   † ñö
=ð Ø"Ø!ñð ðð ð	ð
 ðð 
÷ð r   r½   c                   óf   • \ rS rSrSrSS jrSSSSS\\SS\SSS4S	\	S
\
S\
S\	S\	S\	S\4S jjrSrg)ÚWordMapiª  z
A WordMap maps words->chars.
r,   Nc                 ó   • Xl         g r/   ©r¿   rÃ   s     r   rÅ   ÚWordMap.__init__¯  s   € Ø�r   Fr   TÚlayoutÚlayout_width_charsÚlayout_height_charsÚuse_text_flowÚ	presortedÚexpand_ligaturesc                 óf  • / n[        U R                  5      (       d  [        U5      $ U(       a  [        O0 nU(       ag  U(       a  U(       a  [	        S5      eO[        [        X&-  5      5      nU(       a  U(       a  [	        S5      eO[        [        X7-  5      5      nS/U-  nO/ nSnU(       d  U(       a  U R                  O[        U R                  S S9nUS   S   nUS   US   -
  n[        [        US	 U
5      5       GHV  u  nnU(       a  US   S   S   UU	-   -
  U-  OSn[        [        US:„  5      [        U5      U-
  5      n[        U5       H5  n[        U5      (       a  US
   S   S:X  a  UU-  nUR                  S5        M7     UU-  nSnU(       d  U(       a  UO
[        US S9nU HŒ  u  nnU(       a  US   U-
  U-  OSn[        [        SU5      [        U5      U-
  5      nUS/U-  -  nUU-  nU H<  nUR                  US   US   5      n U  H  n!UR                  U!U45        US-  nM     M>     MŽ     U(       d  GMJ  US/UU-
  -  -  nGMY     U(       aD  UUS-   -
  n"[        U"5       H  nUS:”  a  UU-  nUR                  S5        M!     US
   S:X  a  USS
 n[        U5      $ )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:

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

- Calculate the initial doctop for the starting page.

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

- For each cluster, calculate the distance between that doctop and the
  initial doctop, in points, minus `y_shift`. Divide that distance 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`.

Note: This approach currently works best for horizontal, left-to-right
text, but will display all words regardless of orientation. There is room
for improvement in better supporting right-to-left text, as well as
vertical text.
z;`layout_width` and `layout_width_chars` cannot both be set.z=`layout_height` and `layout_height_chars` cannot both be set.)ru   Nr   c                 ó$   • [        U S   S   5      $ ©Nr   Údoctop©ÚfloatrD   s    r   rF   Ú$WordMap.to_textmap.<locals>.<lambda>  s   € ´5¸¸1¹¸h¹Ô3Hr   rI   rè   r«   c                 ó$   • [        U S   S   5      $ rç   ré   rD   s    r   rF   rë     s   € ¬u°Q°q±T¸(±^Ô/Dr   rN   rq   )rq   Nc                 ó$   • [        U S   S   5      $ )Nr   r   ré   rD   s    r   rF   rë   )  s   € ¬e°A°a±D¸±JÔ.?r   r   r   r…   N)rZ   r¿   r½   Ú	LIGATURESÚ
ValueErrorr×   rY   rW   Ú	enumerateÚcluster_objectsr"   r[   rX   r#   rT   )#rÄ   rß   Úlayout_widthÚlayout_heightrà   rá   Ú	x_densityÚ	y_densityÚx_shiftÚy_shiftÚy_tolerancerâ   rã   rä   Ú_textmapÚ
expansionsÚ
blank_lineÚnum_newlinesÚwords_sorted_doctopÚ
first_wordÚdoctop_startre   ÚwsÚy_distÚnum_newlines_prependÚline_lenÚline_words_sorted_x0Úwordrt   Úx_distÚnum_spaces_prependr   ÚlettersÚletterÚnum_newlines_appends#                                      r   Ú
to_textmapÚWordMap.to_textmap²  sÿ  € ðf ˆä�4—;‘;×ÑÜ˜8Ó$Ð$æ"2•Y¸ˆ
æÞ!ÞÜ$ØUóð ð  ô
 &)¬¨|Ñ/GÓ)HÓ%IÐ"æ"Þ Ü$ØWóð ð !ô
 '*¬%°Ñ0IÓ*JÓ&KÐ#à%˜Ð);Ñ;‰JàˆJàˆö žMð �KŠKä˜Ÿ™Ñ)HÑIð 	ð )¨Ñ+¨AÑ.ˆ
Ø! (Ñ+¨j¸Ñ.?Ñ?ˆäÜØ#Ñ%DÀkó÷
‰EˆAˆrö ð �A‘�q‘˜(Ñ# |°gÑ'=Ñ>À)ÒKàð ô
 $'ä�A˜‘E“
ä�f“ Ñ,ó	$Ð ô Ð/Ö0�Ü˜8—}‘}¨°©°Q©¸4Ó(?Ø 
Ñ*�HØ—‘ Ö-ñ 1ð
 Ð0Ñ0ˆLàˆHö ¦ñ ä˜BÑ$?Ñ@ð !ó  4‘��eÞ?E˜$˜t™* wÑ.°)Ò;È1�Ü%(¬¨Q°Ó)9¼5À»=È8Ñ;SÓ%TÐ"Ø˜[˜MÐ,>Ñ>Ñ>�ØÐ.Ñ.�ã�AØ(Ÿn™n¨Q¨v©Y¸¸&¹	ÓB�GÛ")˜Ø Ÿ™¨°¨Ô4Ø  A™šó #*ó ñ  4÷ ‰vØ˜[˜MÐ-?À(Ñ-JÑKÑK“ñ]
öb Ø"5¸ÈÑ9IÑ"JÐÜÐ.Ö/�Ø�q“5Ø 
Ñ*�HØ—‘ Ö-ñ 0ð ˜‰|˜|Ó+Ø# C R˜=�ä�xÓ Ð r   rÝ   rÕ   )r–   r—   r˜   r™   rÖ   rÅ   ÚDEFAULT_X_DENSITYÚDEFAULT_Y_DENSITYÚDEFAULT_Y_TOLERANCErØ   r×   r½   r  rš   r   r   r   rÛ   rÛ   ª  sŒ   † ñôð
 ØØØ"#Ø#$Ø#Ø#ØØØ'Ø#ØØ!%ñV!àðV!ð
  ðV!ð !ðV!ð ðV!ð ðV!ð ðV!ð 
÷V!ð V!r   rÛ   c            	       ó†   • \ rS rSr\\SSSSSSS4	S\4S jjrS\4S jr	S	\4S
 jr
S rS rS rS	\4S jrS\S	\4S jrSrg)ÚWordExtractoriK  FTNÚkeep_blank_charsc
                 óâ   • Xl         X l        X0l        X@l        XPl        X`l        Uc  / OUU l        USL a  [        R                  O
U=(       d    SU l	        U	(       a  [        U l        g 0 U l        g )NTrm   )Úx_tolerancerø   r  râ   Úhorizontal_ltrÚvertical_ttbÚextra_attrsÚstringÚpunctuationÚsplit_at_punctuationrî   rú   )
rÄ   r  rø   r  râ   r  r  r  r  rä   s
             r   rÅ   ÚWordExtractor.__init__L  sm   € ð 'ÔØ&ÔØ 0ÔØ*ÔØ,ÔØ(ÔØ!,Ñ!4™2¸+ˆÔð
 $ tÒ+ô ×Òà&×,¨"ð 	Ô!ö (8œ)ˆ�¸Rˆ�r   Úordered_charsc           
      óÈ  ^ • [        U5      u  p#pEUS   S   US   S   -
  nUS   S   nU(       a  T R                  (       a  OT R                  (       a  SOSnUS   S   n	Sn
U(       d  U	S   S:  a  [        U5      nSn
U	S   S:  a  U	S	   S:  a  S
n
OU	S   S:”  a  Sn
SR	                  U 4S jU 5       5      UUUX6-   UUUU
S.	nT R
                   H  nUS   U   X¼'   M     U$ )Nr   rè   r«   Úuprightr   rN   Úmatrixé  r
   é´   éZ   rm   c              3   óh   >#   • U  H'  nTR                   R                  US    US    5      v •  M)     g7f©r…   N)rú   rT   )r   r   rÄ   s     €r   r   Ú,WordExtractor.merge_chars.<locals>.<genexpr>|  s0   øé € ð ÚCP¸a�—‘×#Ñ# A f¡I¨q°©y×9Ð9Â=ùs   ƒ/2)	r…   r   r   r«   rè   r¬   r  Ú	directionÚrotation)rÎ   r  r  ÚreversedrÀ   r  )rÄ   r  r   r«   r   r¬   Ú
doctop_adjr  r&  r  r'  r  rJ   s   `            r   Úmerge_charsÚWordExtractor.merge_charsi  s  ø€ Ü-¨mÓ<Ñˆ�Ø" 1Ñ% hÑ/°-ÀÑ2BÀ5Ñ2IÑIˆ
Ø Ñ" 9Ñ-ˆÞ18˜$×-×-Ð-¸d×>O×>O‘AÐVXˆ	à˜qÑ! (Ñ+ˆàˆÞ˜6 !™9 q›=Ü$ ]Ó3ˆMØˆHà�!‰9�q‹=˜V A™Y¨›]Ø‰HØ�A‰Y˜‹]ØˆHð —G‘Gô ÙCPóó ð ØØØÑ&ØØØ"Ø ñ
ˆð ×#Ô#ˆCØ% aÑ(¨Ñ-ˆD‹Iñ $ð ˆr   r,   c                 ó¾  • US   (       aV  U R                   nU R                  nUS   nUS   nU R                  (       a  US   nUS   nUS   n	OhUS   * nUS   * nUS   * n	OUU R                  nU R                   nUS   nUS   nU R                  (       a  US   nUS   nUS   n	OUS   * nUS   * nUS   * n	[	        X—:  =(       d    X˜U-   :„  =(       d    XeU-   :„  5      $ )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«   r   r   r¬   )r  rø   r  r  rØ   )
rÄ   Ú	prev_charÚ	curr_charrE   r2   ÚayÚcyÚaxÚbxÚcxs
             r   Úchar_begins_new_wordÚ"WordExtractor.char_begins_new_wordŽ  s'  € ðN �Y×Ø× Ñ ˆAØ× Ñ ˆAØ˜5Ñ!ˆBØ˜5Ñ!ˆBØ×"×"Ø˜t‘_�Ø˜t‘_�Ø˜t‘_‘à ‘oÐ%�Ø ‘oÐ%�Ø ‘oÐ%‘ð × Ñ ˆAØ× Ñ ˆAØ˜4‘ˆBØ˜4‘ˆBØ× × Ø˜uÑ%�Ø˜xÑ(�Ø˜uÑ%‘à Ñ)Ð)�Ø Ñ&Ð&�Ø Ñ)Ð)�äà‰W÷ Ø˜!‘V‘÷ð ˜!‘V‘ó
ð 	
r   c              #   óÀ  ^#   • / mSU4S jjnU Hµ  nUS   nU R                   (       d'  UR                  5       (       a  U" S 5       S h  v•N   M@  X@R                  ;   a"  U" U5       S h  v•N   U" S 5       S h  v•N   Mq  T(       a,  U R                  TS   U5      (       a  U" U5       S h  v•N   M¤  TR	                  U5        M·     T(       a  Tv •  g g  NŒ Nm N_ N.7f)Nc              3   ó6   >#   • T(       a  Tv •  U c  / mg U /mg 7fr/   r   )Únew_charÚcurrent_words    €r   Ústart_next_wordÚ:WordExtractor.iter_chars_to_words.<locals>.start_next_wordÜ  s!   øé € ö Ø"Ò"à!)Ñ!1˜2‰L¸°z‰Lùó   ƒr…   rN   r/   )r  Úisspacer  r4  rX   )rÄ   r  r:  r�   r…   r9  s        @r   Úiter_chars_to_wordsÚ!WordExtractor.iter_chars_to_wordsÙ  sÉ   øé € Øˆ÷	Bó "ˆDØ˜‘<ˆDà×(×(¨T¯\©\¯^©^Ù*¨4Ó0×0Ò0à×2Ñ2Ó2Ù*¨4Ó0×0Ð0Ù*¨4Ó0×0Ò0æ $×";Ñ";¸LÈÑ<LÈd×"SÑ"SÙ*¨4Ó0×0Ò0ð ×#Ñ# DÖ)ñ "ö" ØÓð ñ 1ñ 1Ù0ñ 1ùsH   ƒACÁ	CÁ
 CÁ*CÁ+CÁ:CÁ;2CÂ-CÂ.)CÃCÃCÃCc              #   óª  #   • S[         4S jn[        [        U5      US5       H¦  nUS   S   nU(       a  SOSn[        U[        U5      U R                  5      nU Hj  nU(       a  SOSn[        U[        U5      S9n	U(       a  U R                  (       d'  OU R                  (       d  [        U	5       S h  v•N   M`  U	 S h  v•N   Ml     M¨     g  N N7f)Nr,   c                 ó    • [        U S   5      * $ ©Nr  )r×   rD   s    r   Úupright_keyÚ2WordExtractor.iter_sort_chars.<locals>.upright_keyù  s   € Ü˜˜)™Ó%Ð%Ð%r   r   r  rè   r   rI   )	r×   rñ   r·   r   rø   rW   r  r  r(  )
rÄ   rt   rC  Úupright_clusterr  Úcluster_keyÚsubclustersÚscÚsort_keyÚto_yields
             r   Úiter_sort_charsÚWordExtractor.iter_sort_charsø  s¾   é € ð	&œcô 	&ô  /¬t°E«{¸KÈÖKˆOØ% aÑ(¨Ñ3ˆGÞ&-™(°4ˆKô *Ø¤¨KÓ!8¸$×:JÑ:JóˆKó "�æ#*™4°�Ü! "¬*°XÓ*>Ñ?�ö 07˜×+×+Ð+¸D×<M×<MÜ'¨Ó1×1Ò1à'×'Ò'ó "ò  Lñ  2á'ùs$   ‚B3CÂ5CÂ6CÃCÃCÃCc              #   ó  #   • U R                   (       a  UOU R                  U5      n[        S/U R                  Q76 n[        R
                  " X#5      nU H2  u  pVU R                  U5       H  nU R                  U5      U4v •  M     M4     g 7frB  )râ   rK  r   r  Ú	itertoolsÚgroupbyr>  r*  )rÄ   rt   r  Úgrouping_keyÚgrouped_charsÚkeyvalsÚ
char_groupÚ
word_charss           r   Úiter_extract_tuplesÚ!WordExtractor.iter_extract_tuples  s}   é € Ø!%×!3×!3™¸×9MÑ9MÈeÓ9Tˆä! )Ð?¨d×.>Ñ.>Ò?ˆÜ!×)Ò)¨-ÓFˆã#0ÑˆGØ"×6Ñ6°zÖB�
Ø×'Ñ'¨
Ó3°ZÐ@Ô@ó Cò $1ùs   ‚B
Bc                 óH   • [        [        U R                  U5      5      5      $ r/   )rÛ   r·   rU  )rÄ   rt   s     r   Úextract_wordmapÚWordExtractor.extract_wordmap  s   € Ü”t˜D×4Ñ4°UÓ;Ó<Ó=Ð=r   rt   c                 óH   • [        S U R                  U5       5       5      nU$ )Nc              3   ó*   #   • U  H	  u  pUv •  M     g 7fr/   r   )r   r  rT  s      r   r   Ú.WordExtractor.extract_words.<locals>.<genexpr>  s   é € ÐRÒ2QÑ.˜d•TÒ2Qùó   ‚)r·   rU  )rÄ   rt   Úwordss      r   Úextract_wordsÚWordExtractor.extract_words  s"   € ÜÑR°$×2JÑ2JÈ5Ô2QÓRÓRˆØˆr   )	rú   r  r  r  r  râ   r  r  rø   )r–   r—   r˜   r™   ÚDEFAULT_X_TOLERANCEr  rØ   rÅ   r·   r*  r4  r>  rK  rU  rÛ   rX  r_  rš   r   r   r   r  r  K  s~   † ð (Ø'Ø!&ØØØØØ"Øñ@ð õ	@ð:#¨ô #ðJI
ð 
ô	I
òVò>(ò0Að>¨ô >ð 4ð ¨D÷ r   r  rt   c                 ó6   • [        S0 UD6R                  U 5      $ )Nr   )r  r_  )rt   Úkwargss     r   r_  r_  "  s   € ÜÑ"˜6Ñ"×0Ñ0°Ó7Ð7r   c           
      ó  • UR                  SS05        [        S0 [         Vs0 s H  o"U;   d  M
  X!U   _M     snD6nUR                  U 5      nUR                  " S0 [
         Vs0 s H  o"U;   d  M
  X!U   _M     snD6nU$ s  snf s  snf )Nrã   Tr   )Úupdater  ÚWORD_EXTRACTOR_KWARGSrX  r  ÚTEXTMAP_KWARGS)rt   rc  ÚkÚ	extractorÚwordmapÚtextmaps         r   Úchars_to_textmaprl  *  sš   € Ø
‡M�M�; Ð%Ô&äñ Ý!6Ó
FÒ!6˜A¸v¹+‹<ˆ1�Q‰iŠ<Ñ!6Ñ
Fñ€Ið ×'Ñ'¨Ó.€GØ× Ò ñ Ý!/Ó
?¢˜A¸±;‹<ˆ1�Q‰iŠ<¡Ñ
?ñ€Gð €Nùò Gùò @s   £	B°	BÁ%	BÁ2	Bc           
      ó>  • [        U 5      n [        U 5      S:X  a  gUR                  S5      (       a  [        U 40 UD6R                  $ UR                  S[
        5      n[        S0 [         Vs0 s H  o3U;   d  M
  X1U   _M     snD6nUR                  U 5      nU(       a	  US   S   nOSnUS:X  a6  UR                  S S9  S	R                  U Vs/ s H  owS
   PM	     sn5      nU$ US:X  a6  UR                  S S9  S	R                  U Vs/ s H  owS
   PM	     sn5      nU$ [        U[        S5      U5      nSR                  S U 5       5      nUS:X  a2  SR                  [        U5       V	s/ s H  o™S:w  a  U	OS	PM     sn	5      nU$ s  snf s  snf s  snf s  sn	f )Nr   rm   rß   rø   r'  r"  c                 ó   • U S   U S   * 4$ ©Nr   r«   r   ©Úws    r   rF   Úextract_text.<locals>.<lambda>K  s   €  a¨¡g°°%±¨yÑ%9r   rI   ru   r…   r   c                 ó   • U S   * U S   4$ ro  r   rp  s    r   rF   rr  N  s   €  q¨¡w h°°%±Ñ%9r   rè   rq   c              3   óR   #   • U  H  nS R                  S U 5       5      v •  M     g7f)ru   c              3   ó*   #   • U  H	  oS    v •  M     g7fr$  r   )r   r  s     r   r   Ú)extract_text.<locals>.<genexpr>.<genexpr>R  s   é € Ð&EÂ¸¨F¦|Âùr]  N)rÀ   )r   r‡   s     r   r   Úextract_text.<locals>.<genexpr>R  s$   é € ÐXÒRWÈ$˜cŸh™hÑ&EÁÓ&E×EÐEÒRWùs   ‚%'r!  r   )r»   rZ   rT   rl  rÂ   r  r  rf  r_  ÚsortrÀ   rñ   r   r(  )
rt   rc  rø   rh  ri  r^  r'  rq  ro   r   s
             r   Úextract_textry  8  s–  € Ü�E‹N€EÜ
ˆ5ƒz�QƒØà‡z�z�(×ÑÜ Ñ0¨Ñ0×:Ñ:Ð:à—j‘j Ô0CÓDˆÜ!ñ 
Ý%:ÓJÒ%: À6¹k‹|ˆq˜‘)Š|Ñ%:ÑJñ
ˆ	ð ×'Ñ'¨Ó.ˆÞØ˜Q‘x 
Ñ+‰HàˆHà�r‹>Ø�J‰JÑ9ˆJÑ:Ø—H‘H±Ó7²¨A œi±Ñ7Ó8ˆEð ˆð ˜‹_Ø�J‰JÑ9ˆJÑ:Ø—H‘H±Ó7²¨A œi±Ñ7Ó8ˆEð ˆô $ E¬:°hÓ+?ÀÓMˆEØ—I‘IÑXÑRWÓXÓXˆEØ˜3‹ØŸ™ÄHÈUÄOÓ TÂO¸q¨D£y¡!°cÒ"9ÁOÑ TÓU�àˆùò) Kùò 8ùò 8ùò
 !Us   Á-	FÁ:	FÃFÄFÅ/FÚ
line_charsc                 ó€   • SnS n[        U [        S5      S9 H"  nUb  US   X1-   :”  a  US-  nUS   nX$S   -  nM$     U$ )Nrm   r   rI   ru   r   r…   )rW   r   )rz  Ú	toleranceÚcollÚlast_x1r�   s        r   Úcollate_liner  Y  s]   € ð €DØ€GÜ�z¤z°$Ó'7Ô8ˆØÑ d¨4¡j°GÑ4GÓ&HØ�C‰KˆDØ�t‘*ˆØ�V‘ÑŠñ	 9ð
 €Kr   c                 ó’   ^^^• [        SSSS5      m[        SS5      mS[        4UUU4S jjnU" U 5      n[        X0R                  S	9$ )
u�   
Removes duplicate chars â€”Â those sharing the same text, fontname, size,
and positioning (within `tolerance`) as other characters in the set.
ÚfontnameÚsizer  r…   rè   r   rt   c              3   ó  >#   • [        U TS9n[        R                  " UTS9 HW  u  p#[        [	        U5      [        S5      T5       H/  n[        U[        S5      T5       H  n[        UTS9S   v •  M     M1     MY     g 7f)NrI   rè   r   r   )rW   rN  rO  rñ   r·   r   )	rt   Úsorted_charsÚgrpÚ	grp_charsÚ	y_clusterÚ	x_clusterrJ   Úpos_keyr|  s	         €€€r   Úyield_unique_charsÚ(dedupe_chars.<locals>.yield_unique_charso  s|   øé € Ü˜e¨Ñ-ˆÜ'×/Ò/°À#ÔF‰NˆCÜ,Ü�Y“¤¨HÓ!5°yö�	ô "1Øœz¨$Ó/°ö"�Iô ! °Ñ8¸Ñ;Ô;ó"óò Gùs   ƒA<A?rI   )r   r·   rW   Úindex)rt   r|  rŠ  ÚdedupedrJ   r‰  s    `  @@r   Údedupe_charsrŽ  g  sM   ú€ ô
 �Z ¨°FÓ
;€CÜ˜ 4Ó(€Gð	<¤$÷ 	<ñ 	<ñ ! Ó'€GÜ�'Ÿ{™{Ñ+Ð+r   c                 óB   • [        U 5      nU S   U S   :X  a  SOSUS'   U$ )Nr«   r¬   ÚhÚvÚorientation)rÙ   )r‡   Úedges     r   Úline_to_edger”  ~  s+   € Ü�‹:€DØ"& u¡+°°h±Ó"?™#Àc€DˆÑØ€Kr   c           	      ó\  • [        S5       Vs/ s H  n[        U 5      PM     snu  p#pEUR                  SSU S   U S   SS.5        UR                  SSU S   U S   U S	   -   U S
   U S	   -   SS.5        UR                  SSU S   SS.5        UR                  SSU S   SS.5        X#XE/$ s  snf )Né   Ú	rect_edger   r   r«   r�  )Úobject_typeÚheightr   r¬   r’  r   r™  rè   )r˜  r™  r   r«   rè   r’  r   r‘  )r˜  Úwidthr   r’  r   )r˜  rš  r   r’  )r[   rÙ   re  )r   rE   r«   r¬   ÚleftÚrights         r   Úrect_to_edgesr�  „  sç   € Ü49¸!´HÓ=²H¨q¤ T¦
±HÑ=Ñ€C�Ø‡J�Jà&ØØ�t‘*Ø˜5‘kØñ	
ôð ‡M�Mà&ØØ�t‘*Ø˜‘;  h¡Ñ/Ø˜8‘n t¨H¡~Ñ5Øñ	
ô	ð 	‡K�Kà&ØØ�t‘*Øñ		
ôð 
‡L�Là&ØØ�t‘*Øñ		
ôð ˜Ð%Ð%ùòI  >s   ŽB)c                 ó²  • [        U S   U S   SS  5      nU VVs/ s H­  u  p#S[        US   US   5      [        US   US   5      [        US   US   5      [        US   US   5      U S   U S   -
  -   [        US   US   5      [        US   US   -
  5      [        US   US   -
  5      US   US   :X  a  SOUS   US   :X  a  SOS S	.	PM¯     snn$ s  snnf )
NÚptsr   Ú
curve_edger   rè   r«   r‘  r�  )	r˜  r   r   r«   rè   r¬   rš  r™  r’  )Úzipr#   r"   r{   )ÚcurveÚpoint_pairsÚp0Úp1s       r   Úcurve_to_edgesr¦  ¬  s  € Ü�e˜E‘l E¨%¡L°°Ð$4Ó5€Kñ "ôò "‰FˆBð (Ü�b˜‘e˜R ™UÓ#Ü�b˜‘e˜R ™UÓ#Ü�r˜!‘u˜b ™eÓ$Ü˜"˜Q™%  A¡Ó'¨5°©?¸UÀ5¹\Ñ+IÑJÜ˜"˜Q™%  A¡Ó'Ü˜˜A™  A¡™Ó'Ü˜"˜Q™% " Q¡%™-Ó(Ø"$ Q¡%¨2¨a©5£.™3¸bÀ¹eÀrÈ!Áu»n±sÐRVô
	
ñ "òð ùó s   ›B4Cc                 ón   • U S   nSU;   a  U /$ US:X  a  [        U 5      /$ [        [        S.U   " U 5      $ )Nr˜  Ú_edger‡   )r   r¢  )r”  r�  r¦  )ÚobjÚts     r   Úobj_to_edgesr«  ¾  sD   € ØˆMÑ€AØ�!ƒ|ØˆuˆØ	
ˆf‹Ü˜SÓ!Ð"Ð"ä%´Ñ?ÀÒBÀ3ÓGÐGr   c                 ór   ^^^• TS;  a  [        S5      eS[        4UUU4S jjn[        [        X@5      5      $ )N)r‘  r�  NúOrientation must be 'v' or 'h'r,   c                 ó¢   >• U S   S:X  a  SOSnTb  U S   T:H  OSnTS L =(       d    U S   T:H  n[        U=(       a    U=(       a    X   T:¬  5      $ )Nr’  r‘  r™  rš  r˜  T©rØ   )ÚeÚdimÚ
et_correctÚorient_correctÚ	edge_typeÚ
min_lengthr’  s       €€€r   ÚtestÚfilter_edges.<locals>.testÑ  sb   ø€ Ø˜MÑ*¨cÓ1‰h°wˆØ6?Ñ6K�Q�}Ñ%¨Ò2ÐQUˆ
Ø$¨Ð,×O°°-Ñ0@ÀKÑ0OˆÜ�J×L >×L°q±vÀÑ7KÓMÐMr   )rï   rØ   r·   Úfilter)Úedgesr’  r´  rµ  r¶  s    ``` r   Úfilter_edgesrº  È  s@   ú€ ð Ð*Ó*ÜÐ9Ó:Ð:ðN”4÷ Nñ Nô ”�tÓ#Ó$Ð$r   c                 ó�  • US:X  a  [        U 5       Vs/ s H  o"/PM     sn$ [        U 5      S:  a  [        U 5       Vs/ s H  o"/PM     sn$ / n[        [        U 5      5      n U S   /nU S   nU SS   H3  nX%U-   ::  a  UR                  U5        OUR                  U5        U/nUnM5     UR                  U5        U$ s  snf s  snf )Nr   r	   r   )rW   rZ   r·   rX   )Úxsr|  rE   rË   Úcurrent_groupÚlasts         r   Úcluster_listr¿  Ú  sÉ   € Ø�Aƒ~Ü# BœZÓ(šZ˜“™ZÑ(Ð(Ü
ˆ2ƒw�ƒ{Ü# BœZÓ(šZ˜“™ZÑ(Ð(Ø€FÜ	Œf�R‹jÓ	€BØ˜‘U�G€MØˆa‰5€DØ��‹VˆØ˜	Ñ!Ó"Ø× Ñ  Õ#à�M‰M˜-Ô(Ø˜CˆMØŠñ ð ‡M�M�-Ô Ø€Mùò )ùâ(s
   ”B>¿Cc           
      óô   • [        [        [        U 5      5      U5      n[        U5       VVVs/ s H  u  p4U Vs/ s H  oUU4PM     snPM     nnnn[	        [
        R                  " U6 5      $ s  snf s  snnnf r/   )r¿  r·   Úsetrð   rÙ   rN  Úchain)Úvaluesr|  Úclustersre   Úvalue_clusterÚvalÚnested_tupless          r   Úmake_cluster_dictrÈ  î  sq   € ÜœD¤ V£Ó-¨yÓ9€Hô ENÈhÔDWõÚDWÑ0@°™]Ó+š]�cˆq‹™]Ô+ÑDWð ò ô ”	—’ Ð/Ó0Ð0ùò 	,ùôs   ®A3ºA.ÁA3Á.A3c           
      óD  ^^
• [        T5      (       d  [        T5      m[        TU 5      n[        X25      m
[        S5      [        S5      pT[	        U
U4S jU  5       US9n[
        R                  " XeS9nU VV	s/ s H  u  p‰[        [        XI5      5      PM     sn	n$ s  sn	nf )Nr   r   c              3   óT   >#   • U  H  oTR                  T" U5      5      4v •  M     g 7fr/   )rT   )r   rE   Úcluster_dictÚkey_fns     €€r   r   Ú"cluster_objects.<locals>.<genexpr>  s#   øé € ÐJÂrÀ! ×!1Ñ!1±&¸³)Ó!<Õ=Ârùs   ƒ%(rI   )Úcallabler   rÁ   rÈ  rW   rN  rO  r·   )r¼  rÌ  r|  rÃ  Úget_0Úget_1Úcluster_tuplesÚgroupedrh  r‘  rË  s    `        @r   rñ   rñ   ø  s‚   ù€ Ü�F×ÑÜ˜FÓ#ˆä�˜‹_€FÜ$ VÓ7€Lä˜a“=¤*¨Q£-ˆ5äÕJÁrÓJÐPUÑV€Nä×Ò Ñ:€Gá,3Ô4ªG¡D AŒD”�U“Ö©GÒ4Ð4ùÓ4s   Á8 BÚaxisc                 óD  • US;   d   eUS:X  a  SU S   U-   4SU S   U-   4/nUS:X  aE  SU S   U-   4SU S   U-   4/nSU ;   a  USU S   U-   4/-  nS	U ;   a  US	U S	   U-
  4S
U S
   U-
  4/-  nU R                  [        U R                  5       5      [        W5      -   5      $ )N)r�  r‘  r�  r   r   r‘  r«   r¬   rè   r   r   )Ú	__class__r]   Úitems)r©  rÓ  ÚvalueÚ	new_itemss       r   Úmove_objectrÙ    sô   € Ø�:ÓÐÐØˆsƒ{à�3�t‘9˜uÑ$Ð%Ø�3�t‘9˜uÑ$Ð%ð
ˆ	ð ˆsƒ{à�C˜‘J Ñ&Ð'Ø�s˜8‘} uÑ,Ð-ð
ˆ	ð �s‹?Ø˜8 S¨¡]°UÑ%:Ð;Ð<Ñ<ˆIØ�3‹;ØØ�s˜4‘y 5Ñ(Ð)Ø�s˜4‘y 5Ñ(Ð)ðñ ˆIð �=‰=œ˜sŸy™y›{Ó+¬e°IÓ.>Ñ>Ó?Ð?r   Úattrc                 ó¨  • SSSSS.U   n[        U 5      n[        U[        U5      U5      nU Vs/ s H-  n[        [	        [        U5      U5      5      [        U5      -  PM/     nn[        XW5       VVV	s/ s H'  u  phU V	s/ s H  n	[        X“X‰U   -
  5      PM     sn	PM)     n
nnn	[        [        R                  " U
6 5      $ s  snf s  sn	f s  sn	nnf )Nr�  r‘  ©r   r   r«   r¬   )
r·   rñ   r   ÚsumrÁ   rZ   r¡  rÙ  rN  rÂ  )ÚobjsrÚ  r|  rÓ  Ú	list_objsrÄ  ÚclusterÚavgsÚavgr©  Úsnapped_clusterss              r   Úsnap_objectsrä    sÊ   € Ø˜S¨¸Ñ<¸TÑB€DÜ�T“
€IÜ˜y¬*°TÓ*:¸IÓF€HÙNVÓWÊhÀ7ŒC””J˜tÓ$ gÓ.Ó/´#°g³,Ô>Éh€DÐWô   Ô/õâ/‰LˆGñ =DÓDºG°SŒ�S ¨$¡i¡Ö	0¹GÔDÙ/ð ò ô ”	—’Ð!1Ð2Ó3Ð3ùò XùâDùôs   °4CÁ5CÂCÂCÃCc                 ó’   • / / S.nU  H  nX4S      R                  U5        M     [        US   SU5      n[        US   SU5      nXV-   $ )zg
Given a list of edges, snap any within `tolerance` pixels of one another
to their positional average.
©r‘  r�  r’  r‘  r   r�  r«   )rX   rä  )r¹  r  rø   Úby_orientationr°  Ú	snapped_vÚ	snapped_hs          r   Ú
snap_edgesrê  *  s_   € ð  BÑ'€NÛˆØ˜Ñ'Ñ(×/Ñ/°Ö2ñ ô ˜^¨CÑ0°$¸ÓD€IÜ˜^¨CÑ0°%¸ÓE€IØÑ Ð r   rJ   c                 óŒ  • US;   d   eX   nX#-
  nX4/nUS:X  a$  X S   ::  d   eUR                  SU S   U-
  45        OÓUS:X  a#  X S   :¼  d   eUR                  SX S   -
  45        OªUS:X  a\  X S   ::  d   eUR                  SU S   U-   45        UR                  SU S   U-
  45        S	U ;   a  UR                  S	U S	   U-
  45        OHUS:X  aB  X S   :¼  d   eUR                  SU S   U-   45        S
U ;   a  UR                  S
U S
   U-
  45        U R                  [        U R                  5       5      [        U5      -   5      $ )NrÜ  r   r   rš  r«   r¬   rè   r™  r   r   )rX   rÕ  r]   rÖ  )r©  rJ   r×  Ú	old_valueÚdiffrØ  s         r   Úresize_objectrî  <  s  € ØÐ/Ó/Ð/Ð/Ø‘€IØÑ€Dà	ˆð€Ið ˆdƒ{Ø˜D™	Ó!Ð!Ð!Ø×Ñ˜' 3 t¡9¨uÑ#4Ð5Õ6Ø	�‹Ø˜D™	Ó!Ð!Ð!Ø×Ñ˜' 5¨t©9Ñ#4Ð5Õ6Ø	�‹Ø˜H™Ó%Ð%Ð%Ø×Ñ˜( C¨¡M°DÑ$8Ð9Ô:Ø×Ñ˜( C¨¡M°DÑ$8Ð9Ô:Ø�3‹;Ø×Ñ˜d C¨¡I°Ñ$4Ð5Ô6øØ	�‹Ø˜E™
Ó"Ð"Ð"Ø×Ñ˜( C¨¡M°DÑ$8Ð9Ô:Ø�3‹;Ø×Ñ˜d C¨¡I°Ñ$4Ð5Ô6Ø�=‰=œ˜sŸy™y›{Ó+¬e°IÓ.>Ñ>Ó?Ð?r   r’  c                 ó(  • US:X  a  Su  p4OUS:X  a  Su  p4O[        S5      e[        [        U [        U5      S95      nUS   /nUSS	  HE  nUS
   nXs   X„   U-   ::  a  Xt   X„   :”  a  [	        X„Xt   5      US
'   M2  M4  UR                  U5        MG     U$ )zs
Given a list of edges along the same infinite line, join those that
are within `tolerance` pixels of one another.
r�  rR   r‘  )r«   r¬   r­  rI   r   r   NrN   )rï   r·   rW   r   rî  rX   )	r¹  r’  r|  Úmin_propÚmax_propÚsorted_edgesÚjoinedr°  r¾  s	            r   Újoin_edge_grouprô  W  s¹   € ð
 �cÓØ'Ñˆ�(Ø	˜Ó	Ø,Ñˆ�(äÐ9Ó:Ð:äœ˜u¬*°XÓ*>Ñ?Ó@€LØ˜1‰oÐ€FØ˜!˜"ÓˆØ�b‰zˆØ‰;˜4™>¨IÑ5Ó6Ø‰{˜T™^Ó+ä*¨4¸1¹;ÓG��r“
ñ ,ð
 �M‰M˜!Öñ ð €Mr   c                 óÌ   ^^• S nUS:”  d  US:”  a  [        XU5      n [        XS9n[        R                  " XeS9nUU4S jU 5       n[	        [        R
                  " U6 5      n U $ )zp
Using the `snap_edges` and `join_edge_group` methods above,
merge a list of edges into a more "seamless" list.
c                 ó0   • U S   S:X  a  SU S   4$ SU S   4$ )Nr’  r�  r«   r‘  r   r   )r“  s    r   Ú	get_groupÚmerge_edges.<locals>.get_group~  s-   € Ø�Ñ #Ó%Ø˜˜e™Ð%Ð%à˜˜d™Ð$Ð$r   r   rI   c              3   ó\   >#   • U  H!  u  p[        X!S    US    S:X  a  TOT5      v •  M#     g7f)r   r�  N)rô  )r   rh  rÖ  r    r¡   s      €€r   r   Úmerge_edges.<locals>.<genexpr>‰  s?   øé € ð ò $‰HˆAô 	Ø�Q‘4¨a°©d°c«kÑ*Ð?O÷	
ð 	
ò $ùs   ƒ),)rê  rW   rN  rO  r·   rÂ  )	r¹  r�   rž   r    r¡   r÷  Ú_sortedÚedge_groupsÚedge_gens	      ``    r   Úmerge_edgesrþ  r  sl   ù€ ò%ð ˜!ÓÐ/°!Ó3Ü˜5Ð4DÓEˆä�UÑ*€GÜ×#Ò# GÑ;€Kõñ $ó	€Hô ”—’ (Ð+Ó,€EØ€Lr   c                 ó(   • U S   U S   U S   U S   S.$ )zX
Return the rectangle (i.e a dict with keys "x0", "top", "x1",
"bottom") for an object.
r   r   r	   r
   )r   r«   r   r¬   r   ©r1   s    r   Úbbox_to_rectr  “  s#   € ð
 �q‘' $ q¡'°°a±ÀDÈÁGÑLÐLr   c                 ó*   • [        [        U 5      5      $ )z�
Given an iterable of objects, return the smallest rectangle (i.e. a
dict with "x0", "top", "x1", and "bottom" keys) that contains them
all.
)r  rÎ   ©Úobjectss    r   Úobjects_to_rectr  ›  s   € ô œ¨Ó0Ó1Ð1r   c                 ól   • [        U 6 u  pp4[        U5      [        U5      [        U5      [        U5      4$ )z_
Given an iterable of bounding boxes, return the smallest bounding box
that contains them all.
)r¡  r#   r"   )Úbboxesr   r«   r   r¬   s        r   Úmerge_bboxesr  ¤  s1   € ô
 ˜v˜,Ñ€BˆRÜ�‹G”S˜“Xœs 2›w¬¨F«Ð4Ð4r   c                 ó4   • [        [        [        U 5      5      $ )zX
Given an iterable of objects, return the smallest bounding box that
contains them all.
)r  rÁ   Úbbox_getterr  s    r   rÎ   rÎ   ­  s   € ô
 œœK¨Ó1Ó2Ð2r   Úword_thresholdc           
      ó€  ^• [        U [        S5      S5      n[        U4S jU5      n[        [	        [
        U5      5      n[        U5      S:X  a  / $ [        [	        [        S5      U5      5      n[        [	        [        S5      U5      5      n/ nU H(  nUUUUS   US   Xe-
  SS.UUUS	   US	   Xe-
  SS./-  nM*     U$ )
z]
Find (imaginary) horizontal lines that connect the tops
of at least `word_threshold` words.
r«   r   c                 ó    >• [        U 5      T:¬  $ r/   ©rZ   ©rE   r  s    €r   rF   Ú"words_to_edges_h.<locals>.<lambda>»  ó   ø€ ¤c¨!£f°Ò&>r   r   r   r   r�  )r   r   r«   r¬   rš  r’  r¬   )	rñ   r   r¸  r·   rÁ   r  rZ   r#   r"   )	r^  r  Úby_topÚlarge_clustersÚrectsÚmin_x0Úmax_x1r¹  r0   s	    `       r   Úwords_to_edges_hr  µ  sÝ   ø€ ô
 ˜U¤J¨uÓ$5°qÓ9€FÜÔ>ÀÓG€NÜ””_ nÓ5Ó6€EÜ
ˆ5ƒz�QƒØˆ	Ü””Z Ó% uÓ-Ó.€FÜ””Z Ó% uÓ-Ó.€Fà€EÛˆØð ØØ˜‘xØ˜E™(Ø™Ø"ñð ØØ˜‘{Ø˜H™+Ø™Ø"ñð
ñ 	
Šñ ð0 €Lr   c                 ó°   • U u  p#pEUu  pgp‰[        X&5      n
[        XH5      n[        XY5      n[        X75      nXº-
  nXÍ-
  nUS:¼  a  US:¼  a  Xþ-   S:”  a  X­X¼4$ g rC   r!   )ÚaÚbÚa_leftÚa_topÚa_rightÚa_bottomÚb_leftÚb_topÚb_rightÚb_bottomÚo_leftÚo_rightÚo_bottomÚo_topÚo_widthÚo_heights                   r   Úget_bbox_overlapr)  Þ  ss   € Ø'(Ñ$€F�7Ø'(Ñ$€F�7Ü�Ó €FÜ�'Ó#€GÜ�8Ó&€HÜ�Ó€EØÑ€GØÑ€HØ�1ƒ}˜ A›¨(Ñ*<¸qÓ*@Ø˜wÐ1Ð1àr   c           
      óð  ^^• [        U [        S5      S5      n[        U [        S5      S5      nS n[        XS5      nX#-   U-   n[        US S9n[        U4S jU5      n[	        [        [        U5      5      n	/ n
U	 H2  m[        U4S jU
 5       5      nU(       a  M!  U
R                  T5        M4     U
(       d  / $ [        [        U
5      n[	        [        U[        S5      S95      n[        [        [        S5      U5      5      n[        [        [        S	5      U5      5      n[        [        [        S
5      U5      5      nU Vs/ s H  nUS   US   UUUU-
  SS.PM     snUUUUUU-
  SS./-   $ s  snf )zm
Find (imaginary) vertical lines that connect the left, right, or
center of at least `word_threshold` words.
r   r   r   c                 ó0   • [        U S   U S   -   5      S-  $ )Nr   r   r	   ré   )r  s    r   Ú
get_centerÚ$words_to_edges_v.<locals>.get_centerö  s   € Ü�T˜$‘Z $ t¡*Ñ,Ó-°Ñ1Ð1r   c                 ó   • [        U 5      * $ r/   r  rD   s    r   rF   Ú"words_to_edges_v.<locals>.<lambda>ý  s
   € ´c¸!³f±Wr   rI   c                 ó    >• [        U 5      T:¬  $ r/   r  r  s    €r   rF   r/  þ  r  r   c              3   ó<   >#   • U  H  n[        TU5      v •  M     g 7fr/   )r)  ©r   r   r1   s     €r   r   Ú#words_to_edges_v.<locals>.<genexpr>  s   øé € ÐJÒ9I°AÔ& t¨Q×/Ð/Ò9Iùs   ƒr«   r¬   r‘  ©r   r   r«   r¬   r™  r’  )rñ   r   rW   r¸  r·   rÁ   rÎ   r   rX   r  r"   r#   )r^  r  Úby_x0Úby_x1r,  Ú	by_centerrÄ  Úsorted_clustersr  r  Úcondensed_bboxesÚoverlapÚcondensed_rectsÚsorted_rectsr  Úmin_topÚ
max_bottomr  r1   s    `                @r   Úwords_to_edges_vr?  í  s’  ù€ ô ˜E¤:¨dÓ#3°QÓ7€EÜ˜E¤:¨dÓ#3°QÓ7€Eò2ô   °1Ó5€IØ‰}˜yÑ(€Hô ˜XÑ+<Ñ=€OÜÔ>ÀÓP€Nô ”#”o ~Ó6Ó7€Fð ÐÛˆÜÔJÑ9IÓJÓJˆßˆwØ×#Ñ# DÖ)ñ ö
 Øˆ	äœ,Ð(8Ó9€OÜœ˜´J¸tÓ4DÑEÓF€Lä””Z Ó% |Ó4Ó5€FÜ”#”j Ó'¨Ó6Ó7€GÜ”Sœ HÓ-¨|Ó<Ó=€Jñ ó
ò ˆAð �D‘'Ø�D‘'ØØ Ø  7Ñ*Øô	
ñ ñ
ð ØØØ Ø  7Ñ*Øñ	
ð		ñð ùò 
s   ÅE3c           	      óè  ^• 0 nS V^s/ s H  m[        [        U4S jU 5      5      PM     snu  pV[        U[        SS5      S9 H¤  n[        U[        SS5      S9 H‰  nUS   US   U-   ::  d  M  US   US   U-
  :¼  d  M%  US   US   U-
  :¼  d  M6  US   US   U-   ::  d  MG  US   US   4n	X“;  a  / / S.X9'   X9   S   R	                  U5        X9   S	   R	                  U5        M‹     M¦     U$ s  snf )
z]
Given a list of edges, return the points at which they intersect
within `tolerance` pixels.
ræ  c                 ó   >• U S   T:H  $ )Nr’  r   )rE   Úos    €r   rF   Ú(edges_to_intersections.<locals>.<lambda>1  s   ø€ ˜a Ñ.°!Ò3r   r   r«   rI   r¬   r   r‘  r�  )r·   r¸  rW   r   rX   )
r¹  r  rø   ÚintersectionsrB  Úv_edgesÚh_edgesr‘  r�  Úvertexs
       `     r   Úedges_to_intersectionsrH  *  s  ø€ ð
 €MáFPôÚFPÀŒŒVÔ3°UÓ;Ö<ÁjñÑ€Gô �G¤¨D°%Ó!8Ô9ˆÜ˜¤Z°°tÓ%<Ô=ˆAà�5‘˜a ™h¨Ñ4Õ5Ø�x‘[ Q u¡X°Ñ%;Õ<Ø�t‘W  4¡¨;Ñ!6Õ7Ø�t‘W  4¡¨;Ñ!6Õ7à˜D™' 1 U¡8Ð,�ØÓ.Ø24¸2Ñ,>�MÑ)ØÑ% cÑ*×1Ñ1°!Ô4ØÑ% cÑ*×1Ñ1°!Ö4ó >ñ :ð Ðùò!s   ‰#C/c                 ó   • [        U 5      $ )z(
Return the bounding box for an object.
)r
  )r©  s    r   Úobj_to_bboxrJ  C  s   € ô �sÓÐr   c                 ó
  ^ ^^^^• S[         4U 4S jjm[        [        T R                  5       5      5      m[	        T5      mS[
        4UU U4S jjmUU4S j[        [	        T5      5       5       n[        [        SU5      5      $ )a   
Given a list of points (`intersections`), return all rectangular "cells"
that those points describe.

`intersections` should be a dictionary with (x0, top) tuples as keys,
and a list of edge objects as values. The edge objects should correspond
to the edges that touch the intersection.
r,   c                 ó$  >• S nU S   US   :X  a:  U" TU    S   5      R                  U" TU   S   5      5      n[        U5      (       a  gU S   US   :X  a:  U" TU    S   5      R                  U" TU   S   5      5      n[        U5      (       a  gg)Nc                 ó4   • [        [        [        U 5      5      $ r/   )rÁ  rÁ   rJ  )r¹  s    r   Úedges_to_setÚCintersections_to_cells.<locals>.edge_connects.<locals>.edges_to_setU  s   € Ü”sœ;¨Ó.Ó/Ð/r   r   r‘  Tr   r�  F)r(   rZ   )r¥  Úp2rN  ÚcommonrD  s       €r   Úedge_connectsÚ-intersections_to_cells.<locals>.edge_connectsT  s©   ø€ ò	0ð ˆa‰5�B�q‘E‹>Ù! -°Ñ"3°CÑ"8Ó9×FÑFÙ˜]¨2Ñ.¨sÑ3Ó4óˆFô �6�{‰{Øàˆa‰5�B�q‘E‹>Ù! -°Ñ"3°CÑ"8Ó9×FÑFÙ˜]¨2Ñ.¨sÑ3Ó4óˆFô �6�{‰{ØØr   re   c                 ó¨  >• UTS-
  :X  a  g X   nXS-   S  nU Vs/ s H  oDS   US   :X  d  M  UPM     nnU Vs/ s H  oDS   US   :X  d  M  UPM     nnU Hn  nT
" X'5      (       d  M  U HV  nT
" X(5      (       d  M  US   US   4n	U	T;   d  M$  T
" X˜5      (       d  M3  T
" X—5      (       d  MB  US   US   U	S   U	S   4s  s  $    Mp     g s  snf s  snf )Nr   r   r   )Úpointsre   ÚptÚrestrE   Úbelowrœ  Úbelow_ptÚright_ptÚbottom_rightrR  rD  Ún_pointss             €€€r   Úfind_smallest_cellÚ2intersections_to_cells.<locals>.find_smallest_cellj  sô   ø€ Ø�˜1‘ÓØØ‰YˆØ˜!‘e�gˆˆá Ó2šD�q a¡D¨B¨q©E¡M—™DˆÐ2Ù Ó2šD�q a¡D¨B¨q©E¡M—™DˆÐ2ÛˆHÙ  ×.Ñ.Ùã!�Ù$ R×2Ñ2Ùà (¨¡¨X°a©[Ð9�ð " ]Õ2Ù% l×=Ó=Ù% l×=Ó=à˜q™E 2 a¡5¨,°q©/¸<È¹?ÐKÔKó "ñ	 ð  ùò% 3ùÚ2s   ›C
®C
ºCÁCc              3   ó6   >#   • U  H  nT" TU5      v •  M     g 7fr/   r   )r   re   r]  rU  s     €€r   r   Ú)intersections_to_cells.<locals>.<genexpr>„  s   øé € ÐJÒ7I°!Ñ" 6¨1×-Ð-Ò7Iùr<  N)rØ   r·   rW   ÚkeysrZ   r×   r[   r¸  )rD  Úcell_genrR  r]  r\  rU  s   ` @@@@r   Úintersections_to_cellsrc  J  sk   ü€ ð¤÷ ô& ”&˜×+Ñ+Ó-Ó.Ó/€FÜ�6‹{€Hð¤c÷ ñ õ4 K´u¼SÀ»[Ô7IÓJ€HÜ”�t˜XÓ&Ó'Ð'r   c                 ó–  ^• S[         4S jn[        U5      n[        5       m/ n/ n[        U5      (       Ga  [        U5      n[        U5       H™  nU" U5      n[        U5      S:X  a2  T[        U5      -  mUR	                  U5        UR                  U5        ML  [        U4S jU 5       5      n	U	S:”  d  Mi  T[        U5      -  mUR	                  U5        UR                  U5        M›     [        U5      U:X  a:  UR	                  [        U5      5        TR                  5         UR                  5         [        U5      (       a  GM  [        U5      (       a  UR	                  [        U5      5        [        [        U5      S-
  SS5       H±  n
[        R                  " 5       n[        5       n[        5       nXZ    H/  nX¾-  nUR                  US   5        UR                  US   5        M1     [        U5      S:  d=  [        U5      S:  d.  [        R                  U R                  U[        S95      (       d  M¯  XZ	 M³     [!        US	 S
9nU$ )zy
Given a list of bounding boxes (`cells`), return a list of tables that
hold those cells most simply (and contiguously).
r,   c                 ó    • U u  pp4X4X4X24X444$ r/   r   )r1   r   r«   r   r¬   s        r   Úbbox_to_cornersÚ(cells_to_tables.<locals>.bbox_to_cornersŽ  s#   € Ø"Ñˆ�Ø�	˜B˜<¨"¨°R°LÐAÐAr   r   c              3   ó,   >#   • U  H	  oT;   v •  M     g 7fr/   r   )r   r   Úcurrent_cornerss     €r   r   Ú"cells_to_tables.<locals>.<genexpr>§  s   øé € Ð"NÂ¸A¨Ö#7Âùs   ƒr   rN   r	   ©r<   c                 ó&   • [        S U  5       5      $ )Nc              3   ó4   #   • U  H  oS    US   4v •  M     g7f)r   r   Nr   ©r   r   s     r   r   Ú4cells_to_tables.<locals>.<lambda>.<locals>.<genexpr>Ö  s   é € Ð.GÂQÀ°!±°a¸±d­|ÂQùs   ‚)r#   )rª  s    r   rF   Ú!cells_to_tables.<locals>.<lambda>Ö  s   € ¬3Ñ.GÁQÓ.GÔ+Gr   rI   )r]   r·   rÁ  rZ   rX   ÚremoverÝ  Úclearr[   r7   Ú
EMPTY_RECTÚaddr|   Ú
issupersetÚget_textboxÚTEXTPAGErW   )Úpager^   rf  Úremaining_cellsÚcurrent_cellsÚtablesÚinitial_cell_countrj   Úcell_cornersÚcorner_countre   r0   Úx1_valsÚx0_valsr   rû  ri  s                   @r   Úcells_to_tablesr�  ˆ  s  ø€ ðB¤ô Bô ˜5“k€Oô
 “e€OØ€Mà€FÜ
ˆo×
Ò
Ü  Ó/ÐÜ˜Ö)ˆDÙ*¨4Ó0ˆLä�=Ó! QÓ&à¤3 |Ó#4Ñ4�Ø×$Ñ$ TÔ*Ø×&Ñ& tÖ,ô  #Ô"NÁÓ"NÓN�ð   !Õ#à#¤s¨<Ó'8Ñ8�OØ!×(Ñ(¨Ô.Ø#×*Ñ*¨4Ö0ñ# *ô( ˆ}ÓÐ!3Ó3à�M‰Mœ$˜}Ó-Ô.Ø×!Ñ!Ô#Ø×ÑÔ!ô5 ˆo×
Ô
ô> ˆ=×Ñà�‰”d˜=Ó)Ô*ô ”3�v“; ‘? B¨Ö+ˆÜ×ÒÓ ˆÜ“%ˆÜ“%ˆØ”ˆAØ‰FˆAØ�K‰K˜˜!™ÔØ�K‰K˜˜!™Öñ ô
 �‹L˜1ÓÜ�7‹|˜aÓÜ×&Ñ&Ø× Ñ ØÜ%ð !ð ÷ó ð ’	ñ% ,ô, �VÑ!GÑH€GØ€Nr   c                   ó   • \ rS rSrS rSrg)Ú	CellGroupiÚ  c                 óV  • Xl         [        [        [        S5      [	        S U5      5      5      [        [        [        S5      [	        S U5      5      5      [        [        [        S5      [	        S U5      5      5      [        [        [        S5      [	        S U5      5      5      4U l        g ©Nr   r   r	   r
   )r^   r#   rÁ   r   r¸  r"   r1   )rÄ   r^   s     r   rÅ   ÚCellGroup.__init__Û  sx   € ØŒ
ä””J˜q“M¤6¨$°Ó#6Ó7Ó8Ü””J˜q“M¤6¨$°Ó#6Ó7Ó8Ü””J˜q“M¤6¨$°Ó#6Ó7Ó8Ü””J˜q“M¤6¨$°Ó#6Ó7Ó8ð	
ˆ�	r   )r1   r^   N)r–   r—   r˜   r™   rÅ   rš   r   r   r   rƒ  rƒ  Ú  s   † õ
r   rƒ  c                   ó   • \ rS rSrSrg)ÚTableRowiå  r   Nr•   r   r   r   rˆ  rˆ  å  r›   r   rˆ  c                   ó   • \ rS rSrSrS rSrg)ÚTableHeaderié  z9PyMuPDF extension containing the identified table header.c                 ó4   • Xl         X l        X0l        X@l        g r/   )r1   r^   ÚnamesÚexternal)rÄ   r1   r^   rŒ  Úaboves        r   rÅ   ÚTableHeader.__init__ì  s   € ØŒ	ØŒ
ØŒ
Ø�r   )r1   r^   r�  rŒ  N)r–   r—   r˜   r™   rÖ   rÅ   rš   r   r   r   rŠ  rŠ  é  s
   † ÙCõr   rŠ  c                   óš   • \ rS rSrS r\S 5       r\S\4S j5       r\S\	4S j5       r
\S\	4S j5       rS\4S jrSS	 jrS
 rSS jrSrg)ÚTableió  c                 óT   • Xl         S U l        X l        U R                  5       U l        g r/   )rx  r<   r^   Ú_get_headerÚheader)rÄ   rx  r^   s      r   rÅ   ÚTable.__init__ô  s#   € ØŒ	ØˆŒØŒ
Ø×&Ñ&Ó(ˆ�r   c           
      ó  • U R                   n[        [        [        S5      U5      5      [        [        [        S5      U5      5      [	        [        [        S5      U5      5      [	        [        [        S5      U5      5      4$ r…  )r^   r#   rÁ   r   r"   )rÄ   r   s     r   r1   Ú
Table.bboxú  sa   € à�J‰Jˆä””J˜q“M 1Ó%Ó&Ü””J˜q“M 1Ó%Ó&Ü””J˜q“M 1Ó%Ó&Ü””J˜q“M 1Ó%Ó&ð	
ð 	
r   r,   c                 óÀ  • [        U R                  [        SS5      S9n[        [        [	        [        [        S5      U R                  5      5      5      5      n/ n[        R                  " U[        S5      5       HU  u  pEU Vs0 s H  ofS   U_M
     nn[        U Vs/ s H  o‡R                  U5      PM     sn5      n	UR                  U	5        MW     U$ s  snf s  snf )Nr   r   rI   )rW   r^   r   r·   rÁ  rÁ   rN  rO  rˆ  rT   rX   )
rÄ   rû  r¼  Úrowsr2   Ú	row_cellsrj   ÚxdictrE   Úrows
             r   r™  Ú
Table.rows  s³   € ä˜Ÿ™¬°A°qÓ)9Ñ:ˆÜ”&œœS¤¨A£°·
±
Ó;Ó<Ó=Ó>ˆØˆÜ%×-Ò-¨g´zÀ!³}ÖE‰LˆAÙ/8Ó9ªy t˜!‘W˜d’]©yˆEÐ9Ü±"Ó5²"¨QŸI™I ažL±"Ñ5Ó6ˆCØ�K‰K˜Öñ Fð ˆùò :ùÚ5s   ÂCÂC
c                 ó,   • [        U R                  5      $ r/   )rZ   r™  )rÄ   s    r   Ú	row_countÚTable.row_count  s   € ä�4—9‘9‹~Ðr   c                 ó~   • [        U R                   Vs/ s H  n[        UR                  5      PM     sn5      $ s  snf r/   )r"   r™  rZ   r^   )rÄ   r0   s     r   Ú	col_countÚTable.col_count  s+   € ä¨$¯)ª)Ó4ª) Q”C˜Ÿ™–L©)Ñ4Ó5Ð5ùÒ4s   ”:c           	      ó  • [         n/ nS[        4S jnU R                   HÛ  n/ nU Vs/ s H  ot" XuR                  5      (       d  M  UPM     nnUR                   H‹  n	U	c  S n
OqU Vs/ s H  ot" Xy5      (       d  M  UPM     nn[        U5      (       a?  U	S   US'   U	S   US'   SU;   a  U	S   U	S   -
  US	'   U	S
   U	S   -
  US'   [        U40 UD6n
OSn
UR                  U
5        M�     UR                  U5        MÝ     U$ s  snf s  snf )Nr,   c                 ó    • U S   U S   -   S-  nU S   U S   -   S-  nUu  pEpg[        X4:¬  =(       a    X6:  =(       a    X%:¬  =(       a    X':  5      $ )Nr«   r¬   r	   r   r   r¯  )r�   r1   Úv_midÚh_midr   r«   r   r¬   s           r   Úchar_in_bboxÚ#Table.extract.<locals>.char_in_bbox  sa   € Ø˜%‘[ 4¨¡>Ñ1°QÑ6ˆEØ˜$‘Z $ t¡*Ñ,°Ñ1ˆEØ"&ÑˆB�RÜØ‘×V 5¡:×V°E±L×VÀuÁ~óð r   r   rö   r   r÷   rß   r	   rò   r
   ró   rm   )r   rØ   r™  r1   r^   rZ   ry  rX   )rÄ   rc  rt   Ú	table_arrr¨  rœ  Úarrr�   Ú	row_charsrj   Ú	cell_textÚ
cell_charss               r   ÚextractÚTable.extract  s)  € ÜˆØˆ	ð	¬ô 	ð —9”9ˆCØˆCÙ*/ÓPª% $°<ÀÇhÁh×3OŸ©%ˆIÐPàŸ	œ	�Ø‘<Ø $‘Iñ *3ó"Ú)2 °lÀ4×6NŸ©ð ð "ô ˜:—‘Ø,0°©G˜˜yÑ)Ø,0°©G˜˜yÑ)Ø# vÓ-Ø59¸!±W¸tÀA¹wÑ5F˜F >Ñ2Ø6:¸1±gÀÀQÁÑ6G˜F ?Ñ3Ü$0°Ñ$F¸vÑ$F™	à$&˜	Ø—
‘
˜9Ö%ñ# "ð$ ×Ñ˜SÖ!ñ- ð0 Ðùò- Qùò"s   ©DÁDÁ(DÁ<Dc                 ój  • SnU R                   nU R                  nU R                   VVs/ s H  ofR                   Vs/ s H  owPM     snPM      nnn[	        U5       V	V
s/ s H  n	[	        U5       V
s/ s H  n
SPM     sn
PM!     nn	n
[        U5       H=  u  p¬[        U5       H)  u  p�Uc  M
  [        U R                  XŠ   U	   SS9Xº   U	'   M+     M?     U(       a†  [	        U5       H4  n	[	        US-
  5       H  n
X¹   U
S-      b  M  X¹   U
   X¹   U
S-   '   M!     M6     [	        U5       H4  n
[	        US-
  5       H  n	X¹S-      U
   b  M  X¹   U
   X¹S-      U
'   M!     M6     [        U R                  R                  5       HZ  u  p®U(       d  SU
S-    3nUR                  SS5      nU(       a&  [        R                  " UR                  S	S
5      5      nX>S-   -  nM\     US-  nUSSR                  S [	        U R                  5       5       5      -   S-   -  nU R                  R                  (       a  SOSn	X¹S  H[  nSn[        U5       H>  u  p­Uc  SnU(       a&  [        R                  " UR                  S	S
5      5      nXýS-   -  nM@     US-  nX?-  nM]     US-   $ s  snf s  snnf s  sn
f s  sn
n	f )a  Output table content as a string in Github-markdown format.

If "clean" then markdown syntax is removed from cell content.
If "fill_empty" then cell content None is replaced by the values
above (columns) or left (rows) in an effort to approximate row and
columns spans.

Ú|NT)r„   r   ÚColrq   rp   Ú-z&#45;c              3   ó&   #   • U  H  nS v •  M	     g7f)z---Nr   )r   re   s     r   r   Ú$Table.to_markdown.<locals>.<genexpr>o  s   é € Ð FÒ0E¨1¥Ò0Eùs   ‚z|
r   rm   )rŸ  r¢  r™  r^   r[   rð   r’   r<   r”  rŒ  ÚreplaceÚhtmlÚescaperÀ   r�  )rÄ   ÚcleanÚ
fill_emptyÚoutputr™  Úcolsr0   r   Ú
cell_boxesri   re   r^   rœ  rj   Únamer‡   s                   r   Úto_markdownÚTable.to_markdown=  sŠ  € ð ˆØ�~‰~ˆØ�~‰~ˆð 59·I²IÔ>²I¨q§'¢'Ó*¢'˜Q’q¡'Ô*±Iˆ
Ñ>ô 7<¸D´kÔB²k°¤ d¤Ó,¢˜1“$¡Ô,±kˆÑBÜ 
Ö+‰FˆAÜ$ Sž>‘�ØÓ#Ü"/ØŸ™ z¡}°QÑ'7À$ñ#�E‘H˜Q“Kó *ñ ,ö ô ˜4–[�Ü˜t a™xž�AØ‘x  A¡‘Ó.Ø*/©(°1©+˜™  Q¡›ó )ñ !ô ˜4–[�Ü˜t a™xž�AØ ™U‘| A‘Ó.Ø*/©(°1©+˜ !™e™ Q›ó )ñ !ô ! §¡×!2Ñ!2Ö3‰GˆAÞØ˜Q˜q™S˜E�{�Ø—<‘<  fÓ-ˆDÞÜ—{’{ 4§<¡<°°WÓ#=Ó>�Ø˜S‘jÑ ŠFñ 4ð 	�$‰ˆà�#˜Ÿ™Ñ F´°d·n±nÔ0EÓ FÓFÑFÈÑNÑNˆð —‘×%×%‰A¨1ˆð ˜“9ˆCØˆDÜ$ Sž>‘�ð ‘<Ø�DÞÜŸ;š; t§|¡|°C¸Ó'AÓB�DØ˜s™
Ñ"’ñ *ð �D‰LˆDØ‰NŠFñ ð ˜‰}Ðùòm +ùÓ>ùò -ùÓBs.   ªJ$½JÁJ$Á J/Á3J*Á?J/ÊJ$Ê*J/c                 óŒ  •  SSK n0 nU R	                  5       nU R
                  nU R
                  R                  n[        U5      n[        U5       H  nXh   n	U	(       a  M  SU 3Xh'   M     U[        [        U5      5      :w  a*  [        U5       H  nXh   n	U	SU 3:w  d  M  U SU	 3Xh'   M     UR                  (       d  USS n[        U5       H>  nXh   n
/ n[        [        U5      5       H  nUR                  XL   U   5        M     X³U
'   M@     UR                  U5      $ ! [         a    [        R                  " S5        e f = f)z/Return a pandas DataFrame version of the table.r   Nz!Package 'pandas' is not installedr³  r´  r   )ÚpandasÚModuleNotFoundErrorr7   Úmessager¯  r”  rŒ  rZ   r[   rÁ  r�  rX   Ú	DataFrame)rÄ   rc  ÚpdÚpd_dictr¯  ÚhdrrŒ  Úhdr_lenre   r¿  rJ   r×  ri   s                r   Ú	to_pandasÚTable.to_pandasƒ  s6  € ð	Ûð
 ˆØ—,‘,“.ˆØ�k‰kˆØ—‘×!Ñ!ˆÜ�e“*ˆä�w–ˆAØ‘8ˆDß�4Ø   ˜9�“ñ  ð ”cœ#˜e›*“oÓ%Ü˜7–^�Ø‘x�Ø˜S  ˜9Õ$Ø"#  A d V˜}�E“Hñ $ð
 �|�|Ø˜a˜b�kˆGä�w–ˆAØ‘(ˆCØˆEÜœ3˜w›<Ö(�Ø—‘˜W™Z¨™]Ö+ñ )à �C‹Lñ  ð �|‰|˜GÓ$Ð$øô= #ó 	Ü�OŠOÐ?Ô@Øð	ús   ‚D! Ä!"Ec                 óV  ^(• U R                   m(UnU(4S jnS n U R                  S   nUR                  n[        R                  " UR
                  5      n[        XvU R                  5       S   S5      n[        U R                  5      S:  a  U$ [        U5      S:  a  U$ U R                  S   n	[        S U	R                   5       5      (       a  U$ U" U5      n
U
(       a  U" U	R
                  5      (       d  U$ U" U 5      (       a  U$ USS	  Vs/ s H  o»b  US   OSPM     nnU7nSUl        UR                  Ul        T(R                  S
U[        R                  S9S   n[        U VVVs/ s H[  nUS     HN  nUS     HA  n[         R#                  US   5      (       a  M"  US   [        R$                  -  (       a  M?  UPMC     MP     M]     snnnS SS9n/ n/ n/ n['        [        U5      5       GH  nUU   nUS   S   nUUS   S   -
  nUS   [        R(                  -  nUS:X  a5  UR+                  U5        UR+                  U5        UR+                  U5        Mm  US	   nUS	   nUS	   nU(       a	  U(       d    O•UU-
  U::  d  [-        UU-
  US   S   -
  5      U::  a+  US   S   UU-
  US   S   U4US'   UUU'   U(       a  UUS	'   MÛ  UU-
  SU-  :”  a    O8UR+                  U5        UR+                  U5        UR+                  U5        GM     U/ :X  a  U$ USS nUR                  US   -
  US   :¼  a  U$ U
(       a  US   (       d  U$ U/ :X  a  U$ [        R.                  " 5       nU Vs/ s H  nUS   S   US	   :¼  d  M  UPM     sn H  nUUS   -  nM     UR0                  (       d  UnUR                  Ul        T(R                  SUS9 Vs/ s H  n[        R                  " USS 5      PM     nn[        [3        [5        U V s/ s H  n U S   PM
     sn 5      5      SS9n!/ nU! Hb  n"U V#V s/ s H7  n#U#c  M  U  H(  n U S   U":X  d  M  U S   U#:  d  M  U S   U#:”  d  M$  U#U 4PM*     M9     n$n#n U$/ :X  a  UR+                  U"5        Mb    O   U/ :X  a  U$ U7n%US	   U%l        U Vs/ s H(  nUb   US   U%R                  US   U%R                  4OSPM*     n&nU R
                  S   U%l        U R
                  S   U%l        U& Vs/ s HG  nUb?  T(R;                  U5      R=                  SS5      R=                  SS5      R?                  5       OSPMI     n'n[        [A        U%5      U&U'S5      $ ! [         a     gf = fs  snf s  snnnf s  snf s  snf s  sn f s  sn n#f s  snf s  snf ) aê  Identify the table header.

*** PyMuPDF extension. ***

Starting from the first line above the table upwards, check if it
qualifies to be part of the table header.

Criteria include:
* A one-line table never has an extra header.
* Column borders must not intersect any word. If this happens, all
  text of this line and above of it is ignored.
* No excess inter-line distance: If a line further up has a distance
  of more than 1.5 times of its font size, it will be ignored and
  all lines above of it.
* Must have same text properties.
* Starting with the top table line, a bold text property cannot change
  back to non-bold.

If not all criteria are met (or there is no text above the table),
the first table row is assumed to be the header.
c                 ó*  >• [         R                  " U R                  S   R                  5      nUSUR                  * SUR                  * 4-   nTR                  US9R                  5       S   nTR                  US9R                  5       S   nX4:w  a  gg)z£
Compare top row background color with color of same-sized bbox
above. If different, return True indicating that the original
table top row is already the header.
r   ©Úclipr   TF)r7   rV   r™  r1   r™  Ú
get_pixmapÚcolor_topusage)rÄ   Úbbox0ÚbboxtÚ
top_color0Ú
top_colortrx  s        €r   Útop_row_bg_colorÚ+Table._get_header.<locals>.top_row_bg_colorÀ  sˆ   ø€ ô —L’L §¡¨1¡×!2Ñ!2Ó3ˆEØ˜Q §¡ ¨q°5·<±<°-Ð@Ñ@ˆEØŸ™¨e˜Ð4×CÑCÓEÀaÑHˆJØŸ™¨e˜Ð4×CÑCÓEÀaÑHˆJØÓ'ØØr   c                 ó6   ^ • [        U 4S j[         5       5      $ )a,  Check if a row contains some bold text.

If e.g. true for the top row, then it will be used as (internal)
column header row if any of the following is true:
* the previous (above) text line has no bold span
* the second table row text has no bold span

Returns True if any spans are bold else False.
c              3   ót   >#   • U  H-  n[        US    US   US   US   4T5      (       d  M&  US   v •  M/     g7f)r   r   r   r   ÚboldN)r   r2  s     €r   r   Ú:Table._get_header.<locals>.row_has_bold.<locals>.<genexpr>Ø  sA   øé € ð â�AÜ  4¡¨!¨D©'°1°T±7¸A¸d¹GÐ DÀd×Kó ��&–	Úùs   ƒ%8¬8)r   r   r   s   `r   Úrow_has_boldÚ'Table._get_header.<locals>.row_has_boldÎ  s   ø€ ô ô åóó ð r   r   NFr	   r   c              3   ó(   #   • U  H  oS L v •  M
     g 7fr/   r   rn  s     r   r   Ú$Table._get_header.<locals>.<genexpr>ò  s   é € Ð-¢*˜Q�D�y¢*ùs   ‚rN   rÙ   ©rÐ  rw   rn   ro   rs   r…   rw   c                 ó   • U S   S   $ )Nr1   r
   r   ©Úss    r   rF   Ú#Table._get_header.<locals>.<lambda>  s   € ˜!˜F™) Aš,r   T)rJ   Úreverser1   r
   g      ø?é   r^  rÏ  r–  )ræ  rq   ru   z  rm   )!rx  r™  r^   r7   rV   r1   Ú
IndexErrorrŠ  r¯  rZ   Úallr   r   Úget_textÚTEXTFLAGS_TEXTrW   r|   ru  ÚTEXT_FONT_SUPERSCRIPTr[   ÚTEXT_FONT_BOLDrX   r{   rs  r\   r·   rÁ  r   r   rv  r·  rƒ   r]   ))rÄ   rø   Úy_deltar×  rÝ  rœ  r^   r1   Úheader_top_rowÚrow2Útop_row_boldr   Úcol_xrÐ  rn   r  Úlrä  rs   ÚselectÚline_heightsÚ
line_boldsre   r   r�  rÛ  r   Úh0Úbold0Úncliprq  r4   r0   Ú	word_topsr«   rE   ÚintersectingÚhdr_bboxÚ	hdr_cellsÚ	hdr_namesrx  s)                                           @r   r“  ÚTable._get_header§  s)  ø€ ð, �y‰yˆØˆõ	ò	ð 	Ø—)‘)˜A‘,ˆCØ—I‘IˆEÜ—<’< §¡Ó)ˆDô
 % T°$·,±,³.ÀÑ2CÀUÓKˆô ˆt�y‰y‹>˜AÓØ!Ð!ô ˆu‹:˜‹>Ø!Ð!ð �y‰y˜‰|ˆÜÑ- $§*¢*Ó-×-Ñ-Ø!Ð!ñ $ DÓ)ˆö ¡¨T¯Y©Y× 7Ñ 7Ø!Ð!á˜D×!Ñ!ð "Ð!ð ;@ÀÀ¹*ÓEº*°Q™��1’¨DÒ0¹*ˆÐEð ˆuˆØˆŒØ—'‘'ˆŒà—‘˜v¨D¼×8NÑ8N�ÐOØñ
ˆô ñ  õ	â�AØ˜7��AØ˜7��Aä ×+Ñ+¨A¨f©I×6ó ð ˜‘z¤G×$AÑ$AÕA÷ ñ $ñ á#ñ Ùó	ñ 'Øñ
ˆð ˆØˆØˆ
ô ”s˜5“z×"ˆAØ�a‘ˆAØ�6‘˜1‘ˆBØ�Q�v‘Y˜q‘\Ñ!ˆAØ�W‘:¤× 6Ñ 6Ñ6ˆDð �A‹vØ—‘˜bÔ!Ø×#Ñ# AÔ&Ø×!Ñ! $Ô'Ùð ˜‘ˆBØ˜bÑ!ˆBØ˜r‘NˆEæžTÙð �B‰w˜'Ó!¤S¨"¨r©'°Q°v±Y¸q±\Ñ)AÓ%BÀgÓ%MØ˜v™Y q™\¨2°©7°A°f±I¸a±LÀ"ÐE��&‘	Ø��a‘ÞØ%)�J˜r‘NÙØ�b‘˜3 ™8Ó#ÙØ�M‰M˜"ÔØ×Ñ Ô"Ø×Ñ˜d×#ñA #ðD �R‹<Ø!Ð!à˜˜�ˆð �7‰7�V˜A‘YÑ ,¨q¡/Ó1Ø!Ð!ö  
¨1§Ø!Ð!à�B‹;Ø!Ð!ô ×"Ò"Ó$ˆÙ"ÓAšU˜ a¨¡i°¡l°f¸R±jÑ&@—!™UÔAˆAØ�Q�v‘YÑŠEñ Bà�~�~ØˆDà—'‘'ˆŒð 48·=±=ÀÈt°=Ñ3TÓUÒ3T¨a”g—l’l 1 R a 5Ö)Ñ3Tˆ
ÐUÜœ4¤±:Ó$>²:¨a Q q¤T±:Ñ$>Ó ?Ó@È$ÑOˆ	àˆó ˆCñ ôâ�AØó ô $�AØ�Q‘4˜3‘;ó	 ð $% Q¡4¨!¡8ó	 ð 12°!±°q±ó	 ��A“ñ $ñ Ùð ñ ð ˜rÓ!Ø—‘˜cÖ"áñ ð �R‹<Ø!Ð!à�5ˆØ˜R‘jˆŒñ ó
â�ð 78±mˆQˆq‰T�8—;‘;  !¡ h§k¡kÑ2ÈÒMÙð 	ð 
ð —i‘i ‘lˆŒØ—i‘i ‘lˆŒñ ó
ò �ð ‘=ð × Ñ  Ó#×+Ñ+¨D°#Ó6×>Ñ>¸tÀSÓI×OÑOÔQàòñ ð 	ð 
ô œ5 ›?¨I°yÀ$ÓGÐGøôO ó 	Ùð	üòB Fùô	ùòN Bùò VùÚ$>ùóùò"
ùò
sl   š;U0 ÄV Å,3VÆ#VÇ VÍ/VÎVÏ#VÐVÐ5VÑ VÑVÑVÑ'VÒ,/V!Ô	AV&Õ0
U=Õ<U=)r^   r”  rx  r<   N)FT)r
   )r–   r—   r˜   r™   rÅ   Úpropertyr1   r·   r™  r×   rŸ  r¢  r¯  rÀ  rË  r“  rš   r   r   r   r‘  r‘  ó  s�   † ò)ð ñ
ó ð
ð ð�dó ó ðð ð˜3ó ó ðð ð6˜3ó 6ó ð6ð$ 4ô $ôLDòL"%÷HbHr   r‘  c                   ó"  • \ rS rSr% Sr\\S'   Sr\\S'   Sr\	\S'   Sr
\	\S'   \r\\S'   \r\\S	'   \r\\S
'   \r\\S'   \r\\S'   \r\\S'   Sr\\S'   \r\\S'   \r\\S'   Sr\\S'   \r\\S'   \r\\S'   Sr\\S'   SS jr\ SS j5       r!Sr"g)ÚTableSettingsiŒ  ro   Úvertical_strategyÚhorizontal_strategyNÚexplicit_vertical_linesÚexplicit_horizontal_linesrœ   r�   rž   rŸ   r    r¡   r
   r¢   r£   r¤   r¥   r¦   r§   Útext_settingsc           	      óH  • [          H*  n[        X5      =(       d    SS:  d  M  [        SU S35      e   S H?  n[        XS-   5      nU[        ;  d  M  [        U SSR	                  [        5       S35      e   U R
                  c  0 U l        S	 H=  nX@R
                  ;  d  M  U R
                  R                  S
S5      U R
                  U'   M?     S
U R
                  ;   a  U R
                  S
	 S H.  u  pE[        X5      [        L d  M  [        X[        X5      5        M0     U $ )ao  Clean up user-provided table settings.

Validates that the table settings provided consists of acceptable values and
returns a cleaned up version. The cleaned up version fills out the missing
values with the default values in the provided settings.

TODO: Can be further used to validate that the values are of the correct
    type. For example, raising a value error when a non-boolean input is
    provided for the key ``keep_blank_chars``.

:param table_settings: User-provided table settings.
:returns: A cleaned up version of the user-provided table settings.
:raises ValueError: When an unrecognised key is provided.
r   zTable setting 'z' cannot be negative)r‰   ÚverticalÚ	_strategyz_strategy must be one of{Ú,Ú})r  rø   r|  r
   ))r�   rœ   )rž   rœ   )r    rŸ   )r¡   rŸ   )r¦   r¥   )r§   r¥   )	ÚNON_NEGATIVE_SETTINGSÚgetattrrï   ÚTABLE_STRATEGIESrÀ   r  rT   ÚUNSETÚsetattr)rÄ   Úsettingr’  ÚstrategyrÚ  Úfallbacks         r   Ú__post_init__ÚTableSettings.__post_init__   s)  € ÷  -ˆGÜ˜Ó&×+¨!¨qÕ0Ü  ?°7°)Ð;OÐ!PÓQÐQñ -ó 6ˆKÜ˜t°;Ñ%>Ó?ˆHØÔ/Õ/Ü Ø"�mð $ØŸ™Ô"2Ó3Ð4°Bð8óð ñ 6ð ×ÑÑ%Ø!#ˆDÔó 3ˆDØ×-Ñ-Õ-Ø+/×+=Ñ+=×+AÑ+AÀ+ÈqÓ+Q�×"Ñ" 4Ó(ñ 3ð ˜$×,Ñ,Ó,Ø×"Ñ" ;Ð/ó
‰NˆDô �tÓ"¤eÔ+Ü˜¤G¨DÓ$;Ö<ñ
ð ˆr   c                 óþ   • Uc  U " 5       $ [        X5      (       a  U$ [        U[        5      (       a?  0 n0 nUR                  5        H  u  pEUS S S:X  a	  XSUSS  '   M  XRU'   M     X2S'   U " S0 UD6$ [        SU 35      e)Nrç  Útext_r  zCannot resolve settings: r   )r¶   rÙ   rÖ  rï   )ÚclsÚsettingsÚcore_settingsr  rh  r‘  s         r   ÚresolveÚTableSettings.resolveÕ  s˜   € àÑÙ“5ˆLÜ˜×&Ñ&ØˆOÜ˜¤$×'Ñ'ØˆMØˆMØ Ÿ™Ö(‘�Ø�R�a�5˜GÓ#Ø+, ! A B %Ó(à'( !Ó$ñ	 )ð
 .;˜/Ñ*ÙÑ'˜Ñ'Ð'äÐ8¸¸
ÐCÓDÐDr   )r  )r,   r  r/   )#r–   r—   r˜   r™   r  ÚstrÚ__annotations__r  r  r·   r  ÚDEFAULT_SNAP_TOLERANCErœ   rê   r  r�   rž   ÚDEFAULT_JOIN_TOLERANCErŸ   r    r¡   r¢   ÚDEFAULT_MIN_WORDS_VERTICALr£   ÚDEFAULT_MIN_WORDS_HORIZONTALr¤   r¥   r¦   r§   r  rÙ   r  Úclassmethodr  rš   r   r   r   r  r  Œ  sÕ   ‡ à$Ð�sÓ$Ø&Ð˜Ó&Ø$(Ð˜TÓ(Ø&*Ð˜tÓ*Ø2€N�EÓ2Ø#Ð�eÓ#Ø#Ð�eÓ#Ø2€N�EÓ2Ø#Ð�eÓ#Ø#Ð�eÓ#Ø€O�UÓØ :Ð˜Ó:Ø">Ð˜%Ó>Ø$%Ð˜EÓ%Ø&+Ð˜eÓ+Ø&+Ð˜eÓ+Ø€M�4Óô3ðj óEó óEr   r  c                   ó6   • \ rS rSrSrS	S jrS\4S jrS rSr	g)
ÚTableFinderié  a  
Given a PDF page, find plausible table structures.

Largely borrowed from Anssi Nurminen's master's thesis:
http://dspace.cc.tut.fi/dpub/bitstream/handle/123456789/21520/Nurminen.pdf?sequence=3

... and inspired by Tabula:
https://github.com/tabulapdf/tabula-extractor/issues/16
Nc                 ó   • [         R                  " U5      U l        S U l        [        R                  U5      U l        U R                  5       U l        [        U R                  U R                  R                  U R                  R                  5      U l        [        U R                  5      U l        [        U R                  U R                  5       Vs/ s H  n[!        U R                  U5      PM     snU l        g s  snf r/   )ÚweakrefÚproxyrx  r<   r  r  r  Ú	get_edgesr¹  rH  r¦   r§   rD  rc  r^   r�  r‘  r{  )rÄ   rx  r  Ú
cell_groups       r   rÅ   ÚTableFinder.__init__ô  s»   € Ü—M’M $Ó'ˆŒ	ØˆŒÜ%×-Ñ-¨hÓ7ˆŒØ—^‘^Ó%ˆŒ
Ü3Ø�J‰JØ�M‰M×2Ñ2Ø�M‰M×2Ñ2ó
ˆÔô
 ,¨D×,>Ñ,>Ó?ˆŒ
ô .¨d¯i©i¸¿¹ÔDó
âD�
ô �$—)‘)˜ZÖ(ÙDñ
ˆ�ùò 
s   Ã C;r,   c           
      óÒ  • U R                   nS HL  n[        XS-   5      nUS:X  d  M  [        USU-   S-   5      n[        U5      S:  d  M<  [        SU SU S	35      e   UR                  nUR
                  nUS
:X  d  US
:X  a$  [        [        40 UR                  =(       d    0 D6nO/ n/ nUR                  =(       d    /  H¿  n	[        U	[        5      (       a0  [        U	5       H  n
U
S   S:X  d  M  UR                  U
5        M!     MH  UR                  U	U	U R                  R                  S   U R                  R                  S   U R                  R                  S   U R                  R                  S   -
  SS.5        MÁ     US:X  a  [!        ["        S5      nO;US:X  a  [!        ["        SSS9nO%US
:X  a  [%        XqR&                  S9nOUS:X  a  / nO/ nX¸-   n/ nUR(                  =(       d    /  H¿  n	[        U	[        5      (       a0  [        U	5       H  n
U
S   S:X  d  M  UR                  U
5        M!     MH  UR                  U R                  R                  S   U R                  R                  S   U R                  R                  S   U R                  R                  S   -
  U	U	SS.5        MÁ     US:X  a  [!        ["        S5      nO;US:X  a  [!        ["        SSS9nO%US
:X  a  [+        XqR,                  S9nOUS:X  a  / nO/ nXí-   n[/        U5      [/        U5      -   n[1        UUR2                  UR4                  UR6                  UR8                  S9n[!        UUR:                  S9$ )N)r	  r‰   r
  r©   Ú	explicit_Ú_linesr	   zIf z"_strategy == 'explicit', explicit_zD_lines must be specified as a list/tuple of two or more floats/ints.r…   r’  r‘  r   r
   r4  ro   r¨   r‡   )r´  )r  r�  r   )r   r   rš  r«   r¬   r’  )r�   rž   r    r¡   )rµ  )r  r  rZ   rï   r  r  r_  r   r  r  r¶   rÙ   r«  rX   rx  r   rº  ÚEDGESr?  r£   r  r  r¤   r·   rþ  r�   rž   r    r¡   r¢   )rÄ   r  r’  r  ro   Úv_stratÚh_stratr^  Ú
v_explicitÚdescr°  Úv_baser‘  Ú
h_explicitÚh_baser�  r¹  s                    r   r*  ÚTableFinder.get_edges  s<  € Ø—=‘=ˆã5ˆKÜ˜x°{Ñ)BÓCˆHØ˜:Õ%Ü ¨+¸Ñ*CÀhÑ*NÓO�Ü�u“: •>Ü$Ø˜k˜]ð +$Ø$/ =ð 1'ð(óð ñ 6ð ×,Ñ,ˆØ×.Ñ.ˆà�fÓ ¨6Ó 1Ü!¤%ÑJ¨H×,BÑ,B×,HÀbÑJ‰EàˆEàˆ
Ø×4Ñ4×:¸Ò:ˆDÜ˜$¤×%Ñ%Ü% dÖ+�AØ˜Ñ'¨3Õ.Ø"×)Ñ)¨!Ö,ó ,ð ×!Ñ!à"Ø"Ø#Ÿy™yŸ~™~¨aÑ0Ø"&§)¡)§.¡.°Ñ"3Ø"&§)¡)§.¡.°Ñ"3°d·i±i·n±nÀQÑ6GÑ"GØ'*ñö	ñ ;ð" �gÓÜ!¤%¨Ó-‰FØ˜Ó&Ü!¤%¨¸Ñ?‰FØ˜ÓÜ% e×<WÑ<WÑX‰FØ˜
Ó"Ø‰FàˆFàÑˆàˆ
Ø×6Ñ6×<¸"Ò<ˆDÜ˜$¤×%Ñ%Ü% dÖ+�AØ˜Ñ'¨3Õ.Ø"×)Ñ)¨!Ö,ó ,ð ×!Ñ!à"Ÿi™iŸn™n¨QÑ/Ø"Ÿi™iŸn™n¨QÑ/Ø!%§¡§¡°Ñ!2°T·Y±Y·^±^ÀAÑ5FÑ!FØ#Ø"&Ø'*ñö	ñ =ð" �gÓÜ!¤%¨Ó-‰FØ˜Ó&Ü!¤%¨¸Ñ?‰FØ˜ÓÜ%Ø×&CÑ&Cñ‰Fð ˜
Ó"Ø‰FàˆFàÑˆä�Q“œ$˜q›'Ñ!ˆäØØ%×6Ñ6Ø%×6Ñ6Ø%×6Ñ6Ø%×6Ñ6ñ
ˆô ˜E¨h×.FÑ.FÑGÐGr   c                 óŽ   • [        U R                  5      nX:¼  a  [        S5      eUS:  a  X-  nUS:  a  M  U R                  U   $ )Nztable not on pager   )rZ   r{  rè  )rÄ   re   Útcounts      r   Ú__getitem__ÚTableFinder.__getitem__g  sF   € Ü�T—[‘[Ó!ˆØ‹;ÜÐ0Ó1Ð1Ø�!‹eØ‰KˆAð �!�eà�{‰{˜1‰~Ðr   )r^   r¹  rD  rx  r  r{  r<   r/   )
r–   r—   r˜   r™   rÖ   rÅ   r·   r*  r;  rš   r   r   r   r&  r&  é  s"   † ñô
ð aH˜4ô aHõFr   r&  c                 óÊ  • U R                   S-   nU R                  R                  nU R                  nU R	                  U[
        S9nU R                  SUS9S   nX0R                   -  nU GHu  nUS    GHg  n	U	S   n
[        U
S   S	5      [        U
S   S	5      4n
[        R                  " U
S   U
S   * U
S   U
S   SS5      nU
S   S:X  a  S
nOSn[        U	S   S S9 GH÷  nUS   nUS   n[        US   [        R                  -  =(       d    US   S-  5      n[        R                  " US   5      n[        US   S S9 GH�  n[        R                  " US   5      nUU-  n[        R                  " US   5      U-  nUR                   Ul        UR$                  Ul        US   n0 SU(       a  UR(                  UR*                  -
  OUR,                  UR.                  -
  _SUR,                  _SUR.                  U-   _SU_SUR,                  UR.                  -
  _S[1        U5      _S S!_S"U_S#S$_S%S&_S'U_SU(       a  UOUR,                  UR.                  -
  _S(U_S)S$_S*U_S+U_S,UR.                  _UUR(                  UR*                  -
  UR*                  UR(                  UR.                  UR,                  S-.En[2        R5                  U5        GM’     GMú     GMj     GMx     U$ ).z(Extract text as "rawdict" to fill CHARS.r   rá  Úrawdictrk  rn   ro   rr   r   r–  TFrs   c                 ó   • U S   S   $ ©Nr1   r   r   rã  s    r   rF   Úmake_chars.<locals>.<lambda>–  s   € ¸A¸f¹IÀaºLr   rI   Úfontr‚  rw   rv   é   Úcolorrt   c                 ó   • U S   S   $ r@  r   )r   s    r   rF   rA  �  s   € ÀÀ&Á	È!Âr   r1   Úoriginr   Úadvr¬   rè   r�  r™  r  ÚncsÚ	DeviceRGBÚnon_stroking_colorÚnon_stroking_patternNr˜  r�   Úpage_numberÚstroking_colorÚstroking_patternrÛ  r…   r«   )r  rš  r   r   r   r   )Únumberr   r™  Útransformation_matrixÚget_textpageÚFLAGSrê  rY   r7   ÚMatrixrW   rØ   rí  ÚsRGB_to_pdfrV   ÚPointrE   r°  r2   Úfr   r   r   r   r]   r   rX   )rx  rÐ  rL  Úpage_heightÚctmrw  rn   Údoctop_baser_   r‡   Úldirr  r  rŠ   r�  ÚfontsizeÚ	span_boldrD  r�   r1   Úbbox_ctmrF  r…   Ú	char_dicts                           r   Ú
make_charsr_  …  s!  € à—+‘+ ‘/€KØ—)‘)×"Ñ"€KØ
×
$Ñ
$€CØ× Ñ  d´%Ð Ð8€HØ�]‰]˜9¨xˆ]Ð8¸ÑB€FØ§¡Ñ+€KÜˆØ˜'•NˆDØ˜‘;ˆDÜ˜$˜q™' 1Ó%¤u¨T°!©W°aÓ'8Ð9ˆDÜ—^’^ D¨¡G¨d°1©g¨X°t¸A±wÀÀQÁÈÈAÓNˆFØ�A‰w˜!‹|Ø‘à�Ü˜t G™}Ñ2HÕI�Ø ™<�Ø ™<�Ü Ø˜‘M¤G×$:Ñ$:Ñ:×T¸dÀ<Ñ>PÐSTÑ>Tó�	ô  ×+Ò+¨D°©MÓ:�Ü" 4¨¡=Ñ6LÕM�DÜ"Ÿ<š<¨¨V©Ó5�DØ# c™z�HÜ$Ÿ]š]¨4°©>Ó:¸SÑ@�FØ%Ÿx™x�F”HØ%Ÿx™x�F”HØ ™9�Dð!Ø¶G˜tŸw™w¨¯©Ò0ÀÇÁÈ4Ï7É7ÑARð!à  $§'¡'ð!ð ! $§'¡'¨KÑ"7ð!ð # Hð	!ð
 ! $§'¡'¨D¯G©GÑ"3ð!ð !¤%¨£-ð!ð ˜{ð!ð -¨eð!ð /°ð!ð & vð!ð & {ð!ð ®G¡¸¿¹À4Ç7Á7Ñ9Jð!ð )¨%ð!ð +¨Dð!ð  	ð!ð   ð!!ð" ˜tŸw™wð#!ð$ $+Ø!%§¡¨4¯7©7Ñ!2Ø"Ÿg™gØ"Ÿg™gØ&Ÿk™kØ&Ÿk™kò/!�Iô2 —L‘L ×+ôA Nô Jô #ñ ðb €Or   c                 óš  ^ ^^^ ^!^"^#^$^%• UR                   m$UR                  m%UR                  nUR                  S:H  =(       d    UR                  S:H  m!T R
                  R                  m"T R                  T"-  mT R                  S-   m#T R
                  nT R                  S;   a&  UR                  u  p‰[        R                  " SSX˜5      nUb  [        R                  " U5      nOUnU$U%4S jmSUU!U U$U%4S jjn
U
" US9u  p³U$U%4S jm UU U"U#4S	 jnU GH.  nUS
   nUS   (       a8  US   S   S:X  a,  US   S   S:X  a   UR                  SUS   S   US   S   45        U GHÜ  nUS   S;  a  M  US   S:X  a<  USS  u  nnU" UUUU5      nU(       a   [        R                  [        U5      5        MR  MT  US   S:X  Ga±  US   R                  5       nUR                   U::  a´  UR                   UR                  :  aš  [#        UR$                  UR&                  -   5      S-  n[        R(                  " UUR*                  5      n[        R(                  " UUR,                  5      nU" UUUU5      nU(       a  [        R                  [        U5      5        GM5  UR                  U::  a´  UR                  UR                   :  aš  [#        UR,                  UR*                  -   5      S-  n[        R(                  " UR&                  U5      n[        R(                  " UR$                  U5      nU" UUUU5      nU(       a  [        R                  [        U5      5        GMù  U" UUR.                  UR0                  U5      nU(       a  [        R                  [        U5      5        U" UUR0                  UR                  U5      nU(       a  [        R                  [        U5      5        U" UUR                  UR2                  U5      nU(       a  [        R                  [        U5      5        U" UUR2                  UR.                  U5      nU(       a!  [        R                  [        U5      5        GM  GM  US   u  nnnnU" UUUU5      nU(       a  [        R                  [        U5      5        U" UUUU5      nU(       a  [        R                  [        U5      5        U" UUUU5      nU(       a  [        R                  [        U5      5        U" UUUU5      nU(       d  GM¾  [        R                  [        U5      5        GMß     GM1     SS SS.nU GH  nU" UUR.                  UR2                  U5      nU(       a  [        R                  [        U5      5        U" UUR0                  UR                  U5      nU(       a  [        R                  [        U5      5        U" UUR.                  UR0                  U5      nU(       a  [        R                  [        U5      5        U" UUR2                  UR                  U5      nU(       d  Mø  [        R                  [        U5      5        GM     Ub  [5        U[6        [8        45      (       d   eO/ nU Hd  u  nn[        R(                  " U5      n[        R(                  " U5      nU" UUUU5      nU(       d  MF  [        R                  [        U5      5        Mf     Ub  [5        U[6        [8        45      (       d   eO/ nU GH-  n[        R                  " U5      nU" UUR.                  UR0                  U5      nU(       a  [        R                  [        U5      5        U" UUR0                  UR                  U5      nU(       a  [        R                  [        U5      5        U" UUR                  UR2                  U5      nU(       a  [        R                  [        U5      5        U" UUR2                  UR.                  U5      nU(       d  GM  [        R                  [        U5      5        GM0     g )Nr¨   r   ©r"  r   r   c                 óF  >• UR                   T-
  U R                   s=::  a  UR                  T-   ::  d6  O  UR                   T-
  U R                  s=::  a  UR                  T-   ::  al  O  OiUR                  T-
  U R                  s=::  a  UR                  T-   ::  d7  O  UR                  T-
  U R                  s=::  a  UR                  T-   ::  a   g  OgU R                   T-
  UR                   s=::  a  U R                  T-   ::  d6  O  U R                   T-
  UR                  s=::  a  U R                  T-   ::  al  O  gU R                  T-
  UR                  s=::  a  U R                  T-   ::  d7  O  U R                  T-
  UR                  s=::  a  U R                  T-   ::  a   g  ggg)a  Detect whether r1, r2 are neighbors.

Defined as:
The minimum distance between points of r1 and points of r2 is not
larger than some delta.

This check supports empty rect-likes and thus also lines.

Note:
This type of check is MUCH faster than native Rect containment checks.
TF)r   r   r   r   )r$   r%   Úsnap_xÚsnap_ys     €€r   Úare_neighborsÚ!make_edges.<locals>.are_neighborsÚ  s6  ø€ ð �E‰E�F‰N˜bŸe™eÕ5 r§u¡u¨v¡~Õ5Ø�u‰u�v‰~ §¡Õ8¨"¯%©%°&©.Ö8à�E‰E�F‰N˜bŸe™eÕ5 r§u¡u¨v¡~Õ5Ø�u‰u�v‰~ §¡Õ8¨"¯%©%°&©.Ô8àñ 9àð �E‰E�F‰N˜bŸe™eÕ5 r§u¡u¨v¡~Õ5Ø�u‰u�v‰~ §¡Õ8¨"¯%©%°&©.Õ8ð ð	 �E‰E�F‰N˜bŸe™eÕ5 r§u¡u¨v¡~Õ5Ø�u‰u�v‰~ §¡Õ8¨"¯%©%°&©.Ô8àð 9ð ð Ør   c           	      ó”  >• U c  TR                  5       nOU SS n/ nU HL  nT
(       a1  US   S:X  a(  US   R                  T:”  a  US   R                  T:”  a  M;  UR                  U5        MN     [	        [        U Vs/ s H  o3S   PM	     sn5      S S9n/ nU(       a£  US   nSnU(       ac  S	n[        [        U5      S
-
  SS5       H;  nT	" XdU   5      (       d  M  XdU   R                  -  nXdU   R                  -  nXH	 SnM=     U(       a  Mc  [        [        U5      (       a  UR                  U5        US	 U(       a  M£  XR4$ s  snf )z:Detect and join rectangles of "connected" vector graphics.Nr@   rV  r   c                 ó2   • U R                   U R                  4$ r/   )r   r   rP   s    r   rF   Ú4make_edges.<locals>.clean_graphics.<locals>.<lambda>	  s   € ÈÏÉÈaÏdÉdÁ|r   rI   r   TFr   rN   )Úget_drawingsrš  r™  rX   rW   rÁ  r[   rZ   ÚtlÚbrr   r   )ÚnpathsÚallpathsÚpathsÚpÚprectsÚ	new_rectsÚprect0Úrepeatre   re  r¨   rx  rc  rd  s            €€€€€r   Úclean_graphicsÚ"make_edges.<locals>.clean_graphicsú  sJ  ø€ à‰>Ø×(Ñ(Ó*‰Hà™a�yˆHØˆÛˆAö Ø�f‘I Ó$Ø�f‘I—O‘O fÓ,Ø�f‘I×$Ñ$ vÓ-áØ�L‰L˜ŽOñ ô œ±Ó6²¨1˜vœY±Ñ6Ó7Ñ=SÑTˆØˆ	ö Ø˜A‘YˆFØˆFÞØ�Üœs 6›{¨Q™°°2Ö6�AÙ$ V°A©Y×7Ó7Ø¨¡)§,¡,Ñ.˜Ø¨¡)§,¡,Ñ.˜Ø"˜IØ!%šñ 7÷ �&ô œU F×+Ñ+à× Ñ  Ô(Ø�q�	÷! ˆfð$ ÐÐùò3 7s   Á=E)rm  c                 ó    >• [        U R                  UR                  -
  5      T::  d&  [        U R                  UR                  -
  5      T::  a  gg)z'Check if line is roughly axis-parallel.TF)r{   rE   r2   )r¥  rP  rc  rd  s     €€r   Úis_parallelÚmake_edges.<locals>.is_parallel+	  s:   ø€ äˆr�t‰t�b—d‘d‰{Ó˜vÓ%¬¨R¯T©T°B·D±D©[Ó)9¸VÓ)CØØr   c                 ód  >• T" X5      (       d  0 $ [        UR                  UR                  5      n[        UR                  UR                  5      n[        UR                  UR                  5      n[        UR                  UR                  5      nXCR                  :”  d-  XSR
                  :  d  XcR                  :”  d  XsR                  :  a  0 $ XCR
                  :  a  UR
                  nXSR                  :”  a  UR                  nXcR                  :  a  UR                  nXsR                  :”  a  UR                  nXT-
  nXv-
  n	X‰s=:X  a  S:X  a   0 $   0 SU_STU-
  _SU_STU-
  _SU_SU	_SXF4XW4/_S	U S   _S
S_SS_SS_SU S   (       a  U S   OU S   _SS_SS_ST_SS_SS_UUUT-   S.En
U
$ )z;Given 2 points, make a line dictionary for table detection.r   r   r   r   r   rš  r™  rŸ  Ú	linewidthÚstrokeTÚfillFÚevenoddrM  rD  rJ  Nr˜  r‡   rL  rN  rK  )r«   r¬   rè   )r#   rE   r"   r2   r   r   r   r   )rp  r¥  rP  rÐ  r   r   r   r   rš  r™  Ú	line_dictÚdoctop_basisrx  rW  rL  s              €€€€r   Ú	make_lineÚmake_edges.<locals>.make_line1	  s  ø€ á˜2×"Ñ"ØˆIä�—‘�r—t‘t‹_ˆÜ�—‘�r—t‘t‹_ˆÜ�—‘�r—t‘t‹_ˆÜ�—‘�r—t‘t‹_ˆð —‘‹<˜2§¡›<¨2·±«<¸2ÇÁ»<ØˆIà—‘‹<Ø—‘ˆBà—‘‹<Ø—‘ˆBà—‘‹<Ø—‘ˆBà—‘‹<Ø—‘ˆBà‘ˆØ‘ˆØÕ˜aÔØˆIð  ð
Ø�"ð
à�+ Ñ"ð
ð �"ð
ð �+ Ñ"ð	
ð
 �Uð
ð �fð
ð �R�H˜r˜hÐ'ð
ð ˜˜7™ð
ð �dð
ð �Eð
ð �uð
ð ¨A¨g¯J˜a šj¸A¸f¹Ið
ð ! $ð
ð ˜6ð
ð ˜;ð
ð   ð!
ð" # Dð#
ð$ ØØ˜<Ñ'ò)
ˆ	ð, Ðr   rÖ  Ú	closePathró  rN   r	   )ró  ÚreÚqur„  )r   r   r   )rD  r}  rš  r/   )r�   rž   r¢   r  r  r   r™  rO  r'  rl  r7   rV   rX   r0  r”  Ú	normalizerš  r{   r   r   rU  r   r   rk  ÚblÚtrr¶   r]   r·   )&rx  rÐ  Útsetro  Ú	add_linesÚ	add_boxesrµ  Úprectrq  r�  ru  r  r�  rp  rÖ  re   r¥  rP  r  r   rE   r2   ÚulÚurÚllÚlrÚpathr1   Úboxr0   re  r€  rx  r¨   rW  rL  rc  rd  s&   `                             @@@@@@@@r   Ú
make_edgesr“  Æ  sd  ÿø€ Ø×"Ñ"€FØ×"Ñ"€FØ×%Ñ%€Jà×Ñ .Ñ0÷ 	6Ø×#Ñ# ~Ñ5ð ð —)‘)×"Ñ"€KØ—;‘; Ñ,€LØ—+‘+ ‘/€KØ�I‰I€EØ‡}�}˜	Ó!Ø�x‰x‰ˆÜ—’˜Q  1Ó(ˆØÑÜ�|Š|˜DÓ!‰àˆö÷@- ó - ñ^ #¨%Ñ0�M€Fö÷4ð 4ôl ˆØ�'‘
ˆð ˆ[�>˜e A™h q™k¨SÓ0°U¸2±Y¸q±\ÀSÓ5HØ�L‰L˜#˜u R™y¨™|¨U°1©X°a©[Ð9Ô:äˆAØ�‰tÐ,Ó,Ùà�‰t�s‹{Ø˜1˜2˜‘��BÙ% a¨¨R°Ó6�	ÞÜ—L‘L¤¨iÓ!8Ö9ñ ð �1‘˜”ð ˜‘t—~‘~Ó'�ð —J‘J *Ó,°·±¸d¿k¹kÓ1Iä˜DŸG™G d§g¡gÑ-Ó.°Ñ2�AÜ Ÿš q¨$¯'©'Ó2�BÜ Ÿš q¨$¯'©'Ó2�BÙ )¨!¨R°°TÓ :�IÞ ÜŸ™¤\°)Ó%<Ô=Úð —K‘K :Ó-°$·+±+ÀÇ
Á
Ó2Jä˜DŸG™G d§g¡gÑ-Ó.°Ñ2�AÜ Ÿš t§w¡w°Ó2�BÜ Ÿš t§w¡w°Ó2�BÙ )¨!¨R°°TÓ :�IÞ ÜŸ™¤\°)Ó%<Ô=Úá% a¨¯©°$·'±'¸4Ó@�	ÞÜ—L‘L¤¨iÓ!8Ô9á% a¨¯©°$·'±'¸4Ó@�	ÞÜ—L‘L¤¨iÓ!8Ô9á% a¨¯©°$·'±'¸4Ó@�	ÞÜ—L‘L¤¨iÓ!8Ô9á% a¨¯©°$·'±'¸4Ó@�	ÞÜ—L‘L¤¨iÓ!8×9ò ð
 "# 1¡‘��B˜˜Bá% a¨¨R°Ó6�	ÞÜ—L‘L¤¨iÓ!8Ô9á% a¨¨R°Ó6�	ÞÜ—L‘L¤¨iÓ!8Ô9á% a¨¨R°Ó6�	ÞÜ—L‘L¤¨iÓ!8Ô9á% a¨¨R°Ó6�	ß‘9Ü—L‘L¤¨iÓ!8×9ôO ñ ð` ¨°qÑ9€DÜˆÙ˜d D§G¡G¨T¯W©W°dÓ;ˆ	ÞÜ�L‰Lœ iÓ0Ô1á˜d D§G¡G¨T¯W©W°dÓ;ˆ	ÞÜ�L‰Lœ iÓ0Ô1á˜d D§G¡G¨T¯W©W°dÓ;ˆ	ÞÜ�L‰Lœ iÓ0Ô1á˜d D§G¡G¨T¯W©W°dÓ;ˆ	ßˆ9Ü�L‰Lœ iÓ0×1ñ ð" ÑÜ˜)¤e¬T ]×3Ñ3Ð3Ñ3àˆ	Û‰ˆˆBÜ�]Š]˜2ÓˆÜ�]Š]˜2ÓˆÙ˜d B¨¨DÓ1ˆ	ßˆ9Ü�L‰Lœ iÓ0Ö1ñ ð ÑÜ˜)¤e¬T ]×3Ñ3Ð3Ñ3àˆ	ÜˆÜ�LŠL˜ÓˆÙ˜d A§D¡D¨!¯$©$°Ó5ˆ	ÞÜ�L‰Lœ iÓ0Ô1Ù˜d A§D¡D¨!¯$©$°Ó5ˆ	ÞÜ�L‰Lœ iÓ0Ô1Ù˜d A§D¡D¨!¯$©$°Ó5ˆ	ÞÜ�L‰Lœ iÓ0Ô1Ù˜d A§D¡D¨!¯$©$°Ó5ˆ	ß‰9Ü�L‰Lœ iÓ0×1ò r   c           	      óB  • U R                   nU R                  nU R                   nUS:X  aM  [        R                  " SSSSUR                  UR
                  -
  UR                  -
  UR                  -
  S5      nOˆUS:X  aM  [        R                  " SSSSSUR
                  UR                  -
  UR                  -
  UR                  -
  5      nO5[        R                  " SSSSSUR                  -  SUR                  -  5      nX@R                  -  nS[        U5      -  n[        R                  R                  XS5      nUS;   a.  Uu  p‰p«X“l        Xƒl        X³l        X£l        U R                  U5        U R                  S5        U R                  nU R                  nXÍ   n XX!4$ )zµNullify page rotation.

To correctly detect tables, page rotation must be zero.
This function performs the necessary adjustments and returns information
for reverting this changes.
r"  r   r   r   éþÿÿÿs   %g %g %g %g %g %g cm ra  )Úmediaboxr'  r7   rS  r   r   r   r   Úderotation_matrixr]   ÚTOOLSÚ_insert_contentsÚset_mediaboxÚset_rotationÚparentrO  )rx  r–  ÚrotÚmbÚmat0ÚmatÚcmdÚxrefr   r   r   r   ÚdocÚpnos                 r   Úpage_rotation_set0r¥  è	  s^  € ð �}‰}€HØ
�-‰-€Cà	�‰€Bà
ˆbƒyä�~Š~˜a  A q¨"¯%©%°"·%±%©-¸"¿%¹%Ñ*?À"Ç%Á%Ñ*GÈÓK‰Ø	�‹ä�~Š~˜a  A q¨!¨R¯U©U°R·U±U©]¸R¿U¹UÑ-BÀRÇUÁUÑ-JÓK‰ä�~Š~˜a  A q¨"¨r¯u©u©*°b¸2¿5¹5±jÓAˆð ×'Ñ'Ñ
'€CØ
"¤U¨3£ZÑ
/€CÜ�=‰=×)Ñ)¨$°QÓ7€Dð ˆiÓØ‰ˆ�ØŒØŒØŒØŒØ×Ñ˜"Ôà×Ñ�aÔð �+‰+€CØ
�+‰+€CØ‰8€DØ�sÐ$Ð$r   c                 ó¦   • U R                   nUR                  US5        U R                  U5        U R                  U5        U R                  nXE   n U $ )zLReset page rotation to original values.

To be used before we return tables.ó    )rœ  Úupdate_streamrš  r›  rO  )rx  r¢  r�  r–  r£  r¤  s         r   Úpage_rotation_resetr©  
  sN   € ð �+‰+€CØ×Ñ�d˜DÔ!Ø×Ñ�hÔØ×Ñ�cÔØ
�+‰+€CØ‰8€DØ€Kr   ro   r  r  Úvertical_linesÚhorizontal_linesrœ   r�   rž   rŸ   r    r¡   r¢   r£   r¤   r¥   r¦   r§   c           	      óÀ	  ^$^%• [         R                  " 5         [        R                  5         [        R                  5         S n[        [         R                  R                  5       5      n[         R                  R                  S5        U R                  S:w  a  [        U 5      u  n nnnOSu  nnnUc  [        nUc  [        nU
c  [        n
Uc  [        nUc  [        nUc  [        nUb  UnUn0 SU_SU_SU_SU_SU_S	U_S
U_SU	_SU
_SU_SU_SU_SU_SU_SU_SU_SU_UUS.En[         R                  R                  5       n U R                  5         U R                  (       a^  [         R                  R                  S5        U R                   V s/ s H'  n U S   S:X  d  M  [         R                  " U S S 5      PM)     n!n O/ n!U!(       a  OiU R                  b\  [        U 5      n"U"[         R                  R                  U5        Ub  [!        U UUU5      n [         R                  R                  U5        $ ["        R%                  US9n#U#U l        [)        XS9n[+        U UU#UUUS9  [        U U#S9n"UU"l        U!(       a?  U"R.                   V$^$s/ s H!  m$[1        U$4S jU! 5       5      (       d  M  T$PM#     sn$U"l        U! V%^%s/ s H+  m%[3        U%4S jU"R.                   5       5      (       d  M)  T%PM-     n&n%U&(       aJ  UR5                  5        V's/ s H  n'[         R                  " U'S S 5      PM     n(n'U R7                  [8        S9n)U& H5  n*[;        W)W(U*5      n+U"R.                  R=                  [?        U U+5      5        M7      [         R                  R                  U5        Ub  [!        U UUU5      n [         R                  R                  U5        U"R.                   H
  n-UU-l        M     U"$ s  sn f s  sn$f s  sn%f s  sn'f ! [@         a{  n,[         RB                  " S[E        U,5      -  5         S n,A,[         R                  R                  U5        Ub  [!        U UUU5      n [         R                  R                  U5        g S n,A,ff = f! [         R                  R                  U5        Ub  [!        U UUU5      n [         R                  R                  U5        f = f) NTr   )NNNr  r  r  r  rœ   r�   rž   rŸ   r    r¡   r¢   r£   r¤   r¥   r¦   r§   Útext_tolerance)Útext_x_toleranceÚtext_y_tolerancerN   Útabler–  )r  rÏ  )rÐ  r‰  ro  rŠ  r‹  c              3   óV   >#   • U  H  n[        TR                  U5      S :¬  v •  M      g7f©g333333ã?N©r+   r1   )r   r0   Útabs     €r   r   Úfind_tables.<locals>.<genexpr>”
  s!   øé € Ð?º°A”t˜CŸH™H aÓ(¨CÖ/ºùó   ƒ&)c              3   óV   >#   • U  H  n[        TUR                  5      S :  v •  M      g7fr²  r³  )r   r´  r0   s     €r   r   rµ  ˜
  s!   øé € Ð#RÂzÀ¤D¨¨C¯H©HÓ$5¸Ö$;Âzùr¶  )rw   z#find_tables: exception occurred: %s)#r7   Ú_warn_layout_oncer   rr  r0  rØ   r˜  Úset_small_glyph_heightsr'  r¥  r  Úunset_quad_correctionsÚ
get_layoutÚlayout_informationrV   r&  r©  r  r  Útable_settingsr_  r“  r<   r{  r   ré  ÚextractWORDSrQ  ÚTABLE_DETECTOR_FLAGSrk   rX   r‘  Ú	ExceptionrÅ  r  ).rx  rÐ  r  r  rª  r«  rœ   r�   rž   rŸ   r    r¡   r¢   r£   r¤   r¥   r¦   r§   r­  r®  r¯  r  rŠ  r‹  ro  rw  Ú	old_smallÚold_xrefÚold_rotÚold_mediaboxr  Úold_quad_correctionsr  ÚboxesÚtbfr‰  r´  r0   Úmy_boxesrq  r4   Útp2r   r^   r°  r°  s.                                       ``        r   Úfind_tablesrÊ  !
  sì  ù€ ô6 ×ÒÔÜ	‡K�K„MÜ	‡K�K„MØ€HÜ”W—]‘]×:Ñ:Ó<Ó=€IÜ‡M�M×)Ñ)¨$Ô/Ø‡}�}˜ÓÜ0BÀ4Ó0HÑ-ˆˆh˜¡à*:Ñ'ˆ�'˜<àÑÜ ÐØÑÜ ÐØÑÜ ÐØÑÜ ÐØÑ'Ü#(Ð ØÑ'Ü#(Ð ØÑØ$ÐØ&ÐðØÐ.ðàÐ2ðð 	" >ðð 	$Ð%5ð	ð
 	˜.ðð 	Ð,ðð 	Ð,ðð 	˜.ðð 	Ð,ðð 	Ð,ðð 	˜?ðð 	Ð0ðð 	Ð 4ðð 	!Ð"8ðð 	#Ð$<ðð  	#Ð$<ð!ð" 	˜.ð#ð$ -Ø,ò'€Hô, #Ÿ=™=×?Ñ?ÓAÐð9CØ�‰ÔØ×"×"Ü�M‰M×0Ñ0°Ô6à-1×-DÒ-DóÚ-D¨ÈÈ"ÉÐQXÑHXÓ#”—’˜Q˜r ˜UÖ#Ñ-Dð ð ˆEð ˆEæØØ×$Ñ$Ñ0ô ˜dÓ#ˆCØôL 	�‰×-Ñ-¨iÔ8ØÑÜ& t¨X°wÀÓMˆDÜ�‰×,Ñ,Ð-AÕBôO ×$Ñ$¨hÐ$Ð7ˆØ"ˆÔä˜dÑ.ˆÜØØØØØØò	
ô ˜$¨Ñ.ˆØˆŒÞð Ÿ:š:ôâ%�CÜÔ?¹Ó?×?÷ Ù%ñˆCŒJñ ô
Ú�!¤Ô#RÀsÇzÂzÓ#R× R�A‘uð 	ð 
ö Ø7?×7LÑ7LÔ7NÓOÒ7N°!œ'Ÿ,š, q¨¨! uÖ-Ñ7NˆJÐOØ×#Ñ#Ô*>Ð#Ð?ˆCÛˆDÜ(¨¨j¸$Ó?ˆEØ�J‰J×Ñœe D¨%Ó0Ö1ò ô 	�‰×-Ñ-¨iÔ8ØÑÜ& t¨X°wÀÓMˆDÜ�‰×,Ñ,Ð-AÔBØ—”ˆØ!ˆŽñ à€Jùòqùò>ùò
ùò Pøô
 ó Ü�ŠÐ=ÄÀAÃÑFÔGÛä�‰×-Ñ-¨iÔ8ØÑÜ& t¨X°wÀÓMˆDÜ�‰×,Ñ,Ð-AÕBûðûô 	�‰×-Ñ-¨iÔ8ØÑÜ& t¨X°wÀÓMˆDÜ�‰×,Ñ,Ð-AÕBús|   ÅAP ÆO0Æ$O0Ç&P È7AP ÊO5Ê1O5Ê7P Ë(O:Ë0O:Ë6P Ì#O?Ì4AP Ï0P Ð
R	Ð"RÐ0R ÒR	Ò	R ÒAS)F)r   )NNr   )r   )r   r   r/   )NNNNN)nrÖ   ÚinspectrN  r  r¸  Úcollections.abcr   Údataclassesr   Úoperatorr   r(  r7   r   r0  r   rw  ÚFZ_STEXT_BOLDr~   ÚFZ_STEXT_STRIKEOUTr}   rë  ÚTEXT_COLLECT_STYLESÚTEXT_ACCURATE_BBOXESÚTEXT_MEDIABOX_CLIPrR  ÚTEXT_SEGMENTÚTEXT_COLLECT_VECTORSr¿  rÁ  Ú
whitespacer|   r   r   r+   rØ   r5   r>   rk   r’   rê   r”   r  r  r  r   r!  r"  r#  ra  r  r  r  r
  rî   r·   r»   r½   rÛ   r  r_  Ú	signaturer  Ú
parametersra  rg  rf  rl  r  ry  r  rŽ  r”  r�  r¦  r«  rº  r¿  rÙ   rÈ  rñ   rÙ  rä  rê  rî  rô  rþ  r  r  r  rÎ   r×   r  r)  r?  rH  rJ  rc  r�  rƒ  rˆ  rŠ  r‘  r  r&  r_  r“  r¥  r©  rÊ  r   r   r   Ú<module>rÙ     s/  ðñHóT Û Û Û Ý $Ý !Ý Û Û Ý ð 	€Ø
€Ø€Ø×Ñ€	Ø×)Ñ)€àØ×Ññà×!Ñ!ñ"ð ×"Ñ"ñ#ð × Ñ ñ	!ð ð Ø×"Ñ"ñ#à×Ññð ×"Ñ"ñ#ð × Ñ ñ	!ð ñ �6×$Ñ$Ó%€òò	ò	9ðM¨tô Mòò8ôveôZ	�ô 	òÐ ò  AÐ Ù�1‹€ØÐ ØÐ ØÐ Ø Ð ØÐ ØÐ ØÐ ØÐ Ù˜˜u d¨HÓ5€ð ØØØØØØñ€	ð	 ˜4ô 	 ÷#ñ #÷L^!ñ ^!÷BTñ Tðn8˜ð 8¨Dô 8ð ×"Ò" 7×#5Ñ#5Ó6×AÑA×FÑFÓH€Ø×)Ò)¨-Ó8×CÑC×HÑHÓJÐ ð˜Dð ¨wô ð˜ð ¨3ô ðF "ñØðð 	õñ,˜ð ,¨dõ ,ò.ð%&˜4ô %&ðP˜Tô ð$H˜ô Hð ØØñ	%ð
 
õ%ñ$ Tõ ð(1¨Dô 1ð5¨dô 5ð @˜3ô @ð,	4˜Sð 	4°ô 	4ð 'Ø&ô!ð$@˜Cô @ð6 8Nñ ¨õ ò6ðBM˜$ô Mð2 ô 2ò5ò3ð 3Oñ &¨Cõ &òRð 3Mñ :¨Cõ :ñzÀ4õ ò2ò;(ð|O Dô O÷d
ñ 
ô	ˆyô 	÷ñ ÷VHñ VHðr ÷YEð YEó ðYE÷xDñ DðNô*9ôB_2òD	)%òX
ð 
Ø$Ø&ØØ!Ø2Ø"Ø"Ø2Ø"Ø"ØØ :Ø">Ø$%Ø&*Ø&*ØØØØØØØ
ñ3Ið ðIð ð	Ið
 ðIð ðIð ðIð ðIð ðIð ðIð ðIð ðIð ðIð ðIð  ðIð  "ð!Ið" $ð#Ið$ $ö%Ir   