improve font drawing api

master
Ondřej Hruška 4 years ago
parent 2e28f71d48
commit 17a228faa7
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 148
      main/graphics/drawing.c
  2. 26
      main/graphics/drawing.h
  3. 2
      main/liquid/gui.c
  4. 8
      main/scenes/scene_demo.c
  5. 23
      main/scenes/scene_menu.c
  6. 2
      main/scenes/scene_menu.h
  7. 4
      main/scenes/scene_number.c
  8. 2
      main/scenes/scene_root.c

@ -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);
}
}
x++;
if (x > (LCD_WIDTH - 5)) // Enables wrap around
{
x = 0;
y += 8;
}
if (limit > 0) {
limit -= 1;
if (limit == 0) return;
}
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 += 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 += 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 += spacingx;
if (x > (LCD_WIDTH - charw)) {
if (style.nowrap) break;
if (style.wrap_to_0) {
x = 0;
y += 8;
} else {
x = x0;
}
y += charh + spacingy;
}
// no more characters could be seen
if (y >= LCD_HEIGHT) {
break;
}
}
}

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

@ -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,19 +6,37 @@
#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 + 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));
}
}
#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 + self->visible_lines); i++, row++) {
bool selected = self->selected==i;
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,
});
}
}
static struct SceneEvent onInput(struct MenuScene *self, struct InputEvent event) {
switch (event.kind) {
@ -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) {

Loading…
Cancel
Save