o
    j2                     @   s   d Z ddlZddlmZ ddlmZ G dd dZG dd	 d	eZG d
d deZG dd deZ	G dd deZ
G dd dZG dd dZdS )u  
Objects representing PDF path (stroke and filling) extracted from pdf drawings and annotations.

Data structure based on results of ``page.get_drawings()``::

    {
        'color': (x,x,x) or None,  # stroke color
        'fill' : (x,x,x) or None,  # fill color
        'width': float,            # line width
        'closePath': bool,         # whether to connect last and first point
        'rect' : rect,             # page area covered by this path
        'items': [                 # list of draw commands: lines, rectangle or curves.
            ("l", p1, p2),         # a line from p1 to p2
            ("c", p1, p2, p3, p4), # cubic Bézier curve from p1 to p4, p2 and p3
                                   # are the control points
            ("re", rect),          # a rect represented with two diagonal points
            ("qu", quad)           # a quad represented with four corner points
        ],
        ...
    }

References:
    - https://pymupdf.readthedocs.io/en/latest/page.html#Page.get_drawings
    - https://pymupdf.readthedocs.io/en/latest/faq.html#extracting-drawings

.. note::
    The coordinates extracted by ``page.get_drawings()`` is based on **real** page CS,
    i.e. with rotation considered. This is different from ``page.get_text('rawdict')``.
    N   )	rgb_value)	constantsc                   @   *   e Zd ZdZdd ZdedefddZdS )	Segmentz9A segment of path, e.g. a line or a rectangle or a curve.c                 C   s   |dd  | _ d S N   points)selfitem r   T/var/www/html/Deteccion_Ine/venv/lib/python3.10/site-packages/pdf2docx/shape/Path.py__init__&   s   zSegment.__init__widthcolorc                 C   s   g S Nr   )r   r   r   r   r   r   
to_strokes)   s    zSegment.to_strokesN__name__
__module____qualname____doc__r   floatlistr   r   r   r   r   r   $   s    r   c                   @   s.   e Zd ZdZedd ZdedefddZdS )	Lz(Line path with source ``("l", p1, p2)``.c                 C   s8   | j d \}}| j d \}}|| d || d  d S )zLength of line.r   r   r   g      ?r	   )r   x0y0x1y1r   r   r   length/   s   zL.lengthr   r   c                 C   s,   g }| | jd | jd |t|d |S )a  Convert to stroke dict.

        Args:
            width (float): Specify width for the stroke.
            color (list): Specify color for the stroke.

        Returns:
            list: A list of ``Stroke`` dicts.

        .. note::
            A line corresponds to one stroke, but considering the consistence,
            the return stroke dict is append to a list. So, the length of list
            is always 1.
        r   r   startendr   r   )appendr
   r   )r   r   r   strokesr   r   r   r   7   s   zL.to_strokesN)	r   r   r   r   propertyr    r   r   r   r   r   r   r   r   ,   s
    
r   c                   @   r   )	Rz'Rect path with source ``("re", rect)``.c                 C   s8   |d \}}}}||f||f||f||f||fg| _ d S r   r	   )r   r   r   r   r   r   r   r   r   r   R   s   
z
R.__init__r   r   c                 C   sL   g }t t| jd D ]}|| j| | j|d  |d t|d q|S )aA  Convert each edge to stroke dict.

        Args:
            width (float): Specify width for the stroke.
            color (list): Specify color for the stroke.

        Returns:
            list: A list of ``Stroke`` dicts.

        .. note::
            One Rect path is converted to a list of 4 stroke dicts.
        r          @r!   )rangelenr
   r$   r   )r   r   r   r%   ir   r   r   r   [   s   
zR.to_strokesNr   r   r   r   r   r'   P   s    	r'   c                   @   s   e Zd ZdZdd ZdS )Qz'Quad path with source ``("qu", quad)``.c                 C   s$   |d \}}}}|||||g| _ d S r   r	   )r   r   ZulurZlllrr   r   r   r   u   s   z
Q.__init__N)r   r   r   r   r   r   r   r   r   r,   s   s    r,   c                   @   s   e Zd ZdZdS )Cz8Bezier curve path with source ``("c", p1, p2, p3, p4)``.N)r   r   r   r   r   r   r   r   r/   |   s    r/   c                   @   sx   e Zd ZdZddefddZdd Zedd	 Zed
d Z	edd Z
edd ZdedefddZdefddZdS )Segmentsz,A sub-path composed of one or more segments.Fitemsc                 C   s   g | _ |D ]=}|d dkr| j t| q|d dkr%| j t| q|d dkr4| j t| q|d dkrB| j t| q|rgd| j d jd | j d jd f}t|}|jdkri| j | d S d S d S )Nr   lcrequMbP?)
_instancesr$   r   r/   r'   r,   r
   r    )r   r1   
close_pathr   liner   r   r   r      s   "zSegments.__init__c                 C   s   dd | j D S )Nc                 s   s    | ]}|V  qd S r   r   ).0instancer   r   r   	<genexpr>   s    z$Segments.__iter__.<locals>.<genexpr>)r8   r   r   r   r   __iter__   s    zSegments.__iter__c                 C   s    g }| j D ]}||j q|S )zConnected points of segments.)r8   extendr
   )r   r
   segmentr   r   r   r
      s   
zSegments.pointsc                 C   s"   | j  }|dkp| j| tjkS )zCISO-oriented criterion: the ratio of real area to bbox exceeds 0.9.r   )bboxget_areaarear   ZFACTOR_MOST)r   Z	bbox_arear   r   r   is_iso_oriented   s   
zSegments.is_iso_orientedc           
      C   s   | j }|d |d }}t|d |d  t|d |d   dkr$dS d}tt|d D ]}|| \}}||d  \}}	|||	 ||  7 }q.t|d S )zCalculate segments area with Green formulas. Note the boundary of Bezier curve
        is simplified with its control points.

        * https://en.wikipedia.org/wiki/Shoelace_formula
        r   r6   r   r7           r(   )r
   absr)   r*   )
r   r
   r"   r#   rD   r+   r   r   r   r   r   r   r   rD      s   ,zSegments.areac                 C   s~   | j }t|dd dd }t|dd dd }t|dd dd }t|dd dd }tt|d	t|d	t|d	t|d	S )
zCalculate segments bbox. c                 S      | d S Nr   r   pointr   r   r   <lambda>       zSegments.bbox.<locals>.<lambda>)keyr   c                 S   rH   r   r   rJ   r   r   r   rL      rM   r   c                 S   rH   rI   r   rJ   r   r   r   rL      rM   c                 S   rH   r   r   rJ   r   r   r   rL      rM   r   )r
   minmaxfitzRectround)r   r
   r   r   r   r   r   r   r   rB      s    zSegments.bboxr   r   c                 C   &   g }| j D ]}|||| q|S )zConvert each segment to a ``Stroke`` dict.

        Args:
            width (float): Specify stroke width.
            color (list): Specify stroke color.

        Returns:
            list: A list of ``Stroke`` dicts.
        )r8   r@   r   )r   r   r   r%   rA   r   r   r   r      s   

zSegments.to_strokesc                 C   s   t | jt|dS )zConvert segment closed area to a ``Fill`` dict.

        Args:
            color (list): Specify fill color.

        Returns:
            dict: ``Fill`` dict.
        )rB   r   )r   rB   r   )r   r   r   r   r   to_fill   s   
zSegments.to_fillN)F)r   r   r   r   r   r   r?   r&   r
   rE   rD   rB   r   r   rU   r   r   r   r   r0      s    



r0   c                   @   s~   e Zd ZdZdefddZedd Zedd Z	ed	d
 Z
edd Zdd ZdedefddZdefddZdd ZdS )Pathz=Path extracted from PDF, consist of one or more ``Segments``.rawc                 C   s   || _ |d | _| jrdn|dd}g | _t | _|dd}| |d D ]'}t	||}| j
| |j}| dkrH|| | ||f7 }|  j|O  _q(d	S )
zInit path in real page CS.

        Args:
            raw (dict): Raw dict extracted with `PyMuPDF`, see link
            https://pymupdf.readthedocs.io/en/latest/page.html#Page.get_drawings
        typeT	closePathFr   rF   r1   r   N)rW   	path_typeis_fillgetr1   rQ   rR   rB   _group_segmentsr0   r$   rC   )r   rW   r9   wsegmentsSrectr   r   r   r      s   


 zPath.__init__c                 C   s   g g }}d}| D ]=}|d dv r1|d |d }}|r ||kr&| | n| | |g}|}q	|d dv rF|r@| | g }| |g q	|rN| | |S )zGroup connected segments.

        Args:
            items (dict): Raw dict extracted from ``page.get_drawings()``.

        Returns:
            list: A list of segments list.
        Nr   )r2   r3   r   r6   )r4   r5   )r$   )r1   r_   Zsegments_listcursorr   r"   r#   r   r   r   r]     s$   



zPath._group_segmentsc                 C   
   d| j v S )NsrZ   r>   r   r   r   	is_stroke2     
zPath.is_strokec                 C   rc   )Nfre   r>   r   r   r   r[   5  rg   zPath.is_fillc                 C   s   | j D ]}|js dS qdS )z@It is iso-oriented when all contained segments are iso-oriented.FT)r1   rE   )r   r_   r   r   r   rE   8  s   
zPath.is_iso_orientedc                 C   sd   g }d}| j r| jd|}| jdd}|| || | jr0| jd|}|| | |S )zkConvert path to ``Shape`` raw dicts.

        Returns:
            list: A list of ``Shape`` dict.
        )r   r   r   r   r   rF   fill)rf   rW   r\   r@   _to_strokesr[   	_to_fills)r   Z
iso_shapeswhiteZstroke_colorr   Z
fill_colorr   r   r   	to_shapes@  s   zPath.to_shapesr   r   c                 C   rT   )zmConvert path to ``Stroke`` raw dicts.

        Returns:
            list: A list of ``Stroke`` dict.
        )r1   r@   r   )r   r   r   r%   r_   r   r   r   rj   W  s   
zPath._to_strokesc                 C   s$   g }| j D ]
}||| q|S )zConvert path to ``Fill`` raw dicts.

        Returns:
            list: A list of ``Fill`` dict.

        .. note::
            The real filling area of this path may be not a rectangle.
        )r1   r$   rU   )r   r   Zfillsr_   r   r   r   rk   c  s   	
zPath._to_fillsc                 C   s8  | j dg D ]J}|d dkr||d |d  q|d dkr(||d  q|d dkr6||d  q|d dkrM||d |d |d	 |d
  qtd||j| j dd| j dd| j dd| j dd| j dd| j ddd| j v rt| j d nd| j dd| j dd| j ddd
 dS )z Plot path for debug purpose.

        Args:
            canvas: ``PyMuPDF`` drawing canvas by ``page.new_shape()``.

        Reference:

            https://pymupdf.readthedocs.io/en/latest/faq.html#extracting-drawings
        r1   r   r2   r   r   r4   r5   r3         zunhandled drawingri   Nr   dasheseven_oddFrY   lineJoinlineCapr   stroke_opacityfill_opacity)
ri   r   rp   rq   rY   rr   rs   r   rt   ru   )	rW   r\   Z	draw_lineZ	draw_rectZ	draw_quadZdraw_bezier
ValueErrorfinishrP   )r   Zcanvasr   r   r   r   plotr  s,   "

z	Path.plotN)r   r   r   r   dictr   staticmethodr]   r&   rf   r[   rE   rm   r   r   rj   rk   rx   r   r   r   r   rV      s    
,


rV   )r   rQ   Zcommon.sharer   commonr   r   r   r'   r,   r/   r0   rV   r   r   r   r   <module>   s    $#	g