Fix indentation, format code according to autopep8

This commit is contained in:
Roel Nieskens 2019-09-10 13:59:15 +02:00
parent 833a43d032
commit 9eade97ded

View file

@ -17,7 +17,6 @@
# Google Author(s): Behdad Esfahbod, Stuart Gill, Roozbeh Pournader # Google Author(s): Behdad Esfahbod, Stuart Gill, Roozbeh Pournader
# #
from __future__ import print_function from __future__ import print_function
import sys, struct, StringIO import sys, struct, StringIO
from png import PNG from png import PNG
@ -26,33 +25,38 @@ from os import path
from nototools import font_data from nototools import font_data
def get_glyph_name_from_gsub (string, font, cmap_dict):
def get_glyph_name_from_gsub(string, font, cmap_dict):
ligatures = font['GSUB'].table.LookupList.Lookup[0].SubTable[0].ligatures ligatures = font['GSUB'].table.LookupList.Lookup[0].SubTable[0].ligatures
first_glyph = cmap_dict[ord (string[0])] first_glyph = cmap_dict[ord(string[0])]
rest_of_glyphs = [cmap_dict[ord (ch)] for ch in string[1:]] rest_of_glyphs = [cmap_dict[ord(ch)] for ch in string[1:]]
for ligature in ligatures[first_glyph]: for ligature in ligatures[first_glyph]:
if ligature.Component == rest_of_glyphs: if ligature.Component == rest_of_glyphs:
return ligature.LigGlyph return ligature.LigGlyph
def div (a, b): def div(a, b):
return int (round (a / float (b))) return int(round(a / float(b)))
class FontMetrics: class FontMetrics:
def __init__ (self, upem, ascent, descent): def __init__(self, upem, ascent, descent):
self.upem = upem self.upem = upem
self.ascent = ascent self.ascent = ascent
self.descent = descent self.descent = descent
class StrikeMetrics: class StrikeMetrics:
def __init__ (self, font_metrics, advance, bitmap_width, bitmap_height): def __init__(self, font_metrics, advance, bitmap_width, bitmap_height):
self.width = bitmap_width # in pixels self.width = bitmap_width # in pixels
self.height = bitmap_height # in pixels self.height = bitmap_height # in pixels
self.advance = advance # in font units self.advance = advance # in font units
self.x_ppem = self.y_ppem = div (bitmap_width * font_metrics.upem, advance) self.x_ppem = self.y_ppem = div(bitmap_width * font_metrics.upem,
advance)
class GlyphMap: class GlyphMap:
def __init__ (self, glyph, offset, image_format): def __init__(self, glyph, offset, image_format):
self.glyph = glyph self.glyph = glyph
self.offset = offset self.offset = offset
self.image_format = image_format self.image_format = image_format
@ -60,47 +64,48 @@ class GlyphMap:
# Based on http://www.microsoft.com/typography/otspec/ebdt.htm # Based on http://www.microsoft.com/typography/otspec/ebdt.htm
class CBDT: class CBDT:
def __init__(self, font_metrics, options=(), stream=None):
def __init__ (self, font_metrics, options = (), stream = None): self.stream = stream if stream != None else bytearray()
self.stream = stream if stream != None else bytearray ()
self.options = options self.options = options
self.font_metrics = font_metrics self.font_metrics = font_metrics
self.base_offset = 0 self.base_offset = 0
self.base_offset = self.tell () self.base_offset = self.tell()
def tell (self): def tell(self):
return len (self.stream) - self.base_offset return len(self.stream) - self.base_offset
def write (self, data):
self.stream.extend (data) def write(self, data):
def data (self): self.stream.extend(data)
def data(self):
return self.stream return self.stream
def write_header (self): def write_header(self):
self.write (struct.pack (">L", 0x00030000)) # FIXED version self.write(struct.pack(">L", 0x00030000)) # FIXED version
def start_strike (self, strike_metrics): def start_strike(self, strike_metrics):
self.strike_metrics = strike_metrics self.strike_metrics = strike_metrics
self.glyph_maps = [] self.glyph_maps = []
def write_glyphs (self, glyphs, glyph_filenames, image_format): def write_glyphs(self, glyphs, glyph_filenames, image_format):
write_func = self.image_write_func (image_format) write_func = self.image_write_func(image_format)
for glyph in glyphs: for glyph in glyphs:
img_file = glyph_filenames[glyph] img_file = glyph_filenames[glyph]
# print 'writing data for glyph %s' % path.basename(img_file) # print 'writing data for glyph %s' % path.basename(img_file)
offset = self.tell () offset = self.tell()
write_func (PNG (img_file)) write_func(PNG(img_file))
self.glyph_maps.append (GlyphMap (glyph, offset, image_format)) self.glyph_maps.append(GlyphMap(glyph, offset, image_format))
def end_strike (self): def end_strike(self):
self.glyph_maps.append (GlyphMap (None, self.tell (), None)) self.glyph_maps.append(GlyphMap(None, self.tell(), None))
glyph_maps = self.glyph_maps glyph_maps = self.glyph_maps
del self.glyph_maps del self.glyph_maps
del self.strike_metrics del self.strike_metrics
return glyph_maps return glyph_maps
def write_glyphMetrics (self, width, height, big_metrics): def write_glyphMetrics(self, width, height, big_metrics):
ascent = self.font_metrics.ascent ascent = self.font_metrics.ascent
descent = self.font_metrics.descent descent = self.font_metrics.descent
@ -109,15 +114,15 @@ class CBDT:
x_bearing = 0 x_bearing = 0
# center vertically # center vertically
line_height = (ascent + descent) * y_ppem / float (upem) line_height = (ascent + descent) * y_ppem / float(upem)
line_ascent = ascent * y_ppem / float (upem) line_ascent = ascent * y_ppem / float(upem)
y_bearing = int (round (line_ascent - .5 * (line_height - height))) y_bearing = int(round(line_ascent - .5 * (line_height - height)))
# fudge y_bearing if calculations are a bit off # fudge y_bearing if calculations are a bit off
if y_bearing == 128: if y_bearing == 128:
y_bearing = 127 y_bearing = 127
advance = width advance = width
vert_x_bearing = - width / 2 vert_x_bearing = -width / 2
vert_y_bearing = 0 vert_y_bearing = 0
vert_advance = height vert_advance = height
@ -129,130 +134,131 @@ class CBDT:
# CHAR horiBearingX # CHAR horiBearingX
# CHAR horiBearingY # CHAR horiBearingY
# BYTE horiAdvance # BYTE horiAdvance
# add for bigGlyphMetrics: # add for bigGlyphMetrics:
# CHAR vertBearingX # CHAR vertBearingX
# CHAR vertBearingY # CHAR vertBearingY
# BYTE vertAdvance # BYTE vertAdvance
try: try:
if big_metrics: if big_metrics:
self.write (struct.pack ("BBbbBbbB", self.write(
height, width, struct.pack("BBbbBbbB", height, width, x_bearing,
x_bearing, y_bearing, y_bearing, advance, vert_x_bearing,
advance, vert_y_bearing, vert_advance))
vert_x_bearing, vert_y_bearing, else:
vert_advance)) self.write(
else: struct.pack("BBbbB", height, width, x_bearing, y_bearing,
self.write (struct.pack ("BBbbB", advance))
height, width, except Exception as e:
x_bearing, y_bearing, raise ValueError("%s, h: %d w: %d x: %d y: %d %d a:" %
advance)) (e, height, width, x_bearing, y_bearing, advance))
except Exception as e:
raise ValueError("%s, h: %d w: %d x: %d y: %d %d a:" % (
e, height, width, x_bearing, y_bearing, advance))
def write_format1 (self, png): def write_format1(self, png):
import cairo import cairo
img = cairo.ImageSurface.create_from_png (png.stream ()) img = cairo.ImageSurface.create_from_png(png.stream())
if img.get_format () != cairo.FORMAT_ARGB32: if img.get_format() != cairo.FORMAT_ARGB32:
raise Exception ("Expected FORMAT_ARGB32, but image has format %d" % img.get_format ()) raise Exception("Expected FORMAT_ARGB32, but image has format %d" %
img.get_format())
width = img.get_width () width = img.get_width()
height = img.get_height () height = img.get_height()
stride = img.get_stride () stride = img.get_stride()
data = img.get_data () data = img.get_data()
self.write_smallGlyphMetrics (width, height) self.write_smallGlyphMetrics(width, height)
if sys.byteorder == "little" and stride == width * 4: if sys.byteorder == "little" and stride == width * 4:
# Sweet. Data is in desired format, ship it! # Sweet. Data is in desired format, ship it!
self.write (data) self.write(data)
return return
# Unexpected stride or endianness, do it the slow way # Unexpected stride or endianness, do it the slow way
offset = 0 offset = 0
for y in range (height): for y in range(height):
for x in range (width): for x in range(width):
pixel = data[offset + 4 * x: offset + 4 * (x + 1)] pixel = data[offset + 4 * x:offset + 4 * (x + 1)]
# Convert to little endian # Convert to little endian
pixel = struct.pack ("<I", struct.unpack ("@I", pixel)[0]) pixel = struct.pack("<I", struct.unpack("@I", pixel)[0])
self.write (pixel) self.write(pixel)
offset += stride offset += stride
png_allowed_chunks = ["IHDR", "PLTE", "tRNS", "sRGB", "IDAT", "IEND"] png_allowed_chunks = ["IHDR", "PLTE", "tRNS", "sRGB", "IDAT", "IEND"]
def write_format17 (self, png): def write_format17(self, png):
self.write_format17or18(png, False) self.write_format17or18(png, False)
def write_format18 (self, png): def write_format18(self, png):
self.write_format17or18(png, True) self.write_format17or18(png, True)
def write_format17or18 (self, png, big_metrics): def write_format17or18(self, png, big_metrics):
width, height = png.get_size () width, height = png.get_size()
if 'keep_chunks' not in self.options: if 'keep_chunks' not in self.options:
png = png.filter_chunks (self.png_allowed_chunks) png = png.filter_chunks(self.png_allowed_chunks)
self.write_glyphMetrics (width, height, big_metrics) self.write_glyphMetrics(width, height, big_metrics)
png_data = png.data () png_data = png.data()
# ULONG data length # ULONG data length
self.write (struct.pack(">L", len (png_data))) self.write(struct.pack(">L", len(png_data)))
self.write (png_data) self.write(png_data)
def image_write_func (self, image_format): def image_write_func(self, image_format):
if image_format == 1: return self.write_format1 if image_format == 1: return self.write_format1
if image_format == 17: return self.write_format17 if image_format == 17: return self.write_format17
if image_format == 18: return self.write_format18 if image_format == 18: return self.write_format18
return None return None
# Based on http://www.microsoft.com/typography/otspec/eblc.htm # Based on http://www.microsoft.com/typography/otspec/eblc.htm
class CBLC: class CBLC:
def __init__(self, font_metrics, options=(), stream=None):
def __init__ (self, font_metrics, options = (), stream = None): self.stream = stream if stream != None else bytearray()
self.stream = stream if stream != None else bytearray ()
self.streams = [] self.streams = []
self.options = options self.options = options
self.font_metrics = font_metrics self.font_metrics = font_metrics
self.base_offset = 0 self.base_offset = 0
self.base_offset = self.tell () self.base_offset = self.tell()
def tell (self): def tell(self):
return len (self.stream) - self.base_offset return len(self.stream) - self.base_offset
def write (self, data):
self.stream.extend (data) def write(self, data):
def data (self): self.stream.extend(data)
def data(self):
return self.stream return self.stream
def push_stream (self, stream):
self.streams.append (self.stream) def push_stream(self, stream):
self.streams.append(self.stream)
self.stream = stream self.stream = stream
def pop_stream (self):
def pop_stream(self):
stream = self.stream stream = self.stream
self.stream = self.streams.pop () self.stream = self.streams.pop()
return stream return stream
def write_header (self): def write_header(self):
self.write (struct.pack (">L", 0x00030000)) # FIXED version self.write(struct.pack(">L", 0x00030000)) # FIXED version
def start_strikes (self, num_strikes): def start_strikes(self, num_strikes):
self.num_strikes = num_strikes self.num_strikes = num_strikes
self.write (struct.pack (">L", self.num_strikes)) # ULONG numSizes self.write(struct.pack(">L", self.num_strikes)) # ULONG numSizes
self.bitmapSizeTables = bytearray () self.bitmapSizeTables = bytearray()
self.otherTables = bytearray () self.otherTables = bytearray()
def write_strike (self, strike_metrics, glyph_maps): def write_strike(self, strike_metrics, glyph_maps):
self.strike_metrics = strike_metrics self.strike_metrics = strike_metrics
self.write_bitmapSizeTable (glyph_maps) self.write_bitmapSizeTable(glyph_maps)
del self.strike_metrics del self.strike_metrics
def end_strikes (self): def end_strikes(self):
self.write (self.bitmapSizeTables) self.write(self.bitmapSizeTables)
self.write (self.otherTables) self.write(self.otherTables)
del self.bitmapSizeTables del self.bitmapSizeTables
del self.otherTables del self.otherTables
def write_sbitLineMetrics_hori (self): def write_sbitLineMetrics_hori(self):
ascent = self.font_metrics.ascent ascent = self.font_metrics.ascent
descent = self.font_metrics.descent descent = self.font_metrics.descent
@ -273,33 +279,43 @@ class CBLC:
# CHAR minAfterBL # CHAR minAfterBL
# CHAR pad1 # CHAR pad1
# CHAR pad2 # CHAR pad2
line_height = div ((ascent + descent) * y_ppem, upem) line_height = div((ascent + descent) * y_ppem, upem)
ascent = div (ascent * y_ppem, upem) ascent = div(ascent * y_ppem, upem)
descent = - (line_height - ascent) descent = -(line_height - ascent)
self.write (struct.pack ("bbBbbbbbbbbb", self.write(
ascent, descent, struct.pack(
self.strike_metrics.width, "bbBbbbbbbbbb",
0, 0, 0, ascent,
0, 0, 0, 0, # TODO descent,
0, 0)) self.strike_metrics.width,
0,
0,
0,
0,
0,
0,
0, # TODO
0,
0))
def write_sbitLineMetrics_vert (self): def write_sbitLineMetrics_vert(self):
self.write_sbitLineMetrics_hori () # XXX self.write_sbitLineMetrics_hori() # XXX
def write_indexSubTable1 (self, glyph_maps): def write_indexSubTable1(self, glyph_maps):
image_format = glyph_maps[0].image_format image_format = glyph_maps[0].image_format
self.write (struct.pack(">H", 1)) # USHORT indexFormat self.write(struct.pack(">H", 1)) # USHORT indexFormat
self.write (struct.pack(">H", image_format)) # USHORT imageFormat self.write(struct.pack(">H", image_format)) # USHORT imageFormat
imageDataOffset = glyph_maps[0].offset imageDataOffset = glyph_maps[0].offset
self.write (struct.pack(">L", imageDataOffset)) # ULONG imageDataOffset self.write(struct.pack(">L", imageDataOffset)) # ULONG imageDataOffset
for gmap in glyph_maps[:-1]: for gmap in glyph_maps[:-1]:
self.write (struct.pack(">L", gmap.offset - imageDataOffset)) # ULONG offsetArray self.write(struct.pack(">L", gmap.offset -
imageDataOffset)) # ULONG offsetArray
assert gmap.image_format == image_format assert gmap.image_format == image_format
self.write (struct.pack(">L", glyph_maps[-1].offset - imageDataOffset)) self.write(struct.pack(">L", glyph_maps[-1].offset - imageDataOffset))
def write_bitmapSizeTable (self, glyph_maps): def write_bitmapSizeTable(self, glyph_maps):
# count number of ranges # count number of ranges
count = 1 count = 1
@ -313,8 +329,8 @@ class CBLC:
last_image_format = gmap.image_format last_image_format = gmap.image_format
headersLen = count * 8 headersLen = count * 8
headers = bytearray () headers = bytearray()
subtables = bytearray () subtables = bytearray()
start = glyph_maps[0].glyph start = glyph_maps[0].glyph
start_id = 0 start_id = 0
last_glyph = start last_glyph = start
@ -322,64 +338,69 @@ class CBLC:
last_id = 0 last_id = 0
for gmap in glyph_maps[1:-1]: for gmap in glyph_maps[1:-1]:
if last_glyph + 1 != gmap.glyph or last_image_format != gmap.image_format: if last_glyph + 1 != gmap.glyph or last_image_format != gmap.image_format:
headers.extend (struct.pack(">HHL", start, last_glyph, headersLen + len (subtables))) headers.extend(
self.push_stream (subtables) struct.pack(">HHL", start, last_glyph,
self.write_indexSubTable1 (glyph_maps[start_id:last_id+2]) headersLen + len(subtables)))
self.pop_stream () self.push_stream(subtables)
self.write_indexSubTable1(glyph_maps[start_id:last_id + 2])
self.pop_stream()
start = gmap.glyph start = gmap.glyph
start_id = last_id + 1 start_id = last_id + 1
last_glyph = gmap.glyph last_glyph = gmap.glyph
last_image_format = gmap.image_format last_image_format = gmap.image_format
last_id += 1 last_id += 1
headers.extend (struct.pack(">HHL", start, last_glyph, headersLen + len (subtables))) headers.extend(
self.push_stream (subtables) struct.pack(">HHL", start, last_glyph,
self.write_indexSubTable1 (glyph_maps[start_id:last_id+2]) headersLen + len(subtables)))
self.pop_stream () self.push_stream(subtables)
self.write_indexSubTable1(glyph_maps[start_id:last_id + 2])
self.pop_stream()
indexTablesSize = len (headers) + len (subtables) indexTablesSize = len(headers) + len(subtables)
numberOfIndexSubTables = count numberOfIndexSubTables = count
bitmapSizeTableSize = 48 * self.num_strikes bitmapSizeTableSize = 48 * self.num_strikes
indexSubTableArrayOffset = 8 + bitmapSizeTableSize + len (self.otherTables) indexSubTableArrayOffset = 8 + bitmapSizeTableSize + len(
self.otherTables)
self.push_stream (self.bitmapSizeTables) self.push_stream(self.bitmapSizeTables)
# bitmapSizeTable # bitmapSizeTable
# Type Name Description # Type Name Description
# ULONG indexSubTableArrayOffset offset to index subtable from beginning of CBLC. # ULONG indexSubTableArrayOffset offset to index subtable from beginning of CBLC.
self.write (struct.pack(">L", indexSubTableArrayOffset)) self.write(struct.pack(">L", indexSubTableArrayOffset))
# ULONG indexTablesSize number of bytes in corresponding index subtables and array # ULONG indexTablesSize number of bytes in corresponding index subtables and array
self.write (struct.pack(">L", indexTablesSize)) self.write(struct.pack(">L", indexTablesSize))
# ULONG numberOfIndexSubTables an index subtable for each range or format change # ULONG numberOfIndexSubTables an index subtable for each range or format change
self.write (struct.pack(">L", numberOfIndexSubTables)) self.write(struct.pack(">L", numberOfIndexSubTables))
# ULONG colorRef not used; set to 0. # ULONG colorRef not used; set to 0.
self.write (struct.pack(">L", 0)) self.write(struct.pack(">L", 0))
# sbitLineMetrics hori line metrics for text rendered horizontally # sbitLineMetrics hori line metrics for text rendered horizontally
self.write_sbitLineMetrics_hori () self.write_sbitLineMetrics_hori()
self.write_sbitLineMetrics_vert () self.write_sbitLineMetrics_vert()
# sbitLineMetrics vert line metrics for text rendered vertically # sbitLineMetrics vert line metrics for text rendered vertically
# USHORT startGlyphIndex lowest glyph index for this size # USHORT startGlyphIndex lowest glyph index for this size
self.write (struct.pack(">H", glyph_maps[0].glyph)) self.write(struct.pack(">H", glyph_maps[0].glyph))
# USHORT endGlyphIndex highest glyph index for this size # USHORT endGlyphIndex highest glyph index for this size
self.write (struct.pack(">H", glyph_maps[-2].glyph)) self.write(struct.pack(">H", glyph_maps[-2].glyph))
# BYTE ppemX horizontal pixels per Em # BYTE ppemX horizontal pixels per Em
self.write (struct.pack(">B", self.strike_metrics.x_ppem)) self.write(struct.pack(">B", self.strike_metrics.x_ppem))
# BYTE ppemY vertical pixels per Em # BYTE ppemY vertical pixels per Em
self.write (struct.pack(">B", self.strike_metrics.y_ppem)) self.write(struct.pack(">B", self.strike_metrics.y_ppem))
# BYTE bitDepth the Microsoft rasterizer v.1.7 or greater supports the # BYTE bitDepth the Microsoft rasterizer v.1.7 or greater supports the
# following bitDepth values, as described below: 1, 2, 4, and 8. # following bitDepth values, as described below: 1, 2, 4, and 8.
self.write (struct.pack(">B", 32)) self.write(struct.pack(">B", 32))
# CHAR flags vertical or horizontal (see bitmapFlags) # CHAR flags vertical or horizontal (see bitmapFlags)
self.write (struct.pack(">b", 0x01)) self.write(struct.pack(">b", 0x01))
self.pop_stream () self.pop_stream()
self.push_stream (self.otherTables) self.push_stream(self.otherTables)
self.write (headers) self.write(headers)
self.write (subtables) self.write(subtables)
self.pop_stream () self.pop_stream()
def main (argv): def main(argv):
import glob import glob
from fontTools import ttx, ttLib from fontTools import ttx, ttLib
@ -389,16 +410,16 @@ def main (argv):
"-V": "verbose", "-V": "verbose",
"-O": "keep_outlines", "-O": "keep_outlines",
"-U": "uncompressed", "-U": "uncompressed",
"-S": "small_glyph_metrics", "-S": "small_glyph_metrics",
"-C": "keep_chunks", "-C": "keep_chunks",
} }
for key, value in option_map.items (): for key, value in option_map.items():
if key in argv: if key in argv:
options.append (value) options.append(value)
argv.remove (key) argv.remove(key)
if len (argv) < 4: if len(argv) < 4:
print(""" print("""
Usage: Usage:
@ -431,55 +452,54 @@ By default they are dropped.
If -C is given, unused chunks (color profile, etc) are NOT If -C is given, unused chunks (color profile, etc) are NOT
dropped from the PNG images when embedding. dropped from the PNG images when embedding.
By default they are dropped. By default they are dropped.
""", file=sys.stderr) """,
sys.exit (1) file=sys.stderr)
sys.exit(1)
font_file = argv[1] font_file = argv[1]
out_file = argv[2] out_file = argv[2]
img_prefixes = argv[3:] img_prefixes = argv[3:]
del argv del argv
def add_font_table (font, tag, data): def add_font_table(font, tag, data):
tab = ttLib.tables.DefaultTable.DefaultTable (tag) tab = ttLib.tables.DefaultTable.DefaultTable(tag)
tab.data = str(data) tab.data = str(data)
font[tag] = tab font[tag] = tab
def drop_outline_tables (font): def drop_outline_tables(font):
for tag in ['cvt ', 'fpgm', 'glyf', 'loca', 'prep', 'CFF ', 'VORG']: for tag in ['cvt ', 'fpgm', 'glyf', 'loca', 'prep', 'CFF ', 'VORG']:
try: try:
del font[tag] del font[tag]
except KeyError: except KeyError:
pass pass
print() print()
font = ttx.TTFont (font_file) font = ttx.TTFont(font_file)
print("Loaded font '%s'." % font_file) print("Loaded font '%s'." % font_file)
font_metrics = FontMetrics (font['head'].unitsPerEm, font_metrics = FontMetrics(font['head'].unitsPerEm, font['hhea'].ascent,
font['hhea'].ascent, -font['hhea'].descent)
-font['hhea'].descent)
print("Font metrics: upem=%d ascent=%d descent=%d." % \ print("Font metrics: upem=%d ascent=%d descent=%d." % \
(font_metrics.upem, font_metrics.ascent, font_metrics.descent)) (font_metrics.upem, font_metrics.ascent, font_metrics.descent))
glyph_metrics = font['hmtx'].metrics glyph_metrics = font['hmtx'].metrics
unicode_cmap = font['cmap'].getcmap (3, 10) unicode_cmap = font['cmap'].getcmap(3, 10)
if not unicode_cmap: if not unicode_cmap:
unicode_cmap = font['cmap'].getcmap (3, 1) unicode_cmap = font['cmap'].getcmap(3, 1)
if not unicode_cmap: if not unicode_cmap:
raise Exception ("Failed to find a Unicode cmap.") raise Exception("Failed to find a Unicode cmap.")
image_format = 1 if 'uncompressed' in options else (17 image_format = 1 if 'uncompressed' in options else (
if 'small_glyph_metrics' in options else 18) 17 if 'small_glyph_metrics' in options else 18)
ebdt = CBDT (font_metrics, options) ebdt = CBDT(font_metrics, options)
ebdt.write_header () ebdt.write_header()
eblc = CBLC (font_metrics, options) eblc = CBLC(font_metrics, options)
eblc.write_header () eblc.write_header()
eblc.start_strikes (len (img_prefixes)) eblc.start_strikes(len(img_prefixes))
def is_vs(cp): def is_vs(cp):
return cp >= 0xfe00 and cp <= 0xfe0f return cp >= 0xfe00 and cp <= 0xfe0f
for img_prefix in img_prefixes: for img_prefix in img_prefixes:
print() print()
@ -487,85 +507,88 @@ By default they are dropped.
img_files = {} img_files = {}
glb = "%s*.png" % img_prefix glb = "%s*.png" % img_prefix
print("Looking for images matching '%s'." % glb) print("Looking for images matching '%s'." % glb)
for img_file in glob.glob (glb): for img_file in glob.glob(glb):
codes = img_file[len (img_prefix):-4] codes = img_file[len(img_prefix):-4]
if "_" in codes: if "_" in codes:
pieces = codes.split ("_") pieces = codes.split("_")
cps = [int(code, 16) for code in pieces] cps = [int(code, 16) for code in pieces]
uchars = "".join ([unichr(cp) for cp in cps if not is_vs(cp)]) uchars = "".join([unichr(cp) for cp in cps if not is_vs(cp)])
else: else:
cp = int(codes, 16) cp = int(codes, 16)
if is_vs(cp): if is_vs(cp):
print("ignoring unexpected vs input %04x" % cp) print("ignoring unexpected vs input %04x" % cp)
continue continue
uchars = unichr(cp) uchars = unichr(cp)
img_files[uchars] = img_file img_files[uchars] = img_file
if not img_files: if not img_files:
raise Exception ("No image files found in '%s'." % glb) raise Exception("No image files found in '%s'." % glb)
print("Found images for %d characters in '%s'." % (len (img_files), glb)) print("Found images for %d characters in '%s'." %
(len(img_files), glb))
glyph_imgs = {} glyph_imgs = {}
advance = width = height = 0 advance = width = height = 0
for uchars, img_file in img_files.items (): for uchars, img_file in img_files.items():
if len (uchars) == 1: if len(uchars) == 1:
try: try:
glyph_name = unicode_cmap.cmap[ord (uchars)] glyph_name = unicode_cmap.cmap[ord(uchars)]
except: except:
print("no cmap entry for %x" % ord(uchars)) print("no cmap entry for %x" % ord(uchars))
raise ValueError("%x" % ord(uchars)) raise ValueError("%x" % ord(uchars))
else: else:
glyph_name = get_glyph_name_from_gsub (uchars, font, unicode_cmap.cmap) glyph_name = get_glyph_name_from_gsub(uchars, font,
glyph_id = font.getGlyphID (glyph_name) unicode_cmap.cmap)
glyph_id = font.getGlyphID(glyph_name)
glyph_imgs[glyph_id] = img_file glyph_imgs[glyph_id] = img_file
if "verbose" in options: if "verbose" in options:
uchars_name = ",".join (["%04X" % ord (char) for char in uchars]) uchars_name = ",".join(["%04X" % ord(char) for char in uchars])
# print "Matched U+%s: id=%d name=%s image=%s" % ( # print "Matched U+%s: id=%d name=%s image=%s" % (
# uchars_name, glyph_id, glyph_name, img_file) # uchars_name, glyph_id, glyph_name, img_file)
advance += glyph_metrics[glyph_name][0] advance += glyph_metrics[glyph_name][0]
w, h = PNG (img_file).get_size () w, h = PNG(img_file).get_size()
width += w width += w
height += h height += h
glyphs = sorted (glyph_imgs.keys ()) glyphs = sorted(glyph_imgs.keys())
if not glyphs: if not glyphs:
raise Exception ("No common characters found between font and '%s'." % glb) raise Exception(
print("Embedding images for %d glyphs for this strike." % len (glyphs)) "No common characters found between font and '%s'." % glb)
print("Embedding images for %d glyphs for this strike." % len(glyphs))
advance, width, height = (div (x, len (glyphs)) for x in (advance, width, height)) advance, width, height = (div(x, len(glyphs))
strike_metrics = StrikeMetrics (font_metrics, advance, width, height) for x in (advance, width, height))
strike_metrics = StrikeMetrics(font_metrics, advance, width, height)
print("Strike ppem set to %d." % (strike_metrics.y_ppem)) print("Strike ppem set to %d." % (strike_metrics.y_ppem))
ebdt.start_strike (strike_metrics) ebdt.start_strike(strike_metrics)
ebdt.write_glyphs (glyphs, glyph_imgs, image_format) ebdt.write_glyphs(glyphs, glyph_imgs, image_format)
glyph_maps = ebdt.end_strike () glyph_maps = ebdt.end_strike()
eblc.write_strike (strike_metrics, glyph_maps) eblc.write_strike(strike_metrics, glyph_maps)
print() print()
ebdt = ebdt.data () ebdt = ebdt.data()
add_font_table (font, 'CBDT', ebdt) add_font_table(font, 'CBDT', ebdt)
print("CBDT table synthesized: %d bytes." % len (ebdt)) print("CBDT table synthesized: %d bytes." % len(ebdt))
eblc.end_strikes () eblc.end_strikes()
eblc = eblc.data () eblc = eblc.data()
add_font_table (font, 'CBLC', eblc) add_font_table(font, 'CBLC', eblc)
print("CBLC table synthesized: %d bytes." % len (eblc)) print("CBLC table synthesized: %d bytes." % len(eblc))
print() print()
if 'keep_outlines' not in options: if 'keep_outlines' not in options:
drop_outline_tables (font) drop_outline_tables(font)
print("Dropped outline ('glyf', 'CFF ') and related tables.") print("Dropped outline ('glyf', 'CFF ') and related tables.")
# hack removal of cmap pua entry for unknown flag glyph. If we try to # hack removal of cmap pua entry for unknown flag glyph. If we try to
# remove it earlier, getGlyphID dies. Need to restructure all of this # remove it earlier, getGlyphID dies. Need to restructure all of this
# code. # code.
font_data.delete_from_cmap(font, [0xfe82b]) font_data.delete_from_cmap(font, [0xfe82b])
font.save (out_file) font.save(out_file)
print("Output font '%s' generated." % out_file) print("Output font '%s' generated." % out_file)
if __name__ == '__main__': if __name__ == '__main__':
main (sys.argv) main(sys.argv)