From 34b3baae6017273f3382276fc86a8fb28712a2f0 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 19 Apr 2024 12:28:11 +0100 Subject: [PATCH] TEST: PicoVector: Break things until they work. --- libraries/pico_vector/af-memory.h | 1 + libraries/pico_vector/alright-fonts.h | 47 +++++++++------ libraries/pico_vector/pico_vector.cpp | 17 ++++-- libraries/pico_vector/pico_vector.hpp | 21 ++++++- micropython/modules/picovector/picovector.cpp | 60 ++++++++++++++----- 5 files changed, 104 insertions(+), 42 deletions(-) diff --git a/libraries/pico_vector/af-memory.h b/libraries/pico_vector/af-memory.h index 81c647bda..22e01c909 100644 --- a/libraries/pico_vector/af-memory.h +++ b/libraries/pico_vector/af-memory.h @@ -2,4 +2,5 @@ extern "C" { void *af_malloc(size_t size); void *af_realloc(void *p, size_t size); void af_free(void *p); + void af_debug(const char *fmt, ...); } \ No newline at end of file diff --git a/libraries/pico_vector/alright-fonts.h b/libraries/pico_vector/alright-fonts.h index 701c7a078..f66cb230b 100644 --- a/libraries/pico_vector/alright-fonts.h +++ b/libraries/pico_vector/alright-fonts.h @@ -52,6 +52,10 @@ #define AF_FGETC(stream) fgetc(stream) #endif +#ifndef AF_DEBUG + #define AF_DEBUG(...) +#endif + #include "pretty-poly.h" #ifdef __cplusplus @@ -99,9 +103,9 @@ typedef struct { } af_text_metrics_t; bool af_load_font_file(AF_FILE file, af_face_t *face); -void af_render_character(af_face_t *face, wchar_t codepoint, af_text_metrics_t *tm); -void af_render(af_face_t *face, wchar_t *text, af_text_metrics_t *tm); -pp_rect_t af_measure(af_face_t *face, const wchar_t *text, af_text_metrics_t *tm); +void af_render_character(af_face_t *face, const char codepoint, af_text_metrics_t *tm); +void af_render(af_face_t *face, const char *text, af_text_metrics_t *tm); +pp_rect_t af_measure(af_face_t *face, const char *text, af_text_metrics_t *tm); #ifdef AF_USE_PRETTY_POLY #endif @@ -146,6 +150,11 @@ bool af_load_font_file(AF_FILE file, af_face_t *face) { void *buffer = AF_MALLOC(sizeof(af_glyph_t) * glyph_count + \ sizeof( af_path_t) * path_count + \ sizeof(af_point_t) * point_count); + + if(!buffer) { + return false; // failed memory allocation + } + af_glyph_t *glyphs = (af_glyph_t *) buffer; af_path_t *paths = ( af_path_t *)(glyphs + (sizeof(af_glyph_t) * glyph_count)); af_point_t *points = (af_point_t *)( paths + (sizeof( af_path_t) * path_count)); @@ -193,7 +202,7 @@ bool af_load_font_file(AF_FILE file, af_face_t *face) { return true; } -af_glyph_t *find_glyph(af_face_t *face, wchar_t c) { +af_glyph_t *find_glyph(af_face_t *face, char c) { for(int i = 0; i < face->glyph_count; i++) { if(face->glyphs[i].codepoint == c) { return &face->glyphs[i]; @@ -223,12 +232,12 @@ void af_render_glyph(af_glyph_t* glyph, af_text_metrics_t *tm) { for(uint32_t i = 0; i < poly.count; i++) { pp_path_t *path = &poly.paths[i]; - free(path->points); + AF_FREE(path->points); } - free(poly.paths); + AF_FREE(poly.paths); } -void af_render_character(af_face_t *face, wchar_t c, af_text_metrics_t *tm) { +void af_render_character(af_face_t *face, const char c, af_text_metrics_t *tm) { af_glyph_t *glyph = find_glyph(face, c); if(!glyph) { return; @@ -236,10 +245,10 @@ void af_render_character(af_face_t *face, wchar_t c, af_text_metrics_t *tm) { af_render_glyph(glyph, tm); } -int get_line_width(af_face_t *face, wchar_t *text, af_text_metrics_t *tm) { +int get_line_width(af_face_t *face, const char *text, af_text_metrics_t *tm) { int line_width = 0; - wchar_t *end = wcschr(text, L'\n'); - for(wchar_t c = *text; text < end; text++, c = *text) { + char *end = strchr(text, '\n'); + for(char c = *text; text < end; text++, c = *text) { af_glyph_t *glyph = find_glyph(face, c); if(!glyph) { continue; @@ -254,22 +263,22 @@ int get_line_width(af_face_t *face, wchar_t *text, af_text_metrics_t *tm) { return line_width; } -int get_max_line_width(af_face_t *face, wchar_t *text, af_text_metrics_t *tm) { +int get_max_line_width(af_face_t *face, const char *text, af_text_metrics_t *tm) { int max_width = 0; - wchar_t *end = wcschr(text, L'\n'); + char *end = strchr(text, '\n'); while(end) { int width = get_line_width(face, text, tm); max_width = max_width < width ? width : max_width; text = end + 1; - end = wcschr(text, L'\n'); + end = strchr(text, '\n'); } return max_width; } -void af_render(af_face_t *face, wchar_t *text, af_text_metrics_t *tm) { +void af_render(af_face_t *face, const char *text, af_text_metrics_t *tm) { pp_mat3_t *old = pp_transform(NULL); float line_height = (tm->line_height * 128.0f) / 100.0f; @@ -285,11 +294,11 @@ void af_render(af_face_t *face, wchar_t *text, af_text_metrics_t *tm) { caret.x = 0; caret.y = 0; - wchar_t *end = wcschr(text, L'\n'); + char *end = strchr(text, '\n'); while(end) { int line_width = get_line_width(face, text, tm); - for(wchar_t c = *text; text < end; text++, c = *text) { + for(char c = *text; text < end; text++, c = *text) { af_glyph_t *glyph = find_glyph(face, c); if(!glyph) { continue; @@ -320,7 +329,7 @@ void af_render(af_face_t *face, wchar_t *text, af_text_metrics_t *tm) { } text = end + 1; - end = wcschr(text, L'\n'); + end = strchr(text, '\n'); caret.x = 0; caret.y += line_height; @@ -331,12 +340,12 @@ void af_render(af_face_t *face, wchar_t *text, af_text_metrics_t *tm) { pp_transform(old); } -pp_rect_t af_measure(af_face_t *face, const wchar_t *text, af_text_metrics_t *tm) { +pp_rect_t af_measure(af_face_t *face, const char *text, af_text_metrics_t *tm) { pp_rect_t result; bool first = true; pp_mat3_t t = *tm->transform; - for(size_t i = 0; i < wcslen(text); i++) { + for(size_t i = 0; i < strlen(text); i++) { af_glyph_t *glyph = find_glyph(face, text[i]); if(!glyph) { continue; diff --git a/libraries/pico_vector/pico_vector.cpp b/libraries/pico_vector/pico_vector.cpp index 8566e43fb..9c20f0735 100644 --- a/libraries/pico_vector/pico_vector.cpp +++ b/libraries/pico_vector/pico_vector.cpp @@ -56,9 +56,15 @@ namespace pimoroni { } } - pp_point_t PicoVector::text(std::wstring_view text, pp_point_t offset, pp_mat3_t *t) { + pp_point_t PicoVector::text(std::string_view text, pp_mat3_t *t) { pp_point_t caret = {0, 0}; + text_metrics.transform = t; + + af_render(text_metrics.face, text.data(), &text_metrics); + + return caret; +/* // Align text from the bottom left caret.y += (PP_COORD_TYPE)text_metrics.line_height; @@ -69,7 +75,7 @@ namespace pimoroni { pp_point_t space; pp_point_t carriage_return = {0, -(PP_COORD_TYPE)text_metrics.line_height}; - wchar_t spc = L' '; + char spc = ' '; space.x = af_measure(text_metrics.face, &spc, &text_metrics).w; if (space.x == 0) { @@ -110,10 +116,10 @@ namespace pimoroni { } for(size_t j = i; j < std::min(next_break + 1, text.length()); j++) { - if (text[j] == L'\n') { // Linebreak + if (text[j] == '\n') { // Linebreak caret = pp_point_sub(&caret, &carriage_return); carriage_return = initial_carriage_return; - } else if (text[j] == L' ') { // Space + } else if (text[j] == ' ') { // Space caret = pp_point_add(&caret, &space); carriage_return = pp_point_add(&carriage_return, &space); } else { @@ -125,7 +131,7 @@ namespace pimoroni { af_render_character(text_metrics.face, text[j], &text_metrics); } pp_point_t advance = { - (PP_COORD_TYPE)af_measure(text_metrics.face, (const wchar_t *)text[j], &text_metrics).w + text_metrics.letter_spacing, + (PP_COORD_TYPE)af_measure(text_metrics.face, &text[j], &text_metrics).w + text_metrics.letter_spacing, (PP_COORD_TYPE)0 }; advance = pp_point_transform(&advance, t); @@ -137,5 +143,6 @@ namespace pimoroni { } return {caret.x, caret.y}; +*/ } } \ No newline at end of file diff --git a/libraries/pico_vector/pico_vector.hpp b/libraries/pico_vector/pico_vector.hpp index fd1532b0f..d5f442244 100644 --- a/libraries/pico_vector/pico_vector.hpp +++ b/libraries/pico_vector/pico_vector.hpp @@ -14,6 +14,8 @@ #define PP_REALLOC(p, size) af_realloc(p, size) #define PP_FREE(p) af_free(p) +#define AF_DEBUG(...) af_debug(__VA_ARGS__) + #include "pretty-poly.h" #include "alright-fonts.h" #include "pico_graphics.hpp" @@ -40,6 +42,15 @@ namespace pimoroni { pp_antialias(graphics->supports_alpha_blend() ? PP_AA_X4 : PP_AA_NONE); pp_clip(graphics->clip.x, graphics->clip.y, graphics->clip.w, graphics->clip.h); + + text_metrics.align = AF_H_ALIGN_LEFT; + text_metrics.line_height = 110; + text_metrics.letter_spacing = 95; + text_metrics.word_spacing = 200; + text_metrics.size = 48; + // Shoud be set before rendering chars + //text_metrics.transform = (pp_mat3_t *)af_malloc(sizeof(pp_mat3_t)); + //*text_metrics.transform = pp_mat3_identity(); } static void tile_callback(const pp_tile_t *tile) { @@ -86,17 +97,21 @@ namespace pimoroni { } bool set_font(std::string_view font_path, unsigned int font_size) { + if(text_metrics.face) { + af_free(text_metrics.face->glyphs); + af_free(text_metrics.face); + } + text_metrics.face = (af_face_t *)af_malloc(sizeof(af_face_t)); //bool result = text_metrics.face.load(font_path); void* font = fileio_open(font_path.data()); - af_load_font_file(font, text_metrics.face); - bool result = false; + bool result = af_load_font_file(font, text_metrics.face); set_font_size(font_size); return result; } - pp_point_t text(std::wstring_view text, pp_point_t origin, pp_mat3_t *t); + pp_point_t text(std::string_view text, pp_mat3_t *t); void transform(pp_path_t *path, pp_mat3_t *t); void transform(pp_poly_t *poly, pp_mat3_t *t); diff --git a/micropython/modules/picovector/picovector.cpp b/micropython/modules/picovector/picovector.cpp index d911fb6eb..08daca658 100644 --- a/micropython/modules/picovector/picovector.cpp +++ b/micropython/modules/picovector/picovector.cpp @@ -10,6 +10,7 @@ extern "C" { #include "py/stream.h" #include "py/reader.h" #include "extmod/vfs.h" +#include typedef struct _ModPicoGraphics_obj_t { mp_obj_base_t base; @@ -29,10 +30,31 @@ typedef struct _PATH_obj_t { pp_path_t path; } _PATH_obj_t; +void __printf_debug_flush() { + for(auto i = 0u; i < 10; i++) { + sleep_ms(1); + mp_event_handle_nowait(); + } +} + +int mp_vprintf(const mp_print_t *print, const char *fmt, va_list args); + +void af_debug(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int ret = mp_vprintf(&mp_plat_print, fmt, ap); + va_end(ap); + __printf_debug_flush(); + (void)ret; +} + void *af_malloc(size_t size) { - mp_printf(&mp_plat_print, "af_malloc %lu\n", size); - mp_event_handle_nowait(); - return m_tracked_calloc(sizeof(uint8_t), size); + //mp_printf(&mp_plat_print, "af_malloc %lu\n", size); + //__printf_debug_flush(); + void *addr = m_tracked_calloc(sizeof(uint8_t), size); + //mp_printf(&mp_plat_print, "addr %lu\n", addr); + //__printf_debug_flush(); + return addr; } void *af_realloc(void *p, size_t size) { @@ -40,16 +62,16 @@ void *af_realloc(void *p, size_t size) { } void af_free(void *p) { - mp_printf(&mp_plat_print, "af_free\n"); - mp_event_handle_nowait(); + //mp_printf(&mp_plat_print, "af_free\n"); + //__printf_debug_flush(); m_tracked_free(p); } void* fileio_open(const char *filename) { mp_obj_t fn = mp_obj_new_str(filename, (mp_uint_t)strlen(filename)); - mp_printf(&mp_plat_print, "Opening file %s\n", filename); - mp_event_handle_nowait(); + //mp_printf(&mp_plat_print, "Opening file %s\n", filename); + //__printf_debug_flush(); mp_obj_t args[2] = { fn, @@ -58,10 +80,10 @@ void* fileio_open(const char *filename) { // Stat the file to get its size // example tuple response: (32768, 0, 0, 0, 0, 0, 5153, 1654709815, 1654709815, 1654709815) - mp_obj_t stat = mp_vfs_stat(fn); - mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR2(stat, mp_obj_tuple_t); - int filesize = mp_obj_get_int(tuple->items[6]); - mp_printf(&mp_plat_print, "Size %lu\n", filesize); + //mp_obj_t stat = mp_vfs_stat(fn); + //mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR2(stat, mp_obj_tuple_t); + //int filesize = mp_obj_get_int(tuple->items[6]); + //mp_printf(&mp_plat_print, "Size %lu\n", filesize); mp_obj_t fhandle = mp_vfs_open(MP_ARRAY_SIZE(args), &args[0], (mp_map_t *)&mp_const_empty_map); @@ -73,14 +95,17 @@ void fileio_close(void* fhandle) { } size_t fileio_read(void* fhandle, void *buf, size_t len) { - mp_printf(&mp_plat_print, "Reading %lu bytes\n", len); + //mp_printf(&mp_plat_print, "Reading %lu bytes\n", len); + //__printf_debug_flush(); int error; return mp_stream_read_exactly((mp_obj_t)fhandle, buf, len, &error); } int fileio_getc(void* fhandle) { unsigned char buf; - fileio_read((mp_obj_t)fhandle, &buf, 1); + //mp_printf(&mp_plat_print, "Reading char\n"); + //__printf_debug_flush(); + fileio_read(fhandle, (void *)&buf, 1); return (int)buf; } @@ -410,7 +435,7 @@ mp_obj_t VECTOR_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) GET_STR_DATA_LEN(text_obj, str, str_len); - const std::wstring_view t((const wchar_t *)str, str_len); + const std::string_view t((const char *)str, str_len); int x = args[ARG_x].u_int; int y = args[ARG_y].u_int; @@ -423,7 +448,12 @@ mp_obj_t VECTOR_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) pp_mat3_rotate(&tt, mp_obj_get_float(args[ARG_angle].u_obj)); } - self->vector->text(t, {(float)x, (float)y}, &tt); + pp_mat3_translate(&tt, (float)x, (float)y); + + //mp_printf(&mp_plat_print, "self->vector->text()\n"); + //__printf_debug_flush(); + + self->vector->text(t, &tt); return mp_const_none; }