
    huQ                     <   d Z ddlZddlZddlZddlmZmZmZmZ ddl	m
Z
 ddlmZmZ dZdZdZdZd	Z G d
 d      Z e       Z	 	 	 	 ddedee   dededee   deee   ef   fdZ	 ddedededeeef   fdZ	 	 	 ddededee   dee   dee   ddfdZdefdZy)a  Font management utilities for converting SVG to ReportLab graphics.

This module provides font mapping and registration functionality for converting
SVG fonts to ReportLab-compatible fonts. It handles font discovery, registration,
and mapping between SVG font specifications and ReportLab font names.

The module includes:
- FontMap class for managing font mappings
- Font discovery using system fontconfig
- Support for standard PDF fonts
- Automatic font file detection and registration
    N)DictOptionalTupleUnion)registerFont)TTFErrorTTFont)Times-RomanTimes-Italic
Times-BoldTimes-BoldItalic	HelveticaHelvetica-ObliqueHelvetica-BoldHelvetica-BoldObliqueCourierCourier-ObliqueCourier-BoldCourier-BoldObliqueSymbolZapfDingbatsr   normal   c                   F   e Zd ZdZddZe	 ddedededefd	       Ze	 	 	 dd
ededededef
d       Z	 ddededede	e
e   ef   fdZddZ	 	 	 ddedede
e   de
e   de
e   ddfdZ	 	 	 	 ddede
e   dedede
e   de	e
e   ef   fdZ	 ddededede	eef   fdZy)FontMapa  Manages mapping of SVG font names to ReportLab fonts and handles registration.

    This class provides a centralized way to map SVG font specifications (family,
    weight, style) to ReportLab-compatible font names. It supports automatic font
    discovery, registration of custom fonts, and fallback to standard PDF fonts.

    The internal font map uses normalized font names as keys for efficient lookup
    and supports both exact and approximate font matching.
    returnNc                 2    i | _         | j                          y)a  Initialize the FontMap with an empty font registry.

        Creates an empty internal font map and registers all default font mappings
        for standard PDF fonts and common font family aliases.

        The internal font map structure:
            'internal_name': {
                'svg_family': 'family_name',
                'svg_weight': 'font_weight',
                'svg_style': 'font_style',
                'rlgFont': 'reportlab_font_name',
                'exact': True/False
            }

        Internal names are normalized for efficient lookup and follow the pattern:
        'Family-WeightStyle' (e.g., 'Arial-BoldItalic').
        N)_mapregister_default_fontsselfs    </home/dcms/DCMS/lib/python3.12/site-packages/svglib/fonts.py__init__zFontMap.__init__7   s    $ BD	##%    r   familyweightstylec                     | }|dk7  s|dk7  r|dz  }|dk7  r8t        |t              r|| z  }n!||j                         j                         z  }|dk7  r!||j                         j                         z  }|S )a+  Build normalized internal font name from family, weight, and style.

        Creates a standardized font name for internal mapping by combining the
        font family with capitalized weight and style variants. This follows
        the standard naming convention used by most font systems.

        Args:
            family: Font family name (e.g., "Arial", "Times New Roman").
            weight: Font weight ("normal", "bold", or numeric value).
            style: Font style ("normal" or "italic").

        Returns:
            Normalized font name string (e.g., "Arial-BoldItalic").

        Examples:
            >>> FontMap.build_internal_name("Arial", "bold", "italic")
            'Arial-BoldItalic'
            >>> FontMap.build_internal_name("Times", "normal", "normal")
            'Times'
        r   -)
isinstanceintlower
capitalize)r%   r&   r'   result_names       r"   build_internal_namezFontMap.build_internal_nameM   s    0 X(!23KX&#&&*v||~88::H5;;=3355Kr$   basename	extensionc                     d}|j                         dk(  }|j                         dk(  }|r|sd}n|r|rd}n|s|rd}|  | d| }|S )a8  Guess font filename based on family, weight, and style parameters.

        Attempts to construct a likely font filename using common naming conventions
        for TrueType fonts. This works well for standard system fonts on Windows and
        many Unix-like systems.

        Args:
            basename: Base font family name (e.g., "arial", "times").
            weight: Font weight ("normal" or "bold").
            style: Font style ("normal" or "italic").
            extension: File extension (default "ttf").

        Returns:
            Guessed filename with appropriate weight/style suffix.

        Examples:
            >>> FontMap.guess_font_filename("arial", "bold", "italic")
            'arialbi.ttf'
            >>> FontMap.guess_font_filename("times", "normal", "normal")
            'times.ttf'
         bolditalicbdbii.)r,   )r0   r&   r'   r1   prefixis_bold	is_italicfilenames           r"   guess_font_filenamezFontMap.guess_font_filenameq   s`    8 ,,.F*KKMX-	9FFYFZxq4r$   	font_namec                 `   d}	 t        j                  ddd|gt         j                  t         j                        }|j                         d   j	                  t        j                               }|j                  d      }|D ]  }	 t        t        ||             |}	 n |S |j                         t        j                  j                  |	      j                         v }
t         j#                  |||      }|||||
d| j$                  |<   ||
fS # t        $ r |cY S w xY w# t        $ r Y w xY w)	a  Find and register a font using system fontconfig.

        Uses the system's fontconfig utility to locate and register fonts that
        match the given specifications. This provides access to system-installed
        fonts that aren't part of the standard PDF font set.

        Args:
            font_name: Name of the font family to search for.
            weight: Font weight specification ("normal" or "bold").
            style: Font style specification ("normal" or "italic").

        Returns:
            Tuple of (font_name, is_exact_match). Returns (None, False) if
            fontconfig is unavailable or no suitable font is found.

        Raises:
            OSError: If fontconfig command is not available on the system.

        Note:
            Fontconfig may return a default fallback font if the exact font
            is not found. The exact_match flag indicates whether the returned
            font is an exact match for the requested font.
        NFzfc-matchz-sz--format=%{file}\n)stdoutstderrr   

svg_family
svg_weight	svg_stylerlgFontexact)
subprocessPopenPIPEcommunicatedecodesysgetfilesystemencodingOSErrorsplitr   r	   r   r,   ospathr0   r   r/   r   )r!   r?   r&   r'   	NOT_FOUNDpipeoutput
font_paths	font_pathsuccess_font_pathrJ   internal_names               r"   use_fontconfigzFontMap.use_fontconfig   s<   4 "		##T#8)D!!D
 %%'*11#2K2K2MNF \\$'
# 		IVIy9: %.!		 !RWW%5%56G%H%N%N%PP33IvuM#  $
		-  %/  		  s$   A,D D!DD!	D-,D-c                    | j                  dd       | j                  ddd       | j                  ddd	       | j                  dddd
       | j                  dd       | j                  ddd       | j                  ddd	       | j                  dddd       | j                  dd       | j                  ddd       | j                  ddd	       | j                  dddd       | j                  ddd	       | j                  dddd       | j                  dd       | j                  ddd       | j                  ddd	       | j                  dddd       | j                  dd       | j                  ddd       | j                  ddd	       | j                  dddd
       | j                  dd       | j                  ddd       | j                  ddd	       | j                  dddd
       | j                  dd       | j                  ddd       | j                  ddd	       | j                  dddd       y)a  Register mappings for standard PDF fonts and common font families.

        Sets up the default font mappings that are always available in ReportLab.
        This includes the 14 standard PDF fonts and common font family aliases
        like "serif", "sans-serif", and "monospace" that map to appropriate
        standard fonts.

        This method is called automatically during FontMap initialization and
        establishes the baseline font support for SVG to PDF conversion.
        zTimes New Romanr
   )rlgFontNamer4   r   )r&   r_   r5   r   )r'   r_   r   )r&   r'   r_   r   r   r   r   zCourier Newr   r   r   r   z
sans-serifseriftimes	monospaceNregister_fontr    s    r"   r   zFontMap.register_default_fonts   s    	,-H,VVX> 	 	
 	*	 	 	
 	;K@;vCST;hDWX/	 	 	
 	=i@=^T=FWX-	 	 	
 	9HBSTfHBW 	 	
 	<[A<DTU6I 	 	
 	/	 	 	
 	7>76|L7(OF(@R 	 	
 	7>76|L7(OF(@R 	 	
 	;I>;v>R;hDUV-	 	 	
r$   r4   r5   
bolditalicc                     | j                  ||       || j                  ||d       || j                  ||d       || j                  ||dd       yy)a  Register a complete font family with all style variants.

        Convenience method to register an entire font family at once by providing
        the font paths for different style combinations. This automatically creates
        mappings for normal, bold, italic, and bold-italic variants.

        Args:
            family: Font family name (e.g., "MyCustomFont").
            normal: Path or name for the normal weight/style variant.
            bold: Optional path or name for bold variant.
            italic: Optional path or name for italic variant.
            bolditalic: Optional path or name for bold-italic variant.

        Example:
            >>> font_map.register_font_family(
            ...     "MyFont",
            ...     "/path/to/myfont-regular.ttf",
            ...     "/path/to/myfont-bold.ttf",
            ...     "/path/to/myfont-italic.ttf",
            ...     "/path/to/myfont-bolditalic.ttf"
            ... )
        Nr4   )r&   r5   )r'   )r&   r'   rc   )r!   r%   r   r4   r5   re   s         r"   register_font_familyzFontMap.register_font_family(  sl    < 	66*vtF;vvX>!vz&Q "r$   font_familyrZ   r_   c                    d}t         j                  |||      }||}|t        v r||||dd| j                  |<   |dfS |t        vr1|/	 t	        t        ||             ||||dd| j                  |<   |dfS |S # t        $ r |cY S w xY w)a  Register a font or create a mapping to a ReportLab font name.

        This method handles two scenarios:
        1. Registering a custom TrueType font file with ReportLab
        2. Creating a mapping from SVG font specifications to existing ReportLab fonts

        For standard PDF fonts, only the mapping is created. For custom fonts,
        the font file is registered with ReportLab and then mapped.

        Args:
            font_family: SVG font family name (e.g., "Arial", "Times New Roman").
            font_path: Path to TrueType font file (.ttf). If None, assumes this
                is a mapping to an existing ReportLab font.
            weight: Font weight ("normal" or "bold").
            style: Font style ("normal" or "italic").
            rlgFontName: ReportLab font name to map to. If None, uses the
                normalized internal name.

        Returns:
            Tuple of (internal_font_name, success_flag). Returns (None, False)
            if registration fails.

        Raises:
            TTFError: If the font file cannot be loaded or registered.

        Examples:
            >>> # Map to existing ReportLab font
            >>> font_map.register_font("MyArial", rlgFontName="Helvetica")
            ('MyArial', True)

            >>> # Register custom font file
            >>> font_map.register_font("MyFont", "/path/to/font.ttf")
            ('MyFont', True)
        rA   TrE   )r   r/   STANDARD_FONT_NAMESr   r   r	   r   )r!   rh   rZ   r&   r'   r_   rV   r\   s           r"   rd   zFontMap.register_fontN  s    T "	33KO (K-- *$"&(DIIm$ !$&& 33	8M!VK;<"-"(!&*!,		-( %d**
 	  !  !s   
-A: :BBc                 r   t         j                  |||      }|t        v r|dfS || j                  v r+| j                  |   }t	        |d         t        |d         fS t         j                  |||      }| j                  ||      \  }}|||fS | j                  |||      }	|	d   
|	d   |	d   fS t        dfS )aV  Find the best matching ReportLab font for given specifications.

        Searches through the font registry to find the most appropriate font match.
        Uses a multi-step fallback strategy: exact match, standard fonts, file-based
        registration, fontconfig discovery, and finally default fallback.

        Args:
            font_name: SVG font family name to search for.
            weight: Font weight ("normal" or "bold").
            style: Font style ("normal" or "italic").

        Returns:
            Tuple of (reportlab_font_name, is_exact_match). The exact_match flag
            indicates whether the returned font is an exact match for the request.

        Note:
            If no suitable font is found, falls back to DEFAULT_FONT_NAME (Helvetica).
            The search prioritizes exact matches over approximate ones.
        TrI   rJ   r      F)
r   r/   rj   r   strboolr>   rd   r]   DEFAULT_FONT_NAME)
r!   r?   r&   r'   r\   
font_entryguessed_filenamereg_namerJ   fontconfig_results
             r"   	find_fontzFontMap.find_font  s    ,  33IvuM// $&&DII%=1JJy)*Z()  #66y&%P,,Y8HI%U?" //	65IQ+$Q'):1)=== %''r$   )r   Nr   r   )r   r   ttfNNNNr   r   N)__name__
__module____qualname____doc__r#   staticmethodrm   r/   r>   r   r   rn   r]   r   rg   rd   rt    r$   r"   r   r   ,   s   &, :B!! !47!	! !F  	%%% % 	%
 
% %P DL: : &): =@: 	x}d"	#: xQ
n # $$($R$R $R sm	$R
 $R SM$R 
$RR $(%)KK C=K 	K
 K c]K 
x}d"	#K\ DL+(+(&)+(=@+(	sDy	+(r$   r   r?   rZ   r&   r'   r_   r   c                 4    t         j                  | ||||      S )a  Register a font with the global font map.

    Convenience function that delegates to the global FontMap instance.
    Registers a custom font or creates a mapping to an existing ReportLab font.

    Args:
        font_name: SVG font family name (e.g., "Arial", "Times New Roman").
        font_path: Path to TrueType font file (.ttf). Optional for mappings
            to existing fonts.
        weight: Font weight ("normal" or "bold").
        style: Font style ("normal" or "italic").
        rlgFontName: ReportLab font name to map to.

    Returns:
        Tuple of (internal_font_name, success_flag).

    See Also:
        FontMap.register_font: The underlying implementation method.
    )	_font_maprd   )r?   rZ   r&   r'   r_   s        r"   rd   rd     s    4 ""9iTTr$   c                 0    t         j                  | ||      S )a  Find the best matching font from the global font registry.

    Convenience function that delegates to the global FontMap instance.
    Searches for fonts using a multi-step fallback strategy.

    Args:
        font_name: SVG font family name to search for.
        weight: Font weight ("normal" or "bold").
        style: Font style ("normal" or "italic").

    Returns:
        Tuple of (reportlab_font_name, is_exact_match).

    See Also:
        FontMap.find_font: The underlying implementation method.
    )r   rt   )r?   r&   r'   s      r"   rt   rt     s    & y&%88r$   r%   r4   r5   re   c                 6    t         j                  | ||||       y)a`  Register a complete font family with the global font map.

    Convenience function that delegates to the global FontMap instance.
    Registers an entire font family with all style variants at once.

    Args:
        family: Font family name (e.g., "MyCustomFont").
        normal: Path or name for the normal weight/style variant.
        bold: Optional path or name for bold variant.
        italic: Optional path or name for italic variant.
        bolditalic: Optional path or name for bold-italic variant.

    See Also:
        FontMap.register_font_family: The underlying implementation method.
    N)r   rg   )r%   r   r4   r5   re   s        r"   rg   rg     s    , ""664Lr$   c                      t         S )a  Get the global FontMap instance used by the module.

    Returns the singleton FontMap instance that manages all font registrations
    and mappings for the svglib module. This is the same instance used by all
    module-level font functions.

    Returns:
        The global FontMap instance.

    Note:
        Direct access to the FontMap allows for advanced font management
        operations not available through the convenience functions.
    )r   r~   r$   r"   get_global_font_mapr     s
     r$   rx   ru   rw   )r|   rT   rK   rP   typingr   r   r   r   reportlab.pdfbase.pdfmetricsr   reportlab.pdfbase.ttfontsr   r	   rj   ro   DEFAULT_FONT_WEIGHTDEFAULT_FONT_STYLEDEFAULT_FONT_SIZEr   r   rm   rn   rd   rt   rg   r   r~   r$   r"   <module>r      s\   
  
 / / 5 6        Z( Z(z I	
  $!%UU}U U 	U
 #U 8C=$U< :B999369
3992   $MMM 3-M SM	M
 M 
M2W r$   