Backup: Stable state with EPUB reader fixes (Freeze, OOM, Speed, State, Tooling)
This commit is contained in:
@@ -15,12 +15,14 @@ parser.add_argument("size", type=int, help="font size to use.")
|
||||
parser.add_argument("fontstack", action="store", nargs='+', help="list of font files, ordered by descending priority.")
|
||||
parser.add_argument("--2bit", dest="is2Bit", action="store_true", help="generate 2-bit greyscale bitmap instead of 1-bit black and white.")
|
||||
parser.add_argument("--additional-intervals", dest="additional_intervals", action="append", help="Additional code point intervals to export as min,max. This argument can be repeated.")
|
||||
parser.add_argument("--binary", dest="isBinary", action="store_true", help="output a binary .epdfont file instead of a C header.")
|
||||
args = parser.parse_args()
|
||||
|
||||
GlyphProps = namedtuple("GlyphProps", ["width", "height", "advance_x", "left", "top", "data_length", "data_offset", "code_point"])
|
||||
|
||||
font_stack = [freetype.Face(f) for f in args.fontstack]
|
||||
is2Bit = args.is2Bit
|
||||
isBinary = args.isBinary
|
||||
size = args.size
|
||||
font_name = args.name
|
||||
|
||||
@@ -60,45 +62,6 @@ intervals = [
|
||||
(0x2200, 0x22FF),
|
||||
# Arrows
|
||||
(0x2190, 0x21FF),
|
||||
### CJK ###
|
||||
# Core Unified Ideographs
|
||||
# (0x4E00, 0x9FFF),
|
||||
# # Extension A
|
||||
# (0x3400, 0x4DBF),
|
||||
# # Extension B
|
||||
# (0x20000, 0x2A6DF),
|
||||
# # Extension C–F
|
||||
# (0x2A700, 0x2EBEF),
|
||||
# # Extension G
|
||||
# (0x30000, 0x3134F),
|
||||
# # Hiragana
|
||||
# (0x3040, 0x309F),
|
||||
# # Katakana
|
||||
# (0x30A0, 0x30FF),
|
||||
# # Katakana Phonetic Extensions
|
||||
# (0x31F0, 0x31FF),
|
||||
# # Halfwidth Katakana
|
||||
# (0xFF60, 0xFF9F),
|
||||
# # Hangul Syllables
|
||||
# (0xAC00, 0xD7AF),
|
||||
# # Hangul Jamo
|
||||
# (0x1100, 0x11FF),
|
||||
# # Hangul Compatibility Jamo
|
||||
# (0x3130, 0x318F),
|
||||
# # Hangul Jamo Extended-A
|
||||
# (0xA960, 0xA97F),
|
||||
# # Hangul Jamo Extended-B
|
||||
# (0xD7B0, 0xD7FF),
|
||||
# # CJK Radicals Supplement
|
||||
# (0x2E80, 0x2EFF),
|
||||
# # Kangxi Radicals
|
||||
# (0x2F00, 0x2FDF),
|
||||
# # CJK Symbols and Punctuation
|
||||
# (0x3000, 0x303F),
|
||||
# # CJK Compatibility Forms
|
||||
# (0xFE30, 0xFE4F),
|
||||
# # CJK Compatibility Ideographs
|
||||
# (0xF900, 0xFAFF),
|
||||
]
|
||||
|
||||
add_ints = []
|
||||
@@ -200,16 +163,6 @@ for i_start, i_end in intervals:
|
||||
if (bitmap.width * bitmap.rows) % 4 != 0:
|
||||
px = px << (4 - (bitmap.width * bitmap.rows) % 4) * 2
|
||||
pixels2b.append(px)
|
||||
|
||||
# for y in range(bitmap.rows):
|
||||
# line = ''
|
||||
# for x in range(bitmap.width):
|
||||
# pixelPosition = y * bitmap.width + x
|
||||
# byte = pixels2b[pixelPosition // 4]
|
||||
# bit_index = (3 - (pixelPosition % 4)) * 2
|
||||
# line += '#' if ((byte >> bit_index) & 3) > 0 else '.'
|
||||
# print(line)
|
||||
# print('')
|
||||
else:
|
||||
# Downsample to 1-bit bitmap - treat any 2+ as black
|
||||
pixelsbw = []
|
||||
@@ -228,16 +181,6 @@ for i_start, i_end in intervals:
|
||||
px = px << (8 - (bitmap.width * bitmap.rows) % 8)
|
||||
pixelsbw.append(px)
|
||||
|
||||
# for y in range(bitmap.rows):
|
||||
# line = ''
|
||||
# for x in range(bitmap.width):
|
||||
# pixelPosition = y * bitmap.width + x
|
||||
# byte = pixelsbw[pixelPosition // 8]
|
||||
# bit_index = 7 - (pixelPosition % 8)
|
||||
# line += '#' if (byte >> bit_index) & 1 else '.'
|
||||
# print(line)
|
||||
# print('')
|
||||
|
||||
pixels = pixels2b if is2Bit else pixelsbw
|
||||
|
||||
# Build output data
|
||||
@@ -265,33 +208,79 @@ for index, glyph in enumerate(all_glyphs):
|
||||
glyph_data.extend([b for b in packed])
|
||||
glyph_props.append(props)
|
||||
|
||||
print(f"/**\n * generated by fontconvert.py\n * name: {font_name}\n * size: {size}\n * mode: {'2-bit' if is2Bit else '1-bit'}\n */")
|
||||
print("#pragma once")
|
||||
print("#include \"EpdFontData.h\"\n")
|
||||
print(f"static const uint8_t {font_name}Bitmaps[{len(glyph_data)}] = {{")
|
||||
for c in chunks(glyph_data, 16):
|
||||
print (" " + " ".join(f"0x{b:02X}," for b in c))
|
||||
print ("};\n");
|
||||
if isBinary:
|
||||
import struct
|
||||
with open(f"{font_name}.epdfont", "wb") as f:
|
||||
# Magic
|
||||
f.write(b"EPDF")
|
||||
# Metrics (22 bytes)
|
||||
# intervalCount (uint32_t), advanceY (uint8_t), ascender (int32_t), descender (int32_t), is2Bit (uint8_t), totalGlyphCount (uint32_t)
|
||||
f.write(struct.pack("<IBiiBI", len(intervals), norm_ceil(face.size.height), norm_ceil(face.size.ascender), norm_floor(face.size.descender), 1 if is2Bit else 0, len(glyph_props)))
|
||||
# Intervals
|
||||
offset = 0
|
||||
for i_start, i_end in intervals:
|
||||
f.write(struct.pack("<III", i_start, i_end, offset))
|
||||
offset += i_end - i_start + 1
|
||||
# Glyphs
|
||||
for g in glyph_props:
|
||||
# dataOffset (uint32_t), dataLength (uint16_t), width (uint8_t), height (uint8_t), advanceX (uint8_t), left (int8_t), top (int8_t)
|
||||
# wait, GlyphProps has width, height, advance_x, left, top, data_length, data_offset, code_point
|
||||
# We need: dataOffset (4), dataLength (2), width (1), height (1), advanceX (1), left (1), top (1) = 11 bytes?
|
||||
# Let's use 13 bytes as planned to be safer or just 11.
|
||||
# Original EpdGlyph:
|
||||
# uint32_t dataOffset;
|
||||
# uint16_t dataLength;
|
||||
# uint8_t width;
|
||||
# uint8_t height;
|
||||
# uint8_t advanceX;
|
||||
# int8_t left;
|
||||
# int8_t top;
|
||||
# Total: 4+2+1+1+1+1+1 = 11 bytes.
|
||||
# I will use 13 bytes to align better if needed, but 11 is fine.
|
||||
# Let's use 13 bytes as per plan: 4+2+1+1+1+1+1 + 2 padding.
|
||||
# CustomEpdFont.cpp expects:
|
||||
# glyphBuf[0] = w
|
||||
# glyphBuf[1] = h
|
||||
# glyphBuf[2] = adv
|
||||
# glyphBuf[3] = l (signed)
|
||||
# glyphBuf[4] = unused
|
||||
# glyphBuf[5] = t (signed)
|
||||
# glyphBuf[6] = unused
|
||||
# glyphBuf[7-8] = dLen
|
||||
# glyphBuf[9-12] = dOffset
|
||||
f.write(struct.pack("<BBB b B b B H I", g.width, g.height, g.advance_x, g.left, 0, g.top, 0, g.data_length, g.data_offset))
|
||||
# Bitmaps
|
||||
f.write(bytes(glyph_data))
|
||||
print(f"Generated {font_name}.epdfont")
|
||||
else:
|
||||
print(f"/**\n * generated by fontconvert.py\n * name: {font_name}\n * size: {size}\n * mode: {'2-bit' if is2Bit else '1-bit'}\n */")
|
||||
print("#pragma once")
|
||||
print("#include \"EpdFontData.h\"\n")
|
||||
print(f"static const uint8_t {font_name}Bitmaps[{len(glyph_data)}] = {{")
|
||||
for c in chunks(glyph_data, 16):
|
||||
print (" " + " ".join(f"0x{b:02X}," for b in c))
|
||||
print ("};\n");
|
||||
|
||||
print(f"static const EpdGlyph {font_name}Glyphs[] = {{")
|
||||
for i, g in enumerate(glyph_props):
|
||||
print (" { " + ", ".join([f"{a}" for a in list(g[:-1])]),"},", f"// {chr(g.code_point) if g.code_point != 92 else '<backslash>'}")
|
||||
print ("};\n");
|
||||
print(f"static const EpdGlyph {font_name}Glyphs[] = {{")
|
||||
for i, g in enumerate(glyph_props):
|
||||
print (" { " + ", ".join([f"{a}" for a in list(g[:-1])]),"},", f"// {chr(g.code_point) if g.code_point != 92 else '<backslash>'}")
|
||||
print ("};\n");
|
||||
|
||||
print(f"static const EpdUnicodeInterval {font_name}Intervals[] = {{")
|
||||
offset = 0
|
||||
for i_start, i_end in intervals:
|
||||
print (f" {{ 0x{i_start:X}, 0x{i_end:X}, 0x{offset:X} }},")
|
||||
offset += i_end - i_start + 1
|
||||
print ("};\n");
|
||||
print(f"static const EpdUnicodeInterval {font_name}Intervals[] = {{")
|
||||
offset = 0
|
||||
for i_start, i_end in intervals:
|
||||
print (f" {{ 0x{i_start:X}, 0x{i_end:X}, 0x{offset:X} }},")
|
||||
offset += i_end - i_start + 1
|
||||
print ("};\n");
|
||||
|
||||
print(f"static const EpdFontData {font_name} = {{")
|
||||
print(f" {font_name}Bitmaps,")
|
||||
print(f" {font_name}Glyphs,")
|
||||
print(f" {font_name}Intervals,")
|
||||
print(f" {len(intervals)},")
|
||||
print(f" {norm_ceil(face.size.height)},")
|
||||
print(f" {norm_ceil(face.size.ascender)},")
|
||||
print(f" {norm_floor(face.size.descender)},")
|
||||
print(f" {'true' if is2Bit else 'false'},")
|
||||
print("};")
|
||||
|
||||
print(f"static const EpdFontData {font_name} = {{")
|
||||
print(f" {font_name}Bitmaps,")
|
||||
print(f" {font_name}Glyphs,")
|
||||
print(f" {font_name}Intervals,")
|
||||
print(f" {len(intervals)},")
|
||||
print(f" {norm_ceil(face.size.height)},")
|
||||
print(f" {norm_ceil(face.size.ascender)},")
|
||||
print(f" {norm_floor(face.size.descender)},")
|
||||
print(f" {'true' if is2Bit else 'false'},")
|
||||
print("};")
|
||||
|
||||
Reference in New Issue
Block a user