tools/ttf_outline: twiddle at compile-time

This commit is contained in:
Zack Buhman 2024-12-01 10:30:01 -06:00
parent 81e76ee428
commit 671fe92b12
15 changed files with 105 additions and 187 deletions

View File

@ -36,9 +36,9 @@ geometry/%.hpp: geometry/%.obj
$(BUILD_BINARY_O)
build-fonts:
./tools/ttf_outline 20 7f 20 0 little /usr/share/fonts/dejavu/DejaVuSans.ttf dejavusansmono.data
./tools/ttf_outline 20 7f 20 1 little /usr/share/fonts/dejavu/DejaVuSans.ttf dejavusansmono_mono.data
./tools/ttf_outline 20 7f 20 1 little /usr/share/fonts/terminus/ter-u20n.otb ter_u20n.data
./tools/ttf_outline 20 7f 20 0 little /usr/share/fonts/dejavu/DejaVuSans.ttf font/dejavusansmono/dejavusansmono.data
./tools/ttf_outline 20 7f 20 1 little /usr/share/fonts/dejavu/DejaVuSans.ttf font/dejavusansmono/dejavusansmono_mono.data
./tools/ttf_outline 20 7f 20 1 little /usr/share/fonts/terminus/ter-u20n.otb font/ter_u20n/ter_u20n.data
include example/example.mk
include chess/chess.mk

View File

@ -1,3 +1,5 @@
#pragma once
#include <stdint.h>
#include <stddef.h>

View File

@ -191,22 +191,12 @@ void init_texture_memory(const struct opb_size& opb_size)
}
void inflate_font(const uint8_t * src,
const uint32_t width,
const uint32_t height)
const uint32_t z_curve_max_ix)
{
auto texture = reinterpret_cast<volatile uint32_t *>(&texture_memory64[texture_memory_alloc::texture.start / 4]);
const uint32_t size = width * height;
uint8_t temp[size] __attribute__((aligned(4)));
twiddle::texture(temp,
src,
width,
height);
for (uint32_t i = 0; i < size / 4; i++) {
texture[i] = reinterpret_cast<uint32_t *>(temp)[i];
for (uint32_t i = 0; i < z_curve_max_ix / 4; i++) {
texture[i] = reinterpret_cast<const uint32_t *>(src)[i];
}
}
@ -232,8 +222,7 @@ void main()
*/
inflate_font(texture,
font->texture_width,
font->texture_height);
font->max_z_curve_ix);
palette_data<256>();
// The address of `ta_parameter_buf` must be a multiple of 32 bytes.

View File

@ -7,7 +7,7 @@
void main()
{
//serial::init(0);
serial::init(0);
uint8_t send_buf[1024] __attribute__((aligned(32)));
uint8_t recv_buf[1024] __attribute__((aligned(32)));

View File

@ -36,11 +36,10 @@ struct font {
int32_t max_advance; // 26.6 fixed point
} face_metrics;
uint16_t glyph_count;
uint16_t texture_stride;
uint16_t _texture_stride;
uint16_t texture_width;
uint16_t texture_height;
uint32_t texture_size;
uint32_t max_z_curve_ix;
} __attribute__ ((packed));
static_assert((sizeof (font)) == ((sizeof (uint32_t)) * 8));
static_assert((sizeof (font)) == ((sizeof (uint32_t)) * 7));

Binary file not shown.

133
ftdi.conf
View File

@ -1,133 +0,0 @@
#see http://developer.intra2net.com/git/?p=libftdi;a=blob;f=src/ftdi.c
#and http://developer.intra2net.com/git/?p=libftdi;a=blob;f=src/ftdi.h
#and http://developer.intra2net.com/git/?p=libftdi;a=tree;f=ftdi_eeprom
#and http://developer.intra2net.com/git/?p=libftdi;a=blob;f=ftdi_eeprom/example.conf
#and http://developer.intra2net.com/git/?p=libftdi;a=blob;f=ftdi_eeprom/main.c
############
# Filename #
############
filename=eeprom.new # Filename of the EE file to be generated. Leave empty to skip file writing
#flash_raw=false # Boolean:
## Include another config file?
#include
############
# IDs #
############
# Future Technology Devices International, Ltd FT232H Single HS USB-UART/FIFO IC
vendor_id="0x0403"
product_id="0x6014"
##############################
# Device and Serial Strings #
##############################
manufacturer="FTDI" # String: Manufacturer. FT245R factory default FTDI
product="FT232H Single HS USB-UART/FIFO" # String: Product. FT245R factory default FT245R USB FIFO
serial="00-00"
use_serial=true
############
# Options #
############
max_power=500 # Integer: Max. power consumption: value * 2 mA(?). Use 0 if self_powered = true. FT245R factory default 90
self_powered=false # Boolean: Turn this off for bus powered
remote_wakeup=true # Boolean: Turn this on for remote wakeup feature
# Normally you don't have to change one of these flags
#in_is_isochronous=false # Boolean: In Endpoint is Isochronous
#out_is_isochronous=false # Boolean: Out Endpoint is Isochronous
#suspend_pull_downs=false # Boolean: Enable suspend pull downs for lower power
#change_usb_version=false # Boolean: Change USB Version
#usb_version=0x00 # Integer: Only used when change_usb_version is enabled
#default_pid=0x6001 # Integer: Default Pid.
eeprom_type=6 # Integer: Chip Type / EEPROM Type. Corresponds to ftdi_chip_type struct in ftdi.h
#high_current=false # Boolean: High Current Drive
##Type_R chips
# Only used on FT-R chips (when omitted, use chip defaults)
# Possible values correspond to enum ftdi_cbus_func in ftdi.h and strings are defined in function parse_cbus in ftdi_eeprom/main.c
# Values in the struct are (see current ftid.h for an up to date list):
# CBUS_TXDEN = 0, CBUS_PWREN = 1, CBUS_RXLED = 2, CBUS_TXLED = 3, CBUS_TXRXLED = 4, CBUS_SLEEP = 5, CBUS_CLK48 = 6, CBUS_CLK24 = 7, CBUS_CLK12 = 8, CBUS_CLK6 = 9, CBUS_IOMODE = 0xa, CBUS_BB_WR = 0xb, CBUS_BB_RD = 0xc
# Strings to be used here are:
# "TXDEN", "PWREN", "RXLED", "TXLED", "TXRXLED", "SLEEP", "CLK48", "CLK24", "CLK12", "CLK6", "IOMODE", "BB_WR", "BB_RD"
#cbus0=TXLED # String parsed to integer: FT245R factory default TXLED
#cbus1=RXLED # String parsed to integer: FT245R factory default RXLED
#cbus2=TXDEN # String parsed to integer: FT245R factory default TXDEN
#cbus3=PWREN # String parsed to integer: FT245R factory default PWREN
#cbus4=SLEEP # String parsed to integer: FT245R factory default SLEEP
## Only used on FT232H chips (when omitted, use chip defaults)
# Possible values correspond to enum ftdi_cbush_func in ftdi.h and strings are defined in function parse_cbush in ftdi_eeprom/main.c.
# Values are (see current ftid.h for an up to date list):
# CBUSH_TRISTATE = 0, CBUSH_TXLED = 1, CBUSH_RXLED = 2, CBUSH_TXRXLED = 3, CBUSH_PWREN = 4, CBUSH_SLEEP = 5, CBUSH_DRIVE_0 = 6, CBUSH_DRIVE1 = 7, CBUSH_IOMODE = 8, CBUSH_TXDEN = 9, CBUSH_CLK30 = 10, CBUSH_CLK15 = 11, CBUSH_CLK7_5 = 12
# Strings to be used in this config file are:
# "TRISTATE", "TXLED", "RXLED", "TXRXLED", "PWREN", "SLEEP", "DRIVE_0", "DRIVE1", "IOMODE", "TXDEN", "CLK30", "CLK15", "CLK7_5"
##Type_232H Chips
#cbush0=TRISTATE # String parsed to integer:
#cbush1=TRISTATE # String parsed to integer:
#cbush2=TRISTATE # String parsed to integer:
#cbush3=TRISTATE # String parsed to integer:
#cbush4=TRISTATE # String parsed to integer:
#cbush5=TRISTATE # String parsed to integer:
#cbush6=TRISTATE # String parsed to integer:
#cbush7=TRISTATE # String parsed to integer:
cbush8=TXLED # String parsed to integer:
cbush9=RXLED # String parsed to integer:
# Group Drive
# Strings to be used in this config file are:
# "4MA", "8MA", "12MA", "16MA"
#group0_drive # Integer:
# Only used on FT230X chips (when omitted, use chip defaults)
# Possible values correspond to enum ftdi_cbusx_func in ftdi.h and strings are defined in function parse_cbusx in ftdi_eeprom/main.c.
# Values are (see current ftid.h for an up to date list):
# CBUSX_TRISTATE = 0, CBUSX_TXLED = 1, CBUSX_RXLED = 2, CBUSX_TXRXLED = 3, CBUSX_PWREN = 4, CBUSX_SLEEP = 5, CBUSX_DRIVE_0 = 6, CBUSX_DRIVE1 = 7, CBUSX_IOMODE = 8, CBUSX_TXDEN = 9, CBUSX_CLK24 = 10, CBUSX_CLK12 = 11, CBUSX_CLK6 = 12, CBUSX_BAT_DETECT = 13, CBUSX_BAT_DETECT_NEG = 14, CBUSX_I2C_TXE = 15, CBUSX_I2C_RXF = 16, CBUSX_VBUS_SENSE = 17, CBUSX_BB_WR = 18, CBUSX_BB_RD = 19, CBUSX_TIME_STAMP = 20, CBUSX_AWAKE = 21
# Strings to be used in this config file are:
# "TRISTATE", "TXLED", "RXLED", "TXRXLED", "PWREN", "SLEEP", "DRIVE_0", "DRIVE1", "IOMODE", "TXDEN", "CLK24", "CLK12", "CLK6", "BAT_DETECT", "BAT_DETECT_NEG", "I2C_TXE", "I2C_RXF", "VBUS_SENSE", "BB_WR", "BB_RD", "TIME_STAMP", "AWAKE"
#cbusx0=TXDEN # String parsed to integer:
#cbusx1=RXLED # String parsed to integer:
#cbusx2=TXLED # String parsed to integer:
#cbusx3=SLEEP # String parsed to integer:
########
# Misc #
########
## Pin Configuration
#invert_txd # Boolean: Invert TXD signal
#invert_rxd # Boolean: Invert RXD signal
#invert_rts # Boolean: Invert RTS signal
#invert_cts # Boolean: Invert CTS signal
#invert_dtr # Boolean: Invert DTR signal
#invert_dsr # Boolean: Invert DSR signal
#invert_dcd # Boolean: Invert DCD signal
#invert_ri # Boolean: Invert RI signal
## Channel Types and Drivers
# Possible values are (see current ftid.h (Interface Mode macros) and ftdi.c "channel_mode" for an up to date list). They are parsed in fucntion parse_chtype in ftdi_eeprom/main.c.
# (from ftid.h): UART= 0x0, FIFO = 0x1, OPTO = 0x2, CPU = 0x4, FT1284 = 0x8, RS485 = 0x10
# (from ftdi.c): UART = 0x0, FIOF = 0x1, CPU = 0x2, OPTO = 0x3, FT1284 = 0x3
# Strings to be used in this config file are:
# "UART", "FIFO", "OPTO", "CPU", "FT1284"
cha_type=UART
# String parsed to integer:
#chb_type
# String parsed to integer:
cha_vcp=false # Boolean:
#chb_vcp=false # Boolean:
#chc_vcp=false # Boolean:
#chd_vcp=false # Boolean:
#cha_rs485 # Boolean:
#chb_rs485 # Boolean:
#chc_rs485 # Boolean:
#chd_rs485 # Boolean:
## Include user defined binary data into the the eeprom at address?
#user_data_addr # Integer:
#user_data_file # String: Filename of the data file to be used

28
memory.hpp Normal file
View File

@ -0,0 +1,28 @@
namespace memory {
template <typename T>
void move(T * dst, const T * src, const uint32_t n)
{
if (dst < src) {
while (n > 0) {
*d++ = *s++;
n--;
}
} else {
while (n > 0) {
n--;
d[n] = s[n];
}
}
}
template <typename T>
inline void copy(T * dst, const T * src, const uint32_t n)
{
while (n > 0) {
*dst++ = *src++;
n--;
}
}
}

View File

@ -10,19 +10,6 @@ namespace serial_load {
struct state state;
static void move(void *dst, const void *src, uint32_t n)
{
uint8_t * d = reinterpret_cast<uint8_t *>(dst);
const uint8_t * s = reinterpret_cast<const uint8_t *>(src);
if (d==s) return;
if (d<s) {
for (; n; n--) *d++ = *s++;
} else {
while (n) n--, d[n] = s[n];
}
}
void init(uint32_t speed)
{
state.len = 0;

View File

@ -32,7 +32,7 @@ FTDI_OBJ = \
ftdi_transfer: $(FTDI_OBJ)
$(CXX) $^ -o $@ $(FTDI_LDFLAGS)
ttf_outline: ttf_outline.o 2d_pack.o
ttf_outline: ttf_outline.o ttf_2d_pack.o
clean:
rm -f *.o ttf_outline

View File

@ -2,11 +2,12 @@
#include <cstdint>
#include <compare>
#include <iostream>
#include <array>
#include "insertion_sort.hpp"
#include "rect.hpp"
#include "../twiddle.hpp"
#include "2d_pack.hpp"
#include "ttf_2d_pack.hpp"
struct size {
uint16_t width;
@ -37,6 +38,39 @@ inline bool area_valid(const uint8_t texture[max_texture.height][max_texture.wid
return true;
}
constexpr inline std::array<uint32_t, 2>
from_ix(uint32_t curve_ix)
{
std::array<uint32_t, 2> x_y = {0, 0};
uint32_t curve_bit = 0;
while (curve_ix != 0) {
x_y[(curve_bit + 1) % 2] |= (curve_ix & 1) << (curve_bit / 2);
curve_ix >>= 1;
curve_bit += 1;
}
return x_y;
}
static_assert(from_ix(0) == std::array<uint32_t, 2>{{0b000, 0b000}});
static_assert(from_ix(2) == std::array<uint32_t, 2>{{0b001, 0b000}});
static_assert(from_ix(8) == std::array<uint32_t, 2>{{0b010, 0b000}});
static_assert(from_ix(10) == std::array<uint32_t, 2>{{0b011, 0b000}});
static_assert(from_ix(32) == std::array<uint32_t, 2>{{0b100, 0b000}});
static_assert(from_ix(34) == std::array<uint32_t, 2>{{0b101, 0b000}});
static_assert(from_ix(40) == std::array<uint32_t, 2>{{0b110, 0b000}});
static_assert(from_ix(42) == std::array<uint32_t, 2>{{0b111, 0b000}});
static_assert(from_ix(1) == std::array<uint32_t, 2>{{0b000, 0b001}});
static_assert(from_ix(4) == std::array<uint32_t, 2>{{0b000, 0b010}});
static_assert(from_ix(5) == std::array<uint32_t, 2>{{0b000, 0b011}});
static_assert(from_ix(16) == std::array<uint32_t, 2>{{0b000, 0b100}});
static_assert(from_ix(17) == std::array<uint32_t, 2>{{0b000, 0b101}});
static_assert(from_ix(20) == std::array<uint32_t, 2>{{0b000, 0b110}});
static_assert(from_ix(21) == std::array<uint32_t, 2>{{0b000, 0b111}});
uint32_t pack_into(uint8_t texture[max_texture.height][max_texture.width],
struct size& window,
struct rect& rect)
@ -50,7 +84,7 @@ uint32_t pack_into(uint8_t texture[max_texture.height][max_texture.width],
}
while (true) {
auto [x_offset, y_offset] = twiddle::from_ix(z_curve_ix);
auto [x_offset, y_offset] = from_ix(z_curve_ix);
if (x_offset >= window.width and y_offset >= window.height) {
//std::cerr << z_curve_ix << ' ' << window.width << ' ' << window.height << '\n';
@ -78,7 +112,9 @@ uint32_t pack_into(uint8_t texture[max_texture.height][max_texture.width],
rect.y = y_offset;
return twiddle::from_xy(rect.x + rect.width - 1,
rect.y + rect.height - 1);
rect.y + rect.height - 1,
1024,
1024);
} else {
z_curve_ix += 1;
continue;

View File

@ -10,7 +10,7 @@
#include "../font/font.hpp"
#include "rect.hpp"
#include "2d_pack.hpp"
#include "ttf_2d_pack.hpp"
#include "../twiddle.hpp"
std::endian _target_endian;
@ -93,8 +93,8 @@ load_outline_char(const FT_Face face,
assert(bits_per_pixel == 8 || bits_per_pixel == 4 || bits_per_pixel == 2 || bits_per_pixel == 1);
const uint32_t pixels_per_byte = 8 / bits_per_pixel;
const uint32_t texture_stride = texture_width / pixels_per_byte;
std::cerr << "pixels per byte: " << pixels_per_byte << '\n';
std::cerr << "texture stride: " << texture_stride << '\n';
//std::cerr << "pixels per byte: " << pixels_per_byte << '\n';
//std::cerr << "texture stride: " << texture_stride << '\n';
for (uint32_t y = 0; y < rect.height; y++) {
for (uint32_t x = 0; x < rect.width; x++) {
@ -159,7 +159,7 @@ load_all_positions(const FT_Face face,
const uint32_t start,
const uint32_t end,
glyph * glyphs,
uint32_t * texture
uint8_t * texture
)
{
const uint32_t num_glyphs = (end - start) + 1;
@ -197,7 +197,7 @@ load_all_positions(const FT_Face face,
bits_per_pixel,
char_code,
&glyphs[char_code - start],
reinterpret_cast<uint8_t *>(texture),
texture,
window_curve_ix.window.width,
rects[i]);
if (err < 0) assert(false);
@ -271,19 +271,27 @@ int main(int argc, char *argv[])
uint32_t num_glyphs = (end - start) + 1;
glyph glyphs[num_glyphs];
uint32_t texture[max_texture_size / 4];
uint8_t texture[max_texture_size];
memset(texture, 0x00, max_texture_size);
auto window_curve_ix = load_all_positions(face, monochrome, start, end, glyphs, texture);
uint32_t texture_stride;
//uint32_t texture_stride;
uint32_t texture_size;
if (monochrome) {
texture_stride = window_curve_ix.window.width / 8;
//texture_stride = window_curve_ix.window.width / 8;
texture_size = window_curve_ix.window.width * window_curve_ix.window.height / 8;
} else {
texture_stride = window_curve_ix.window.width;
texture_size = window_curve_ix.window.width * window_curve_ix.window.height;
//texture_stride = window_curve_ix.window.width;
texture_size = window_curve_ix.max_z_curve_ix;
}
uint8_t twiddle_texture[window_curve_ix.window.width * window_curve_ix.window.height];
if (!monochrome) {
twiddle::texture<uint8_t>(twiddle_texture,
texture,
window_curve_ix.window.width,
window_curve_ix.window.height);
}
font font;
@ -292,18 +300,16 @@ int main(int argc, char *argv[])
font.face_metrics.height = byteswap<int32_t>(face->size->metrics.height);
font.face_metrics.max_advance = byteswap<int32_t>(face->size->metrics.max_advance);
font.glyph_count = byteswap<uint16_t>(num_glyphs);
font.texture_stride = byteswap<uint16_t>(texture_stride);
//font.texture_stride = byteswap<uint16_t>(texture_stride);
font.texture_width = byteswap<uint16_t>(window_curve_ix.window.width);
font.texture_height = byteswap<uint16_t>(window_curve_ix.window.height);
font.texture_size = byteswap<uint32_t>(texture_size);
font.max_z_curve_ix = byteswap<uint32_t>(window_curve_ix.max_z_curve_ix);
std::cerr << "start: 0x" << std::hex << start << '\n';
std::cerr << "end: 0x" << std::hex << end << '\n';
std::cerr << "texture_stride: " << std::dec << texture_stride << '\n';
//std::cerr << "texture_stride: " << std::dec << texture_stride << '\n';
std::cerr << "texture_width: " << std::dec << window_curve_ix.window.width << '\n';
std::cerr << "texture_height: " << std::dec << window_curve_ix.window.height << '\n';
std::cerr << "texture_size: " << std::dec << texture_size << '\n';
std::cerr << "max_z_curve_ix: " << std::dec << window_curve_ix.max_z_curve_ix << '\n';
FILE * out = fopen(argv[output_file_path], "w");
@ -314,7 +320,11 @@ int main(int argc, char *argv[])
fwrite(reinterpret_cast<void*>(&font), (sizeof (font)), 1, out);
fwrite(reinterpret_cast<void*>(&glyphs[0]), (sizeof (glyph)), num_glyphs, out);
fwrite(reinterpret_cast<void*>(&texture[0]), (sizeof (uint8_t)), texture_size, out);
if (monochrome) {
fwrite(reinterpret_cast<void*>(&texture[0]), (sizeof (uint8_t)), texture_size, out);
} else {
fwrite(reinterpret_cast<void*>(&twiddle_texture[0]), (sizeof (uint8_t)), texture_size, out);
}
fclose(out);
}