712db9c597
Add B1 directory-type seed mechanism to AGENT_WORKSPACE_SEED_FILES: - Extended agentWorkspaceFilesForRun with collectDirectorySeedFiles helper - arm2d-skill (SKILL.md + references/ + python/) auto-injected to .agents/skills/arm2d-skill/ - Enables Code Agent to follow ARM-2D constraints and call asset scripts in case Skill source: https://github.com/notLabyet/HWLabOA
586 lines
21 KiB
Python
586 lines
21 KiB
Python
#!/usr/bin/python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# *************************************************************************************************
|
|
# Arm 2D project
|
|
# @file ttf2c.py
|
|
# @brief TrueTypeFont to C-array converter
|
|
#
|
|
# *************************************************************************************************
|
|
#
|
|
# * Copyright (C) 2025 ARM Limited or its affiliates. All rights reserved.
|
|
# *
|
|
# * SPDX-License-Identifier: Apache-2.0
|
|
# *
|
|
# * Licensed under the Apache License, Version 2.0 (the License); you may
|
|
# * not use this file except in compliance with the License.
|
|
# * You may obtain a copy of the License at
|
|
# *
|
|
# * www.apache.org/licenses/LICENSE-2.0
|
|
# *
|
|
# * Unless required by applicable law or agreed to in writing, software
|
|
# * distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
|
# * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# * See the License for the specific language governing permissions and
|
|
# * limitations under the License.
|
|
# */
|
|
|
|
|
|
import os
|
|
import sys
|
|
import argparse
|
|
import freetype
|
|
import numpy as np
|
|
import math
|
|
import binascii
|
|
import tempfile
|
|
|
|
c_head_string="""
|
|
|
|
/* generated with ttf2c.py (v2.4.1) */
|
|
|
|
#include "arm_2d_helper.h"
|
|
|
|
#if defined(__clang__)
|
|
# pragma clang diagnostic push
|
|
# pragma clang diagnostic ignored "-Wunknown-warning-option"
|
|
# pragma clang diagnostic ignored "-Wreserved-identifier"
|
|
# pragma clang diagnostic ignored "-Wmissing-variable-declarations"
|
|
# pragma clang diagnostic ignored "-Wcast-qual"
|
|
# pragma clang diagnostic ignored "-Wmissing-declarations"
|
|
# pragma clang diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
|
|
# pragma clang diagnostic ignored "-Wimplicit-int-conversion"
|
|
# pragma clang diagnostic ignored "-Wdeclaration-after-statement"
|
|
# pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
|
|
# pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
|
|
# pragma clang diagnostic ignored "-Wpadded"
|
|
# pragma clang diagnostic ignored "-Wunused-parameter"
|
|
# pragma clang diagnostic ignored "-Wunused-variable"
|
|
# pragma clang diagnostic ignored "-Wsign-conversion"
|
|
#elif defined(__IS_COMPILER_GCC__)
|
|
# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
|
|
# pragma GCC diagnostic ignored "-Wunused-variable"
|
|
#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
|
|
# pragma diag_suppress=1296,1,64,177
|
|
#endif
|
|
|
|
typedef struct {
|
|
uint16_t hwIndex;
|
|
arm_2d_size_t tCharSize;
|
|
int16_t iAdvance;
|
|
int16_t iBearingX;
|
|
int16_t iBearingY;
|
|
uint8_t chCodeLength;
|
|
uint8_t chUTF8[4];
|
|
} const __ttf_char_descriptor_t;
|
|
"""
|
|
|
|
|
|
c_body_string="""
|
|
|
|
|
|
ARM_SECTION(\"arm2d.tile.c_tileUTF8{0}A{5}Mask\")
|
|
static const arm_2d_tile_t c_tileUTF8{0}A{5}Mask = {{
|
|
.tRegion = {{
|
|
.tSize = {{
|
|
.iWidth = {1},
|
|
.iHeight = {4},
|
|
}},
|
|
}},
|
|
.tInfo = {{
|
|
.bIsRoot = true,
|
|
.bHasEnforcedColour = true,
|
|
.tColourInfo = {{
|
|
.chScheme = ARM_2D_COLOUR_{5}BIT,
|
|
}},
|
|
}},
|
|
.pchBuffer = (uint8_t *)c_bmpUTF8{0}A{5}Font,
|
|
}};
|
|
|
|
#define __UTF8_FONT_SIZE_{5}__
|
|
|
|
|
|
|
|
static
|
|
IMPL_FONT_GET_CHAR_DESCRIPTOR(__utf8_a{5}_font_get_char_descriptor)
|
|
{{
|
|
assert(NULL != ptFont);
|
|
assert(NULL != ptDescriptor);
|
|
assert(NULL != pchCharCode);
|
|
|
|
arm_2d_user_font_t *ptThis = (arm_2d_user_font_t *)ptFont;
|
|
ARM_2D_UNUSED(ptThis);
|
|
|
|
memset(ptDescriptor, 0, sizeof(arm_2d_char_descriptor_t));
|
|
|
|
ptDescriptor->tileChar.ptParent = (arm_2d_tile_t *)&ptFont->tileFont;
|
|
ptDescriptor->tileChar.tInfo.bDerivedResource = true;
|
|
|
|
/* use the white space as the default char */
|
|
__ttf_char_descriptor_t *ptUTF8Char =
|
|
(__ttf_char_descriptor_t *)&c_tUTF8{0}LookUpTableA{5}[dimof(c_tUTF8{0}LookUpTableA{5})-1];
|
|
|
|
arm_foreach(__ttf_char_descriptor_t, c_tUTF8{0}LookUpTableA{5}, ptChar) {{
|
|
if (0 == strncmp( (char *)pchCharCode,
|
|
(char *)ptChar->chUTF8,
|
|
ptChar->chCodeLength)) {{
|
|
/* found the UTF8 char */
|
|
ptUTF8Char = ptChar;
|
|
break;
|
|
}}
|
|
}}
|
|
|
|
ptDescriptor->chCodeLength = ptUTF8Char->chCodeLength;
|
|
ptDescriptor->tileChar.tRegion.tSize = ptUTF8Char->tCharSize;
|
|
ptDescriptor->tileChar.tRegion.tLocation.iY = (int16_t)ptUTF8Char->hwIndex;
|
|
|
|
ptDescriptor->iAdvance = ptUTF8Char->iAdvance;
|
|
ptDescriptor->iBearingX= ptUTF8Char->iBearingX;
|
|
ptDescriptor->iBearingY= ptUTF8Char->iBearingY;
|
|
|
|
return ptDescriptor;
|
|
}}
|
|
|
|
ARM_SECTION(\"arm2d.asset.FONT.ARM_2D_FONT_{0}_A{5}\")
|
|
const
|
|
struct {{
|
|
implement(arm_2d_user_font_t);
|
|
arm_2d_char_idx_t tUTF8Table;
|
|
}} ARM_2D_FONT_{0}_A{5} = {{
|
|
|
|
.use_as__arm_2d_user_font_t = {{
|
|
.use_as__arm_2d_font_t = {{
|
|
.tileFont = impl_child_tile(
|
|
c_tileUTF8{0}A{5}Mask,
|
|
0, /* x offset */
|
|
0, /* y offset */
|
|
{1}, /* width */
|
|
{4} /* height */
|
|
),
|
|
.tCharSize = {{
|
|
.iWidth = {1},
|
|
.iHeight = {2},
|
|
}},
|
|
.nCount = {3}, //!< Character count
|
|
.fnGetCharDescriptor = &__utf8_a{5}_font_get_char_descriptor,
|
|
.fnDrawChar = &__arm_2d_lcd_text_default_a{5}_font_draw_char,
|
|
}},
|
|
.hwCount = 1,
|
|
.hwDefaultCharIndex = 1, /* tBlank */
|
|
}},
|
|
|
|
.tUTF8Table = {{
|
|
.hwCount = {3},
|
|
.hwOffset = 0,
|
|
}},
|
|
}};
|
|
|
|
#undef __UTF8_FONT_SIZE_{5}__
|
|
"""
|
|
|
|
|
|
c_body_string_ascii="""
|
|
|
|
|
|
ARM_SECTION(\"arm2d.tile.c_tileUTF8{0}A{5}Mask\")
|
|
static const arm_2d_tile_t c_tileUTF8{0}A{5}Mask = {{
|
|
.tRegion = {{
|
|
.tSize = {{
|
|
.iWidth = {1},
|
|
.iHeight = {4},
|
|
}},
|
|
}},
|
|
.tInfo = {{
|
|
.bIsRoot = true,
|
|
.bHasEnforcedColour = true,
|
|
.tColourInfo = {{
|
|
.chScheme = ARM_2D_COLOUR_{5}BIT,
|
|
}},
|
|
}},
|
|
.pchBuffer = (uint8_t *)c_bmpUTF8{0}A{5}Font,
|
|
}};
|
|
|
|
#define __UTF8_FONT_SIZE_{5}__
|
|
|
|
|
|
|
|
static
|
|
IMPL_FONT_GET_CHAR_DESCRIPTOR(__utf8_a{5}_font_get_char_descriptor)
|
|
{{
|
|
assert(NULL != ptFont);
|
|
assert(NULL != ptDescriptor);
|
|
assert(NULL != pchCharCode);
|
|
|
|
arm_2d_user_font_t *ptThis = (arm_2d_user_font_t *)ptFont;
|
|
ARM_2D_UNUSED(ptThis);
|
|
|
|
memset(ptDescriptor, 0, sizeof(arm_2d_char_descriptor_t));
|
|
|
|
ptDescriptor->tileChar.ptParent = (arm_2d_tile_t *)&ptFont->tileFont;
|
|
ptDescriptor->tileChar.tInfo.bDerivedResource = true;
|
|
|
|
/* use the white space as the default char */
|
|
__ttf_char_descriptor_t *ptUTF8Char = NULL;
|
|
|
|
if (pchCharCode[0] > 0x20 && pchCharCode[0] <= 0x7e) {{
|
|
ptUTF8Char = (__ttf_char_descriptor_t *)
|
|
&c_tUTF8{0}LookUpTableA{5}[
|
|
pchCharCode[0] - c_tUTF8{0}LookUpTableA{5}[0].chUTF8[0]];
|
|
}} else {{
|
|
/* use the white space as the default char */
|
|
ptUTF8Char = (__ttf_char_descriptor_t *)
|
|
&c_tUTF8{0}LookUpTableA{5}[dimof(c_tUTF8{0}LookUpTableA{5})-1];
|
|
}}
|
|
|
|
ptDescriptor->chCodeLength = ptUTF8Char->chCodeLength;
|
|
ptDescriptor->tileChar.tRegion.tSize = ptUTF8Char->tCharSize;
|
|
ptDescriptor->tileChar.tRegion.tLocation.iY = (int16_t)ptUTF8Char->hwIndex;
|
|
|
|
ptDescriptor->iAdvance = ptUTF8Char->iAdvance;
|
|
ptDescriptor->iBearingX= ptUTF8Char->iBearingX;
|
|
ptDescriptor->iBearingY= ptUTF8Char->iBearingY;
|
|
|
|
return ptDescriptor;
|
|
}}
|
|
|
|
ARM_SECTION(\"arm2d.asset.FONT.ARM_2D_FONT_{0}_A{5}\")
|
|
const
|
|
struct {{
|
|
implement(arm_2d_user_font_t);
|
|
arm_2d_char_idx_t tUTF8Table;
|
|
}} ARM_2D_FONT_{0}_A{5} = {{
|
|
|
|
.use_as__arm_2d_user_font_t = {{
|
|
.use_as__arm_2d_font_t = {{
|
|
.tileFont = impl_child_tile(
|
|
c_tileUTF8{0}A{5}Mask,
|
|
0, /* x offset */
|
|
0, /* y offset */
|
|
{1}, /* width */
|
|
{4} /* height */
|
|
),
|
|
.tCharSize = {{
|
|
.iWidth = {1},
|
|
.iHeight = {2},
|
|
}},
|
|
.nCount = {3}, //!< Character count
|
|
.fnGetCharDescriptor = &__utf8_a{5}_font_get_char_descriptor,
|
|
.fnDrawChar = &__arm_2d_lcd_text_default_a{5}_font_draw_char,
|
|
}},
|
|
.hwCount = 1,
|
|
.hwDefaultCharIndex = 1, /* tBlank */
|
|
}},
|
|
|
|
.tUTF8Table = {{
|
|
.hwCount = {3},
|
|
.hwOffset = 0,
|
|
}},
|
|
}};
|
|
|
|
#undef __UTF8_FONT_SIZE_{5}__
|
|
"""
|
|
|
|
|
|
c_tail_string="""
|
|
|
|
#if defined(__clang__)
|
|
# pragma clang diagnostic pop
|
|
#elif defined(__IS_COMPILER_ARM_COMPILER_5__)
|
|
# pragma diag_warning=1296
|
|
#endif
|
|
"""
|
|
|
|
def generate_glyphs_data(input_file, text, pixel_size, font_bit_size, font_index):
|
|
face = freetype.Face(input_file, index=font_index)
|
|
face.set_pixel_sizes(0, pixel_size)
|
|
|
|
glyphs_data = []
|
|
current_index = 0
|
|
|
|
width_max = 0
|
|
height_max = 0
|
|
|
|
for char in set(text):
|
|
# Get the glyph bitmap
|
|
face.load_char(char)
|
|
bitmap = face.glyph.bitmap
|
|
utf8_encoding = char.encode('utf-8')
|
|
|
|
if len(bitmap.buffer) == 0:
|
|
continue
|
|
if list(utf8_encoding) == [0xef, 0xbb, 0xbf]:
|
|
continue
|
|
|
|
width_max = max(bitmap.width, width_max)
|
|
height_max = max(bitmap.rows, height_max)
|
|
|
|
width_max += 2
|
|
height_max += 2
|
|
|
|
for char in sorted(set(text)):
|
|
face.load_char(char)
|
|
bitmap = face.glyph.bitmap
|
|
utf8_encoding = char.encode('utf-8')
|
|
|
|
if len(bitmap.buffer) == 0:
|
|
continue
|
|
if list(utf8_encoding) == [0xef, 0xbb, 0xbf]:
|
|
continue
|
|
|
|
# update advance, bearing x and bearing y as we added the 1px boarder around each glyph.
|
|
advance_width = math.ceil(face.glyph.advance.x / 64.0) + 1
|
|
bearing_x = face.glyph.bitmap_left + 1
|
|
bearing_y = face.glyph.bitmap_top + 1
|
|
width = bitmap.width
|
|
height = bitmap.rows
|
|
pitch = bitmap.pitch
|
|
|
|
if bitmap.pixel_mode == freetype.FT_PIXEL_MODE_MONO:
|
|
buffer = np.frombuffer(bytes(bitmap.buffer), dtype=np.uint8)
|
|
bits_per_row = pitch * 8
|
|
bitmap_array = np.unpackbits(buffer).reshape((height, bits_per_row))[:, :width]
|
|
bitmap_array = bitmap_array.astype(np.uint8) * 255
|
|
|
|
elif bitmap.pixel_mode == freetype.FT_PIXEL_MODE_GRAY2:
|
|
buffer = np.frombuffer(bytes(bitmap.buffer), dtype=np.uint8)
|
|
bits_per_row = pitch * 4
|
|
bitmap_array = np.unpackbits(buffer).reshape((height, bits_per_row))[:, :width * 2]
|
|
bitmap_array = (bitmap_array.reshape((height, width * 2)) * 85).astype(np.uint8)
|
|
|
|
elif bitmap.pixel_mode == freetype.FT_PIXEL_MODE_GRAY4:
|
|
buffer = np.frombuffer(bytes(bitmap.buffer), dtype=np.uint8)
|
|
bits_per_row = pitch * 2
|
|
bitmap_array = np.unpackbits(buffer).reshape((height, bits_per_row))[:, :width * 4]
|
|
bitmap_array = (bitmap_array.reshape((height, width * 2)) * 17).astype(np.uint8)
|
|
|
|
elif bitmap.pixel_mode == freetype.FT_PIXEL_MODE_GRAY:
|
|
bitmap_array = np.array(bitmap.buffer, dtype=np.uint8).reshape((height, width))
|
|
|
|
else:
|
|
raise ValueError(f"Unsupported pixel mode: {bitmap.pixel_mode}")
|
|
continue
|
|
|
|
if width < width_max:
|
|
if (width_max - width) > 1:
|
|
padding = ((0, 0), (1, width_max - width - 1))
|
|
else:
|
|
padding = ((0, 0), (0, width_max - width))
|
|
bitmap_array = np.pad(bitmap_array, padding, 'constant')
|
|
|
|
padding = ((1, 1), (0, 0))
|
|
bitmap_array = np.pad(bitmap_array, padding, 'constant')
|
|
|
|
height += 2
|
|
|
|
char_index_advance = len(bitmap_array.flatten());
|
|
|
|
if font_bit_size == 4:
|
|
def RevBitQuadPerByte(byteArr):
|
|
return ((byteArr & 0x0f) << 4) | ((byteArr & 0xf0) >> 4)
|
|
|
|
# temporary array with 2x reduced width & pad
|
|
(r, c) = np.shape(bitmap_array)
|
|
tmp = np.empty((0, int((c+1)/2)), dtype=np.uint8)
|
|
|
|
for cur in bitmap_array:
|
|
bitsArr = np.unpackbits(cur.astype(np.uint8))
|
|
# generate indexes for MSB bit quadruplet every byte
|
|
idx = np.arange(0, np.size(bitsArr), 8)
|
|
idx = np.reshape(np.column_stack(
|
|
(np.column_stack((idx+0, idx+1)), np.column_stack((idx+2, idx+3)))),
|
|
(1,-1)),
|
|
|
|
# extraction + endianness conversion appended in temp array
|
|
# packbits is taking care of padding
|
|
tmp = np.vstack([tmp, RevBitQuadPerByte(np.packbits(bitsArr[idx]))])
|
|
|
|
bitmap_array = tmp
|
|
|
|
elif font_bit_size == 2:
|
|
def RevBitPairPerByte(byteArr):
|
|
return ((byteArr & 0x03) << 6) | ((byteArr & 0xc0) >> 6) | ((byteArr & 0x30) >> 2 ) | ((byteArr & 0x0c) << 2)
|
|
|
|
# temporary array with 4x reduced width & pad
|
|
(r, c) = np.shape(bitmap_array)
|
|
tmp = np.empty((0, int((c+3)/4)), dtype=np.uint8)
|
|
|
|
for cur in bitmap_array:
|
|
bitsArr = np.unpackbits(cur.astype(np.uint8))
|
|
|
|
# generate indexes for MSB bit pair every byte
|
|
idx = np.arange(0, np.size(bitsArr), 8)
|
|
idx = np.reshape(np.column_stack((idx+0, idx+1)), (1,-1))
|
|
|
|
# extraction + endianness conversion appended in temp array
|
|
tmp = np.vstack([tmp, RevBitPairPerByte(np.packbits(bitsArr[idx]))])
|
|
|
|
bitmap_array = tmp
|
|
|
|
elif font_bit_size == 1:
|
|
def RevBitPerByte(byteArr):
|
|
return ((byteArr & 0x01) << 7) | ((byteArr & 0x80) >> 7) | \
|
|
((byteArr & 0x02) << 5) | ((byteArr & 0x40) >> 5) | \
|
|
((byteArr & 0x04) << 3) | ((byteArr & 0x20) >> 3) | \
|
|
((byteArr & 0x08) << 1) | ((byteArr & 0x10) >> 1)
|
|
|
|
# temporary array with 8x reduced width & pad
|
|
(r, c) = np.shape(bitmap_array)
|
|
tmp = np.empty((0, int((c+7)/8)), dtype=np.uint8)
|
|
|
|
for cur in bitmap_array:
|
|
bitsArr = np.unpackbits(cur.astype(np.uint8))
|
|
|
|
# generate indexes for MSB bit every byte
|
|
idx = np.arange(0, np.size(bitsArr), 8)
|
|
|
|
# extraction + endianness conversion
|
|
tmp = np.vstack([tmp, RevBitPerByte(np.packbits(bitsArr[idx]))])
|
|
|
|
bitmap_array = tmp
|
|
|
|
char_mask_array = bitmap_array.flatten()
|
|
|
|
glyphs_data.append((char, char_mask_array, width + 2, height, current_index, advance_width, bearing_x, bearing_y, utf8_encoding))
|
|
|
|
current_index += char_index_advance
|
|
|
|
return glyphs_data, width_max, height_max
|
|
|
|
|
|
def utf8_to_c_array(utf8_bytes):
|
|
return '{' + ', '.join([f'0x{byte:02x}' for byte in utf8_bytes]) + '}'
|
|
|
|
def write_c_code(glyphs_data, output_file, name, char_max_width, char_max_height, font_bit_size, ascii_mode):
|
|
|
|
with open(output_file, "a") as f:
|
|
|
|
print("ARM_SECTION(\"arm2d.asset.FONT.c_bmpUTF8{0}A{1}Font\")\nconst uint8_t c_bmpUTF8{0}A{1}Font[] = {{\n"
|
|
.format(name, font_bit_size),
|
|
file=f)
|
|
|
|
for char, data, width, height, index, advance_width, bearing_x, bearing_y, utf8_encoding in glyphs_data:
|
|
utf8_c_array = utf8_to_c_array(utf8_encoding)
|
|
f.write(f"\n // Glyph for character {utf8_c_array}\n")
|
|
hex_str = binascii.hexlify(data).decode()
|
|
|
|
for i in range(0, len(hex_str), char_max_width*2):
|
|
line = hex_str[i:i+char_max_width*2]
|
|
spaced_line = ' '.join(f"0x{line[j:j+2]}," for j in range(0, len(line), 2))
|
|
f.write(" ");
|
|
f.write(spaced_line)
|
|
f.write("\n");
|
|
|
|
f.write(" // a white space\n ");
|
|
f.write("0x00, " * (char_max_width * char_max_height))
|
|
f.write("\n};\n\n")
|
|
|
|
print("ARM_SECTION(\"arm2d.asset.FONT.c_tUTF8{0}LookUpTableA{1}\")\n const __ttf_char_descriptor_t c_tUTF8{0}LookUpTableA{1}[{2}] = {{\n"
|
|
.format(name, font_bit_size, len(glyphs_data) + 1), file=f)
|
|
|
|
last_index = 0;
|
|
last_advance = 0;
|
|
last_height = 0;
|
|
for char, data, width, height, index, advance_width, bearing_x, bearing_y, utf8_encoding in glyphs_data:
|
|
utf8_c_array = utf8_to_c_array(utf8_encoding)
|
|
last_index = index
|
|
last_advance = advance_width
|
|
last_height = height;
|
|
f.write(f" {{ {round(index / char_max_width)}, {{ {width}, {height}, }}, {advance_width}, {bearing_x}, {bearing_y}, {len(utf8_encoding)}, {utf8_c_array} }},\n")
|
|
|
|
last_index += char_max_width * last_height
|
|
f.write(f" {{ {round(last_index / char_max_width)}, {{ {char_max_width}, {char_max_height}, }}, {round(char_max_width / 2)}, {0}, {char_max_height}, 1, {{0x20}} }},\n")
|
|
|
|
last_index += char_max_width * char_max_height
|
|
|
|
f.write("};\n")
|
|
|
|
if ascii_mode == True:
|
|
print(c_body_string_ascii.format( name,
|
|
char_max_width,
|
|
char_max_height,
|
|
len(glyphs_data),
|
|
round(last_index / char_max_width)+1,
|
|
font_bit_size), file=f)
|
|
else:
|
|
print(c_body_string.format( name,
|
|
char_max_width,
|
|
char_max_height,
|
|
len(glyphs_data),
|
|
round(last_index / char_max_width)+1,
|
|
font_bit_size), file=f)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description='TrueTypeFont to C array converter (v2.4.1)')
|
|
parser.add_argument("-i", "--input", type=str, help="Path to the TTF file", required=True)
|
|
parser.add_argument("--index", type=int, help="The Font Index in a TTC file", required=False, default=0)
|
|
parser.add_argument("-t", "--text", type=str, help="Path to the text file", required=False)
|
|
parser.add_argument("-n", "--name", type=str, help="The customized UTF8 font name", required=False, default="UTF8")
|
|
parser.add_argument("-o", "--output", type=str, help="Path to the output C file", required=True)
|
|
parser.add_argument("-p", "--pixelsize",type=int, help="Font size in pixels", required=False, default=32)
|
|
parser.add_argument("-s", "--fontbitsize",type=int, help="font bit size (1,2,4,8)", required=False, default=0)
|
|
|
|
if len(sys.argv)==1:
|
|
parser.print_help(sys.stderr)
|
|
sys.exit(1)
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.fontbitsize not in [1, 2, 4, 8, 0]:
|
|
print(f'Invalid alpha size={args.fontbitsize}')
|
|
sys.exit(1)
|
|
|
|
ascii_mode = False
|
|
|
|
if args.text == None or args.text == "" :
|
|
ascii_mode = True
|
|
fd, args.text = tempfile.mkstemp()
|
|
with os.fdopen(fd, 'w') as temptextfile:
|
|
print("!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~", file=temptextfile, end='')
|
|
|
|
with open(args.output, "w") as outputfile:
|
|
print(c_head_string, file=outputfile)
|
|
|
|
if args.fontbitsize in [1, 2, 4, 8]:
|
|
with open(args.text, 'r', encoding='utf-8') as f:
|
|
text = f.read()
|
|
|
|
glyphs_data, char_max_width, char_max_height = generate_glyphs_data(args.input, text, args.pixelsize, args.fontbitsize, args.index)
|
|
write_c_code(glyphs_data, args.output, args.name, char_max_width, char_max_height, args.fontbitsize, ascii_mode)
|
|
|
|
else:
|
|
with open(args.text, 'r', encoding='utf-8') as f:
|
|
text = f.read()
|
|
|
|
glyphs_data, char_max_width, char_max_height = generate_glyphs_data(args.input, text, args.pixelsize, 1, args.index)
|
|
write_c_code(glyphs_data, args.output, args.name, char_max_width, char_max_height, 1, ascii_mode)
|
|
|
|
|
|
with open(args.text, 'r', encoding='utf-8') as f:
|
|
text = f.read()
|
|
|
|
glyphs_data, char_max_width, char_max_height = generate_glyphs_data(args.input, text, args.pixelsize, 2, args.index)
|
|
write_c_code(glyphs_data, args.output, args.name, char_max_width, char_max_height, 2, ascii_mode)
|
|
|
|
|
|
with open(args.text, 'r', encoding='utf-8') as f:
|
|
text = f.read()
|
|
|
|
glyphs_data, char_max_width, char_max_height = generate_glyphs_data(args.input, text, args.pixelsize, 4, args.index)
|
|
write_c_code(glyphs_data, args.output, args.name, char_max_width, char_max_height, 4, ascii_mode)
|
|
|
|
|
|
with open(args.text, 'r', encoding='utf-8') as f:
|
|
text = f.read()
|
|
|
|
glyphs_data, char_max_width, char_max_height = generate_glyphs_data(args.input, text, args.pixelsize, 8, args.index)
|
|
write_c_code(glyphs_data, args.output, args.name, char_max_width, char_max_height, 8, ascii_mode)
|
|
|
|
with open(args.output, "a") as outputfile:
|
|
print(c_tail_string, file=outputfile)
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|