Last active
August 19, 2022 02:47
-
-
Save diogenese/dc54a517a6ea9810d4b9af505c75da2b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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