mirror of
https://github.com/google/fonts.git
synced 2024-12-26 02:04:42 +03:00
Open source add_font and what_subsets.
This commit is contained in:
parent
697f9096d4
commit
cbeaf9a685
132
tools/add_font.py
Normal file
132
tools/add_font.py
Normal file
@ -0,0 +1,132 @@
|
||||
|
||||
import errno
|
||||
import glob
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
|
||||
import fonts_public_pb2 as fonts_pb2
|
||||
from google.protobuf import text_format
|
||||
from google.apputils import app
|
||||
|
||||
from util import google_fonts as fonts
|
||||
|
||||
|
||||
|
||||
def _FileFamilyStyleWeights(fontdir):
|
||||
"""Extracts file, family, style, weight 4-tuples for each font in dir.
|
||||
|
||||
Args:
|
||||
fontdir: Directory that supposedly contains font files for a family.
|
||||
Returns:
|
||||
List of fonts.FileFamilyStyleWeightTuple ordered by weight, style
|
||||
(normal first).
|
||||
Raises:
|
||||
OSError: If the font directory doesn't exist (errno.ENOTDIR) or has no font
|
||||
files (errno.ENOENT) in it.
|
||||
RuntimeError: If the font directory appears to contain files from multiple
|
||||
families.
|
||||
"""
|
||||
if not os.path.isdir(fontdir):
|
||||
raise OSError(errno.ENOTDIR, 'No such directory', fontdir)
|
||||
|
||||
files = glob.glob(os.path.join(fontdir, '*.ttf'))
|
||||
if not files:
|
||||
raise OSError(errno.ENOENT, 'no font files found')
|
||||
|
||||
result = [fonts.FileFamilyStyleWeight(f) for f in files]
|
||||
def _Cmp(r1, r2):
|
||||
return cmp(r1.weight, r2.weight) or -cmp(r1.style, r2.style)
|
||||
result = sorted(result, _Cmp)
|
||||
|
||||
family_names = {i.family for i in result}
|
||||
if len(family_names) > 1:
|
||||
raise RuntimeError('Ambiguous family name; possibilities: %s'
|
||||
% family_names)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def _MakeMetadata(fontdir):
|
||||
"""Builds a dictionary matching a METADATA.pb file.
|
||||
|
||||
Args:
|
||||
fontdir: Directory containing font files for which we want metadata.
|
||||
Returns:
|
||||
OrderedDict of a complete METADATA.pb structure.
|
||||
"""
|
||||
file_family_style_weights = _FileFamilyStyleWeights(fontdir)
|
||||
|
||||
first_file = file_family_style_weights[0].file
|
||||
subsets = ['menu'] + [s[0] for s in fonts.SubsetsInFont(first_file, 50)]
|
||||
|
||||
font_license = fonts.LicenseFromPath(fontdir)
|
||||
|
||||
|
||||
metadata = fonts_pb2.FamilyProto()
|
||||
metadata.name = file_family_style_weights[0].family
|
||||
metadata.designer = 'Unknown'
|
||||
metadata.category = 'SANS_SERIF'
|
||||
metadata.license = font_license
|
||||
for subset in subsets:
|
||||
metadata.subsets.append(subset)
|
||||
metadata.date_added = time.strftime('%Y-%m-%d')
|
||||
|
||||
for (fontfile, family, style, weight) in file_family_style_weights:
|
||||
filename = os.path.basename(fontfile)
|
||||
font_psname = fonts.ExtractName(fontfile, fonts.NAME_PSNAME,
|
||||
os.path.splitext(filename)[0])
|
||||
font_copyright = fonts.ExtractName(fontfile, fonts.NAME_COPYRIGHT, '???.')
|
||||
|
||||
font_metadata = metadata.fonts.add()
|
||||
font_metadata.name = family
|
||||
font_metadata.style = style
|
||||
font_metadata.weight = weight
|
||||
font_metadata.filename = filename
|
||||
font_metadata.post_script_name = font_psname
|
||||
font_metadata.full_name = os.path.splitext(filename)[0].replace('-', ' ')
|
||||
|
||||
return metadata
|
||||
|
||||
|
||||
def _WriteTextFile(filename, text):
|
||||
"""Write text to file.
|
||||
|
||||
Nop if file exists with that exact content. This allows running against files
|
||||
that are in Piper and not marked for editing; you will get an error only if
|
||||
something changed.
|
||||
|
||||
Args:
|
||||
filename: The file to write.
|
||||
text: The content to write to the file.
|
||||
"""
|
||||
if os.path.isfile(filename):
|
||||
with open(filename, 'r') as f:
|
||||
current = f.read()
|
||||
if current == text:
|
||||
print 'No change to %s' % filename
|
||||
return
|
||||
|
||||
with open(filename, 'w') as f:
|
||||
f.write(text)
|
||||
print 'Wrote %s' % filename
|
||||
|
||||
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) != 2:
|
||||
sys.exit('One argument, a directory containing a font family')
|
||||
fontdir = argv[1]
|
||||
|
||||
metadata = _MakeMetadata(fontdir)
|
||||
text_proto = text_format.MessageToString(metadata)
|
||||
|
||||
_WriteTextFile(os.path.join(fontdir, 'DESCRIPTION.en_us.html'), 'N/A')
|
||||
_WriteTextFile(os.path.join(fontdir, 'METADATA.pb'), text_proto)
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
@ -12,11 +12,10 @@ import sys
|
||||
|
||||
from fontTools import ttLib
|
||||
|
||||
|
||||
import fonts_public_pb2 as fonts_pb2
|
||||
from google.protobuf import text_format
|
||||
import gflags as flags
|
||||
from google.apputils import resources
|
||||
from util import py_subsets
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
flags.DEFINE_string('nam_dir', 'encodings/', 'nam file dir')
|
||||
@ -71,6 +70,13 @@ _FS_SELECTION_BITS = [
|
||||
]
|
||||
|
||||
|
||||
# license_dir => license name mappings
|
||||
_KNOWN_LICENSE_DIRS = {
|
||||
'apache': 'APACHE2',
|
||||
'ofl': 'OFL',
|
||||
'ufl': 'UFL',
|
||||
}
|
||||
|
||||
|
||||
FileFamilyStyleWeightTuple = collections.namedtuple(
|
||||
'FileFamilyStyleWeightTuple', ['file', 'family', 'style', 'weight'])
|
||||
@ -145,17 +151,8 @@ def RegularWeight(metadata):
|
||||
|
||||
|
||||
def ListSubsets():
|
||||
"""Returns a list of all subset names, in lowercase, except */all and menu."""
|
||||
|
||||
subsets = []
|
||||
|
||||
with resources.GetResourceAsFile(_SUBSET_RESOURCE_PATH) as f:
|
||||
for l in f:
|
||||
match = _SUBSET_PATTERN.search(l)
|
||||
if match and match.group(1) not in ('ALL', 'MENU'):
|
||||
subsets.append(match.group(2))
|
||||
|
||||
return subsets
|
||||
"""Returns a list of all subset names, in lowercase."""
|
||||
return py_subsets.SUBSETS
|
||||
|
||||
|
||||
def Metadata(file_or_dir):
|
||||
@ -499,3 +496,28 @@ def FsSelectionFlags(fs_selection):
|
||||
return names
|
||||
|
||||
|
||||
def _EntryForEndOfPath(path, answer_map):
|
||||
segments = [s.lower() for s in path.split(os.sep)]
|
||||
answers = [answer_map[s] for s in segments
|
||||
if s in answer_map]
|
||||
if len(answers) != 1:
|
||||
raise ValueError('Found %d possible matches: %s' % (
|
||||
len(answers), answers))
|
||||
return answers[0]
|
||||
|
||||
|
||||
def LicenseFromPath(path):
|
||||
"""Try to figure out the license for a given path.
|
||||
|
||||
Splits path and looks for known license dirs in segments.
|
||||
|
||||
Args:
|
||||
path: A filesystem path, hopefully including a license dir.
|
||||
Returns:
|
||||
The name of the license, eg OFL, UFL, etc.
|
||||
Raises:
|
||||
ValueError: if 0 or >1 licenses match path.
|
||||
"""
|
||||
return _EntryForEndOfPath(path, _KNOWN_LICENSE_DIRS)
|
||||
|
||||
|
||||
|
98
tools/util/py_subsets.py
Executable file
98
tools/util/py_subsets.py
Executable file
@ -0,0 +1,98 @@
|
||||
SUBSETS = [
|
||||
"arabic",
|
||||
"armenian",
|
||||
"avestan",
|
||||
"balinese",
|
||||
"bamum",
|
||||
"batak",
|
||||
"bengali",
|
||||
"brahmi",
|
||||
"buginese",
|
||||
"buhid",
|
||||
"myanmar",
|
||||
"canadian-aboriginal",
|
||||
"carian",
|
||||
"cham",
|
||||
"chakma",
|
||||
"cherokee",
|
||||
"chinese-simplified",
|
||||
"chinese-traditional",
|
||||
"coptic",
|
||||
"cuneiform",
|
||||
"cypriot",
|
||||
"cyrillic",
|
||||
"cyrillic-ext",
|
||||
"deseret",
|
||||
"egyptian-hieroglyphs",
|
||||
"ethiopic",
|
||||
"georgian",
|
||||
"gothic",
|
||||
"greek",
|
||||
"greek-ext",
|
||||
"gujarati",
|
||||
"gurmukhi",
|
||||
"hanunoo",
|
||||
"hebrew",
|
||||
"imperial-aramaic",
|
||||
"inscriptional-pahlavi",
|
||||
"inscriptional-parthian",
|
||||
"devanagari",
|
||||
"japanese",
|
||||
"javanese",
|
||||
"kaithi",
|
||||
"kannada",
|
||||
"kayah-li",
|
||||
"kharoshthi",
|
||||
"khmer",
|
||||
"korean",
|
||||
"lao",
|
||||
"latin",
|
||||
"latin-ext",
|
||||
"lepcha",
|
||||
"limbu",
|
||||
"linear-b",
|
||||
"lisu",
|
||||
"lycian",
|
||||
"lydian",
|
||||
"malayalam",
|
||||
"mandaic",
|
||||
"meetei-mayek",
|
||||
"mongolian",
|
||||
"new-tai-lue",
|
||||
"ol-chiki",
|
||||
"old-italic",
|
||||
"old-persian",
|
||||
"old-south-arabian",
|
||||
"old-turkic",
|
||||
"ogham",
|
||||
"oriya",
|
||||
"osmanya",
|
||||
"phags-pa",
|
||||
"runic",
|
||||
"samaritan",
|
||||
"phoenician",
|
||||
"rejang",
|
||||
"saurashtra",
|
||||
"shavian",
|
||||
"sinhala",
|
||||
"sundanese",
|
||||
"syloti-nagri",
|
||||
"syriac-eastern",
|
||||
"syriac-estrangela",
|
||||
"syriac-western",
|
||||
"tagalog",
|
||||
"tagbanwa",
|
||||
"tai-le",
|
||||
"tai-tham",
|
||||
"tai-viet",
|
||||
"tamil",
|
||||
"telugu",
|
||||
"thaana",
|
||||
"thai",
|
||||
"tibetan",
|
||||
"tifinagh",
|
||||
"vai",
|
||||
"ugaritic",
|
||||
"vietnamese",
|
||||
"yi"
|
||||
]
|
25
tools/what_subsets.py
Normal file
25
tools/what_subsets.py
Normal file
@ -0,0 +1,25 @@
|
||||
|
||||
|
||||
import os
|
||||
|
||||
|
||||
from google.apputils import app
|
||||
import gflags as flags
|
||||
|
||||
from util import google_fonts as fonts
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
|
||||
flags.DEFINE_integer('min_pct', 0,
|
||||
'What percentage of subset codepoints have to be supported'
|
||||
' to print.')
|
||||
|
||||
|
||||
def main(argv):
|
||||
for arg in argv[1:]:
|
||||
for (subset, available, total) in fonts.SubsetsInFont(arg, FLAGS.min_pct):
|
||||
print '%s %s %d/%d' % (os.path.basename(arg), subset, available, total)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run()
|
Loading…
Reference in New Issue
Block a user