From b13470b4fbc3de2b41cb996067eb7d011f66d9c7 Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Tue, 7 Jun 2022 20:19:16 +0100 Subject: [PATCH] PicoGraphics: Add set_palette and set_font. --- libraries/pico_graphics/pico_graphics.cpp | 10 ++++ libraries/pico_graphics/pico_graphics.hpp | 47 ++++++++++------ .../modules/picographics/picographics.c | 21 +++++--- .../modules/picographics/picographics.cpp | 54 +++++++++++++++++++ .../modules/picographics/picographics.h | 2 + 5 files changed, 109 insertions(+), 25 deletions(-) diff --git a/libraries/pico_graphics/pico_graphics.cpp b/libraries/pico_graphics/pico_graphics.cpp index 6b38fe08..ca4bf156 100644 --- a/libraries/pico_graphics/pico_graphics.cpp +++ b/libraries/pico_graphics/pico_graphics.cpp @@ -29,6 +29,16 @@ namespace pimoroni { this->font = font; } + void PicoGraphics::set_font(std::string font){ + if (font == "bitmap6") { + this->font = &font6; + } else if (font == "bitmap8") { + this->font = &font8; + } else if (font == "bitmap14_outline") { + this->font = &font14_outline; + } + } + void PicoGraphics::set_clip(const Rect &r) { clip = bounds.intersection(r); } diff --git a/libraries/pico_graphics/pico_graphics.hpp b/libraries/pico_graphics/pico_graphics.hpp index 954d7733..965ce77e 100644 --- a/libraries/pico_graphics/pico_graphics.hpp +++ b/libraries/pico_graphics/pico_graphics.hpp @@ -5,6 +5,8 @@ #include #include #include "libraries/bitmap_fonts/font6_data.hpp" +#include "libraries/bitmap_fonts/font8_data.hpp" +#include "libraries/bitmap_fonts/font14_outline_data.hpp" #include "common/pimoroni_common.hpp" // A tiny graphics library for our Pico products @@ -105,6 +107,7 @@ namespace pimoroni { virtual void palette_lookup(void *frame_buffer, void *result, uint offset, uint length); void set_font(const bitmap::font_t *font); + void set_font(std::string font); void set_dimensions(int width, int height); @@ -132,20 +135,26 @@ namespace pimoroni { public: uint8_t color; PaletteEntry palette[8]; + const RGB565 default_palette[8] = { + rgb_to_rgb565(57, 48, 57), // Black + rgb_to_rgb565(255, 255, 255), // White + rgb_to_rgb565(58, 91, 70), // Green + rgb_to_rgb565(61, 59, 94), // Blue + rgb_to_rgb565(156, 72, 75), // Red + rgb_to_rgb565(208, 190, 71), // Yellow + rgb_to_rgb565(177, 106, 73), // Orange + rgb_to_rgb565(255, 255, 255) // Clear + }; PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer) : PicoGraphics(width, height, frame_buffer) { this->pen_type = PEN_P4; if(this->frame_buffer == nullptr) { this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); } - palette[0].color = rgb_to_rgb565(57, 48, 57); // Black - palette[1].color = rgb_to_rgb565(255, 255, 255); // White - palette[2].color = rgb_to_rgb565(58, 91, 70); // Green - palette[3].color = rgb_to_rgb565(61, 59, 94); // Blue - palette[4].color = rgb_to_rgb565(156, 72, 75); // Red - palette[5].color = rgb_to_rgb565(208, 190, 71); // Yellow - palette[6].color = rgb_to_rgb565(177, 106, 73); // Orange - palette[7].color = rgb_to_rgb565(255, 255, 255); // Clear + for(auto i = 0u; i < 8; i++) { + palette[i].color = default_palette[i]; + palette[i].used = true; + } } void set_pen(uint c) { color = c & 0xf; @@ -153,6 +162,15 @@ namespace pimoroni { void set_pen(uint8_t r, uint8_t g, uint8_t b) override { // TODO look up closest palette colour, or just NOOP? } + void update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override { + i &= 0xf; + palette[i].color = rgb_to_rgb565(r, g, b); + palette[i].used = true; + } + void reset_pen(uint8_t i) override { + i &= 0xf; + palette[i].color = default_palette[i]; + } void set_pixel(void *frame_buffer, uint x, uint y, uint stride) override { // pointer to byte in framebuffer that contains this pixel uint8_t *buf = (uint8_t *)frame_buffer; @@ -201,10 +219,12 @@ namespace pimoroni { // TODO look up closest palette colour, or just NOOP? } void update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override { + i &= 0xff; palette[i].color = rgb_to_rgb565(r, g, b); palette[i].used = true; } void reset_pen(uint8_t i) override { + i &= 0xff; palette[i].color = 0; palette[i].used = false; } @@ -247,7 +267,8 @@ namespace pimoroni { this->frame_buffer = (void *)(new uint8_t[buffer_size(width, height)]); } for(auto i = 0u; i < 256; i++) { - reset_pen(i); + palette[i].color = rgb332_to_rgb565(i); + palette[i].used = true; } } void set_pen(uint c) override { @@ -256,14 +277,6 @@ namespace pimoroni { void set_pen(uint8_t r, uint8_t g, uint8_t b) override { color = rgb_to_rgb332(r, g, b); } - void update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override { - palette[i].color = rgb_to_rgb565(r, g, b); - palette[i].used = true; - } - void reset_pen(uint8_t i) override { - palette[i].color = rgb332_to_rgb565(i); - palette[i].used = true; - } int create_pen(uint8_t r, uint8_t g, uint8_t b) override { return rgb_to_rgb332(r, g, b); } diff --git a/micropython/modules/picographics/picographics.c b/micropython/modules/picographics/picographics.c index 11b6a31d..523ac5e7 100644 --- a/micropython/modules/picographics/picographics.c +++ b/micropython/modules/picographics/picographics.c @@ -7,11 +7,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_3(ModPicoGraphics_module_RGB565_obj, ModPicoGraph // Class Methods MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics_update_obj, ModPicoGraphics_update); MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_backlight_obj, ModPicoGraphics_set_backlight); -MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_framebuffer_obj, ModPicoGraphics_set_framebuffer); // Palette management MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_update_pen_obj, 5, 5, ModPicoGraphics_update_pen); MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_reset_pen_obj, ModPicoGraphics_reset_pen); +MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_set_palette_obj, 2, ModPicoGraphics_set_palette); // Pen MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_pen_obj, ModPicoGraphics_set_pen); @@ -34,20 +34,17 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_line_obj, 5, 5, ModPicoGraph // Utility MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics_get_bounds_obj, ModPicoGraphics_get_bounds); +MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_font_obj, ModPicoGraphics_set_font); +MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_framebuffer_obj, ModPicoGraphics_set_framebuffer); STATIC const mp_rom_map_elem_t ModPicoGraphics_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&ModPicoGraphics_pixel_obj) }, { MP_ROM_QSTR(MP_QSTR_set_pen), MP_ROM_PTR(&ModPicoGraphics_set_pen_obj) }, + { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&ModPicoGraphics_clear_obj) }, + { MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&ModPicoGraphics_update_obj) }, - - { MP_ROM_QSTR(MP_QSTR_update_pen), MP_ROM_PTR(&ModPicoGraphics_update_pen_obj) }, - { MP_ROM_QSTR(MP_QSTR_reset_pen), MP_ROM_PTR(&ModPicoGraphics_reset_pen_obj) }, - - { MP_ROM_QSTR(MP_QSTR_set_backlight), MP_ROM_PTR(&ModPicoGraphics_set_backlight_obj) }, - { MP_ROM_QSTR(MP_QSTR_create_pen), MP_ROM_PTR(&ModPicoGraphics_create_pen_obj) }, { MP_ROM_QSTR(MP_QSTR_set_clip), MP_ROM_PTR(&ModPicoGraphics_set_clip_obj) }, { MP_ROM_QSTR(MP_QSTR_remove_clip), MP_ROM_PTR(&ModPicoGraphics_remove_clip_obj) }, - { MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&ModPicoGraphics_clear_obj) }, { MP_ROM_QSTR(MP_QSTR_pixel_span), MP_ROM_PTR(&ModPicoGraphics_pixel_span_obj) }, { MP_ROM_QSTR(MP_QSTR_rectangle), MP_ROM_PTR(&ModPicoGraphics_rectangle_obj) }, { MP_ROM_QSTR(MP_QSTR_circle), MP_ROM_PTR(&ModPicoGraphics_circle_obj) }, @@ -58,7 +55,15 @@ STATIC const mp_rom_map_elem_t ModPicoGraphics_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_triangle), MP_ROM_PTR(&ModPicoGraphics_triangle_obj) }, { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&ModPicoGraphics_line_obj) }, + { MP_ROM_QSTR(MP_QSTR_create_pen), MP_ROM_PTR(&ModPicoGraphics_create_pen_obj) }, + { MP_ROM_QSTR(MP_QSTR_update_pen), MP_ROM_PTR(&ModPicoGraphics_update_pen_obj) }, + { MP_ROM_QSTR(MP_QSTR_reset_pen), MP_ROM_PTR(&ModPicoGraphics_reset_pen_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_palette), MP_ROM_PTR(&ModPicoGraphics_set_palette_obj) }, + + { MP_ROM_QSTR(MP_QSTR_set_backlight), MP_ROM_PTR(&ModPicoGraphics_set_backlight_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_bounds), MP_ROM_PTR(&ModPicoGraphics_get_bounds_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_font), MP_ROM_PTR(&ModPicoGraphics_set_font_obj) }, { MP_ROM_QSTR(MP_QSTR_set_framebuffer), MP_ROM_PTR(&ModPicoGraphics_set_framebuffer_obj) }, }; STATIC MP_DEFINE_CONST_DICT(ModPicoGraphics_locals_dict, ModPicoGraphics_locals_dict_table); diff --git a/micropython/modules/picographics/picographics.cpp b/micropython/modules/picographics/picographics.cpp index 329f2977..0bf41566 100644 --- a/micropython/modules/picographics/picographics.cpp +++ b/micropython/modules/picographics/picographics.cpp @@ -12,6 +12,14 @@ extern "C" { #include "picographics.h" #include "micropython/modules/pimoroni_bus/pimoroni_bus.h" +std::string mp_obj_to_string_r(const mp_obj_t &obj) { + if(mp_obj_is_str_or_bytes(obj)) { + GET_STR_DATA_LEN(obj, str, str_len); + return (const char*)str; + } + mp_raise_TypeError("can't convert object to str implicitly"); +} + typedef struct _ModPicoGraphics_obj_t { mp_obj_base_t base; PicoGraphics *graphics; @@ -166,6 +174,12 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size return MP_OBJ_FROM_PTR(self); } +mp_obj_t ModPicoGraphics_set_font(mp_obj_t self_in, mp_obj_t font) { + ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t); + self->graphics->set_font(mp_obj_to_string_r(font)); + return mp_const_none; +} + mp_obj_t ModPicoGraphics_set_framebuffer(mp_obj_t self_in, mp_obj_t framebuffer) { (void)self_in; (void)framebuffer; @@ -277,6 +291,46 @@ mp_obj_t ModPicoGraphics_create_pen(size_t n_args, const mp_obj_t *args) { return mp_obj_new_int(result); } +mp_obj_t ModPicoGraphics_set_palette(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + size_t num_tuples = n_args - 1; + const mp_obj_t *tuples = pos_args + 1; + + ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(pos_args[0], ModPicoGraphics_obj_t); + + // Check if there is only one argument, which might be a list + if(n_args == 2) { + if(mp_obj_is_type(pos_args[1], &mp_type_list)) { + mp_obj_list_t *points = MP_OBJ_TO_PTR2(pos_args[1], mp_obj_list_t); + + if(points->len <= 0) mp_raise_ValueError("set_palette(): cannot provide an empty list"); + + num_tuples = points->len; + tuples = points->items; + } + else { + mp_raise_TypeError("set_palette(): can't convert object to list"); + } + } + + for(size_t i = 0; i < num_tuples; i++) { + mp_obj_t obj = tuples[i]; + if(!mp_obj_is_type(obj, &mp_type_tuple)) mp_raise_ValueError("set_palette(): can't convert object to tuple"); + + mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR2(obj, mp_obj_tuple_t); + + if(tuple->len != 3) mp_raise_ValueError("set_palette(): tuple must contain R, G, B values"); + + self->graphics->update_pen( + i, + mp_obj_get_int(tuple->items[0]), + mp_obj_get_int(tuple->items[1]), + mp_obj_get_int(tuple->items[2]) + ); + } + + return mp_const_none; +} + mp_obj_t ModPicoGraphics_set_clip(size_t n_args, const mp_obj_t *args) { enum { ARG_self, ARG_x, ARG_y, ARG_w, ARG_h }; diff --git a/micropython/modules/picographics/picographics.h b/micropython/modules/picographics/picographics.h index c6e55ee0..066e5126 100644 --- a/micropython/modules/picographics/picographics.h +++ b/micropython/modules/picographics/picographics.h @@ -36,6 +36,7 @@ extern mp_obj_t ModPicoGraphics_set_backlight(mp_obj_t self_in, mp_obj_t brightn // Palette management extern mp_obj_t ModPicoGraphics_update_pen(size_t n_args, const mp_obj_t *args); extern mp_obj_t ModPicoGraphics_reset_pen(mp_obj_t self_in, mp_obj_t pen); +extern mp_obj_t ModPicoGraphics_set_palette(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args); // Pen extern mp_obj_t ModPicoGraphics_set_pen(mp_obj_t self_in, mp_obj_t pen); @@ -57,5 +58,6 @@ extern mp_obj_t ModPicoGraphics_triangle(size_t n_args, const mp_obj_t *args); extern mp_obj_t ModPicoGraphics_line(size_t n_args, const mp_obj_t *args); // Utility +extern mp_obj_t ModPicoGraphics_set_font(mp_obj_t self_in, mp_obj_t font); extern mp_obj_t ModPicoGraphics_get_bounds(mp_obj_t self_in); extern mp_obj_t ModPicoGraphics_set_framebuffer(mp_obj_t self_in, mp_obj_t framebuffer); \ No newline at end of file