Skip to content

Instantly share code, notes, and snippets.

@paniq
Last active May 11, 2016 22:40
Show Gist options
  • Save paniq/4a734e9d8e86a2373b5bc4ca719855ec to your computer and use it in GitHub Desktop.
Save paniq/4a734e9d8e86a2373b5bc4ca719855ec to your computer and use it in GitHub Desktop.
# Convert Font Awesome, Google Material Design and Kenney Game icon font
# parameters to C++11 and C89 compatible formats.
#
#------------------------------------------------------------------------------
# 1 - Source material
#
# 1.1 - Font Awesome - https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/src/icons.yml
# 1.2 - Material Design - https://raw.githubusercontent.com/google/material-design-icons/master/iconfont/codepoints
# 1.3 - Kenney icons - https://raw.githubusercontent.com/SamBrishes/kenney-icon-font/master/css/kenney-icons.css
#
#------------------------------------------------------------------------------
# 2 - Data samples
#
# 2.1 - Font Awesome
# - input: - name: Music
# id: music
# unicode: f001
# created: 1.0
# filter:
# - note
# - sound
# categories:
# - Web Application Icons
# - output C++11: #define ICON_FA_MUSIC u8"\uf001"
# - output C89: #define ICON_FA_MUSIC "\xEF\x80\x81"
#
# 2.2 - Google Material Design icons
# - input: 3d_rotation e84d
# - output C++11: #define ICON_MD_3D_ROTATION u8"\ue84d"
# - output C89: #define ICON_MD_3D_ROTATION "\xEE\xA1\x8D"
#
# 2.3 - Kenney Game icons
# - input: .ki-home:before{ content: "\e900"; }
# - output C++11: #define ICON_KI_HOME u8"\ue900"
# - output C89: #define ICON_KI_HOME "\xEE\xA4\x80"
#
# 2.4 - All fonts
# - computed min and max unicode fonts ICON_MIN and ICON_MAX
# - output: #define ICON_MIN_FA 0xf000
# #define ICON_MAX_FA 0xf295
#
#------------------------------------------------------------------------------
# 3 - Script dependencies
#
# 3.1 - Python 2.7 - https://www.python.org/download/releases/2.7/
# 3.2 - Requests - http://docs.python-requests.org/
# 3.3 - PyYAML - http://pyyaml.org/
#
#------------------------------------------------------------------------------
import requests
import yaml
UNICODE_MIN = 'ffff'
UNICODE_MAX = '0'
TIMEOUT = 2
MESSAGE_SUCCESS = '{!s} fonts - conversion success: {!s}'
MESSAGE_ERROR = '{!s} fonts - error \n\t{!s}'
# for each target language, add a new formatter class and
# define lang, filename_template and line_format as in the examples below.
class FormatterC:
lang = "C"
filename_template = "{name}_c.h"
@staticmethod
def line_format_define( name, font_abbr, val):
return '#define ICON_{!s}_{!s} 0x{!s}\n'.format(name, font_abbr, val)
@staticmethod
def get_prelude( url ):
prelude = '// Generated by GenerateIconFontCppHeaders.py \n// from {!s}\n#pragma once\n\n'.format( url )
return prelude
@staticmethod
def line_format( font_abbr, font, unicode):
unicode_base = ''.join([ '{0:x}'.format( ord( x )) for x in unichr( int( unicode, 16 )).encode( 'utf-8' )]).upper()
unicode = '\\x' + unicode_base[ :2 ] + '\\x' + unicode_base[ 2:4 ] + '\\x' + unicode_base[ 4: ]
return '#define ICON_{!s}_{!s} "{!s}"\n'.format( font_abbr, font, unicode )
class FormatterCPP11(FormatterC):
lang = "C++11"
filename_template = "{name}.h"
@staticmethod
def line_format( font_abbr, font, unicode):
return '#define ICON_{!s}_{!s} u8"\u{!s}"\n'.format( font_abbr, font, unicode )
class FormatterNonelang:
lang = "nonelang"
filename_template = "{name}.n"
@staticmethod
def line_format_define( name, font_abbr, val):
return ' var icon-{!s}-{!s} 0x{!s}\n'.format(name.lower(), font_abbr.lower(), val)
@staticmethod
def get_prelude( url ):
prelude = 'none\n; Generated by GenerateIconFontCppHeaders.py \n; from {!s}\n\n$\n'.format( url )
return prelude
@staticmethod
def line_format( font_abbr, font, unicode):
unicode = unichr( int( unicode, 16 )).encode( 'utf-8' )
return ' var icon-{!s}-{!s} "{!s}"\n'.format( font_abbr.lower(), font.lower(), unicode )
formatters = [
FormatterCPP11,
FormatterC,
FormatterNonelang
]
def convert_font_awesome( formatter, font_name, font_abbr, source_url, output_name ):
try:
response = requests.get( source_url, timeout = TIMEOUT )
if response.status_code == 200:
input = yaml.safe_load( response.content )
min = UNICODE_MIN
max = UNICODE_MAX
output_fonts = ''
for item in input[ 'icons' ]:
font = ''
for char in item[ 'id' ]:
font += '_' if ( char == '-' ) else str.upper( char )
unicode = item[ 'unicode' ]
if unicode < min:
min = unicode
elif unicode >= max:
max = unicode
output_fonts += formatter.line_format( font_abbr, font, unicode )
output = formatter.get_prelude( source_url ) + \
formatter.line_format_define( 'MIN', font_abbr, min ) + \
formatter.line_format_define( 'MAX', font_abbr, max ) + \
output_fonts
output_file = formatter.filename_template.format(name = output_name)
with open( output_file, 'w' ) as f:
f.write( output )
print( MESSAGE_SUCCESS.format( font_name, output_file ))
except Exception as e:
print( MESSAGE_ERROR.format( font_name, e ))
def convert_material_design( formatter, font_name, font_abbr, source_url, output_name ):
try:
response = requests.get( source_url, timeout = TIMEOUT )
if response.status_code == 200:
input = str.split( response.content, '\n' )
min = UNICODE_MIN
max = UNICODE_MAX
output_fonts = ''
for line in input:
words = str.split( line )
if words:
font = ''
for char in words[ 0 ]:
font += '_' if ( char == '-' ) else str.upper( char )
unicode = words[ 1 ]
if unicode < min:
min = unicode
elif unicode >= max:
max = unicode
output_fonts += formatter.line_format( font_abbr, font, unicode )
output = formatter.get_prelude( source_url ) + \
formatter.line_format_define( 'MIN', font_abbr, min ) + \
formatter.line_format_define( 'MAX', font_abbr, max ) + \
output_fonts
output_file = formatter.filename_template.format(name = output_name)
with open( output_file, 'w' ) as f:
f.write( output )
print( MESSAGE_SUCCESS.format( font_name, output_file ))
except Exception as e:
print( MESSAGE_ERROR.format( font_name, e ))
def convert_kenney( formatter, font_name, font_abbr, source_url, output_name ):
try:
response = requests.get( source_url, timeout = TIMEOUT )
if response.status_code == 200:
input = str.split( response.content, '\n' )
min = UNICODE_MIN
max = UNICODE_MAX
output_fonts = ''
font_begin= '.ki-'
font_end = ':before'
unicode_begin = '"\\'
unicode_end = '";'
for line in input:
words = str.split( line )
if words:
if font_begin in words[ 0 ]:
font = ''
word = words[ 0 ][( words[ 0 ].find( font_begin ) + len( font_begin )) : ( words[ 0 ].find( font_end ))]
for char in word:
font += '_' if ( char == '-' ) else str.upper( char )
unicode = str( words[ 2 ][( words[ 2 ].find( unicode_begin ) + len( unicode_begin )) : words[ 2 ].find( unicode_end )])
if unicode < min:
min = unicode
elif unicode >= max:
max = unicode
output_fonts += formatter.line_format( font_abbr, font, unicode )
output = formatter.get_prelude( source_url ) + \
formatter.line_format_define( 'MIN', font_abbr, min ) + \
formatter.line_format_define( 'MAX', font_abbr, max ) + \
output_fonts
output_file = formatter.filename_template.format(name = output_name)
with open( output_file, 'w' ) as f:
f.write( output )
print( MESSAGE_SUCCESS.format( font_name, output_file ))
except Exception as e:
print( MESSAGE_ERROR.format( font_name, e ))
# Main
for formatter in formatters:
convert_font_awesome(
formatter,
'Font Awesome', 'FA',
'https://raw.githubusercontent.com/FortAwesome/Font-Awesome/master/src/icons.yml',
'IconsFontAwesome')
convert_material_design(
formatter,
'Material Design', 'MD',
'https://raw.githubusercontent.com/google/material-design-icons/master/iconfont/codepoints',
'IconsMaterialDesign')
convert_kenney(
formatter,
'Kenney', 'KI',
'https://raw.githubusercontent.com/SamBrishes/kenney-icon-font/master/css/kenney-icons.css',
'IconsKenney')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment