#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------
#
#     P A G E B O T
#
#     Copyright (c) 2016+ <NAME> + <NAME>
#     www.pagebot.io
#     Licensed under MIT conditions
#
#     Supporting DrawBot, www.drawbot.com
#     Supporting Flat, xxyxyz.org/flat
# -----------------------------------------------------------------------------
#
#     fontpaths.py
#
import os
import os.path
from pagebot.toolbox.transformer import path2FontName
from pagebot.filepaths import getResourcesPath
from pagebot.constants import DEFAULT_FONT, DEFAULT_FOUNDRY
from pagebot.fonttoolbox.fontnames import FONT_NAME_2_FILE_NAME

#   P A T H S


# Dictionary with all available font paths on the platform, key is the single
# file name.
FONT_PATHS = {}

def getTestFontsPath():
    """Answers the path of the PageBot test fonts."""
    resourcesPath = getResourcesPath()
    return '%s/%s' % (resourcesPath, 'testfonts')

def getDefaultFontPath():
    testFontsPath = getTestFontsPath()
    return '%s/%s/%s.ttf' % (testFontsPath, DEFAULT_FOUNDRY, DEFAULT_FONT)

def getFontPathOfFont(font, default=None):
    """Answers the path that is source of the given font name.
    If the path is already a valid font path, then aswer it unchanged.
    Answer None if the font cannot be found.

    >>> from pagebot.fonttoolbox.objects.font import findFont
    >>> font = findFont('Roboto-Regular')
    >>> path = getFontPathOfFont(font.path) # Set as font path
    >>> path.endswith('/Roboto-Regular.ttf')
    True
    >>> font.path == path
    True
    >>> path = getFontPathOfFont(font) # Set as Font instance
    >>> path.endswith('/Roboto-Regular.ttf')
    True
    >>> font.path == path
    True
    >>> path = getFontPathOfFont('Roboto-Regular') # Set as font name
    >>> path.endswith('/Roboto-Regular.ttf')
    True
    >>> path = getFontPathOfFont('UnknowFont.ttf') # Unknown font is set to getDefaultFontPath()
    >>> path == getDefaultFontPath()
    True
    >>> #getFontPathOfFont('AgencyFB-Regular')

    """
    if hasattr(font, 'path'): # In case it is a Font instance, get its path.
        font = font.path
    if font is not None and not os.path.exists(font):
        font = getFontPaths().get(font)
    if font is None:
        font = default or getDefaultFontPath()
    return font

def _recursivelyCollectFontPaths(path, collectedFontPaths):
    """Recursive helper function for getFontPaths. If the fileName already
    exists in the fontPaths, then ignore."""
    if os.path.exists(path):
        if os.path.isdir(path):
            for fileName in os.listdir(path):
                dirPath = path + '/' + fileName
                _recursivelyCollectFontPaths(dirPath, collectedFontPaths)
        else:
            fontName = path2FontName(path) # File name without extension used as key, works for Flat and DrawBot.
            # If fontName is None, it does not have the right extension.
            # Note that files with the same file name will be overwritten, we expect them to be unique in the OS.
            if fontName is not None:
                collectedFontPaths[fontName] = path

def getPageBotFontPaths():
    paths = {}
    testFontsPath = getTestFontsPath()
    _recursivelyCollectFontPaths(testFontsPath, paths)
    return paths

def getFontPaths(extraPaths=None):
    """Answers a dictionary with all available font paths on the platform, key
    is the single file name. Typically on Mac OS Xthe font paths
    available in these respective directories are returned:

        ('/Library/Fonts', '/Users/<username>/Library/Fonts', '/Users/<username>/<path-to>/PageBot/Fonts')

    Locally defined fonts with the same file name will overwrite the font files
    that  are located deeper.
    TODO: also check app resources path.

    >>> import os
    >>> testFontsPath = getTestFontsPath()
    >>> os.path.exists(testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf')
    True
    >>> fontPaths = getFontPaths() # Only default paths on the platform
    >>> 'Amstelvar-Roman-VF' in fontPaths
    True
    >>> fontPaths = getFontPaths(testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf') # As single extra path
    >>> 'Amstelvar-Roman-VF' in fontPaths
    True
    >>> fontPaths = getFontPaths([testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf']) # As list of extra paths
    >>> 'Amstelvar-Roman-VF' in fontPaths
    True
    >>> fontPaths = getFontPaths(testFontsPath + '/OtherFont.ttf')
    >>> 'OtherFont' in fontPaths # Ignore if extra paths don't exists.
    False
    >>> fontPaths = getFontPaths()
    """
    global FONT_PATHS
    if extraPaths is not None:
        FONT_PATHS = {}  # Force (new) initialization

    if not FONT_PATHS:

        # If forced or initial call, collect the font paths on this
        # platform.
        if os.name == 'posix':
            paths = []

            # TODO: only for darwin platform.
            # Try typical OSX font folders:
            paths += ['/Library/Fonts', os.path.expanduser('~/Library/Fonts')]

            # Add other typical GNU+Linux font folders here to look at:
            paths += ['/usr/share/fonts']

            for path in paths:
                if os.path.exists(path):
                    _recursivelyCollectFontPaths(path, FONT_PATHS)

        elif os.name in ('nt', 'os2', 'ce', 'java', 'riscos'):
            # Add other typical Windows font folders here to look at.
            pass
        else:
            raise NotImplementedError('Unknown platform type "%s"' % os.name)

        # Add the name name:fileName combinations from the predefined
        # dictionary (made with DrawBot.installedFonts())
        for fontName, fileName in FONT_NAME_2_FILE_NAME.items():
            if not fontName in FONT_PATHS:
                for path in paths:
                    fontPath = path + '/' + fileName
                    if os.path.exists(fontPath):
                        FONT_PATHS[fontName] = fontPath
                        break

        # Add PageBot repository fonts, they always exist in this context. But
        # they can be overwritten by fonts with the same (file) name in the
        # extraPaths.
        testFontsPath = getTestFontsPath()
        _recursivelyCollectFontPaths(testFontsPath, FONT_PATHS)

        if extraPaths is not None:
            if not isinstance(extraPaths, (list, tuple)):
                extraPaths = [extraPaths]
            for extraPath in extraPaths:
                _recursivelyCollectFontPaths(extraPath, FONT_PATHS)


    return FONT_PATHS

if __name__ == '__main__':
    import doctest
    import sys
    sys.exit(doctest.testmod()[0])

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
# -----------------------------------------------------------------------------
#
#     P A G E B O T
#
#     Copyright (c) 2016+ <NAME> + <NAME>
#     www.pagebot.io
#     Licensed under MIT conditions
#
#     Supporting DrawBot, www.drawbot.com
#     Supporting Flat, xxyxyz.org/flat
# -----------------------------------------------------------------------------
#
#     fontpaths.py
#
import os
import os.path
from pagebot.toolbox.transformer import path2FontName
from pagebot.filepaths import getResourcesPath
from pagebot.constants import DEFAULT_FONT, DEFAULT_FOUNDRY
from pagebot.fonttoolbox.fontnames import FONT_NAME_2_FILE_NAME

#   P A T H S


# Dictionary with all available font paths on the platform, key is the single
# file name.
FONT_PATHS = {}

def getTestFontsPath():
    """Answers the path of the PageBot test fonts."""
    resourcesPath = getResourcesPath()
    return '%s/%s' % (resourcesPath, 'testfonts')

def getDefaultFontPath():
    testFontsPath = getTestFontsPath()
    return '%s/%s/%s.ttf' % (testFontsPath, DEFAULT_FOUNDRY, DEFAULT_FONT)

def getFontPathOfFont(font, default=None):
    """Answers the path that is source of the given font name.
    If the path is already a valid font path, then aswer it unchanged.
    Answer None if the font cannot be found.

    >>> from pagebot.fonttoolbox.objects.font import findFont
    >>> font = findFont('Roboto-Regular')
    >>> path = getFontPathOfFont(font.path) # Set as font path
    >>> path.endswith('/Roboto-Regular.ttf')
    True
    >>> font.path == path
    True
    >>> path = getFontPathOfFont(font) # Set as Font instance
    >>> path.endswith('/Roboto-Regular.ttf')
    True
    >>> font.path == path
    True
    >>> path = getFontPathOfFont('Roboto-Regular') # Set as font name
    >>> path.endswith('/Roboto-Regular.ttf')
    True
    >>> path = getFontPathOfFont('UnknowFont.ttf') # Unknown font is set to getDefaultFontPath()
    >>> path == getDefaultFontPath()
    True
    >>> #getFontPathOfFont('AgencyFB-Regular')

    """
    if hasattr(font, 'path'): # In case it is a Font instance, get its path.
        font = font.path
    if font is not None and not os.path.exists(font):
        font = getFontPaths().get(font)
    if font is None:
        font = default or getDefaultFontPath()
    return font

def _recursivelyCollectFontPaths(path, collectedFontPaths):
    """Recursive helper function for getFontPaths. If the fileName already
    exists in the fontPaths, then ignore."""
    if os.path.exists(path):
        if os.path.isdir(path):
            for fileName in os.listdir(path):
                dirPath = path + '/' + fileName
                _recursivelyCollectFontPaths(dirPath, collectedFontPaths)
        else:
            fontName = path2FontName(path) # File name without extension used as key, works for Flat and DrawBot.
            # If fontName is None, it does not have the right extension.
            # Note that files with the same file name will be overwritten, we expect them to be unique in the OS.
            if fontName is not None:
                collectedFontPaths[fontName] = path

def getPageBotFontPaths():
    paths = {}
    testFontsPath = getTestFontsPath()
    _recursivelyCollectFontPaths(testFontsPath, paths)
    return paths

def getFontPaths(extraPaths=None):
    """Answers a dictionary with all available font paths on the platform, key
    is the single file name. Typically on Mac OS Xthe font paths
    available in these respective directories are returned:

        ('/Library/Fonts', '/Users/<username>/Library/Fonts', '/Users/<username>/<path-to>/PageBot/Fonts')

    Locally defined fonts with the same file name will overwrite the font files
    that  are located deeper.
    TODO: also check app resources path.

    >>> import os
    >>> testFontsPath = getTestFontsPath()
    >>> os.path.exists(testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf')
    True
    >>> fontPaths = getFontPaths() # Only default paths on the platform
    >>> 'Amstelvar-Roman-VF' in fontPaths
    True
    >>> fontPaths = getFontPaths(testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf') # As single extra path
    >>> 'Amstelvar-Roman-VF' in fontPaths
    True
    >>> fontPaths = getFontPaths([testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf']) # As list of extra paths
    >>> 'Amstelvar-Roman-VF' in fontPaths
    True
    >>> fontPaths = getFontPaths(testFontsPath + '/OtherFont.ttf')
    >>> 'OtherFont' in fontPaths # Ignore if extra paths don't exists.
    False
    >>> fontPaths = getFontPaths()
    """
    global FONT_PATHS
    if extraPaths is not None:
        FONT_PATHS = {}  # Force (new) initialization

    if not FONT_PATHS:

        # If forced or initial call, collect the font paths on this
        # platform.
        if os.name == 'posix':
            paths = []

            # TODO: only for darwin platform.
            # Try typical OSX font folders:
            paths += ['/Library/Fonts', os.path.expanduser('~/Library/Fonts')]

            # Add other typical GNU+Linux font folders here to look at:
            paths += ['/usr/share/fonts']

            for path in paths:
                if os.path.exists(path):
                    _recursivelyCollectFontPaths(path, FONT_PATHS)

        elif os.name in ('nt', 'os2', 'ce', 'java', 'riscos'):
            # Add other typical Windows font folders here to look at.
            pass
        else:
            raise NotImplementedError('Unknown platform type "%s"' % os.name)

        # Add the name name:fileName combinations from the predefined
        # dictionary (made with DrawBot.installedFonts())
        for fontName, fileName in FONT_NAME_2_FILE_NAME.items():
            if not fontName in FONT_PATHS:
                for path in paths:
                    fontPath = path + '/' + fileName
                    if os.path.exists(fontPath):
                        FONT_PATHS[fontName] = fontPath
                        break

        # Add PageBot repository fonts, they always exist in this context. But
        # they can be overwritten by fonts with the same (file) name in the
        # extraPaths.
        testFontsPath = getTestFontsPath()
        _recursivelyCollectFontPaths(testFontsPath, FONT_PATHS)

        if extraPaths is not None:
            if not isinstance(extraPaths, (list, tuple)):
                extraPaths = [extraPaths]
            for extraPath in extraPaths:
                _recursivelyCollectFontPaths(extraPath, FONT_PATHS)


    return FONT_PATHS

if __name__ == '__main__':
    import doctest
    import sys
    sys.exit(doctest.testmod()[0])

#!/usr/bin/env python3 # -*- coding: UTF-8 -*- # ----------------------------------------------------------------------------- # #     P A G E B O T # #     Copyright (c) 2016+ <NAME> + <NAME> #     www.pagebot.io #     Licensed under MIT conditions # #     Supporting DrawBot, www.drawbot.com #     Supporting Flat, xxyxyz.org/flat # ----------------------------------------------------------------------------- # #     fontpaths.py # #   P A T H S # Dictionary with all available font paths on the platform, key is the single # file name. Answers the path of the PageBot test fonts. Answers the path that is source of the given font name.     If the path is already a valid font path, then aswer it unchanged.     Answer None if the font cannot be found.      >>> from pagebot.fonttoolbox.objects.font import findFont     >>> font = findFont('Roboto-Regular')     >>> path = getFontPathOfFont(font.path) # Set as font path     >>> path.endswith('/Roboto-Regular.ttf')     True     >>> font.path == path     True     >>> path = getFontPathOfFont(font) # Set as Font instance     >>> path.endswith('/Roboto-Regular.ttf')     True     >>> font.path == path     True     >>> path = getFontPathOfFont('Roboto-Regular') # Set as font name     >>> path.endswith('/Roboto-Regular.ttf')     True     >>> path = getFontPathOfFont('UnknowFont.ttf') # Unknown font is set to getDefaultFontPath()     >>> path == getDefaultFontPath()     True     >>> #getFontPathOfFont('AgencyFB-Regular') # In case it is a Font instance, get its path. Recursive helper function for getFontPaths. If the fileName already     exists in the fontPaths, then ignore. # File name without extension used as key, works for Flat and DrawBot. # If fontName is None, it does not have the right extension. # Note that files with the same file name will be overwritten, we expect them to be unique in the OS. Answers a dictionary with all available font paths on the platform, key     is the single file name. Typically on Mac OS Xthe font paths     available in these respective directories are returned:          ('/Library/Fonts', '/Users/<username>/Library/Fonts', '/Users/<username>/<path-to>/PageBot/Fonts')      Locally defined fonts with the same file name will overwrite the font files     that  are located deeper.     TODO: also check app resources path.      >>> import os     >>> testFontsPath = getTestFontsPath()     >>> os.path.exists(testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf')     True     >>> fontPaths = getFontPaths() # Only default paths on the platform     >>> 'Amstelvar-Roman-VF' in fontPaths     True     >>> fontPaths = getFontPaths(testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf') # As single extra path     >>> 'Amstelvar-Roman-VF' in fontPaths     True     >>> fontPaths = getFontPaths([testFontsPath + '/fontbureau/Amstelvar-Roman-VF.ttf']) # As list of extra paths     >>> 'Amstelvar-Roman-VF' in fontPaths     True     >>> fontPaths = getFontPaths(testFontsPath + '/OtherFont.ttf')     >>> 'OtherFont' in fontPaths # Ignore if extra paths don't exists.     False     >>> fontPaths = getFontPaths() # Force (new) initialization # If forced or initial call, collect the font paths on this # platform. # TODO: only for darwin platform. # Try typical OSX font folders: # Add other typical GNU+Linux font folders here to look at: # Add other typical Windows font folders here to look at. # Add the name name:fileName combinations from the predefined # dictionary (made with DrawBot.installedFonts()) # Add PageBot repository fonts, they always exist in this context. But # they can be overwritten by fonts with the same (file) name in the # extraPaths.