diff --git a/libraries/pico_graphics/pico_graphics.cpp b/libraries/pico_graphics/pico_graphics.cpp index 1ace1d3f..df3a9175 100644 --- a/libraries/pico_graphics/pico_graphics.cpp +++ b/libraries/pico_graphics/pico_graphics.cpp @@ -164,9 +164,15 @@ namespace pimoroni { } if (hershey_font) { - hershey::text(hershey_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { - line(Point(x1, y1), Point(x2, y2)); - }, t, p.x, p.y, s, a); + if(thickness == 1) { + hershey::text(hershey_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { + line(Point(x1, y1), Point(x2, y2)); + }, t, p.x, p.y, s, a); + } else { + hershey::text(hershey_font, [this](int32_t x1, int32_t y1, int32_t x2, int32_t y2) { + thicc_line(Point(x1, y1), Point(x2, y2), thickness); + }, t, p.x, p.y, s, a); + } return; } } @@ -292,6 +298,42 @@ namespace pimoroni { } } + void PicoGraphics::thicc_line(Point p1, Point p2, uint thickness) { + // general purpose line + // lines are either "shallow" or "steep" based on whether the x delta + // is greater than the y delta + int32_t dx = p2.x - p1.x; + int32_t dy = p2.y - p1.y; + bool shallow = std::abs(dx) > std::abs(dy); + if(shallow) { + // shallow version + int32_t s = std::abs(dx); // number of steps + int32_t sx = dx < 0 ? -1 : 1; // x step value + int32_t sy = (dy << 16) / s; // y step value in fixed 16:16 + int32_t x = p1.x; + int32_t y = p1.y << 16; + while(s--) { + int32_t ht = thickness / 2; + rectangle({x - ht, (y >> 16) - ht, ht * 2, ht * 2}); + y += sy; + x += sx; + } + }else{ + // steep version + int32_t s = std::abs(dy); // number of steps + int32_t sy = dy < 0 ? -1 : 1; // y step value + int32_t sx = (dx << 16) / s; // x step value in fixed 16:16 + int32_t y = p1.y; + int32_t x = p1.x << 16; + while(s--) { + int32_t ht = thickness / 2; + rectangle({(x >> 16) - ht, y - ht, ht * 2, ht * 2}); + y += sy; + x += sx; + } + } + } + void PicoGraphics::line(Point p1, Point p2) { // fast horizontal line if(p1.y == p2.y) { diff --git a/libraries/pico_graphics/pico_graphics.hpp b/libraries/pico_graphics/pico_graphics.hpp index d9f421ca..8e6a0df8 100644 --- a/libraries/pico_graphics/pico_graphics.hpp +++ b/libraries/pico_graphics/pico_graphics.hpp @@ -175,6 +175,7 @@ namespace pimoroni { PenType pen_type; Rect bounds; Rect clip; + uint thickness = 1; @@ -228,6 +229,7 @@ namespace pimoroni { virtual void set_pen(uint8_t r, uint8_t g, uint8_t b) = 0; virtual void set_pixel(const Point &p) = 0; virtual void set_pixel_span(const Point &p, uint l) = 0; + virtual void set_thickness(uint t) = 0; virtual int create_pen(uint8_t r, uint8_t g, uint8_t b); virtual int create_pen_hsv(float h, float s, float v); @@ -264,6 +266,7 @@ namespace pimoroni { void triangle(Point p1, Point p2, Point p3); void line(Point p1, Point p2); void from_hsv(float h, float s, float v, uint8_t &r, uint8_t &g, uint8_t &b); + void thicc_line(Point p1, Point p2, uint thickness); protected: void frame_convert_rgb565(conversion_callback_func callback, next_pixel_func get_next_pixel); @@ -276,6 +279,7 @@ namespace pimoroni { PicoGraphics_Pen1Bit(uint16_t width, uint16_t height, void *frame_buffer); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; + void set_thickness(uint t) override; void set_pixel(const Point &p) override; void set_pixel_span(const Point &p, uint l) override; @@ -292,6 +296,7 @@ namespace pimoroni { PicoGraphics_Pen1BitY(uint16_t width, uint16_t height, void *frame_buffer); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; + void set_thickness(uint t) override; void set_pixel(const Point &p) override; void set_pixel_span(const Point &p, uint l) override; @@ -334,6 +339,7 @@ namespace pimoroni { void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; + void set_thickness(uint t) override {}; void set_pixel(const Point &p) override; void set_pixel_span(const Point &p, uint l) override; @@ -360,6 +366,7 @@ namespace pimoroni { PicoGraphics_PenP4(uint16_t width, uint16_t height, void *frame_buffer); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; + void set_thickness(uint t) override {}; int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; int reset_pen(uint8_t i) override; @@ -389,6 +396,7 @@ namespace pimoroni { PicoGraphics_PenP8(uint16_t width, uint16_t height, void *frame_buffer); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; + void set_thickness(uint t) override {}; int update_pen(uint8_t i, uint8_t r, uint8_t g, uint8_t b) override; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; int reset_pen(uint8_t i) override; @@ -410,6 +418,7 @@ namespace pimoroni { PicoGraphics_PenRGB332(uint16_t width, uint16_t height, void *frame_buffer); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; + void set_thickness(uint t) override {}; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; void set_pixel(const Point &p) override; void set_pixel_span(const Point &p, uint l) override; @@ -431,6 +440,7 @@ namespace pimoroni { PicoGraphics_PenRGB565(uint16_t width, uint16_t height, void *frame_buffer); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; + void set_thickness(uint t) override {}; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; int create_pen_hsv(float h, float s, float v) override; void set_pixel(const Point &p) override; @@ -447,6 +457,7 @@ namespace pimoroni { PicoGraphics_PenRGB888(uint16_t width, uint16_t height, void *frame_buffer); void set_pen(uint c) override; void set_pen(uint8_t r, uint8_t g, uint8_t b) override; + void set_thickness(uint t) override {}; int create_pen(uint8_t r, uint8_t g, uint8_t b) override; int create_pen_hsv(float h, float s, float v) override; void set_pixel(const Point &p) override; diff --git a/libraries/pico_graphics/pico_graphics_pen_1bit.cpp b/libraries/pico_graphics/pico_graphics_pen_1bit.cpp index 30fb1e53..59f2a4af 100644 --- a/libraries/pico_graphics/pico_graphics_pen_1bit.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_1bit.cpp @@ -18,6 +18,10 @@ namespace pimoroni { color = std::max(r, std::max(g, b)) >> 4; } + void PicoGraphics_Pen1Bit::set_thickness(uint t) { + thickness = t; + } + void PicoGraphics_Pen1Bit::set_pixel(const Point &p) { // pointer to byte in framebuffer that contains this pixel uint8_t *buf = (uint8_t *)frame_buffer; diff --git a/libraries/pico_graphics/pico_graphics_pen_1bitY.cpp b/libraries/pico_graphics/pico_graphics_pen_1bitY.cpp index ea4afe99..b391022d 100644 --- a/libraries/pico_graphics/pico_graphics_pen_1bitY.cpp +++ b/libraries/pico_graphics/pico_graphics_pen_1bitY.cpp @@ -18,6 +18,10 @@ namespace pimoroni { color = std::max(r, std::max(g, b)); } + void PicoGraphics_Pen1BitY::set_thickness(uint t) { + thickness = t; + } + void PicoGraphics_Pen1BitY::set_pixel(const Point &p) { // pointer to byte in framebuffer that contains this pixel uint8_t *buf = (uint8_t *)frame_buffer; diff --git a/micropython/modules/picographics/picographics.c b/micropython/modules/picographics/picographics.c index bf01cdc5..6d801fb6 100644 --- a/micropython/modules/picographics/picographics.c +++ b/micropython/modules/picographics/picographics.c @@ -22,6 +22,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(ModPicoGraphics_set_palette_obj, 2, ModPicoGraphics_s MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_pen_obj, ModPicoGraphics_set_pen); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_create_pen_obj, 4, 4, ModPicoGraphics_create_pen); MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_create_pen_hsv_obj, 4, 4, ModPicoGraphics_create_pen_hsv); +MP_DEFINE_CONST_FUN_OBJ_2(ModPicoGraphics_set_thickness_obj, ModPicoGraphics_set_thickness); // Primitives MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(ModPicoGraphics_set_clip_obj, 5, 5, ModPicoGraphics_set_clip); @@ -56,6 +57,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(ModPicoGraphics__del__obj, ModPicoGraphics__del__); 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_set_thickness), MP_ROM_PTR(&ModPicoGraphics_set_thickness_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) }, diff --git a/micropython/modules/picographics/picographics.cpp b/micropython/modules/picographics/picographics.cpp index 20487930..b394bcaf 100644 --- a/micropython/modules/picographics/picographics.cpp +++ b/micropython/modules/picographics/picographics.cpp @@ -711,6 +711,18 @@ mp_obj_t ModPicoGraphics_create_pen_hsv(size_t n_args, const mp_obj_t *args) { return mp_obj_new_int(result); } +mp_obj_t ModPicoGraphics_set_thickness(mp_obj_t self_in, mp_obj_t pen) { + ModPicoGraphics_obj_t *self = MP_OBJ_TO_PTR2(self_in, ModPicoGraphics_obj_t); + + if(self->graphics->pen_type != PicoGraphics::PEN_1BIT) { + mp_raise_msg(&mp_type_RuntimeError, MP_ERROR_TEXT("Thickness not supported!")); + } + + self->graphics->set_thickness(mp_obj_get_int(pen)); + + return mp_const_none; +} + 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; diff --git a/micropython/modules/picographics/picographics.h b/micropython/modules/picographics/picographics.h index e46ba904..d07ad4fd 100644 --- a/micropython/modules/picographics/picographics.h +++ b/micropython/modules/picographics/picographics.h @@ -72,6 +72,7 @@ extern mp_obj_t ModPicoGraphics_hsv_to_rgb(size_t n_args, const mp_obj_t *args); extern mp_obj_t ModPicoGraphics_set_pen(mp_obj_t self_in, mp_obj_t pen); extern mp_obj_t ModPicoGraphics_create_pen(size_t n_args, const mp_obj_t *args); extern mp_obj_t ModPicoGraphics_create_pen_hsv(size_t n_args, const mp_obj_t *args); +extern mp_obj_t ModPicoGraphics_set_thickness(mp_obj_t self_in, mp_obj_t thickness); // Primitives extern mp_obj_t ModPicoGraphics_set_clip(size_t n_args, const mp_obj_t *args);