#!/usr/bin/env python import fontforge import os # Constants SOURCE_FONT_DIR = "input-fonts" OUTPUT_FONT_DIR = "output-fonts" COPYRIGHT = '\nProgramming ligatures added by Ilya Skriblovsky from FiraCode\nFiraCode Copyright (c) 2015 by Nikita Prokopov' def get_input_fontname(): return raw_input('Enter the source font filename (including extension): ') def get_input_path(input_fontname): return SOURCE_FONT_DIR + "/" + input_fontname # "RobotoMono-Regular.ttf" -> "RobotoMono-Regular" def name_without_file_extension(fontname): return fontname[:-4] if fontname.endswith(('.otf', '.ttf')) else fontname # "RobotoMono-Regular" -> "RobotoMono" def name_without_width_variant(fontname): no_variant = fontname if fontname.endswith("Regular"): no_variant = fontname[:-7] elif fontname.endswith("Book"): no_variant = fontname[:-4] return no_variant[:-1] if (no_variant.endswith(" ") or no_variant.endswith("-")) else no_variant def get_output_fontname(input_name): new_fontname = raw_input('Enter a name for your ligaturized font -- or press ENTER to use the same name: ') if new_fontname == "": new_fontname = input_name return name_without_width_variant(name_without_file_extension(new_fontname)) def get_output_font_details(fontname): name_with_spaces = split_camel_case(fontname) return { 'filename': fontname + '.ttf', 'fontname': fontname, 'fullname': name_with_spaces, 'familyname': name_with_spaces, 'copyright_add': COPYRIGHT, 'unique_id': name_with_spaces, } # Add spaces to UpperCamelCase: 'DVCode' -> 'DV Code' def split_camel_case(str): acc = '' for (i, ch) in enumerate(str): prevIsSpace = i > 0 and acc[-1] == ' ' nextIsLower = i + 1 < len(str) and str[i + 1].islower() isLast = i + 1 == len(str) if i != 0 and ch.isupper() and (nextIsLower or isLast) and not prevIsSpace: acc += ' ' + ch elif ch == '-' or ch == '_' or ch == '.': acc += ' ' else: acc += ch return acc config = { 'firacode_ttf': 'FiraCode-Medium.otf', 'add_ligatures': [ { # <- 'chars': ['less', 'hyphen'], 'firacode_ligature_name': 'less_hyphen.liga', }, { # <-- 'chars': ['less', 'hyphen', 'hyphen'], 'firacode_ligature_name': 'less_hyphen_hyphen.liga', }, { # -> 'chars': ['hyphen', 'greater'], 'firacode_ligature_name': 'hyphen_greater.liga', }, { # --> 'chars': ['hyphen', 'hyphen', 'greater'], 'firacode_ligature_name': 'hyphen_hyphen_greater.liga', }, { # <> 'chars': ['less', 'greater'], 'firacode_ligature_name': 'less_greater.liga', }, { # <-> 'chars': ['less', 'hyphen', 'greater'], 'firacode_ligature_name': 'less_hyphen_greater.liga', }, { # => 'chars': ['equal', 'greater'], 'firacode_ligature_name': 'equal_greater.liga', }, { # ==> 'chars': ['equal', 'equal', 'greater'], 'firacode_ligature_name': 'equal_equal_greater.liga', }, { # <== 'chars': ['less', 'equal', 'equal'], 'firacode_ligature_name': 'less_equal_equal.liga', }, { # ?= 'chars': ['question', 'equal'], 'firacode_ligature_name': 'question_equal.liga', }, { # != 'chars': ['exclam', 'equal'], 'firacode_ligature_name': 'exclam_equal.liga', }, { # == 'chars': ['equal', 'equal'], 'firacode_ligature_name': 'equal_equal.liga', }, { # <= 'chars': ['less', 'equal'], 'firacode_ligature_name': 'equal_less.liga', }, { # >= 'chars': ['greater', 'equal'], 'firacode_ligature_name': 'greater_equal.liga', }, { # :: 'chars': ['colon', 'colon'], 'firacode_ligature_name': 'colon_colon.liga', }, { # === 'chars': ['equal', 'equal', 'equal'], 'firacode_ligature_name': 'equal_equal_equal.liga', }, { # !== 'chars': ['exclam', 'equal', 'equal'], 'firacode_ligature_name': 'exclam_equal_equal.liga', }, { # ?? 'chars': ['question', 'question'], 'firacode_ligature_name': 'question_question.liga', }, { # !! 'chars': ['exclam', 'exclam'], 'firacode_ligature_name': 'exclam_exclam.liga', }, { # -- 'chars': ['hyphen', 'hyphen'], 'firacode_ligature_name': 'hyphen_hyphen.liga', }, { # --- 'chars': ['hyphen', 'hyphen', 'hyphen'], 'firacode_ligature_name': 'hyphen_hyphen_hyphen.liga', }, { # /* 'chars': ['slash', 'asterisk'], 'firacode_ligature_name': 'slash_asterisk.liga', }, { # /** 'chars': ['slash', 'asterisk', 'asterisk'], 'firacode_ligature_name': 'slash_asterisk_asterisk.liga', }, { # */ 'chars': ['asterisk', 'slash'], 'firacode_ligature_name': 'asterisk_slash.liga', }, { # // 'chars': ['slash', 'slash'], 'firacode_ligature_name': 'slash_slash.liga', }, { # /// 'chars': ['slash', 'slash', 'slash'], 'firacode_ligature_name': 'slash_slash_slash.liga', }, { # || 'chars': ['bar', 'bar'], 'firacode_ligature_name': 'bar_bar.liga', }, { # ||= 'chars': ['bar', 'bar', 'equal'], 'firacode_ligature_name': 'bar_bar_equal.liga', }, { # |= 'chars': ['bar', 'equal'], 'firacode_ligature_name': 'bar_equal.liga', }, { # ^= 'chars': ['asciicircum', 'equal'], 'firacode_ligature_name': 'asciicircum_equal.liga', }, { # ~= 'chars': ['asciitilde', 'equal'], 'firacode_ligature_name': 'asciitilde_equal.liga', }, { # =~ 'chars': ['equal', 'asciitilde'], 'firacode_ligature_name': 'equal_asciitilde.liga', }, { # ~> 'chars': ['asciitilde', 'greater'], 'firacode_ligature_name': 'asciitilde_greater.liga', }, { # ~~> 'chars': ['asciitilde', 'asciitilde', 'greater'], 'firacode_ligature_name': 'asciitilde_asciitilde_greater.liga', }, { # << 'chars': ['less', 'less'], 'firacode_ligature_name': 'less_less.liga', }, { # >> 'chars': ['greater', 'greater'], 'firacode_ligature_name': 'greater_greater.liga', }, { #