Skip to content
Snippets Groups Projects
update_icon_font.py 4.01 KiB
Newer Older
#!/usr/bin/env python
'''
Updates icon font and header files for CopyQ repository.

First argument is path to upacked Font Awesome archive (https://fontawesome.com/).
'''
import json
import os
import sys

from shutil import copyfile

from fontTools.ttLib import TTFont

fonts_src_dest = [
    ('fa-solid-900.ttf', 'fontawesome-solid.ttf'),
    ('fa-brands-400.ttf', 'fontawesome-brands.ttf'),
]

solid_style = 'solid'
brands_style = 'brands'


def read_icons(icons_json):
    with open(icons_json, 'r') as icons_file:
        icons_content = icons_file.read()
        return json.loads(icons_content)


def write_header_file_preamble(header_file):
    script = os.path.realpath(__file__)
    script_name = os.path.basename(script)
    comment = (
            f'// This file is generated with "{script_name}"'
            + ' from FontAwesome\'s metadata.\n\n')
    header_file.write(comment)


def write_add_icons_header_file(header_add_icons, icons):
    with open(header_add_icons, 'w') as header_file:
        write_header_file_preamble(header_file)
        header_file.write('// List of method calls for IconSelectDialog.\n')

        for style in [solid_style, brands_style]:
            is_brand = 'true' if style == brands_style else 'false'
            for name, icon in icons.items():
                if style in icon['styles']:
                    code = icon['unicode']
                    search_terms = [icon['label'].lower()] + (icon['search']['terms'] or [])
                    search_terms_list = (
                            'QStringList()'
                            + ''.join([' << ' + json.dumps(term) for term in search_terms]))
                    header_file.write(f'addIcon(0x{code}, {is_brand}, {search_terms_list});' + '\n')


def write_icons_header_file(header_icons, icons):
    with open(header_icons, 'w') as header_file:
        write_header_file_preamble(header_file)
        header_file.write('#ifndef ICONS_H\n')
        header_file.write('#define ICONS_H\n')
        header_file.write('\n')
        header_file.write('enum IconId {\n')

        for name, icon in icons.items():
            label = name.title().replace('-', '')
            code = icon['unicode']
            header_file.write(f'    Icon{label} = 0x{code},' + '\n')

        header_file.write('};\n')
        header_file.write('\n')
        header_file.write('#endif // ICONS_H\n')


def rename_font_family(path):
    """
    Adds suffix to font family it doesn't conflict with font installed on
    system, which could be in incorrect version.
    """
    font = TTFont(path)
    name_table = font['name']

    name = name_table.getName(nameID=1, platformID=3, platEncID=1, langID=0x409)
    assert name

    name = name.toUnicode()
    assert name.startswith('Font Awesome')

    name = name + ' (CopyQ)'
    name = name_table.setName(name, nameID=1, platformID=3, platEncID=1, langID=0x409)

    font.save(path)


def copy_fonts(font_awesome_src, target_font_dir):
    font_dir = os.path.join(font_awesome_src, 'webfonts')
    for src_name, dest_name in fonts_src_dest:
        src_path = os.path.join(font_dir, src_name)
        dest_path = os.path.join(target_font_dir, dest_name)
        print(f'Copying: {src_path} -> {dest_path}')
        copyfile(src_path, dest_path)
        rename_font_family(dest_path)


def main():
    font_awesome_src = sys.argv[1]

    script = os.path.realpath(__file__)
    utils_dir = os.path.dirname(script)
    src_dir = os.path.join(utils_dir, '..', 'src')

    header_add_icons = os.path.join(src_dir, 'gui', 'add_icons.h')
    header_icons = os.path.join(src_dir, 'gui', 'icons.h')

    target_font_dir = os.path.join(src_dir, 'images')
    copy_fonts(font_awesome_src, target_font_dir)

    icons_json = os.path.join(
            font_awesome_src, 'metadata', 'icons.json')
    icons = read_icons(icons_json)

    write_add_icons_header_file(header_add_icons, icons)
    print(f'Header file "{header_add_icons}" updated.')

    write_icons_header_file(header_icons, icons)
    print(f'Header file "{header_icons}" updated.')


if __name__ == '__main__':
    main()