improve font drawing api
This commit is contained in:
+74
-74
@@ -150,19 +150,9 @@ void LCD_setCircle(int x0, int y0, int radius, enum Color bw, int lineThickness)
|
||||
}
|
||||
}
|
||||
|
||||
// This function will draw a char (defined in the ASCII table
|
||||
// near the beginning of this sketch) at a defined x and y).
|
||||
// The color can be either black (1) or white (0).
|
||||
void LCD_setChar(struct Utf8Char character, int x, int y, enum Color bw)
|
||||
{
|
||||
LCD_setCharEx(character, x, y, bw, 1);
|
||||
}
|
||||
|
||||
void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color bw, uint8_t style)
|
||||
static void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color color, struct TextStyle style)
|
||||
{
|
||||
const struct FontGraphic *symbol = Font_GetSymbol(character);
|
||||
bool bg = style & 0x80;
|
||||
enum FontStyle style_real = style & 0x7F;
|
||||
|
||||
uint8_t column; // temp byte to store character's column bitmap
|
||||
for (int i = 0; i < 5; i++) // 5 columns (x) per character
|
||||
@@ -172,36 +162,36 @@ void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color bw, uint8
|
||||
{
|
||||
bool bit = column & (1 << j);
|
||||
|
||||
if (style_real == FONT_NORMAL) {
|
||||
if (style.size == FONT_NORMAL) {
|
||||
if (bit) {// test bits to set pixels
|
||||
LCD_setPixel(x + i, y + j, bw);
|
||||
LCD_setPixel(x + i, y + j, color);
|
||||
}
|
||||
else if (bg) {
|
||||
LCD_setPixel(x + i, y + j, !bw);
|
||||
else if (style.bg) {
|
||||
LCD_setPixel(x + i, y + j, !color);
|
||||
}
|
||||
}
|
||||
else if (style_real == FONT_DOUBLE) {
|
||||
else if (style.size == FONT_DOUBLE) {
|
||||
if (bit) {// test bits to set pixels
|
||||
LCD_setPixel(x + i * 2, y + j * 2, bw);
|
||||
LCD_setPixel(x + i * 2 + 1, y + j * 2, bw);
|
||||
LCD_setPixel(x + i * 2, y + j * 2 + 1, bw);
|
||||
LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, bw);
|
||||
LCD_setPixel(x + i * 2, y + j * 2, color);
|
||||
LCD_setPixel(x + i * 2 + 1, y + j * 2, color);
|
||||
LCD_setPixel(x + i * 2, y + j * 2 + 1, color);
|
||||
LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, color);
|
||||
}
|
||||
else if (bg) {
|
||||
LCD_setPixel(x + i * 2, y + j * 2, !bw);
|
||||
LCD_setPixel(x + i * 2 + 1, y + j * 2, !bw);
|
||||
LCD_setPixel(x + i * 2, y + j * 2 + 1, !bw);
|
||||
LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, !bw);
|
||||
else if (style.bg) {
|
||||
LCD_setPixel(x + i * 2, y + j * 2, !color);
|
||||
LCD_setPixel(x + i * 2 + 1, y + j * 2, !color);
|
||||
LCD_setPixel(x + i * 2, y + j * 2 + 1, !color);
|
||||
LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, !color);
|
||||
}
|
||||
}
|
||||
else if (style_real == FONT_BOLD) {
|
||||
else if (style.size == FONT_BOLD) {
|
||||
if (bit) {// test bits to set pixels
|
||||
LCD_setPixel(x + i, y + j, bw);
|
||||
LCD_setPixel(x + i + 1, y + j, bw);
|
||||
LCD_setPixel(x + i, y + j, color);
|
||||
LCD_setPixel(x + i + 1, y + j, color);
|
||||
}
|
||||
else if (bg) {
|
||||
LCD_setPixel(x + i, y + j, !bw);
|
||||
LCD_setPixel(x + i + 1, y + j, !bw);
|
||||
else if (style.bg) {
|
||||
LCD_setPixel(x + i, y + j, !color);
|
||||
LCD_setPixel(x + i + 1, y + j, !color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,67 +204,77 @@ void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color bw, uint8
|
||||
// library.
|
||||
void LCD_setStr(const char *dString, int x, int y, enum Color bw)
|
||||
{
|
||||
LCD_setStrEx(dString, x, y, bw, 1);
|
||||
LCD_setStrEx(dString, x, y, bw, (struct TextStyle) {});
|
||||
}
|
||||
|
||||
static const int char_widths[] = {
|
||||
[FONT_NORMAL] = 5,
|
||||
[FONT_DOUBLE] = 10,
|
||||
[FONT_BOLD] = 6
|
||||
};
|
||||
|
||||
static const int char_spacings[] = {
|
||||
[FONT_NORMAL] = 1,
|
||||
[FONT_DOUBLE] = 2,
|
||||
[FONT_BOLD] = 1
|
||||
};
|
||||
|
||||
static const int char_heights[] = {
|
||||
[FONT_NORMAL] = 8,
|
||||
[FONT_DOUBLE] = 16,
|
||||
[FONT_BOLD] = 8
|
||||
};
|
||||
|
||||
// setStr draws a string of characters, calling setChar with
|
||||
// progressive coordinates until it's done.
|
||||
// This function was grabbed from the SparkFun ColorLCDShield
|
||||
// library.
|
||||
void LCD_setStrEx(const char *dString, int x, int y, enum Color bw, uint8_t style)
|
||||
// library. AND HEAVILY MODIFIED
|
||||
void LCD_setStrEx(const char *dString, int x, int y, enum Color color, struct TextStyle style)
|
||||
{
|
||||
const int x0 = x;
|
||||
struct Utf8Iterator iter;
|
||||
Utf8Iterator_Init(&iter, dString);
|
||||
bool bg = style & 0x80;
|
||||
enum FontStyle style_real = style & 0x7F;
|
||||
|
||||
int charw = char_widths[style.size];
|
||||
int charh = char_heights[style.size];
|
||||
|
||||
int spacingx = char_spacings[style.size] + style.spacing_x;
|
||||
int spacingy = style.spacing_y;
|
||||
|
||||
struct Utf8Char uchar;
|
||||
int limit = style.max_chars;
|
||||
while ((uchar = Utf8Iterator_Next(&iter)).uint) {
|
||||
LCD_setCharEx(uchar, x, y, bw, style);
|
||||
LCD_setCharEx(uchar, x, y, color, style);
|
||||
|
||||
if (style_real == FONT_NORMAL) {
|
||||
x += 5;
|
||||
if (bg) {
|
||||
for (int i = y; i < y + 8; i++) {
|
||||
LCD_setPixel(x, i, !bw);
|
||||
if (limit > 0) {
|
||||
limit -= 1;
|
||||
if (limit == 0) return;
|
||||
}
|
||||
|
||||
x += charw;
|
||||
|
||||
if (style.bg) {
|
||||
for (int i = y; i < y + charh; i++) {
|
||||
for (int j = x; j < x + spacingx; j++) {
|
||||
LCD_setPixel(j, i, !color);
|
||||
}
|
||||
}
|
||||
x++;
|
||||
if (x > (LCD_WIDTH - 5)) // Enables wrap around
|
||||
{
|
||||
x = 0;
|
||||
y += 8;
|
||||
}
|
||||
}
|
||||
else if (style_real == FONT_DOUBLE) {
|
||||
x += 10;
|
||||
if (bg) {
|
||||
for (int i = y; i < y + 16; i++) {
|
||||
LCD_setPixel(x, i, !bw);
|
||||
LCD_setPixel(x + 1, i, !bw);
|
||||
}
|
||||
}
|
||||
x += 2;
|
||||
if (x > (LCD_WIDTH - 10)) // Enables wrap around
|
||||
{
|
||||
|
||||
x += spacingx;
|
||||
if (x > (LCD_WIDTH - charw)) {
|
||||
if (style.nowrap) break;
|
||||
if (style.wrap_to_0) {
|
||||
x = 0;
|
||||
y += 16;
|
||||
} else {
|
||||
x = x0;
|
||||
}
|
||||
y += charh + spacingy;
|
||||
}
|
||||
else if (style_real == FONT_BOLD) {
|
||||
x += 6;
|
||||
if (bg) {
|
||||
for (int i = y; i < y + 8; i++) {
|
||||
LCD_setPixel(x, i, !bw);
|
||||
LCD_setPixel(x + 1, i, !bw);
|
||||
}
|
||||
}
|
||||
x += 1;
|
||||
if (x > (LCD_WIDTH - 6)) // Enables wrap around
|
||||
{
|
||||
x = 0;
|
||||
y += 8;
|
||||
}
|
||||
|
||||
// no more characters could be seen
|
||||
if (y >= LCD_HEIGHT) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-12
@@ -44,19 +44,21 @@ void LCD_setBitmap(const uint8_t *bitArray);
|
||||
size | 0x80 ... clear background behind characters
|
||||
*/
|
||||
|
||||
enum FontStyle {
|
||||
FONT_NORMAL = 1,
|
||||
FONT_DOUBLE = 2,
|
||||
FONT_BOLD = 3,
|
||||
FONT_BG = 0x80,
|
||||
enum TextSize {
|
||||
FONT_NORMAL = 0,
|
||||
FONT_DOUBLE = 1,
|
||||
FONT_BOLD = 2,
|
||||
};
|
||||
|
||||
// This function will draw a char (defined in the ASCII table
|
||||
// near the beginning of this sketch) at a defined x and y).
|
||||
// The color can be either black (1) or white (0).
|
||||
void LCD_setChar(struct Utf8Char character, int x, int y, enum Color bw);
|
||||
|
||||
void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color bw, uint8_t style);
|
||||
struct TextStyle {
|
||||
bool bg; //!< Fill the characters background with the opposite color
|
||||
enum TextSize size; //!< Character size
|
||||
int max_chars; //!< Number of characters to print from the string, if > 0
|
||||
int spacing_x; //!< Additional X spacing
|
||||
int spacing_y; //!< Additional Y spacing
|
||||
bool nowrap; //!< Stop painting when the right edge of the screen is reached
|
||||
bool wrap_to_0; //!< wrap to 0 instead of the initial X coordinate
|
||||
};
|
||||
|
||||
// setStr draws a string of characters, calling setChar with
|
||||
// progressive coordinates until it's done.
|
||||
@@ -64,7 +66,7 @@ void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color bw, uint8
|
||||
// library.
|
||||
void LCD_setStr(const char * dString, int x, int y, enum Color bw);
|
||||
|
||||
void LCD_setStrEx(const char *dString, int x, int y, enum Color bw, uint8_t style);
|
||||
void LCD_setStrEx(const char *dString, int x, int y, enum Color color, struct TextStyle style);
|
||||
|
||||
// This function clears the entire display either white (0) or
|
||||
// black (1).
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ static TimerHandle_t hTicker = NULL;
|
||||
void gui_init() {
|
||||
printf("GUI init\n");
|
||||
LCD_setup();
|
||||
LCD_setContrast(48);
|
||||
LCD_setContrast(57);
|
||||
|
||||
int rv = xTaskCreate(gui_thread, "gui", 4096, NULL, 6, &hGuiThread);
|
||||
assert (rv == pdPASS);
|
||||
|
||||
@@ -70,16 +70,16 @@ static void paint(struct DemoScene *self)
|
||||
break;
|
||||
}
|
||||
|
||||
LCD_setStrEx(header, 0, 3, 1, 3);
|
||||
LCD_setStrEx(header, 3, 1, BLACK, (struct TextStyle) {.size = FONT_BOLD});
|
||||
|
||||
LCD_setRect(0, 12, 83, 31, 1, 1);
|
||||
LCD_setRect(0, 12, 83, 31, true, BLACK);
|
||||
char buf[10];
|
||||
// sprintf(buf, "%3d", priv->pos);
|
||||
// LCD_setStr(buf, 2, 15, 0);
|
||||
sprintf(buf, "🌡%.0f°C", analog_read());
|
||||
LCD_setStrEx(buf, 2, 14, 0, 2);
|
||||
LCD_setStrEx(buf, 2, 14, WHITE, (struct TextStyle) {.size = FONT_DOUBLE});
|
||||
|
||||
LCD_setStr("×↑↓←→⏰⌛☸⏎🌡°🔙▶◀", 2, 33, 1);
|
||||
LCD_setStr("×↑↓←→⏰⌛☸⏎🌡°🔙▶◀", 2, 33, BLACK);
|
||||
}
|
||||
|
||||
struct Scene *NewScene_Demo(void) {
|
||||
|
||||
@@ -6,17 +6,35 @@
|
||||
|
||||
#include "liquid.h"
|
||||
#include "graphics/drawing.h"
|
||||
#include "graphics/display_spec.h"
|
||||
|
||||
#include "scene_menu.h"
|
||||
|
||||
#if 0
|
||||
static void paint(struct MenuScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
|
||||
int row = 0;
|
||||
for (int i = self->scroll_up; i < MIN(self->items_len, self->scroll_up + self->visible_lines); i++, row++) {
|
||||
bool selected = self->selected==i;
|
||||
LCD_setStrEx(self->items[i].label, 0, row * 8, selected?WHITE:BLACK,FONT_NORMAL|(selected?FONT_BG:0));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void paint(struct MenuScene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
|
||||
int row = 0;
|
||||
for (int i = self->scroll_up; i < MIN(self->items_len, self->scroll_up + 6); i++, row++) {
|
||||
for (int i = self->scroll_up; i < MIN(self->items_len, self->scroll_up + self->visible_lines); i++, row++) {
|
||||
bool selected = self->selected==i;
|
||||
LCD_setStrEx(self->items[i].label, 0, row * 8, selected?WHITE:BLACK,FONT_NORMAL|(selected?FONT_BG:0));
|
||||
if (selected) LCD_setRect(0, row*9, LCD_WIDTH-1, row*9 + 8, 1, 1);
|
||||
LCD_setStrEx(self->items[i].label, 1, row * 9 + 1, !selected, (struct TextStyle) {
|
||||
.bg = selected,
|
||||
.max_chars = 13,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +54,7 @@ static struct SceneEvent onInput(struct MenuScene *self, struct InputEvent event
|
||||
self->scroll_up--;
|
||||
}
|
||||
|
||||
while (self->selected - self->scroll_up >= 5 && self->scroll_up < self->items_len - 6) {
|
||||
while (self->selected - self->scroll_up >= (self->visible_lines - 1) && self->scroll_up < self->items_len - self->visible_lines) {
|
||||
self->scroll_up++;
|
||||
}
|
||||
|
||||
@@ -77,6 +95,7 @@ struct MenuScene *NewScene_Menu(struct MenuItem *items, size_t items_len) {
|
||||
|
||||
// TODO long selected label scrolling on tick
|
||||
|
||||
scene->visible_lines = 5;
|
||||
scene->items = items;
|
||||
scene->items_len = items_len;
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ struct MenuScene {
|
||||
int32_t scroll_up;
|
||||
// Selected item number
|
||||
int32_t selected;
|
||||
// Number of lines visible at a time
|
||||
uint8_t visible_lines;
|
||||
// selection handler
|
||||
MenuScene_onSelect_t onSelect;
|
||||
// Extra field for the subclass's private use.
|
||||
|
||||
@@ -40,11 +40,11 @@ static void paint(struct NumberScene *self)
|
||||
struct NumberSceneOpts *opts = self->opts;
|
||||
|
||||
LCD_clearDisplay(0);
|
||||
LCD_setStrEx(opts->label, 1, 1, BLACK, FONT_BOLD);
|
||||
LCD_setStrEx(opts->label, 1, 1, BLACK, (struct TextStyle) {.size = FONT_BOLD});
|
||||
|
||||
char buf[10];
|
||||
snprintf(buf, 10, "%d%s", opts->value, opts->unit);
|
||||
LCD_setStrEx(buf, 1, 9, BLACK, FONT_DOUBLE);
|
||||
LCD_setStrEx(buf, 1, 9, BLACK, (struct TextStyle) {.size = FONT_DOUBLE});
|
||||
}
|
||||
|
||||
static void deinit(struct NumberScene *self)
|
||||
|
||||
@@ -35,7 +35,7 @@ static void paint(struct Scene *self)
|
||||
{
|
||||
LCD_clearDisplay(0);
|
||||
|
||||
LCD_setStrEx("Press DEL to enter setup", 0, 0, 1, 0x3);
|
||||
LCD_setStrEx("Press DEL to enter setup", 0, 0, BLACK, (struct TextStyle) {.size = FONT_BOLD});
|
||||
}
|
||||
|
||||
struct Scene *NewScene_Root(void) {
|
||||
|
||||
Reference in New Issue
Block a user