Skip to content

Instantly share code, notes, and snippets.

@diogenese
Last active August 19, 2022 02:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save diogenese/dc54a517a6ea9810d4b9af505c75da2b to your computer and use it in GitHub Desktop.
Save diogenese/dc54a517a6ea9810d4b9af505c75da2b to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import os
import sys
import argparse
import subprocess
import freetype
import re
import MySQLdb._mysql as _mysql
from shutil import copyfile
from freetype import Face
from pprint import pprint
from os.path import join,isdir,realpath
config = {}
def parsecmd():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("-b", "--base", default='.', help="Base font directory (where to start searching)")
parser.add_argument("-l", "--lib", default="/storage/www/sites/fontlib/lib", help="Font library directory (where copies are kept)")
parser.add_argument("-h", "--host", default="localhost", help="MySQL server host name")
parser.add_argument("-u", "--user", default="root", help="User loggin name")
parser.add_argument("-p", "--passwd", default="hunter2", help="User loggin password")
parser.add_argument("-d", "--database", default="myfontsdb", help="MySQL database name")
group = parser.add_mutually_exclusive_group()
group.add_argument("-t", "--port", type=int, help="Port use to connect to server")
group.add_argument("-s", "--sock", default="/var/lib/mysql/mysql.sock", help="Port use to connect to server")
args = parser.parse_args()
if args.base:
if not isdir( args.base ):
raise ArgumentError('base','Directory does not exist')
config['base'] = args.base
if args.lib:
if not isdir( args.lib ):
os.makedirs(args.lib)
config['lib'] = args.lib
if args.host:
config['host'] = args.host
if args.user:
config['user'] = args.user
if args.passwd:
config['passwd'] = args.passwd
if args.database:
config['database'] = args.database
if args.port:
config['port'] = args.port
if args.sock:
config['unix_socket'] = args.sock
def get_sql_create_table(key):
sql_create = {
'ftface':"""
CREATE TABLE `ftface` (
`id` INT(9) unsigned NOT NULL AUTO_INCREMENT,
`relpath` VARCHAR(128) NOT NULL DEFAULT '',
`libfile` VARCHAR(128) NOT NULL DEFAULT '',
`face_index` INT(3) unsigned NOT NULL DEFAULT 0,
`family_name` VARCHAR(48) NOT NULL DEFAULT '',
`style_name` VARCHAR(48) NOT NULL DEFAULT '',
`postscript_name` VARCHAR(128) NOT NULL DEFAULT '',
`face_flags` SET('SCALABLE','FIXED_SIZES','FIXED_WIDTH','SFNT','HORIZONTAL','VERTICAL',
'KERNING','FAST_GLYPHS','MULTIPLE_MASTERS','GLYPH_NAMES',
'HINTER','CID_KEYED','TRICKY') NOT NULL DEFAULT '',
`style_flags` SET('ITALIC','BOLD') NOT NULL DEFAULT '',
`num_faces` INT(6) unsigned NOT NULL DEFAULT 0,
`num_glyphs` INT(6) unsigned NOT NULL DEFAULT 0,
`num_fixed_sizes` INT(6) unsigned NOT NULL DEFAULT 0,
`fixed_sizes` VARCHAR(255) NOT NULL DEFAULT '',
`num_charmaps` INT(6) unsigned NOT NULL DEFAULT 0,
`num_ascii` INT(3) unsigned NOT NULL DEFAULT 0,
`copyright` TEXT DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `file` (`libfile`),
KEY `face` (`face_index`,`family_name`,`style_name`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci""",
'ftcharmap':"""
CREATE TABLE `ftcharmap` (
`face_id` INT(9) unsigned NOT NULL DEFAULT 0,
`face_index` INT(3) unsigned NOT NULL DEFAULT 0,
`charmap_index` INT(6) unsigned NOT NULL DEFAULT 0,
`encoding` INT(6) unsigned NOT NULL DEFAULT 0,
`platform_id` SMALLINT(1) unsigned NOT NULL DEFAULT 0,
`encoding_id` INT(6) unsigned NOT NULL DEFAULT 0,
`encoding_name` VARCHAR(48) NOT NULL DEFAULT '',
`platform_type` VARCHAR(48) NOT NULL DEFAULT '',
`encoding_type` VARCHAR(48) NOT NULL DEFAULT '',
`num_all` SMALLINT(3) unsigned NOT NULL DEFAULT 0,
`num_ascii` SMALLINT(3) unsigned NOT NULL DEFAULT 0,
`num_upper` SMALLINT(3) unsigned NOT NULL DEFAULT 0,
`num_lower` SMALLINT(3) unsigned NOT NULL DEFAULT 0,
`num_digit` SMALLINT(3) unsigned NOT NULL DEFAULT 0,
`num_space` SMALLINT(3) unsigned NOT NULL DEFAULT 0,
`num_punct` SMALLINT(3) unsigned NOT NULL DEFAULT 0,
`glyph_names` MEDIUMTEXT NOT NULL DEFAULT '',
PRIMARY KEY (`face_id`,`charmap_index`),
KEY `type` (`encoding`,`platform_id`,`encoding_id`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci""",
'ftsfnt':"""
CREATE TABLE `ftsfnt` (
`face_id` INT(9) unsigned NOT NULL DEFAULT 0,
`face_index` INT(3) unsigned NOT NULL DEFAULT 0,
`platform_id` INT(3) unsigned NOT NULL DEFAULT 0,
`encoding_id` INT(6) unsigned NOT NULL DEFAULT 0,
`language_id` INT(6) unsigned NOT NULL DEFAULT 0,
`sfnt_name_id` INT(3) unsigned NOT NULL DEFAULT 0,
`sfnt_name` VARCHAR(48) NOT NULL DEFAULT '',
`platform_type` VARCHAR(48) NOT NULL DEFAULT '',
`encoding_type` VARCHAR(48) NOT NULL DEFAULT '',
`language_type` VARCHAR(48) NOT NULL DEFAULT '',
`name` text DEFAULT NULL,
PRIMARY KEY (`face_id`,`platform_id`,`encoding_id`,`language_id`,`sfnt_name_id`)
) ENGINE=Aria DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci""",
'ftpage_names':"""
create procedure `get_pages` (
`pageitems` INT(4),
`where_clause` VARCHAR(1024),
`orderby` VARCHAR(1024)
) MODIFIES SQL DATA
BEGIN
declare querystr varchar(2048);
declare fontname varchar(512);
declare trecs, currec int(20);
if pageitems > 4 then
drop table if exists `page_names`;
create table `page_names` (
`id` INT(10) unsigned NOT NULL AUTO_INCREMENT,
`name` VARCHAR(512) NOT NULL DEFAULT '',
primary key (`id` )
) ENGINE=Aria DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
set querystr = concat("SELECT COUNT(*) INTO @cnt FROM ftface ft ",`where_clause`);
prepare count_stmt from querystr;
execute count_stmt;
set trecs = @cnt;
drop prepare count_stmt;
set querystr = concat("INSERT page_names(`name`)
SELECT CONCAT(family_name, style_name)
FROM ftface ft ",`where_clause`," ",`orderby`);
PREPARE item_stmt from querystr;
EXECUTE item_stmt;
drop prepare item_stmt;
set querystr = concat("DELETE FROM page_names WHERE MOD(`id` - 1,",pageitems,")>0");
PREPARE item_stmt from querystr;
EXECUTE item_stmt;
drop prepare item_stmt;
end if;
END
""",
'ftsortface':"""
create procedure `sort_face_table` (
) MODIFIES SQL DATA
BEGIN
drop table if exists ftface_tmp;
create table ftface_tmp like ftface;
insert into ftface_tmp (relpath,libfile,face_index,family_name,style_name,
postscript_name,face_flags,style_flags,num_faces,
num_glyphs,num_fixed_sizes,`fixed_sizes`,num_charmaps,
num_ascii,copyright)
select relpath,libfile,face_index,family_name,style_name,postscript_name,
face_flags,style_flags,num_faces,num_glyphs,num_fixed_sizes,
`fixed_sizes`,num_charmaps,num_ascii,copyright
from ftface order by family_name,style_name,face_index;
drop table ftface;
alter table ftface_tmp rename ftface;
END
"""
}
return sql_create[key] if key in sql_create else None
def get_sql_insert(key):
sql_insert = {
'ftface':"""
INSERT `ftface` ( `relpath`, `libfile`, `face_index`, `family_name`, `style_name`, `postscript_name`, `face_flags`,
`style_flags`, `num_faces`, `num_glyphs`, `num_fixed_sizes`, `num_charmaps`, `num_ascii` )
VALUES ( "{relpath}", "{libfile}", "{face_index}", "{family_name}", "{style_name}", "{postscript_name}", "{face_flags}",
"{style_flags}", "{num_faces}", "{num_glyphs}", "{num_fixed_sizes}", "{num_charmaps}", "{num_ascii}" )""",
'ftcharmap':"""
INSERT `ftcharmap` ( `face_id`, `face_index`, `charmap_index`, `encoding`, `platform_id`, `encoding_id`, `encoding_name`,
`platform_type`, `encoding_type`, `num_all`, `num_ascii`, `num_upper`, `num_lower`, `num_digit`, `num_space`,
`num_punct`, `glyph_names` )
VALUES ( "{face_id}", "{face_index}", "{charmap_index}", "{encoding}", "{platform_id}", "{encoding_id}", "{encoding_name}",
"{platform_type}", "{encoding_type}", "{num_all}", "{num_ascii}", "{num_upper}", "{num_lower}", "{num_digit}",
"{num_space}", "{num_punct}", "{glyph_names}" )""",
'ftsfnt':"""
INSERT `ftsfnt` ( `face_id`, `face_index`, `platform_id`, `encoding_id`, `language_id`, `sfnt_name_id`, `sfnt_name`,
`encoding_type`, `language_type`, `platform_type`, `name` )
VALUES ( "{face_id}", "{face_index}", "{platform_id}", "{encoding_id}", "{language_id}", "{sfnt_name_id}", "{sfnt_name}",
"{encoding_type}", "{language_type}", "{platform_type}", "{name}" )""" }
return sql_insert[key] if key in sql_insert else None
def check_db(dbcon,dbname):
if not dbcon or not dbname:
return False
dbcon.query(f'show databases like "{dbname}"')
result = dbcon.store_result()
if not result or not result.num_rows():
print(f"{dbname} does not exist yet")
dbcon.query(f'create database `{dbname}` default character set utf8mb4')
if dbcon.errno():
print(f"Failed to create {dbname}")
return False
dbcon.query(f'use {dbname}')
return True
def store_face_data(dbcon, face_info):
try:
dbcon.query(get_sql_insert('ftface').format(**face_info))
except:
if dbcon.errno():
print(f"Error inserting font record: {dbcon.error}")
return False
return True
def store_charmap_data(dbcon, charmap_info):
try:
dbcon.query(get_sql_insert('ftcharmap').format(**charmap_info))
except:
if dbcon.errno():
print(f"Error inserting ftcharmap record: {dbcon.error}")
def store_sfnt_data(dbcon, sfnt_info):
try:
dbcon.query(get_sql_insert('ftsfnt').format(**sfnt_info))
except:
if dbcon.errno():
print(f"Error inserting ftcharmap record: {dbcon.error}")
def store_glyph_name_data(dbcon, glyph_info):
dbcon.query(get_sql_insert('ftglyph').format(**glyph_info))
if dbcon.errno():
print(f"Error inserting ftcharmap record: {dbcon.error}")
def check_db_table(dbcon,table):
if not dbcon or not table:
return False
dbcon.query(f'show tables like "{table}"')
result = dbcon.store_result()
if not result or not result.num_rows():
print(f"{table} does not exist... yet")
dbcon.query(get_sql_create_table(table))
if dbcon.errno():
print(f"Failed to create {table}")
return False
return True
def check_db_func(dbcon,fname):
if not dbcon or not fname:
return False
try:
dbcon.query(get_sql_create_table(fname))
except:
if dbcon.errno():
print("{}: {}".format(fname, dbcon.error()))
def check_db_tables(dbcon):
if not dbcon:
return False
if not check_db(dbcon,config['database']):
return False
for table in ['ftface','ftcharmap','ftsfnt' ]:
if not check_db_table(dbcon,table):
return False
for func in ['ftpage_names','ftsortface']:
check_db_func(dbcon,func)
return True
def get_face_flags_list(flags):
list = []
if flags & freetype.FT_FACE_FLAG_SCALABLE:
list.append('SCALABLE')
if flags & freetype.FT_FACE_FLAG_FIXED_SIZES:
list.append('FIXES_SIZES')
if flags & freetype.FT_FACE_FLAG_FIXED_WIDTH:
list.append('FIXED_WIDTH')
if flags & freetype.FT_FACE_FLAG_SFNT:
list.append('SFNT')
if flags & freetype.FT_FACE_FLAG_HORIZONTAL:
list.append('HORIZONTAL')
if flags & freetype.FT_FACE_FLAG_VERTICAL:
list.append('VERTICAL')
if flags & freetype.FT_FACE_FLAG_KERNING:
list.append('KERNING')
if flags & freetype.FT_FACE_FLAG_FAST_GLYPHS:
list.append('FAST_GLYPHS')
if flags & freetype.FT_FACE_FLAG_MULTIPLE_MASTERS:
list.append('MULTIPLE_MASTERS')
if flags & freetype.FT_FACE_FLAG_GLYPH_NAMES:
list.append('GLYPH_NAMES')
if flags & freetype.FT_FACE_FLAG_HINTER:
list.append('HINTER')
if flags & freetype.FT_FACE_FLAG_CID_KEYED:
list.append('CID_KEYED')
if flags & freetype.FT_FACE_FLAG_TRICKY:
list.append('TRICKY')
return list
def get_face_style_list(flags):
list = []
if flags & freetype.FT_STYLE_FLAG_ITALIC:
list.append('ITALIC')
if flags & freetype.FT_STYLE_FLAG_BOLD:
list.append('BOLD')
return list
def get_encoding_apple_name(index):
encoding_apple_names = ['Default','Unicode 1.1','ISO-10646','Unicode 2.0','Variant Selector']
return encoding_apple_names[index] if index >=0 and index < len(encoding_apple_names) else 'Unknown'
def get_encoding_mac_name(index):
encoding_mac_names = ['Roman','Japanese','Traditional Chinese','Korean','Arabic','Hebrew','Greek','Russian','Rsymbol','Devanagari',
'Gurmukhi','Gurjarati','Oriya','Bengali','Tamil','Telugu','Kannada','Malayalam','Sinhalese','Burmese',
'Khmer','Thai','Loatian','Georgian','Armenian','Maldivian','Simplified Chinese','Tibetan','Mongolian','Geez',
'Slavic','Vietnamese','Sindhi','Uninterp']
return encoding_mac_names[index] if index >=0 and index < len(encoding_mac_names) else 'Unknown'
def get_encoding_iso_name(index):
encoding_iso_names = ['7bit ASCII','ISO-10646','ISO-8859-1']
return encoding_iso_names[index] if index >=0 and index < len(encoding_iso_names) else 'Unknown'
def get_encoding_ms_name(index):
encoding_ms_names = [ 'Symbol CS', 'Unicode CS', 'Sjis', 'Gb2312', 'Big 5', 'Wansung', 'Johab', 'UCS 4' ]
return encoding_ms_names[index] if index >=0 and index < len(encoding_ms_names) else 'Unknown'
def get_encoding_adobe_name(index):
encoding_adobe_names = ['Standard','Expert','Custom','Latin 1']
return encoding_adobe_names[index] if index >= 0 and index < len(encoding_adobe_names) else 'Unknown'
def get_platform_name(platform_id):
platform_names = ['Apple Unicode','Macintosh','ISO','Microsoft','Custom','Adobe']
return platform_names[platform_id] if platform_id >=0 and platform_id < len(platform_names) else 'Unknown Platform ID'
def get_platform_type(platform_id):
for key, value in freetype.TT_PLATFORMS.items():
if value == platform_id:
return key
return 'Unknown platform'
def encoding_is_unicode(encoding_name):
isunicode = ['Default', 'Unicode 1.1', 'Unicode 2.0', 'ISO-10646', 'Symbol CS', 'Unicode CS' ]
return encoding_name in isunicode
def encoding_is_english(encoding_name):
english = ['Roman', '7bit ASCII','ISO-8859-1']
def get_encoding_name(encoding):
encoding_names = { freetype.FT_ENCODING_NONE: "None", freetype.FT_ENCODING_ADOBE_CUSTOM: "Adobe Custom",
freetype.FT_ENCODING_ADOBE_EXPERT: "Adobe Expert", freetype.FT_ENCODING_ADOBE_LATIN1: "Adobe Latin1",
freetype.FT_ENCODING_ADOBE_STANDARD: "Adobe Standard", freetype.FT_ENCODING_APPLE_ROMAN: "Apple Roman",
freetype.FT_ENCODING_BIG5: "Big5", freetype.FT_ENCODING_GB2312: "GB2312", freetype.FT_ENCODING_JOHAB: "Johab",
freetype.FT_ENCODING_MS_SYMBOL: "Symbol", freetype.FT_ENCODING_OLD_LATIN2: "Latin 2",
freetype.FT_ENCODING_SJIS: "SJIS", freetype.FT_ENCODING_UNICODE: "Unicode", freetype.FT_ENCODING_WANSUNG: "Wansung" }
return encoding_names[encoding] if encoding in encoding_names else "Unknown"
def get_encoding_type(platform_id, encoding_id):
if platform_id == freetype.TT_PLATFORM_APPLE_UNICODE:
return get_encoding_apple_name(encoding_id)
if platform_id == freetype.TT_PLATFORM_MACINTOSH:
return get_encoding_mac_name(encoding_id)
if platform_id == freetype.TT_PLATFORM_MICROSOFT:
return get_encoding_ms_name(encoding_id)
if platform_id == freetype.TT_PLATFORM_ADOBE:
return get_encoding_adobe_name(encoding_id)
if platform_id == freetype.TT_PLATFORM_ISO:
return get_encoding_iso_name(encoding_id)
return 'Unknown encoding'
def get_language_type(platform_id, language_id):
if platform_id == freetype.TT_PLATFORM_MACINTOSH:
languages = freetype.TT_MAC_LANGIDS
precount = 14
elif platform_id == freetype.TT_PLATFORM_MICROSOFT:
languages = freetype.TT_MS_LANGIDS
precount = 13
else:
return 'Unknown'
for key, value in languages.items():
if value == language_id:
return key[precount:].replace('_',' ').title()
return 'Unknown language'
def get_sfnt_name( index ):
sfnt_names = ['copyright', 'font family', 'font subfamily', 'unique ID', 'full name', 'version string', 'PostScript name', 'tradmark',
'manufacturer', 'designer', 'verndor URL', 'license', 'license URL', 'reserved', 'prefered family', 'prefered subfamily',
'Mac full name', 'sample text', 'CID findfont name', 'wws family', 'wws subfamily']
return sfnt_names[index] if index >=0 and index < len(sfnt_names) and index != 15 else 'Unknown'
def store_font_data(dbcon,face_info):
if store_face_data(dbcon, face_info):
# Remember face record ID
last_id = dbcon.insert_id()
for charmap in face_info['charmaps']:
charmap['face_id'] = last_id
store_charmap_data(dbcon,charmap)
for name in face_info['sfnt_names']:
name['face_id'] = last_id
store_sfnt_data(dbcon,name)
if not os.path.exists(os.path.dirname(face_info['destfile'])):
os.makedirs(os.path.dirname(face_info['destfile']), mode=0o755)
print(f"Adding: {face_info['srcfile']}")
copyfile(face_info['srcfile'],face_info['destfile'])
def get_face_charmaps(face):
active = -1
if face.charmap:
active = face.charmap.index
charmaps = []
for charmap in face.charmaps:
charmap_info = { 'face_index': face.face_index, 'charmap_index': charmap.index, 'encoding':charmap.encoding,
'platform_id': charmap.platform_id, 'encoding_id': charmap.encoding_id,
'encoding_name': get_encoding_name(charmap.encoding),
'encoding_type': get_encoding_type(charmap.platform_id,charmap.encoding_id),
'platform_type': get_platform_type(charmap.platform_id), 'char_to_index': {}, 'index_to_char': {},
'num_all':0, 'num_ascii':0, 'num_upper':0, 'num_lower':0, 'num_digit':0, 'num_space':0, 'num_punct':0,
'glyph_names':''}
face.set_charmap(charmap)
for charcode, gindex in face.get_chars():
if face.face_flags & freetype.FT_FACE_FLAG_GLYPH_NAMES:
gname = face.get_glyph_name(gindex)
if gname and len(gname):
if not charmap_info['glyph_names']:
charmap_info['glyph_names'] = '{}:{}:{}'.format(gindex,hex(charcode),gname.decode(encoding='latin_1'))
else:
charmap_info['glyph_names'] += '\n{}:{}:{}'.format(gindex,hex(charcode),gname.decode(encoding='latin_1'))
else:
if not charmap_info['glyph_names']:
charmap_info['glyph_names'] = '{}:{}:'.format(gindex,hex(charcode))
else:
charmap_info['glyph_names'] += '\n{}:{}:'.format(gindex,hex(charcode))
charmap_info['char_to_index'][charcode] = gindex
if gindex in charmap_info['index_to_char']:
charmap_info['index_to_char'][gindex].append(charcode)
else:
charmap_info['index_to_char'][gindex] = [ charcode ]
charmap_info['num_all'] += 1
if charcode == ord(' '):
charmap_info['num_space'] += 1
charmap_info['num_ascii'] += 1
if charcode >= ord('a') and charcode <= ord('z'):
charmap_info['num_lower'] += 1
charmap_info['num_ascii'] += 1
if charcode >= ord('A') and charcode <= ord('Z'):
charmap_info['num_upper'] += 1
charmap_info['num_ascii'] += 1
if charcode >= ord('0') and charcode <= ord('9'):
charmap_info['num_digit'] += 1
charmap_info['num_ascii'] += 1
if (( charcode > ord(' ') and charcode < ord('0')) or
( charcode > ord('9') and charcode < ord('A')) or
( charcode > ord('Z') and charcode < ord('a')) or
( charcode > ord('z') and charcode < 127 )):
charmap_info['num_punct'] += 1
charmap_info['num_ascii'] += 1
if len(charmap_info['char_to_index']) and not (len(charmap_info['char_to_index']) == 1 and charmap_info['char_to_index'][0] == 0):
charmaps.append(charmap_info)
face.set_charmap(face.charmaps[active])
return charmaps if len(charmaps) else None
def strip_unwanted(rawstr):
ns = re.compile("([][#?!()<>{},'\"]|^[._]|[._]$)")
string = ns.sub('',rawstr)
return string.replace('&','and').replace('/','-').strip()
def get_face_info(srcfile, index):
face = Face(srcfile,index) if index else Face(srcfile)
if not face:
print(f"Open failed: {srcfile}")
return None
charmaps = get_face_charmaps(face)
if not charmaps:
print(f"No charmaps created for {srcfile}")
return None
ext = srcfile[-3:].lower()
sizes = [str(avs.size) for avs in face.available_sizes] if face.available_sizes else []
style = get_face_style_list(face.style_flags)
face_info = { 'face_index': face.face_index,
'family_name': strip_unwanted(face.family_name.decode(encoding='latin_1')),
'style_name': strip_unwanted(face.style_name.decode(encoding='latin_1')) if face.style_name else '',
'postscript_name': face.postscript_name.decode(encoding='latin_1') if face.postscript_name else '',
'face_flags': face.face_flags,
'style_flags': ','.join(style),
'num_faces': face.num_faces,
'num_fixed_sizes': face.num_fixed_sizes,
'fixed_sizes': ','.join(sizes),
'num_glyphs': face.num_glyphs,
'num_charmaps': face.num_charmaps,
'sfnt_name_count': face.sfnt_name_count,
'charmaps': charmaps,
'srcfile': srcfile }
family_name = face_info['family_name'].lower().replace(' ','_')
if not len(family_name):
print(f"Font family name missing: {srcfile}")
return None
style_name = face_info['style_name'].lower().replace(' ','_')
style_flags = face_info['style_flags'].lower().replace(',','_') if len(face_info['style_flags']) else None
myre = re.compile('\W+')
parts = [myre.sub('',family_name), myre.sub('',style_name), str(face.num_faces), str(face.num_glyphs),
str(face.num_charmaps), str(face.sfnt_name_count)]
if style_flags:
parts.insert(2,style_flags)
libfile = "{}.{}".format( '-'.join(parts), ext)
myre = re.compile('^_+|(?<=[-._])_+|_+(?=[-.])|_+$')
face_info['libfile'] = myre.sub('', libfile)
face_info['relpath'] = join(ext, face_info['libfile'][:2])
face_info['destfile'] = join(config['lib'], face_info['relpath'], face_info['libfile'])
if os.path.exists(face_info['destfile']):
print("File exists: {}".format(face_info['destfile']))
return None
face_info['num_ascii'] = 0
for charmap in face_info['charmaps']:
if face_info['num_ascii'] < charmap['num_ascii']:
face_info['num_ascii'] = charmap['num_ascii']
if 'SFNT' in get_face_flags_list(face_info['face_flags']):
face_info['sfnt_names'] = []
for index in range(face.sfnt_name_count):
name = face.get_sfnt_name(index)
if name.name_id == 256:
continue
sfnt_name = {'face_index': face.face_index, 'platform_id': name.platform_id, 'encoding_id': name.encoding_id,
'language_id': name.language_id,
'sfnt_name_id': name.name_id, 'sfnt_name': get_sfnt_name(name.name_id),
'platform_type': get_platform_type(name.platform_id),
'encoding_type': get_encoding_type(name.platform_id,name.encoding_id),
'language_type': get_language_type(name.platform_id,name.language_id)}
if encoding_is_unicode(get_encoding_type(name.platform_id,name.encoding_id)):
sfnt_name['name'] = name.string.decode(encoding='utf_16_be',errors='ignore').replace('\\','').replace('"','\\"')
face_info['sfnt_names'].append(sfnt_name)
elif encoding_is_english(get_encoding_type(name.platform_id,name.encoding_id)):
string = name.string.decode() if isinstance(name.string,bytes) else name.string
sfnt_name['name'] = string.replace('\\','').replace('"','\\"')
face_info['sfnt_names'].append(sfnt_name)
return face_info
def check_font_info(dbcon, path, filename):
srcfile = join(config['base'], path, filename)
try:
face = Face(srcfile)
if face.face_index:
for index in range(1,face.num_faces+1):
face_info = get_face_info(srcfile,index)
if face_info:
store_font_data(dbcon,face_info)
else:
print(f"Skipped: {srcfile}")
else:
face_info = get_face_info(srcfile,0)
if face_info:
store_font_data(dbcon,face_info)
else:
print(f"Skipped: {srcfile}")
except KeyboardInterrupt:
sys.exit(0)
except:
print("Failed to process: {}\nError: {}".format( srcfile,sys.exc_info()[1]))
def search_fonts():
dbcon = _mysql.connect(config['host'],config['user'],config['passwd'])
if not dbcon:
print("MySQL connection failed.")
return
dbcon.set_character_set("utf8mb4")
if not check_db_tables(dbcon):
return
olddir = realpath('.')
os.chdir(config['base'])
for root, dirs, files in os.walk('.'):
for file_ in files:
if file_[-4:].lower() not in ['.ttf', '.otf', '.ttc']:
print(f"Skipping {file_}")
continue
check_font_info(dbcon, root[2:],file_)
os.chdir(olddir)
if __name__ == '__main__':
parsecmd()
search_fonts()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment