improve font drawing api
This commit is contained in:
+75
-75
@@ -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
|
static void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color color, struct TextStyle style)
|
||||||
// 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)
|
|
||||||
{
|
{
|
||||||
const struct FontGraphic *symbol = Font_GetSymbol(character);
|
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
|
uint8_t column; // temp byte to store character's column bitmap
|
||||||
for (int i = 0; i < 5; i++) // 5 columns (x) per character
|
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);
|
bool bit = column & (1 << j);
|
||||||
|
|
||||||
if (style_real == FONT_NORMAL) {
|
if (style.size == FONT_NORMAL) {
|
||||||
if (bit) {// test bits to set pixels
|
if (bit) {// test bits to set pixels
|
||||||
LCD_setPixel(x + i, y + j, bw);
|
LCD_setPixel(x + i, y + j, color);
|
||||||
}
|
}
|
||||||
else if (bg) {
|
else if (style.bg) {
|
||||||
LCD_setPixel(x + i, y + j, !bw);
|
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
|
if (bit) {// test bits to set pixels
|
||||||
LCD_setPixel(x + i * 2, y + j * 2, bw);
|
LCD_setPixel(x + i * 2, y + j * 2, color);
|
||||||
LCD_setPixel(x + i * 2 + 1, y + j * 2, bw);
|
LCD_setPixel(x + i * 2 + 1, y + j * 2, color);
|
||||||
LCD_setPixel(x + i * 2, y + j * 2 + 1, bw);
|
LCD_setPixel(x + i * 2, y + j * 2 + 1, color);
|
||||||
LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, bw);
|
LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, color);
|
||||||
}
|
}
|
||||||
else if (bg) {
|
else if (style.bg) {
|
||||||
LCD_setPixel(x + i * 2, y + j * 2, !bw);
|
LCD_setPixel(x + i * 2, y + j * 2, !color);
|
||||||
LCD_setPixel(x + i * 2 + 1, y + j * 2, !bw);
|
LCD_setPixel(x + i * 2 + 1, y + j * 2, !color);
|
||||||
LCD_setPixel(x + i * 2, y + j * 2 + 1, !bw);
|
LCD_setPixel(x + i * 2, y + j * 2 + 1, !color);
|
||||||
LCD_setPixel(x + i * 2 + 1, y + j * 2 + 1, !bw);
|
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
|
if (bit) {// test bits to set pixels
|
||||||
LCD_setPixel(x + i, y + j, bw);
|
LCD_setPixel(x + i, y + j, color);
|
||||||
LCD_setPixel(x + i + 1, y + j, bw);
|
LCD_setPixel(x + i + 1, y + j, color);
|
||||||
}
|
}
|
||||||
else if (bg) {
|
else if (style.bg) {
|
||||||
LCD_setPixel(x + i, y + j, !bw);
|
LCD_setPixel(x + i, y + j, !color);
|
||||||
LCD_setPixel(x + i + 1, y + j, !bw);
|
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.
|
// library.
|
||||||
void LCD_setStr(const char *dString, int x, int y, enum Color bw)
|
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
|
// setStr draws a string of characters, calling setChar with
|
||||||
// progressive coordinates until it's done.
|
// progressive coordinates until it's done.
|
||||||
// This function was grabbed from the SparkFun ColorLCDShield
|
// This function was grabbed from the SparkFun ColorLCDShield
|
||||||
// library.
|
// library. AND HEAVILY MODIFIED
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
const int x0 = x;
|
||||||
struct Utf8Iterator iter;
|
struct Utf8Iterator iter;
|
||||||
Utf8Iterator_Init(&iter, dString);
|
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;
|
struct Utf8Char uchar;
|
||||||
|
int limit = style.max_chars;
|
||||||
while ((uchar = Utf8Iterator_Next(&iter)).uint) {
|
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) {
|
if (limit > 0) {
|
||||||
x += 5;
|
limit -= 1;
|
||||||
if (bg) {
|
if (limit == 0) return;
|
||||||
for (int i = y; i < y + 8; i++) {
|
}
|
||||||
LCD_setPixel(x, i, !bw);
|
|
||||||
|
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 += spacingx;
|
||||||
|
if (x > (LCD_WIDTH - charw)) {
|
||||||
|
if (style.nowrap) break;
|
||||||
|
if (style.wrap_to_0) {
|
||||||
x = 0;
|
x = 0;
|
||||||
y += 8;
|
} else {
|
||||||
|
x = x0;
|
||||||
}
|
}
|
||||||
|
y += charh + spacingy;
|
||||||
}
|
}
|
||||||
else if (style_real == FONT_DOUBLE) {
|
|
||||||
x += 10;
|
// no more characters could be seen
|
||||||
if (bg) {
|
if (y >= LCD_HEIGHT) {
|
||||||
for (int i = y; i < y + 16; i++) {
|
break;
|
||||||
LCD_setPixel(x, i, !bw);
|
|
||||||
LCD_setPixel(x + 1, i, !bw);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x += 2;
|
|
||||||
if (x > (LCD_WIDTH - 10)) // Enables wrap around
|
|
||||||
{
|
|
||||||
x = 0;
|
|
||||||
y += 16;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-12
@@ -44,19 +44,21 @@ void LCD_setBitmap(const uint8_t *bitArray);
|
|||||||
size | 0x80 ... clear background behind characters
|
size | 0x80 ... clear background behind characters
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum FontStyle {
|
enum TextSize {
|
||||||
FONT_NORMAL = 1,
|
FONT_NORMAL = 0,
|
||||||
FONT_DOUBLE = 2,
|
FONT_DOUBLE = 1,
|
||||||
FONT_BOLD = 3,
|
FONT_BOLD = 2,
|
||||||
FONT_BG = 0x80,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This function will draw a char (defined in the ASCII table
|
struct TextStyle {
|
||||||
// near the beginning of this sketch) at a defined x and y).
|
bool bg; //!< Fill the characters background with the opposite color
|
||||||
// The color can be either black (1) or white (0).
|
enum TextSize size; //!< Character size
|
||||||
void LCD_setChar(struct Utf8Char character, int x, int y, enum Color bw);
|
int max_chars; //!< Number of characters to print from the string, if > 0
|
||||||
|
int spacing_x; //!< Additional X spacing
|
||||||
void LCD_setCharEx(struct Utf8Char character, int x, int y, enum Color bw, uint8_t style);
|
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
|
// setStr draws a string of characters, calling setChar with
|
||||||
// progressive coordinates until it's done.
|
// 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.
|
// library.
|
||||||
void LCD_setStr(const char * dString, int x, int y, enum Color bw);
|
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
|
// This function clears the entire display either white (0) or
|
||||||
// black (1).
|
// black (1).
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ static TimerHandle_t hTicker = NULL;
|
|||||||
void gui_init() {
|
void gui_init() {
|
||||||
printf("GUI init\n");
|
printf("GUI init\n");
|
||||||
LCD_setup();
|
LCD_setup();
|
||||||
LCD_setContrast(48);
|
LCD_setContrast(57);
|
||||||
|
|
||||||
int rv = xTaskCreate(gui_thread, "gui", 4096, NULL, 6, &hGuiThread);
|
int rv = xTaskCreate(gui_thread, "gui", 4096, NULL, 6, &hGuiThread);
|
||||||
assert (rv == pdPASS);
|
assert (rv == pdPASS);
|
||||||
|
|||||||
@@ -70,16 +70,16 @@ static void paint(struct DemoScene *self)
|
|||||||
break;
|
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];
|
char buf[10];
|
||||||
// sprintf(buf, "%3d", priv->pos);
|
// sprintf(buf, "%3d", priv->pos);
|
||||||
// LCD_setStr(buf, 2, 15, 0);
|
// LCD_setStr(buf, 2, 15, 0);
|
||||||
sprintf(buf, "🌡%.0f°C", analog_read());
|
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) {
|
struct Scene *NewScene_Demo(void) {
|
||||||
|
|||||||
@@ -6,17 +6,35 @@
|
|||||||
|
|
||||||
#include "liquid.h"
|
#include "liquid.h"
|
||||||
#include "graphics/drawing.h"
|
#include "graphics/drawing.h"
|
||||||
|
#include "graphics/display_spec.h"
|
||||||
|
|
||||||
#include "scene_menu.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)
|
static void paint(struct MenuScene *self)
|
||||||
{
|
{
|
||||||
LCD_clearDisplay(0);
|
LCD_clearDisplay(0);
|
||||||
|
|
||||||
int row = 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;
|
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--;
|
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++;
|
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
|
// TODO long selected label scrolling on tick
|
||||||
|
|
||||||
|
scene->visible_lines = 5;
|
||||||
scene->items = items;
|
scene->items = items;
|
||||||
scene->items_len = items_len;
|
scene->items_len = items_len;
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ struct MenuScene {
|
|||||||
int32_t scroll_up;
|
int32_t scroll_up;
|
||||||
// Selected item number
|
// Selected item number
|
||||||
int32_t selected;
|
int32_t selected;
|
||||||
|
// Number of lines visible at a time
|
||||||
|
uint8_t visible_lines;
|
||||||
// selection handler
|
// selection handler
|
||||||
MenuScene_onSelect_t onSelect;
|
MenuScene_onSelect_t onSelect;
|
||||||
// Extra field for the subclass's private use.
|
// Extra field for the subclass's private use.
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ static void paint(struct NumberScene *self)
|
|||||||
struct NumberSceneOpts *opts = self->opts;
|
struct NumberSceneOpts *opts = self->opts;
|
||||||
|
|
||||||
LCD_clearDisplay(0);
|
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];
|
char buf[10];
|
||||||
snprintf(buf, 10, "%d%s", opts->value, opts->unit);
|
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)
|
static void deinit(struct NumberScene *self)
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ static void paint(struct Scene *self)
|
|||||||
{
|
{
|
||||||
LCD_clearDisplay(0);
|
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) {
|
struct Scene *NewScene_Root(void) {
|
||||||
|
|||||||
Reference in New Issue
Block a user