PicoGraphics: Extremely cursed thickness support for 1bit pens.

Experimental. There must be less cursed way to do this.
This commit is contained in:
Phil Howard 2023-01-24 21:10:43 +00:00
parent 6e44434e7d
commit c3ad87765d
7 changed files with 79 additions and 3 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) },

View File

@ -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;

View File

@ -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);