ó
    /j-jŸe  ã                  ó
  • S r SSKJr  SSKrSSKJr  SSKrSSKJr  SSK	J
r
  SSK	Jr  SS	K	Jr  SS
K	Jr  SSK	Jr  SSK	Jr  SSK	Jr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SrS rS r " S S\5      rg)z+Implementation of the Lattice table parser.é    )ÚannotationsN)ÚAnyé   )ÚImageConversionBackend)Ú_line_crossing)Úadaptive_threshold)Úfind_contours)Úfind_joints)Úfind_joints_from_lines)Ú
find_lines)Úfind_lines_from_layout)Úbbox_from_str)Úmerge_close_lines)Úscale_image)Ú	scale_pdf)Úsegments_in_bbox)Útext_in_bbox_per_axisé   )Ú
BaseParserg     €V@c                ó’   • U u  p#pEX$::  a  X$4OXB4u  pgX5::  a  X54OXS4u  p‰U H"  u  p«pÍXz:¼  d  M  Xl::  d  M  X›:¼  d  M  X�::  d  M"    g   g)a  True if a ruled line's extent overlaps any of the given bboxes.

Used by the vector engine to keep only lines relevant to the
user-supplied ``table_regions``. ``line`` is ``(x0, y0, x1, y1)`` and
each bbox is ``(x0, y0, x1, y1)`` = (left, bottom, right, top), both in
PDF coords.
TF© )ÚlineÚbboxesÚlx0Úly0Úlx1Úly1ÚlxminÚlxmaxÚlyminÚlymaxÚx0Úy0Úx1Úy1s                 ÚT/home/mande/repo/quber/.venv/lib/python3.13/site-packages/camelot/parsers/lattice.pyÚ_line_in_any_bboxr'   #   sW   € ð Ñ€CˆcØ!$£�C‘:°#°�L€EØ!$£�C‘:°#°�L€EÛ ‰ˆ�Ø�;˜5�;¨5­;¸5½;Ùñ !ð ó    c                óÎ   • Uu  p4pV/ nU  HW  nU HN  n	[        X‰5      n
U
c  M  X:S   s=::  a  U::  d  M$  O  M(  XJS   s=::  a  U::  d  M9  O  M=  UR                  U
5        MP     MY     U$ )zäLine crossings (joints) that fall inside ``bbox`` (PDF coords).

The vector engine's equivalent of the raster ``find_joints`` over a
user-supplied ``table_areas`` box: every h/v line intersection within
the box becomes a joint.
r   r   )r   Úappend)Úh_linesÚv_linesÚbboxr"   r#   r$   r%   ÚjointsÚhÚvÚpts              r&   Ú_joints_in_bboxr2   4   sj   € ð �N€BˆBØ€FÛˆÛˆAÜ Ó%ˆBØ‹~ "¨1©Õ"3°×"3Ñ"3¸À¹eÕ8IÀr×8IÑ8IØ—‘˜bÖ!ó ñ ð
 €Mr(   c                  óú   ^ • \ rS rSrSr                    SU 4S jjr\          SS j5       r\        SS j5       rU 4S jr	SS jr
S rS	 r\S
 5       rS rS rS rS rS rS rSrU =r$ )ÚLatticeéE   uÏ  Lattice method looks for lines between text to parse the table.

Parameters
----------
table_regions : list, optional (default: None)
    List of page regions that may contain tables of the form x1,y1,x2,y2
    where (x1, y1) -> left-top and (x2, y2) -> right-bottom
    in PDF coordinate space.
table_areas : list, optional (default: None)
    List of table area strings of the form x1,y1,x2,y2
    where (x1, y1) -> left-top and (x2, y2) -> right-bottom
    in PDF coordinate space.
process_background : bool, optional (default: False)
    Process background lines.
line_scale : int, optional (default: 15)
    Line size scaling factor. The larger the value the smaller
    the detected lines. Making it very large will lead to text
    being detected as lines.
copy_text : list, optional (default: None)
    {'h', 'v'}
    Direction in which text in a spanning cell will be copied
    over.
shift_text : list, optional (default: ['l', 't'])
    {'l', 'r', 't', 'b'}
    Direction in which text in a spanning cell will flow.
split_text : bool, optional (default: False)
    Split text that spans across multiple cells.
flag_size : bool, optional (default: False)
    Flag text based on font size. Useful to detect
    super/subscripts. Adds <s></s> around flagged text.
strip_text : str, optional (default: '')
    Characters that should be stripped from a string before
    assigning it to a cell.
line_tol : int, optional (default: 2)
    Tolerance parameter used to merge close vertical and horizontal
    lines.
joint_tol : int, optional (default: 2)
    Tolerance parameter used to decide whether the detected lines
    and points lie close to each other.
threshold_blocksize : int, optional (default: 15)
    Size of a pixel neighborhood that is used to calculate a
    threshold value for the pixel: 3, 5, 7, and so on.

    For more information, refer `OpenCV's adaptiveThreshold
    <https://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold>`_.
threshold_constant : int, optional (default: -2)
    Constant subtracted from the mean or weighted mean.
    Normally, it is positive but may be zero or negative as well.

    For more information, refer `OpenCV's adaptiveThreshold
    <https://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html#adaptivethreshold>`_.
iterations : int, optional (default: 0)
    Number of dilation passes applied to close small gaps in the
    line mask (useful when a table's ruled lines don't quite meet
    at corners).

    For more information, refer `OpenCV's dilate <https://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html#dilate>`_.
erode_iterations : int, optional (default: 0)
    Number of erosion passes applied **after** dilation. Set equal
    to ``iterations`` for a morphological closing (bridges gaps
    without thickening the mask, which avoids spurious extra
    rows above/below the detected table). See #363.
backend* : str, optional by default "pdfium"
    The backend to use for converting the PDF to an image so it can be processed by OpenCV.
use_fallback* : bool, optional
    Fallback to another backend if unavailable, by default True
resolution : int, optional (default: 300)
    Resolution used for PDF to PNG conversion.
engine : str, optional (default: 'combined')
    Line-detection engine (lattice only):

    - ``'combined'`` (default): OpenCV on the rendered page **plus**
      the PDF's native vector ruled lines unioned into the line masks
      before contour/joint detection â€” recovers tables whose rules
      render faintly. Safe by construction (raster always runs first,
      vector lines can only add; vector lines are clipped to
      ``table_regions`` so it never expands a table past the region).
    - ``'raster'``: OpenCV on the rendered page only (the pre-#763
      behaviour).
    - ``'vector'``: detect tables purely from the PDF's vector ruled
      lines, skipping rasterisation entirely â€” fastest, for PDFs whose
      tables are drawn with real vector strokes (#763).

c                óš  >• US;  a  [        SU< 35      eUU l        / U l        0 U l        [        TU ]  SU
S9  Xl        X l        X0l        X@l	        XPl
        U=(       d    SS/U l        Xpl        X€l        X�l        X°l        XÀl        XÐl        Xàl        Xðl        UU l        UU l        UU l        [/        UUS9U l        S U l        S U l        g )N)ÚrasterÚvectorÚcombinedz5engine must be 'raster', 'vector' or 'combined', got Úlattice)Úreplace_textÚlÚt)Úuse_fallbackÚbackend)Ú
ValueErrorÚengineÚ_vector_segmentsÚ_render_cacheÚsuperÚ__init__Útable_regionsÚtable_areasÚprocess_backgroundÚ
line_scaleÚ	copy_textÚ
shift_textÚ
split_textÚ	flag_sizeÚ
strip_textÚline_tolÚ	joint_tolÚthreshold_blocksizeÚthreshold_constantÚ
iterationsÚerode_iterationsÚ
resolutionr>   r   ÚicbÚ
image_pathÚ	pdf_image)ÚselfrF   rG   rH   rI   rJ   rK   rL   rM   rN   r;   rO   rP   rQ   rR   rS   rT   rU   r>   r?   rA   ÚkwargsÚ	__class__s                         €r&   rE   ÚLattice.__init__›   sß   ø€ ð0 Ð9Ó9ÜØGÈÁzÐRóð ð ˆŒð BDˆÔð .0ˆÔÜ‰Ñ˜°ÐÑ>Ø*ÔØ&ÔØ"4ÔØ$ŒØ"ŒØ$×2¨¨c¨
ˆŒØ$ŒØ"ŒØ$ŒØ ŒØ"ŒØ#6Ô Ø"4ÔØ$ŒØ 0ˆÔØ$ˆŒØ(ˆÔÜ)°|ÈWÑUˆŒØˆŒØˆ�r(   c                ó®  • US:X  aX  US:”  aO  U R                   U   U   R                  (       d.  US-  nUS:”  a#  U R                   U   U   R                  (       d  M.  X4$ US:X  aŠ  U[        U R                   U   5      S-
  :  ah  U R                   U   U   R                  (       dG  US-  nU[        U R                   U   5      S-
  :  a#  U R                   U   U   R                  (       d  MG  X4$ US:X  aX  US:”  aO  U R                   U   U   R                  (       d.  US-  nUS:”  a#  U R                   U   U   R                  (       d  M.  X4$ US:X  a�  U[        U R                   5      S-
  :  ae  U R                   U   U   R
                  (       dD  US-  nU[        U R                   5      S-
  :  a#  U R                   U   U   R
                  (       d  MD  X4$ )a‚  
Shift the index based on the specified direction.

Parameters
----------
table : camelot.core.Table
    The table structure containing rows and columns.
r_idx : int
    Row index of the cell.
c_idx : int
    Column index of the cell.
direction : str
    Direction in which to shift the index ('l', 'r', 't', 'b').

Returns
-------
tuple
    New row and column indices after the shift.
r<   r   r   Úrr=   Úb)ÚcellsÚleftÚlenÚrightÚtopÚbottom)ÚtableÚr_idxÚc_idxÚ	directions       r&   Ú_shift_indexÚLattice._shift_indexÕ   sº  € ð. ˜ÓØ˜!“) E§K¡K°Ñ$6°uÑ$=×$B×$BØ˜‘
�ð ˜!“) E§K¡K°Ñ$6°uÑ$=×$B×$BÑ$Bð ˆ|Ðð ˜#Óàœ˜EŸK™K¨Ñ.Ó/°!Ñ3Ó3ØŸ™ EÑ*¨5Ñ1×7×7à˜‘
�ð œ˜EŸK™K¨Ñ.Ó/°!Ñ3Ó3ØŸ™ EÑ*¨5Ñ1×7×7Ñ7ð ˆ|Ðð ˜#ÓØ˜!“) E§K¡K°Ñ$6°uÑ$=×$A×$AØ˜‘
�ð ˜!“) E§K¡K°Ñ$6°uÑ$=×$A×$AÑ$Að ˆ|Ðð	 ˜#ÓØœ#˜eŸk™kÓ*¨QÑ.Ó.°u·{±{À5Ñ7IÈ%Ñ7P×7W×7WØ˜‘
�ð œ#˜eŸk™kÓ*¨QÑ.Ó.°u·{±{À5Ñ7IÈ%Ñ7P×7W×7WÑ7Wð ˆ|Ðr(   c                óŠ   • / nU H:  u  pEnU H  n[         R                  XXW5      u  pEM     UR                  XEU45        M<     U$ )a  
Reduces the index of a text object if it lies within a spanning cell.

Parameters
----------
table : camelot.core.Table
    The table structure containing rows and columns.
idx : list of tuples
    List of tuples of the form (r_idx, c_idx, text) where r_idx
    is the row index, c_idx is the column index, and text is the
    associated text for that index.
shift_text : list of str
    A list containing one or more of the following strings:
    {'l', 'r', 't', 'b'} to specify the direction in which the
    text in a spanning cell should flow. 'l' for left, 'r' for right,
    't' for top, 'b' for bottom.

Returns
-------
list of tuples
    List of tuples of the form (r_idx, c_idx, text) where r_idx
    and c_idx are the new row and column indices for the text after
    adjustment.
)r4   rj   r*   )rf   ÚidxrK   Úindicesrg   rh   Útextri   s           r&   Ú_reduce_indexÚLattice._reduce_indexþ   sR   € ð8 ˆã"%ÑˆE˜$ã'�	Ü&×3Ñ3°EÀ%ÓS‘�‘uñ (ð �N‰N˜E¨$Ð/Ö0ñ #&ð ˆr(   c                ó^   >• [         TU ]  U5        U R                  U R                  4Ul        g)z*Record data about the origin of the table.N)rD   Úrecord_parse_metadataÚvertical_segmentsÚhorizontal_segmentsÚ	_segments)rY   rf   r[   s     €r&   rs   ÚLattice.record_parse_metadata%  s(   ø€ ä‰Ñ% eÔ,à×1Ñ1°4×3KÑ3KÐLˆ�r(   c                ó(   • UR                   [        :¬  $ )ug  Drop near-empty ruled grids â€” detection noise, not real tables.

A genuine ruled table is mostly filled; a grid whose cells are
~all empty (whitespace in the 90s) is page borders / form rules /
header separators the contour-joint pipeline mistook for a table.
Rejecting these is a precision gate that cuts false positives on
pages with no real table (#36).
)Ú
whitespaceÚ_GRID_WHITESPACE_REJECT)rY   rf   s     r&   Ú_reject_tableÚLattice._reject_table+  s   € ð ×ÑÔ#:Ñ:Ð:r(   c                ó   • U R                   $ )u   Return the effective line-detection engine for this page.

* ``'combined'`` (default) â†’ raster OpenCV pipeline **plus** the
  PDF's vector ruled lines unioned into the line masks (#763). Safe
  by construction: raster always runs first, so vector lines can
  only *add* to the detected masks, never remove â€” a page with no
  usable vector lines yields the same result as ``'raster'``. The
  strongest detector, hence the default.
* ``'raster'`` â†’ the OpenCV pipeline only (the pre-#763 behaviour).
* ``'vector'`` â†’ render-free: detect tables from the PDF's vector
  ruled lines without rasterising the page (fastest) â€” see
  :meth:`_generate_table_bbox_vector`.
)rA   )rY   s    r&   Ú_resolve_engineÚLattice._resolve_engine6  s   € ð �{‰{Ðr(   c                ó²  • [        U SS5      nUc  / / 4$ [        USS9n[        USS9nU R                  bm  U R                   Vs/ s H  n[        U5      PM     nnU V	s/ s H  n	[	        X˜5      (       d  M  U	PM     nn	U V	s/ s H  n	[	        X˜5      (       d  M  U	PM     nn	U R                  XQU5      n
U R                  XbU5      nX«4$ s  snf s  sn	f s  sn	f )uµ  Union the PDF's vector ruled lines into the raster line masks.

The ``'combined'`` engine (#763) draws the layout's vector ruled
lines â€” converted from PDF to image coords with the same
:func:`scale_pdf` the rest of this method uses â€” onto the OpenCV
line masks *before* :func:`find_contours` / :func:`find_joints`.
A table whose rules are PDF vector strokes (and therefore render
faintly / anti-aliased in the raster) is then found just like a
crisply-printed one. The masks are mutated in place; the
image-coord vector segments are returned so the caller can append
them to the segment lists fed to :func:`scale_image`.

A ``None`` layout (no vector graphics available) is a no-op.

When ``table_regions`` are supplied, the vector lines are clipped to
them â€” mirroring the raster ``find_lines(regions=...)`` mask â€” so
combined never expands a table beyond the user's region (the raster
path already respects it; the vector path must too).
ÚlayoutNÚvertical)ri   Ú
horizontal)Úgetattrr   rF   r   r'   Ú_stamp_vector_lines)rY   Úvertical_maskÚhorizontal_maskÚimage_scalersr�   r,   r+   r^   Úregion_bboxesÚlnÚ
v_segmentsÚ
h_segmentss               r&   Ú _augment_masks_with_vector_linesÚ(Lattice._augment_masks_with_vector_linesF  sÖ   € ô2 ˜˜x¨Ó.ˆØ‰>Ø�r�6ˆMÜ(¨¸:ÑFˆÜ(¨¸<ÑHˆØ×ÑÑ)Ø7;×7IÒ7IÓJÒ7I°!œ]¨1Ö-Ñ7IˆMÐJÙ$+ÓT¢G˜bÔ/@À×/S—r¡GˆGÐTÙ$+ÓT¢G˜bÔ/@À×/S—r¡GˆGÐTØ×-Ñ-¨gÀmÓTˆ
Ø×-Ñ-¨gÈÓVˆ
ØÐ%Ð%ùò KùÚTùÚTs   ÁC
ÁCÁ7CÂCÂCc                ó–   • / nU  H@  n[        XB5      u  pVpx[        R                  " XU4Xx4SS5        UR                  XVXx45        MB     U$ )zCDraw PDF-coord lines onto ``mask`` (image coords); return segments.éÿ   r   )r   Úcv2r   r*   )	Ú	pdf_linesÚmaskrˆ   Úsegmentsr   Úix0Úiy0Úix1Úiy1s	            r&   r…   ÚLattice._stamp_vector_linesl  sT   € ð ˆÛˆDÜ!*¨4Ó!?ÑˆC�cô �HŠH�T ˜:¨ z°3¸Ô:Ø�O‰O˜S sÐ0Ö1ñ ð ˆr(   c           	     ó@  • [        U R                  USU R                  U R                  U R                  S9u  pE[        U R                  USU R                  U R                  U R                  S9u  pgUS:X  a%  U R                  XFU5      u  p‰X‰-   U l        XX-   nXy-   nXFXW4$ )am  find_lines for both directions, plus optional vector union.

Extracted from :meth:`_generate_table_bbox` so the raster +
``'combined'`` mask-building is shared between the table-areas and
auto-detect branches (and to keep that method under the
complexity limit). Returns
``(vertical_mask, horizontal_mask, vertical_segments,
horizontal_segments)`` in image coords.
r‚   )Úregionsri   rI   rS   rT   rƒ   r9   )r   Ú	thresholdrI   rS   rT   r�   rB   )
rY   r›   rˆ   rA   r†   rt   r‡   ru   Úv_vecÚh_vecs
             r&   Ú_detect_line_masksÚLattice._detect_line_masksx  s³   € ô ,6Ø�N‰NØØ Ø—‘Ø—‘Ø!×2Ñ2ñ,
Ñ(ˆô 0:Ø�N‰NØØ"Ø—‘Ø—‘Ø!×2Ñ2ñ0
Ñ,ˆð �ZÓØ×@Ñ@Ø°ó‰LˆEð %*¡MˆDÔ!Ø 1Ñ 9ÐØ"5Ñ"=ÐØÐ/@ÐUÐUr(   c                óÒ  ^• U R                  5       nUS:X  a  U R                  5         g U4S jnU R                  R                  U R                  5      nU(       a-  [
        R                  R                  U5      (       a	  X0l        UnO7S U l        U R                  R                  U R                  U R                  5      n[        UU R                  U R                  U R                  U R                   S9u  U l        U l        U R"                  R&                  S   nU R"                  R&                  S   nU[)        U R*                  5      -  nU[)        U R,                  5      -  nU R*                  [)        U5      -  n	U R,                  [)        U5      -  n
XxU R,                  4mXšU4nU R.                  cP  S nU R0                  b  U" U R0                  5      nU R3                  UTU5      u  pÞnn[5        XÞ5      n[7        UXÞ5      nO5U R3                  S TU5      u  pÞnnU" U R.                  5      n[7        UXÞ5      n[9        UUUU5      u  U l        U l        U l        U RA                  5         g )Nr8   c           
     óà   >• / nU  Hd  n[        U5        S UR                  S5       5       u  p4pV[        X4XV4T5      u  p4pVUR                  X4[	        XS-
  5      [	        Xd-
  5      45        Mf     U$ )Nc              3  ó8   #   • U  H  n[        U5      v •  M     g 7f©N)Úfloat)Ú.0r0   s     r&   Ú	<genexpr>ÚDLattice._generate_table_bbox.<locals>.scale_areas.<locals>.<genexpr>ª  s   é € Ð!D²O¨q¤%¨§( (²Oùs   ‚Ú,)r   Úsplitr   r*   Úabs)ÚareasÚscaled_areasÚarear$   r%   Úx2Úy2rˆ   s          €r&   Úscale_areasÚ1Lattice._generate_table_bbox.<locals>.scale_areas¡  sp   ø€ ØˆLÛ�ô ˜dÔ#Ù!D°D·J±J¸s´OÓ!D‘�˜Ü!*¨B°BÐ+;¸]Ó!K‘�˜Ø×#Ñ# R¬S°±«\¼3¸r¹w»<Ð$HÖIñ ð  Ðr(   )rH   Ú	blocksizeÚcÚrotationr   r   )!r~   Ú_generate_table_bbox_vectorrC   ÚgetÚpageÚosÚpathÚexistsrW   rV   Úto_arrayÚfilenamer   rH   rQ   rR   rµ   rX   rœ   Úshaper¥   Ú	pdf_widthÚ
pdf_heightrG   rF   rŸ   r	   r
   r   Útable_bbox_parsesrt   ru   Ú_compute_table_anchors)rY   rA   r±   Úcached_imageÚimage_inputÚimage_widthÚimage_heightÚimage_width_scalerÚimage_height_scalerÚpdf_width_scalerÚpdf_height_scalerÚpdf_scalersr›   r†   r‡   rt   ru   ÚcontoursÚ
table_bboxr¬   rˆ   s                       @r&   Ú_generate_table_bboxÚLattice._generate_table_bbox›  s7  ø€ Ø×%Ñ%Ó'ˆØ�XÓØ×,Ñ,Ô.Øõ	 ð ×)Ñ)×-Ñ-¨d¯i©iÓ8ˆÞœBŸG™GŸN™N¨<×8Ñ8ð +ŒOØ&‰Kð
 #ˆDŒOØŸ(™(×+Ñ+¨D¯M©M¸4¿9¹9ÓEˆKä);ØØ#×6Ñ6Ø×.Ñ.Ø×%Ñ%Ø—]‘]ñ*
Ñ&ˆŒ˜œð —n‘n×*Ñ*¨1Ñ-ˆØ—~‘~×+Ñ+¨AÑ.ˆØ(¬5°·±Ó+@Ñ@ÐØ*¬U°4·?±?Ó-CÑCÐØŸ>™>¬E°+Ó,>Ñ>ÐØ ŸO™O¬e°LÓ.AÑAÐØ+À$Ç/Á/ÐRˆØ'¸LÐIˆà×ÑÑ#ØˆGØ×!Ñ!Ñ-Ù% d×&8Ñ&8Ó9�ð ×'Ñ'¨°ÀÓGñ SˆMÐ,=Ð?Rô % ]ÓDˆHÜ$ X¨}ÓN‰Jð ×'Ñ'¨¨m¸VÓDñ SˆMÐ,=Ð?Rñ   × 0Ñ 0Ó1ˆEÜ$ U¨MÓKˆJô ˜
Ð$5Ð7JÈKÓXñ 	SˆÔ	 Ô!7¸Ô9Qð 	×#Ñ#Õ%r(   c           	     ó  • [        U SS5      nU(       a  [        US5      O/ nU(       a  [        US5      O/ nU R                  bm  U R                   Vs/ s H  n[        U5      PM     nnU Vs/ s H  n[	        Xe5      (       d  M  UPM     nnU Vs/ s H  n[	        Xe5      (       d  M  UPM     nnSU l        SU l        X0l        X l        U R                  bB  U R                   Vs/ s H  n[        U5      PM     nnU V	s0 s H  o™[        X#U	5      _M     n
n	O[        X#5      n
U
R                  5        VVs0 s H
  u  p¼USU0_M     snnU l        U R                  5         gs  snf s  snf s  snf s  snf s  sn	f s  snnf )u.  Detect tables from the PDF's vector ruled lines â€” no rasterisation.

The render-free ``engine='vector'`` path (#763): read ruled lines
from the page layout (already in PDF coordinate space), cluster
them into table bounding boxes + joints with the vector-native
:func:`find_joints_from_lines`, and build the same
``table_bbox_parses`` structure the raster path produces â€” but
skipping the page render, adaptive threshold, and OpenCV
morphology entirely. ``pdf_image`` / ``threshold`` stay ``None``
(extraction never needs them; only the debug plots do).
r�   Nrƒ   r‚   r.   )r„   r   rF   r   r'   rX   rœ   rt   ru   rG   r2   r   ÚitemsrÁ   rÂ   )rY   r�   r+   r,   r^   r›   rŠ   Úar¬   r®   Újoints_by_bboxr-   r.   s                r&   r¶   Ú#Lattice._generate_table_bbox_vectoræ  ss  € ô ˜˜x¨Ó.ˆÞBHÔ(¨°Ô>ÈbˆÞ@FÔ(¨°Ô<ÈBˆà×ÑÑ)Ø15×1CÒ1CÓDÒ1C¨A”} QÖ'Ñ1CˆGÐDÙ$+ÓN¢G˜bÔ/@À×/M—r¡GˆGÐNÙ$+ÓN¢G˜bÔ/@À×/M—r¡GˆGÐNàˆŒØˆŒØ!(ÔØ#*Ô à×ÑÑ'Ø/3×/?Ò/?Ó@Ò/?¨!”] 1Ö%Ñ/?ˆEÐ@áJOóÚJOÀ$”o g¸Ó=Ò=É%ð ð ˆNô 4°GÓEˆNð :H×9MÑ9MÔ9Oô"
Ú9O©¨ˆD�8˜VÐ$Ò$Ñ9Oò"
ˆÔð 	×#Ñ#Õ%ùò) EùÚNùÚNùò Aùòùó"
s0   ÁE$Á.E)ÂE)ÂE.Â*E.Ã'E3ÄE8Ä9E=c                ó2  • U R                   nU R                  R                  5        GHl  u  p#US   n[        [	        S [        US S95      5      n[        S[        U5      5       H1  nXVS-
     S   XV   S   p‡Xq-
  Us=::  a
  Xq-   ::  d  M&  O  M*  XuU   S'   M3     [        US S9n[        S[        U5      5       H1  nXVS-
     S   XV   S   p©X‘-
  U
s=::  a
  X‘-   ::  d  M&  O  M*  X•U   S'   M3     XSS'   [        [	        S	 U5      5      nUR                  US   US
   /5        [        [	        S U5      5      nUR                  US   US   /5        [        [        U5      U R                   S9n[        [        USS9U R                   S9nX³S'   XÃS'   GMo     g)uþ   Derive col/row anchors from each table's joints (raster + vector).

Operates in place on ``self.table_bbox_parses`` â€” shared by both
the raster/combined and the vector paths, which differ only in how
the ``{bbox: {"joints": [...]}}`` mapping is built.
r.   c                ó   • [        U 5      $ r¤   )Úlist)Úxs    r&   Ú<lambda>Ú0Lattice._compute_table_anchors.<locals>.<lambda>  s   € œd 1œgr(   c                ó   • U S   * $ ©Nr   r   ©Újs    r&   rÙ   rÚ     s
   € ÀQÀqÁTÁEr(   )Úkeyr   r   c                ó   • U S   * $ ©Nr   r   rÝ   s    r&   rÙ   rÚ   &  s
   € ÈÈ1ÉÉr(   Újoints_normalizedc                ó   • U S   $ rÜ   r   ©Úcoordss    r&   rÙ   rÚ   1  ó   € ¨6°!ª9r(   r   c                ó   • U S   $ rá   r   rä   s    r&   rÙ   rÚ   3  ræ   r(   é   )rO   T)ÚreverseÚcol_anchorsÚrow_anchorsN)
rO   rÁ   rÑ   r×   ÚmapÚsortedÚrangerb   Úextendr   )rY   rO   r-   Úparser.   râ   rm   Úx_leftÚx_rightÚy_bottomÚy_topÚcolsÚrowss                r&   rÂ   ÚLattice._compute_table_anchors  s·  € ð —=‘=ˆØ×1Ñ1×7Ñ7×9‰KˆDØ˜8‘_ˆFô !%ÜÑ%¤v¨f¹/Ñ'JÓKó!Ðô ˜Q¤Ð$5Ó 6Ö7�à%¨A¡gÑ.¨qÑ1Ø%Ñ*¨1Ñ-ð  ð Ñ$¨ÕD°6Ñ3D×DÑDØ06 cÑ*¨1Ó-ñ 8ô !'Ð'8¹oÑ NÐÜ˜Q¤Ð$5Ó 6Ö7�à%¨A¡gÑ.¨qÑ1Ø%Ñ*¨1Ñ-ð  ð Ñ&¨%ÕF°8Ñ3F×FÑFØ08 cÑ*¨1Ó-ñ 8ð *;Ð%Ñ&äœÑ4°fÓ=Ó>ˆDØ�K‰K˜˜a™ $ q¡'Ð*Ô+ÜœÑ4°fÓ=Ó>ˆDØ�K‰K˜˜a™ $ q¡'Ð*Ô+ô %¤V¨D£\¸D¿M¹MÑJˆDÜ$¤V¨D¸$Ñ%?È$Ï-É-ÑXˆDØ#'�-Ñ Ø#'�-Ô òK :r(   c                óº  • [        XR                  U R                  5      u  p4[        XR                  U R
                  5      U l        U R                  U   n[        S[        US   5      S-
  5       Vs/ s H  nUS   U   US   US-      4PM     nn[        S[        US   5      S-
  5       Vs/ s H  nUS   U   US   US-      4PM     nnXxX44$ s  snf s  snf )Nr   rê   r   rë   )
r   rt   ru   r   Úhorizontal_textÚvertical_textÚt_bboxrÁ   rî   rb   )	rY   r-   Ú	user_colsÚv_sÚh_srð   Úirõ   rö   s	            r&   Ú_generate_columns_and_rowsÚ"Lattice._generate_columns_and_rows<  s  € ä#Ø×(Ñ(¨$×*BÑ*Bó
‰ˆô ,Ø×&Ñ&¨×(:Ñ(:ó
ˆŒð ×&Ñ& tÑ,ˆô ˜1œc %¨Ñ"6Ó7¸!Ñ;Ô<ó
â<�ð �=Ñ! !Ñ$ e¨MÑ&:¸1¸q¹5Ñ&AÓBÙ<ð 	ð 
ô ˜1œc %¨Ñ"6Ó7¸!Ñ;Ô<ó
â<�ð �=Ñ! !Ñ$ e¨MÑ&:¸1¸q¹5Ñ&AÓBÙ<ð 	ð 
ð ˜3Ð#Ð#ùò
ùò
s   Á4CÂ0Cc                ó   • UR                  S5      nUR                  S5      nUb  Uc  [        SU R                   35      eU R                  XX45      nUR	                  XgU R
                  S9nUR                  5       nU R                  U5        U$ )Nrý   rþ   zNo segments found on )rP   )r·   r@   ÚrootnameÚ_initialize_new_tableÚ	set_edgesrP   Ú
set_borderrs   )	rY   Ú	table_idxr-   rõ   rö   rZ   rý   rþ   rf   s	            r&   Ú_generate_tableÚLattice._generate_tableP  s‡   € Ø�j‰j˜ÓˆØ�j‰j˜ÓˆØ‰;˜#™+ÜÐ4°T·]±]°OÐDÓEÐEà×*Ñ*¨9¸DÓGˆà—‘ °D·N±N�ÐCˆà× Ñ Ó"ˆà×"Ñ" 5Ô)Øˆr(   )rC   rB   rJ   rA   rT   rM   ru   rV   rW   rS   rP   rI   rO   rX   rH   rU   rK   rL   rN   rû   rG   rÁ   rF   rœ   rQ   rR   r>   rt   )NNFé   NNFFÚ Nr   r   r
  éþÿÿÿr   r   i,  TÚpdfiumr9   )
rf   r   rg   Úintrh   r  ri   ÚstrÚreturnztuple[int, int])rf   r   rm   úlist[tuple[int, int, str]]rK   z	list[str]r  r  )r  Úbool)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__rE   Ústaticmethodrj   rp   rs   r{   r~   r�   r…   rŸ   rÎ   r¶   rÂ   r   r  Ú__static_attributes__Ú__classcell__)r[   s   @r&   r4   r4   E   s  ø† ñSðn ØØ ØØØØØØØØØØØØØØØØØ÷+8ðt ð&Øð&Øð&Ø'*ð&Ø7:ð&à	ó&ó ð&ðP ð$Øð$Ø3ð$ØAJð$à	#ó$ó ð$õLMô	;òò $&ðL ñ	ó ð	ò!VòFI&òV%&òN-(ò^$÷(ð r(   r4   )r  Ú
__future__r   r¹   Útypingr   r‘   Úbackendsr   Úimage_processingr   r   r	   r
   r   r   r   Úutilsr   r   r   r   r   r   Úbaser   rz   r'   r2   r4   r   r(   r&   Ú<module>r!     sa   ðÙ 1å "ã 	Ý ã 
å -Ý -Ý 1Ý ,Ý *Ý 5Ý )Ý 5Ý !Ý %Ý Ý Ý $Ý )Ý ð Ð òò"ô"Xˆjõ Xr(   