
    'jSH                       U d dl mZ d dlZd dlmZmZmZ d dlZd dlZ	d dl
Zd dlmZmZ d dlmZ d dlmZ d dlmZ d dlmZ d	d
lmZ d	dlmZmZmZmZ d	dlm Z m!Z! d	dl"m#Z# d	dl$m%Z%m&Z& dZ'dZ(de)d<   	 d dl(Z(n# e*$ r  e+d           dZ'Y nw xY wddgZ,dZ-dZ. G d de&j/                  Z0d0dZ1 G d de          Z2ed1d%            Z3	 	 d2d3d,Z4d4d/Z5dS )5    )annotationsN)Iterableno_type_checkAny)Vec2BoundingBox2d)RGB)Command)__version__)make_table_key   )Color)BackendInterfaceBkPath2d
BkPoints2d	ImageData)ConfigurationLineweightPolicy)BackendProperties)layoutrecorderTr   pymupdfzLPython module PyMuPDF (AGPL!) is required: https://pypi.org/project/PyMuPDF/FPyMuPdfBackendis_pymupdf_installedgjZ@)pngppmpbmc                       e Zd ZdZd fdZ ej                    ddddZ ej                    ddddZd ej                    ddddddZ	e
dd            Z xZS )r   a  This backend uses the `PyMuPdf`_ package to create PDF, PNG, PPM and PBM output.
    This backend support content cropping at page margins.

    PyMuPDF is licensed under the `AGPL`_. Sorry, but it's the best package for the job
    I've found so far.

    Install package::

        pip install pymupdf

    .. _PyMuPdf: https://pypi.org/project/PyMuPDF/
    .. _AGPL: https://www.gnu.org/licenses/agpl-3.0.html

    returnNonec                V    t                                                       d| _        d S )NT)super__init___init_flip_y)self	__class__s    V/DATA/AppData/hermes/venv/lib/python3.11/site-packages/ezdxf/addons/drawing/pymupdf.pyr#   zPyMuPdfBackend.__init__;   s'         Nsettings
render_boxpagelayout.Pager*   layout.Settingsr+   BoundingBox2d | NonePyMuPdfRenderBackendc                  d}|                                  }||                                }t          j        || j                  }|                    ||          }t          j        |          }t          |          |_        |	                    |||          }|
                    |           |j        rU|                    |          \  }}	|                    |          }
dt          z  }|                    ||
z  |	|
z  |           d| _        |                     ||          }|                    |           |S )=  Returns the PDF document as bytes.

        Args:
            page: page definition, see :class:`~ezdxf.addons.drawing.layout.Page`
            settings: layout settings, see :class:`~ezdxf.addons.drawing.layout.Settings`
            render_box: set explicit region to render, default is content bounding box
        TN)flip_y)r*   
top_origin)r4   皙?F)playerbboxr   Layoutr$   get_final_pagecopyget_coordinate_output_spaceoutput_coordinate_spaceget_placement_matrix	transformcrop_at_marginsget_margin_rectpage_output_scale_factorMM_TO_POINTS	crop_rectmake_backendreplay)r%   r,   r*   r+   r4   r6   output_layoutmp1p2output_scalemax_sagittabackends                r'   
get_replayzPyMuPdfBackend.get_replay?   sH    
J j9JKKK++D(;; 9X&&+Ft+L+L(..8
 / 
 
 	# 	P))Z)@@FB#<<TBBL,KR,.\0A;OOO!##D(33gr(   bytesc               Z    |                      |||          }|                                S )r2   r)   )rM   get_pdf_bytes)r%   r,   r*   r+   rL   s        r'   rP   zPyMuPdfBackend.get_pdf_bytesm   s-     //$j/QQ$$&&&r(   r   `   F)fmtr*   dpialphar+   rS   intc               4   |t           vrt          d| d          |                     |||          }	 |                    ||          }|                    |          S # t
          $ r*}	t          dt          |	                      Y d}	~	dS d}	~	ww xY w)	a  Returns a pixel image as bytes, supported image formats:

        === =========================
        png Portable Network Graphics
        ppm Portable Pixmap (no alpha channel)
        pbm Portable Bitmap (no alpha channel)
        === =========================

        Args:
            page: page definition, see :class:`~ezdxf.addons.drawing.layout.Page`
            fmt: image format
            settings: layout settings, see :class:`~ezdxf.addons.drawing.layout.Settings`
            dpi: output resolution in dots per inch
            alpha: add alpha channel (transparency)
            render_box: set explicit region to render, default is content bounding box
        zunsupported image format: ''r)   rS   rT   )outputzPyMuPDF Runtime Error: Nr(   )SUPPORTED_IMAGE_FORMATS
ValueErrorrM   
get_pixmaptobytesRuntimeErrorprintstr)
r%   r,   rR   r*   rS   rT   r+   rL   pixmapes
             r'   get_pixmap_byteszPyMuPdfBackend.get_pixmap_bytes~   s    4 ---A3AAABBB//$j/QQ	''Cu'==F>>>--- 	 	 	4CFF4455533333	s   ,A# #
B-BBc                "    t          | |          S )z8Override this method to use a customized render backend.)r0   )r,   r*   s     r'   rD   zPyMuPdfBackend.make_backend   s    
 $D(333r(   r   r    )r,   r-   r*   r.   r+   r/   r   r0   )r,   r-   r*   r.   r+   r/   r   rN   )
r,   r-   r*   r.   rS   rU   r+   r/   r   rN   )r,   r-   r*   r.   r   r0   )__name__
__module____qualname____doc__r#   r   SettingsrM   rP   rc   staticmethodrD   __classcell__)r&   s   @r'   r   r   +   s        ! ! ! ! ! ! %4FO$5$5+/, , , , , ,d %4FO$5$5+/' ' ' ' ' '* $3FO$5$5+/" " " " " "H 4 4 4 \4 4 4 4 4r(   r,   r-   r   rU   c                    t          | j        t          z            }t          | j        t          z            }t	          ||          S N)rU   width_in_mmrB   height_in_mmmax)r,   page_width_in_ptpage_height_in_pts      r'   r;   r;      s@    4+l:;;D-<==!2333r(   c                      e Zd ZdZd>dZd?d
Zd@dAdZdBdZdCdZdDdZ	dEdZ
dFdZdGdZdHd ZdId#ZdJd&ZdKd)ZdLd,ZdMd/ZdNd2ZdOd5ZdPd8ZdQd9ZdQd:ZdQd;ZdQd<Zd=S )Rr0   aq  Creates the PDF/PNG/PSD/SVG output.

    This backend requires some preliminary work, record the frontend output via the
    Recorder backend to accomplish the following requirements:

    - Move content in the first quadrant of the coordinate system.
    - The page is defined by the upper left corner in the origin (0, 0) and
      the lower right corner at (page-width, page-height)
    - The output coordinates are floats in 1/72 inch, scale the content appropriately
    - Replay the recorded output on this backend.

    .. important::

        Python module PyMuPDF is required: https://pypi.org/project/PyMuPDF/

    r,   r-   r*   r.   r   r    c                   t           s
J d            t          j                    | _        | j                            dt          j        d          dt           d           || _        i | _        i | _	        i | _
        t          |j        t          z            | _        t          |j        t          z            | _        d| _        d| _        t&          j        | _        d| _        t/          | j        t          |j        |j        z                      | _        t/          | j        t          | j        |j        z                      | _        t/          | j        t          | j        |j        z                      | _        | j                            d	| j        | j                  | _        | j                                        | _        d S )
NzDPython module PyMuPDF is required: https://pypi.org/project/PyMuPDF/zPyMuPDF r   zezdxf )producercreator皙?      ?r5   ) r   r   opendocset_metadataversionr   r*   _optional_content_groups_stroke_width_cache_color_cacherU   ro   rB   rr   rp   rs   min_lineweightlineweight_scalingr   ABSOLUTElineweight_policyabs_min_stroke_widthrq   r<   max_stroke_widthmin_stroke_widthfixed_stroke_widthnew_pager,   	new_shapecontent_shape)r%   r,   r*   s      r'   r#   zPyMuPdfRenderBackend.__init__   s    	R 	RQ	R 	R <>>;wq'9;;1K11 	
 	
 	
 !8:%79 CE #D$4|$C D D!$T%6%E!F!F""%!1!: %(! (+%083LLMM(
 (

 (+%%(AABB(
 (
 *-%%(CCDD*
 *
 H%%b$*?AWXX	!Y0022r(   rN   c                4    | j                                         S rn   )r|   r]   r%   s    r'   rP   z"PyMuPdfRenderBackend.get_pdf_bytes   s    x!!!r(   FrS   rU   c                :    | j                             ||          S )NrX   )r,   r\   )r%   rS   rT   s      r'   r\   zPyMuPdfRenderBackend.get_pixmap   s    y##5#999r(   r`   c                4    | j                                         S rn   )r,   get_svg_imager   s    r'   r   z"PyMuPdfRenderBackend.get_svg_image   s    y&&(((r(   colorr   c                (   |                      |          }t          |dd                   }|dk    s|dk    rd S | j        }|                    dd| j        | j        g           |                    d d ||           |                                 d S )N   	   )ry   ry   ry           r   )widthr   fillfill_opacity)resolve_coloralpha_to_opacityr   	draw_rectrr   rs   finishcommit)r%   r   rgbopacityshapes        r'   set_backgroundz#PyMuPdfRenderBackend.set_background   s      ''"51:..O##w#~~F"At4d6LMNNN4t#GLLLr(   
layer_namec                    | j         j        sdS t          |          }|| j        vr%| j                            |dd          | j        |<   | j        |         S )Nr   rz   T)nameconfigon)r*   output_layers	layer_keyr   r|   add_ocg)r%   r   s     r'   get_optional_content_groupz/PyMuPdfRenderBackend.get_optional_content_group  sm    }* 	1z**
T:::8<8H8H 9I 9 9D)*5
 ,Z88r(   
propertiesr   closeboolc                   |                      |j                  }|                     |j                  }|                    ||d ddt          |j        dd                   ||                     |j                             d S )Nr   r   r   )r   r   r   lineJoinlineCapstroke_opacity	closePathoc)r   r   resolve_stroke_width
lineweightr   r   r   layer)r%   r   r   r   r   r   s         r'   finish_linez PyMuPdfRenderBackend.finish_line  s    "":#344))**?@@+J,<QqS,ABB..z/?@@ 	 		
 		
 		
 		
 		
r(   c                    |                     d d |                     |j                  t          |j        dd                   dddd|                     |j                  	  	         d S )Nr   r   r   T)	r   r   r   r   r   r   r   even_oddr   )r   r   r   r   r   r   )r%   r   r   s      r'   finish_fillingz#PyMuPdfRenderBackend.finish_filling  sx    ##J$455)**:1Q3*?@@..z/?@@ 	 
	
 
	
 
	
 
	
 
	
r(   tuple[float, float, float]c                    |d d         }	 | j         |         S # t          $ r Y nw xY wt          j        |                                          }|| j         |<   |S )Nr   )r   KeyErrorr	   from_hex	to_floats)r%   r   keycolor_floatss       r'   r   z"PyMuPdfRenderBackend.resolve_color+  sp    BQBi	$S)) 	 	 	D	|E**4466!-#s    
&&r   floatc                d   	 | j         |         S # t          $ r Y nw xY w| j        }| j        t          j        k    r&t          | j        |          t          z  | j	        z  }n0| j        t          j
        k    rt          || j        | j                  }t          | j        |          }|| j         |<   |S rn   )r   r   r   r   r   r   rq   r   rB   r   RELATIVEmap_lineweight_to_stroke_widthr   r   )r%   r   stroke_widths      r'   r   z)PyMuPdfRenderBackend.resolve_stroke_width5  s    	+E22 	 	 	D	,!%5%>>>D'//,>AXX L #'7'@@@9t,d.C L 44lCC*6 's    
posr   c                    | j         }t          |          }|                    ||           |                     ||d           d S NFr   )r   r   	draw_liner   )r%   r   r   r   s       r'   
draw_pointzPyMuPdfRenderBackend.draw_pointG  sJ    "3iiS!!!
%88888r(   startendc                    | j         }|                    t          |          t          |                     |                     ||d           d S r   )r   r   r   r   )r%   r   r   r   r   s        r'   r   zPyMuPdfRenderBackend.draw_lineM  sK    "UT#YY///
%88888r(   linesIterable[tuple[Vec2, Vec2]]c                    | j         }|D ]\  }}|                    ||           |                     ||d           d S r   )r   r   r   )r%   r   r   r   r   r   s         r'   draw_solid_linesz%PyMuPdfRenderBackend.draw_solid_linesR  sW     " 	( 	(JE3OOE3''''
%88888r(   pathr   c                    t          |          dk    rd S | j        }t          ||d           |                     ||d           d S )Nr   Fr   )lenr   add_path_to_shaper   )r%   r   r   r   s       r'   	draw_pathzPyMuPdfRenderBackend.draw_pathZ  sT    t99>>F"%U3333
%88888r(   pathsIterable[BkPath2d]c                n    | j         }|D ]}t          ||d           |                     ||           d S )NTr   )r   r   r   )r%   r   r   r   ps        r'   draw_filled_pathsz&PyMuPdfRenderBackend.draw_filled_pathsa  sO     " 	4 	4AeQd33333E:.....r(   pointsr   c                    |                                 }t          |          dk     rd S | j        }|                    |           |                     ||           d S )N   )to_listr   r   draw_polyliner   )r%   r   r   verticesr   s        r'   draw_filled_polygonz(PyMuPdfRenderBackend.draw_filled_polygoni  sc     >>##x==1F "H%%%E:.....r(   
image_datar   c                   |j         }|j        }|j        \  }}}|dk    sJ t          |                    t          dd          t          |d          t          ||          t          d|          g                    }d |D             }	d |D             }
t          j        t          |	          t          |
          ft          |	          t          |
          f          }|d         |d         z
  j
        }t          j        |d           }|                                dk    }|s|rt          j                            |d          }|r)|                    t          j        j        j                  }|r.|                    | t          j        j        j        d	d
          }t/          j        |          }|j        \  }}}t          j        t          j        t          j                  ||t9          |j                  d	          }| j                            |d||                      |j!                             d S )N   r   c                    g | ]	}|j         
S  )x.0r   s     r'   
<listcomp>z3PyMuPdfRenderBackend.draw_image.<locals>.<listcomp>      ###aac###r(   c                    g | ]	}|j         
S r   )yr   s     r'   r   z3PyMuPdfRenderBackend.draw_image.<locals>.<listcomp>  r   r(   r   r   RGBA)modeT)r   r   r   r   )resampleexpand	fillcolorF)keep_proportionra   r   )"r>   imager   listtransform_verticesr   r   Rectminrq   	angle_degmathisclosedeterminantPILImage	fromarray	transpose	TransposeFLIP_TOP_BOTTOMrotate
ResamplingBICUBICnpasarrayPixmap
ColorspaceCS_RGBrN   datar,   insert_imager   r   )r%   r   r   r>   r   heightr   depthcornersxsysrangleneed_rotate	need_flip	pil_imagera   s                    r'   
draw_imagezPyMuPdfRenderBackend.draw_imageu  s;   (	 ${uzzzz((aT%^^T%-@-@$q&//R 
 

 $#7#####7###L#b''3r77+c"ggs2ww-?@@ gaj(3,uc222 ))++a/	 	/) 	/	++E+??I U%//	0C0STT	 %,,F Y19*	 -  	 Jy))E#(; FE5w~..vuUZ?P?PRV
 

 		!..z/?@@	 	 	
 	
 	
 	
 	
r(   r   r   c                    |j         | _         |j        r"|j        dz  dz  }t          d|          | _        |j        | _        d S )Ngffffff9@i,  rx   )r   r   rq   r   )r%   r   min_lineweight_mms      r'   	configurezPyMuPdfRenderBackend.configure  sO    !'!9  	? & 5 <s B"%d,=">">D"(";r(   c                    d S rn   r   r   s    r'   clearzPyMuPdfRenderBackend.clear      r(   c                8    | j                                          d S rn   )r   r   r   s    r'   finalizezPyMuPdfRenderBackend.finalize  s    !!#####r(   c                    d S rn   r   )r%   entityr   s      r'   enter_entityz!PyMuPdfRenderBackend.enter_entity  r!  r(   c                    d S rn   r   )r%   r%  s     r'   exit_entityz PyMuPdfRenderBackend.exit_entity  r!  r(   N)r,   r-   r*   r.   r   r    )r   rN   )F)rS   rU   )r   r`   )r   r   r   r    )r   r`   r   rU   )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   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    )r   r   r   r   r   r    )r   r   r   r   r   r    )r   r   r   r    re   )rf   rg   rh   ri   r#   rP   r\   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r   r#  r&  r(  r   r(   r'   r0   r0      s        ",3 ,3 ,3 ,3^" " " ": : : : :) ) ) )   
9 
9 
9 
9
 
 
 

 
 
 
      $9 9 9 99 9 9 9
9 9 9 99 9 9 9/ / / /
/ 
/ 
/ 
/.
 .
 .
 .
`< < < <   $ $ $ $        r(   r0   r   r   r   r   r    c                v   |j         }|}|}|                                D ]}|j        }|j        t          j        k    r0|r+|                    |          s|                     ||           |}n|j        t          j        k    r|                     ||           ni|j        t          j	        k    r| 
                    ||j        |           n7|j        t          j        k    r"|                     ||j        |j        |           |}|}|r-|                    |          s|                     ||           d S d S d S rn   )r   commandsr   typer
   MOVE_TOr   r   LINE_TO	CURVE3_TO
draw_curvectrl	CURVE4_TOdraw_bezierctrl1ctrl2)r   r   r   r   sub_path_start
last_pointcommandr   s           r'   r   r     sP   JENJ==??  k<7?** 7^33C88 7~666 NN\W_,,OOE3''''\W...UGL#6666\W...eW]GM3GGG

 4^++J77 4
N333334 4 4 4r(   rx   zG @r   r   r   r   c                    t          t          | |          |          |z
  } ||z
  ||z
  z  }|t          | |z  d          z   S )zDMap the DXF lineweight in mm to stroke-width in viewBox coordinates.r   )rq   r   round)r   r   r   r   max_lineweightfactors         r'   r   r     sQ     S^44nEEVJ!11n~6UVFeJ$7;;;;r(   rT   r`   c                l    t          |           r$	 t          | d          dz  S # t          $ r Y nw xY wdS )N      ry   )r   rU   r[   )rT   s    r'   r   r     sO     5zz 	ub>>C'' 	 	 	D	3s   $ 
11)r,   r-   r   rU   )r   r   r   r   r   r    )rx   r8  )r   r   r   r   r   r   r   r   )rT   r`   r   r   )6
__future__r   r   typingr   r   r   r:   	PIL.Imager  numpyr
  
ezdxf.mathr   r   ezdxf.colorsr	   
ezdxf.pathr
   ezdxf.versionr   ezdxf.lldxf.validatorr   r   
type_hintsr   rL   r   r   r   r   r   r   r   r   r    r   r   r   r   __annotations__ImportErrorr_   __all__rB   rZ   Recorderr   r;   r0   r   r   r   r   r(   r'   <module>rO     s   # " " " " " "  / / / / / / / / / /          * * * * * * * *             % % % % % % = = = = = =       F F F F F F F F F F F F 3 3 3 3 3 3 3 3 ) ) ) ) ) )             !NNNN ! ! !	EV   !	! 3
4 / |4 |4 |4 |4 |4X& |4 |4 |4~4 4 4 4G G G G G+ G G GT 4 4 4 44 
< 
< 
< 
< 
<     s   4A9 9BB