From ffbfcd9fd5b54c513e6cb4ba20722cfbccbc8350 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 23 Dec 2023 18:30:21 +0800 Subject: [PATCH] incomplete 1bpp font experiment --- dejavusansmono_mono.data | Bin 0 -> 5958 bytes dejavusansmono_mono.hpp | 5 + example/example.mk | 13 ++ example/font_outline_punch_through.cpp | 260 +++++++++++++++++++++++++ tools/2d_pack.cpp | 2 +- tools/ttf_outline.cpp | 114 +++++++---- twiddle.hpp | 2 +- 7 files changed, 360 insertions(+), 36 deletions(-) create mode 100644 dejavusansmono_mono.data create mode 100644 dejavusansmono_mono.hpp create mode 100644 example/font_outline_punch_through.cpp diff --git a/dejavusansmono_mono.data b/dejavusansmono_mono.data new file mode 100644 index 0000000000000000000000000000000000000000..4d53cf8b62fad6bdb3650b4dcff9ab5b21fc1f91 GIT binary patch literal 5958 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 literal 0 HcmV?d00001 diff --git a/dejavusansmono_mono.hpp b/dejavusansmono_mono.hpp new file mode 100644 index 0000000..ca93a73 --- /dev/null +++ b/dejavusansmono_mono.hpp @@ -0,0 +1,5 @@ +#include + +extern uint32_t _binary_dejavusansmono_mono_data_start __asm("_binary_dejavusansmono_mono_data_start"); +extern uint32_t _binary_dejavusansmono_mono_data_end __asm("_binary_dejavusansmono_mono_data_end"); +extern uint32_t _binary_dejavusansmono_mono_data_size __asm("_binary_dejavusansmono_mono_data_size"); diff --git a/example/example.mk b/example/example.mk index c3c942c..948292b 100644 --- a/example/example.mk +++ b/example/example.mk @@ -59,6 +59,19 @@ FONT_OUTLINE_OBJ = \ example/font_outline.elf: LDSCRIPT = $(LIB)/alt.lds example/font_outline.elf: $(START_OBJ) $(FONT_OUTLINE_OBJ) +FONT_OUTLINE_PUNCH_THROUGH_OBJ = \ + example/font_outline_punch_through.o \ + vga.o \ + holly/core.o \ + holly/region_array.o \ + holly/background.o \ + holly/ta_fifo_polygon_converter.o \ + serial.o \ + dejavusansmono_mono.data.o + +example/font_outline_punch_through.elf: LDSCRIPT = $(LIB)/alt.lds +example/font_outline_punch_through.elf: $(START_OBJ) $(FONT_OUTLINE_PUNCH_THROUGH_OBJ) + MACAW_MULTIPASS_OBJ = \ example/macaw_multipass.o \ vga.o \ diff --git a/example/font_outline_punch_through.cpp b/example/font_outline_punch_through.cpp new file mode 100644 index 0000000..2a5b65c --- /dev/null +++ b/example/font_outline_punch_through.cpp @@ -0,0 +1,260 @@ +#include + +#include "align.hpp" + +#include "vga.hpp" +#include "holly.hpp" +#include "holly/core.hpp" +#include "holly/core_bits.hpp" +#include "holly/ta_parameter.hpp" +#include "holly/ta_fifo_polygon_converter.hpp" +#include "holly/texture_memory_alloc.hpp" +#include "memorymap.hpp" +#include "holly/background.hpp" +#include "holly/region_array.hpp" +#include "holly/ta_bits.hpp" +#include "twiddle.hpp" +#include "serial.hpp" + +#include "font/font.hpp" +#include "dejavusansmono_mono.hpp" + +#include "sperrypc.hpp" + +struct vertex { + float x; + float y; + float z; + float u; + float v; +}; + +const struct vertex strip_vertices[4] = { + // [ position ] [ uv coordinates ] + { 0.f, 1.f, 0.f, 0.f, 1.f, }, + { 0.f, 0.f, 0.f, 0.f, 0.f, }, + { 1.f, 1.f, 0.f, 1.f, 1.f, }, + { 1.f, 0.f, 0.f, 1.f, 0.f, }, +}; +constexpr uint32_t strip_length = (sizeof (strip_vertices)) / (sizeof (struct vertex)); + +uint32_t transform(ta_parameter_writer& parameter, + const uint32_t first_char_code, + const uint32_t texture_width, uint32_t texture_height, + const glyph * glyphs, + const char * s, const uint32_t len, + const uint32_t y_offset) +{ + uint32_t texture_address = (offsetof (struct texture_memory_alloc, texture)); + + uint32_t advance = 0; // in 26.6 fixed-point + + for (uint32_t string_ix = 0; string_ix < len; string_ix++) { + char c = s[string_ix]; + auto& glyph = glyphs[c - first_char_code]; + if (glyph.bitmap.width == 0 || glyph.bitmap.height == 0) { + advance += glyph.metrics.horiAdvance; + continue; + } + + auto polygon = global_polygon_type_0(texture_address); + polygon.parameter_control_word = para_control::para_type::polygon_or_modifier_volume + | para_control::list_type::opaque + | obj_control::col_type::packed_color + | obj_control::texture; + + polygon.tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one + | tsp_instruction_word::dst_alpha_instr::zero + | tsp_instruction_word::fog_control::no_fog + | tsp_instruction_word::texture_u_size::from_int(texture_width) + | tsp_instruction_word::texture_v_size::from_int(texture_height); + + polygon.texture_control_word = texture_control_word::pixel_format::_4bpp_palette + | texture_control_word::scan_order::twiddled + | texture_control_word::texture_address(texture_address / 8); + parameter.append() = polygon; + + for (uint32_t i = 0; i < strip_length; i++) { + bool end_of_strip = i == strip_length - 1; + + float x = strip_vertices[i].x; + float y = strip_vertices[i].y; + float z = strip_vertices[i].z; + + x *= glyph.bitmap.width; + y *= glyph.bitmap.height; + x += 100.f + ((advance + glyph.metrics.horiBearingX) >> 6); + y += 200.f - ((glyph.metrics.horiBearingY) >> 6); + y += y_offset >> 6; + z = 1.f / (z + 10.f); + + float u = strip_vertices[i].u; + float v = strip_vertices[i].v; + u *= glyph.bitmap.width; + v *= glyph.bitmap.height; + u += glyph.bitmap.x; + v += glyph.bitmap.y; + u = u / static_cast(texture_width); + v = v / static_cast(texture_height); + + parameter.append() = + vertex_polygon_type_3(x, y, z, + u, v, + 0x00000000, // base_color + end_of_strip); + } + + advance += glyph.metrics.horiAdvance; + } + + return parameter.offset; +} + + +void init_texture_memory(const struct opb_size& opb_size) +{ + auto mem = reinterpret_cast(texture_memory32); + + background_parameter(mem->background, 0xff0000ff); + + region_array2(mem->region_array, + (offsetof (struct texture_memory_alloc, object_list)), + 640 / 32, // width + 480 / 32, // height + opb_size + ); +} + +constexpr inline uint32_t b(uint32_t v, uint32_t n) +{ + return ((v >> n) & 1) << (4 * n); +} + +void inflate_font(const uint32_t * src, const uint32_t size) +{ + auto mem = reinterpret_cast(texture_memory64); + auto texture = reinterpret_cast(mem->texture); + + for (uint32_t i = 0; i < (size / 4); i++) { + uint32_t v = src[i]; + texture[(i * 4) + 0] = b(v, 7 ) | b(v, 6 ) | b(v, 5 ) | b(v, 4 ) | b(v, 3 ) | b(v, 2 ) | b(v, 1 ) | b(v, 0 ); + texture[(i * 4) + 1] = b(v, 15) | b(v, 14) | b(v, 13) | b(v, 12) | b(v, 11) | b(v, 10) | b(v, 9 ) | b(v, 8 ); + texture[(i * 4) + 2] = b(v, 23) | b(v, 22) | b(v, 21) | b(v, 20) | b(v, 19) | b(v, 18) | b(v, 17) | b(v, 16); + texture[(i * 4) + 3] = b(v, 31) | b(v, 30) | b(v, 29) | b(v, 28) | b(v, 27) | b(v, 26) | b(v, 25) | b(v, 24); + } +} + +template +void palette_data() +{ + static_assert(C >= 2); + constexpr int increment = 256 / C; + + holly.PAL_RAM_CTRL = pal_ram_ctrl::pixel_format::rgb565; + + // generate a palette with `C` shades of grey, + // ranging in intensity from rgb565(0, 0, 0) to rgb565(31, 63, 31) + for (int i = 0; i < 256; i += increment) { + holly.PALETTE_RAM[i / increment] = ((i >> 3) << 11) + | ((i >> 2) << 5) + | ((i >> 3) << 0); + } +} + +void palette_data_mono() +{ + holly.PALETTE_RAM[0] = 0; + holly.PALETTE_RAM[1] = 0xffff; +} + +uint32_t _ta_parameter_buf[((32 * 10 * 17) + 32) / 4]; + +void main() +{ + vga(); + + auto font = reinterpret_cast(&_binary_dejavusansmono_mono_data_start); + auto glyphs = reinterpret_cast(&font[1]); + auto texture = reinterpret_cast(&glyphs[font->glyph_count]); + + /* + serial::integer(font->first_char_code); + serial::integer(font->glyph_count); + serial::integer(font->glyph_height); + serial::integer(font->texture_width); + serial::integer(font->texture_height); + serial::character('\n'); + serial::integer(((uint32_t)glyphs) - ((uint32_t)font)); + serial::integer(((uint32_t)texture) - ((uint32_t)font)); + */ + + uint32_t texture_size = font->max_z_curve_ix + 1; + inflate_font(texture, texture_size); + palette_data_mono(); + + // The address of `ta_parameter_buf` must be a multiple of 32 bytes. + // This is mandatory for ch2-dma to the ta fifo polygon converter. + uint32_t * ta_parameter_buf = align_32byte(_ta_parameter_buf); + + constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list + | ta_alloc_ctrl::tm_opb::no_list + | ta_alloc_ctrl::t_opb::no_list + | ta_alloc_ctrl::om_opb::no_list + | ta_alloc_ctrl::o_opb::_16x4byte; + + constexpr struct opb_size opb_size = { .opaque = 16 * 4 + , .opaque_modifier = 0 + , .translucent = 0 + , .translucent_modifier = 0 + , .punch_through = 0 + }; + + constexpr uint32_t tiles = (640 / 32) * (320 / 32); + + holly.SOFTRESET = softreset::pipeline_soft_reset + | softreset::ta_soft_reset; + holly.SOFTRESET = 0; + + core_init(); + init_texture_memory(opb_size); + + uint32_t frame_ix = 0; + constexpr uint32_t num_frames = 1; + + const char ana[18] = "A from ana i know"; + const char cabal[27] = "where is this secret cabal"; + + while (true) { + ta_polygon_converter_init(opb_size.total() * tiles, ta_alloc, + 640, 480); + + auto parameter = ta_parameter_writer(ta_parameter_buf); + + transform(parameter, + font->first_char_code, + font->texture_width, font->texture_height, + glyphs, + ana, 17, + font->glyph_height * 0); + + transform(parameter, + font->first_char_code, + font->texture_width, font->texture_height, + glyphs, + cabal, 26, + font->glyph_height * 1); + + parameter.append() = global_end_of_list(); + + ta_polygon_converter_transfer(ta_parameter_buf, parameter.offset); + ta_wait_opaque_list(); + + core_start_render(frame_ix, num_frames); + + v_sync_out(); + v_sync_in(); + core_wait_end_of_render_video(frame_ix, num_frames); + + frame_ix++; + } +} diff --git a/tools/2d_pack.cpp b/tools/2d_pack.cpp index 25a4583..57b512c 100644 --- a/tools/2d_pack.cpp +++ b/tools/2d_pack.cpp @@ -106,7 +106,7 @@ pack_all(struct rect * rects, const uint32_t num_rects) max_z_curve_ix = z_curve_ix; } - std::cerr << "window size: " << window.width << ' ' << window.height << '\n'; + //std::cerr << "window size: " << window.width << ' ' << window.height << '\n'; std::cerr << "max_z_curve_ix: " << max_z_curve_ix << '\n'; return {window.width, window.height, max_z_curve_ix}; } diff --git a/tools/ttf_outline.cpp b/tools/ttf_outline.cpp index 46499cc..ceed772 100644 --- a/tools/ttf_outline.cpp +++ b/tools/ttf_outline.cpp @@ -29,13 +29,14 @@ uint32_t byteswap(const uint32_t n) int32_t load_outline_char_bitmap_rect(const FT_Face face, + const FT_Int32 load_flags, const FT_ULong char_code, struct rect& rect) { FT_Error error; FT_UInt glyph_index = FT_Get_Char_Index(face, char_code); - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + error = FT_Load_Glyph(face, glyph_index, load_flags); if (error) { std::cerr << "FT_Load_Glyph " << FT_Error_String(error) << '\n'; return -1; @@ -52,6 +53,8 @@ load_outline_char_bitmap_rect(const FT_Face face, int32_t load_outline_char(const FT_Face face, + const FT_Int32 load_flags, + const FT_Render_Mode render_mode, const FT_ULong char_code, glyph * glyph, uint8_t * texture, @@ -60,7 +63,7 @@ load_outline_char(const FT_Face face, FT_Error error; FT_UInt glyph_index = FT_Get_Char_Index(face, char_code); - error = FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT); + error = FT_Load_Glyph(face, glyph_index, load_flags); if (error) { std::cerr << "FT_Load_Glyph " << FT_Error_String(error) << '\n'; return -1; @@ -70,7 +73,7 @@ load_outline_char(const FT_Face face, //assert(face->glyph->format == FT_GLYPH_FORMAT_OUTLINE); - error = FT_Render_Glyph(face->glyph, FT_RENDER_MODE_NORMAL); + error = FT_Render_Glyph(face->glyph, render_mode); if (error) { std::cerr << "FT_Render_Glyph " << FT_Error_String(error) << '\n'; return -1; @@ -84,26 +87,34 @@ load_outline_char(const FT_Face face, assert(face->glyph->bitmap.width == rect.width); assert(face->glyph->bitmap.rows == rect.height); - //std::cerr << "num_grays " << face->glyph->bitmap.num_grays << '\n'; - switch (face->glyph->bitmap.num_grays) { - case 2: - assert(false); - break; - case 256: - //std::cerr << "rxy " << rect.x << ' ' << rect.y << '\n'; - //std::cerr << "rwh " << rect.width << ' ' << rect.height << '\n'; + for (uint32_t y = 0; y < rect.height; y++) { + for (uint32_t x = 0; x < rect.width; x++) { + uint32_t texture_ix = (rect.y + y) * max_texture_dim + (rect.x + x); + assert(texture_ix < max_texture_size); - for (uint32_t y = 0; y < rect.height; y++) { - for (uint32_t x = 0; x < rect.width; x++) { - uint32_t texture_ix = (rect.y + y) * max_texture_dim + (rect.x + x); - assert(texture_ix < max_texture_size); - texture[texture_ix] = face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch + x]; + uint8_t level; + + //std::cerr << "rxy " << rect.x << ' ' << rect.y << '\n'; + //std::cerr << "rwh " << rect.width << ' ' << rect.height << '\n'; + + //std::cerr << "pixel_mode " << (int)face->glyph->bitmap.pixel_mode << '\n'; + switch (face->glyph->bitmap.pixel_mode) { + case FT_PIXEL_MODE_MONO: + // [num_grays] is only used with FT_PIXEL_MODE_GRAY; it gives the number + // of gray levels used in the bitmap. + level = (face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch + (x / 8)] >> (7 - (x % 8))) & 1; + break; + case FT_PIXEL_MODE_GRAY: + assert(face->glyph->bitmap.num_grays == 256); + //std::cerr << "num_grays " << face->glyph->bitmap.num_grays << '\n'; + level = face->glyph->bitmap.buffer[y * face->glyph->bitmap.pitch + x]; + break; + default: + assert(false); + break; } + texture[texture_ix] = level; } - - break; - default: - assert(face->glyph->bitmap.num_grays == -1); } glyph_bitmap& bitmap = glyph->bitmap; @@ -124,14 +135,16 @@ enum { start_hex = 1, end_hex = 2, pixel_size = 3, - target_endian = 4, - font_file_path = 5, - output_file_path = 6, - argv_length = 7 + monochrome_out = 4, + target_endian = 5, + font_file_path = 6, + output_file_path = 7, + argv_length = 8 }; struct window_curve_ix load_all_positions(const FT_Face face, + bool monochrome, const uint32_t start, const uint32_t end, glyph * glyphs, @@ -143,18 +156,33 @@ load_all_positions(const FT_Face face, uint8_t temp[max_texture_size]; + FT_Int32 load_flags; + FT_Render_Mode render_mode; + if (monochrome) { + load_flags = FT_LOAD_MONOCHROME | FT_LOAD_TARGET_MONO; + render_mode = FT_RENDER_MODE_MONO; + } else { + load_flags = FT_LOAD_DEFAULT; + render_mode = FT_RENDER_MODE_NORMAL; + } + // first, load all rectangles for (uint32_t char_code = start; char_code <= end; char_code++) { - load_outline_char_bitmap_rect(face, char_code, rects[char_code - start]); + load_outline_char_bitmap_rect(face, + load_flags, + char_code, + rects[char_code - start]); } // calculate a 2-dimensional packing for the rectangles auto window_curve_ix = pack_all(rects, num_glyphs); - // asdf + // render all of the glyps to a temporary buffer; for (uint32_t i = 0; i < num_glyphs; i++) { const uint32_t char_code = rects[i].char_code; int32_t err = load_outline_char(face, + load_flags, + render_mode, char_code, &glyphs[char_code - start], temp, @@ -162,10 +190,22 @@ load_all_positions(const FT_Face face, if (err < 0) assert(false); } - twiddle::texture2<8>(texture, temp, - window_curve_ix.window.width, - window_curve_ix.window.height, - max_texture_dim); + // twiddle the temporary buffer to become the final texture + if (monochrome) { + twiddle::texture2<1>(texture, temp, + window_curve_ix.window.width, + window_curve_ix.window.height, + max_texture_dim); + } else { + twiddle::texture2<8>(texture, temp, + window_curve_ix.window.width, + window_curve_ix.window.height, + max_texture_dim); + } + + if (monochrome) { + window_curve_ix.max_z_curve_ix = window_curve_ix.max_z_curve_ix / 8; + } return window_curve_ix; } @@ -177,9 +217,9 @@ int main(int argc, char *argv[]) FT_Error error; if (argc != argv_length) { - std::cerr << "usage: " << argv[0] << " [start-hex] [end-hex] [pixel-size] [target-endian] [font-file-path] [output-file-path]\n\n"; - std::cerr << "ex. 1: " << argv[0] << " 3000 30ff 30 little ipagp.ttf font.bin\n"; - std::cerr << "ex. 2: " << argv[0] << " 20 7f 30 big DejaVuSans.ttf font.bin\n"; + std::cerr << "usage: " << argv[0] << " [start-hex] [end-hex] [pixel-size] [monochrome-out] [target-endian] [font-file-path] [output-file-path]\n\n"; + std::cerr << "ex. 1: " << argv[0] << " 3000 30ff 30 0 little ipagp.ttf font.bin\n"; + std::cerr << "ex. 2: " << argv[0] << " 20 7f 30 1 big DejaVuSans.ttf font.bin\n"; return -1; } @@ -200,6 +240,12 @@ int main(int argc, char *argv[]) ss3 << std::dec << argv[pixel_size]; ss3 >> font_size; std::cerr << "font_size: " << font_size << '\n'; + std::stringstream ss4; + int monochrome; + ss4 << std::dec << argv[monochrome_out]; + ss4 >> monochrome; + assert(monochrome == 0 || monochrome == 1); + std::cerr << "monochrome: " << monochrome << '\n'; error = FT_Set_Pixel_Sizes(face, 0, font_size); if (error) { @@ -232,7 +278,7 @@ int main(int argc, char *argv[]) uint32_t texture[max_texture_size / 4]; memset(texture, 0x00, max_texture_size); - auto window_curve_ix = load_all_positions(face, start, end, glyphs, texture); + auto window_curve_ix = load_all_positions(face, monochrome, start, end, glyphs, texture); font font; font.first_char_code = byteswap(start); diff --git a/twiddle.hpp b/twiddle.hpp index 9ccedd1..b46a22c 100644 --- a/twiddle.hpp +++ b/twiddle.hpp @@ -147,7 +147,7 @@ void texture2(volatile T * dst, const U * src, static_assert(t_bits >= bits_per_pixel); static_assert((t_bits / bits_per_pixel) * bits_per_pixel == t_bits); constexpr uint32_t pixels_per_t = t_bits / bits_per_pixel; - static_assert(pixels_per_t == 1 || pixels_per_t == 2 || pixels_per_t == 4 || pixels_per_t == 8); + static_assert(pixels_per_t == 1 || pixels_per_t == 2 || pixels_per_t == 4 || pixels_per_t == 8 || pixels_per_t == 16 || pixels_per_t == 32); T dst_val = 0; const uint32_t end_ix = from_xy(width - 1, height - 1);