Skip to content
Snippets Groups Projects
update_icon_font.py 4.22 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
hluk's avatar
hluk committed
from textwrap import dedent
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)

hluk's avatar
hluk committed
def write_icon_list_header_file(header_icon_list, icons):
    with open(header_icon_list, 'w') as header_file:
        items = []
        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 [])
hluk's avatar
hluk committed
                    search_terms_list = '|'.join(search_terms)
                    items.append('{0x%s, %s, "%s"}' % (code, is_brand, search_terms_list))

        item_list_content = ',\n'.join(items)
        content = dedent('''\
            struct Icon {
                unsigned int unicode;
                bool isBrand;
                const char *searchTerms;
            };

            constexpr Icon iconList[] = {
            %s
            };
        ''') % item_list_content

        write_header_file_preamble(header_file)
        header_file.write(content)


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')

hluk's avatar
hluk committed
    header_icon_list = os.path.join(src_dir, 'gui', 'icon_list.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)

hluk's avatar
hluk committed
    write_icon_list_header_file(header_icon_list, icons)
    print(f'Header file "{header_icon_list}" updated.')

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


if __name__ == '__main__':
    main()