From ec57e74bc6ede3ef2dd67cceb479547003e905d9 Mon Sep 17 00:00:00 2001 From: Ryan Turner Date: Wed, 23 Aug 2023 07:32:36 -0500 Subject: [PATCH] feat(ui): add tooling to generate symbols, add GPS status icon and macro latch icon to the macro menu Ref https://github.com/OpenRTX/OpenRTX/issues/161 --- .github/workflows/regenerate_symbols.yml | 33 ++++ meson.build | 1 + openrtx/include/core/graphics.h | 21 +++ openrtx/include/fonts/symbols/Symbols5pt7b.h | 32 ++++ openrtx/include/fonts/symbols/Symbols6pt7b.h | 32 ++++ openrtx/include/fonts/symbols/Symbols8pt7b.h | 32 ++++ openrtx/include/fonts/symbols/sources/LICENSE | 24 +++ .../symbols/sources/alpha-m-box-outline.svg | 1 + openrtx/include/fonts/symbols/sources/cog.svg | 1 + .../fonts/symbols/sources/crosshairs-gps.svg | 1 + .../fonts/symbols/sources/crosshairs.svg | 1 + .../include/fonts/symbols/sources/lock.svg | 1 + .../fonts/symbols/sources/wifi-strength-1.svg | 1 + .../fonts/symbols/sources/wifi-strength-2.svg | 1 + .../fonts/symbols/sources/wifi-strength-3.svg | 1 + .../fonts/symbols/sources/wifi-strength-4.svg | 1 + openrtx/include/fonts/symbols/symbols.h | 13 ++ openrtx/include/ui/ui_default.h | 1 + openrtx/include/ui/ui_mod17.h | 1 + openrtx/src/core/graphics.c | 29 +++- openrtx/src/ui/default/ui.c | 12 +- openrtx/src/ui/default/ui_menu.c | 32 +++- openrtx/src/ui/module17/ui.c | 4 +- requirements.txt | 2 + scripts/generate_symbols.py | 164 ++++++++++++++++++ 25 files changed, 428 insertions(+), 14 deletions(-) create mode 100644 .github/workflows/regenerate_symbols.yml create mode 100644 openrtx/include/fonts/symbols/Symbols5pt7b.h create mode 100644 openrtx/include/fonts/symbols/Symbols6pt7b.h create mode 100644 openrtx/include/fonts/symbols/Symbols8pt7b.h create mode 100644 openrtx/include/fonts/symbols/sources/LICENSE create mode 100644 openrtx/include/fonts/symbols/sources/alpha-m-box-outline.svg create mode 100644 openrtx/include/fonts/symbols/sources/cog.svg create mode 100644 openrtx/include/fonts/symbols/sources/crosshairs-gps.svg create mode 100644 openrtx/include/fonts/symbols/sources/crosshairs.svg create mode 100644 openrtx/include/fonts/symbols/sources/lock.svg create mode 100644 openrtx/include/fonts/symbols/sources/wifi-strength-1.svg create mode 100644 openrtx/include/fonts/symbols/sources/wifi-strength-2.svg create mode 100644 openrtx/include/fonts/symbols/sources/wifi-strength-3.svg create mode 100644 openrtx/include/fonts/symbols/sources/wifi-strength-4.svg create mode 100644 openrtx/include/fonts/symbols/symbols.h create mode 100755 scripts/generate_symbols.py diff --git a/.github/workflows/regenerate_symbols.yml b/.github/workflows/regenerate_symbols.yml new file mode 100644 index 00000000..1a2d1a4e --- /dev/null +++ b/.github/workflows/regenerate_symbols.yml @@ -0,0 +1,33 @@ +name: "Check if symbols need to be regenerated" +on: + workflow_dispatch: + push: + paths: + - 'openrtx/include/fonts/symbols/**/*' + pull_request: + paths: + - 'openrtx/include/fonts/symbols/**/*' + + +jobs: + check-symbol-generation: + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + submodules: recursive + - name: install-deps + run: | + sudo apt update + sudo apt install python3 python3-pip + - name: Setup symbols script dependencies + run: | + cd ${{github.workspace}} + pip3 install -r requirements.txt + - name: Run symbols script + run: ./scripts/generate_symbols.py + - name: Fail the build if there are changes generated + run: | + git --no-pager diff + git diff-index --quiet HEAD diff --git a/meson.build b/meson.build index 50d08447..b996db10 100644 --- a/meson.build +++ b/meson.build @@ -72,6 +72,7 @@ openrtx_inc = ['openrtx/include', 'openrtx/include/calibration', 'openrtx/include/protocols', 'openrtx/include/fonts/adafruit', + 'openrtx/include/fonts/symbols', 'platform/drivers/ADC', 'platform/drivers/NVM', 'platform/drivers/GPS', diff --git a/openrtx/include/core/graphics.h b/openrtx/include/core/graphics.h index 24e8ab70..f1e29710 100644 --- a/openrtx/include/core/graphics.h +++ b/openrtx/include/core/graphics.h @@ -20,6 +20,7 @@ #ifndef GRAPHICS_H #define GRAPHICS_H +#include #include #include #include @@ -89,6 +90,13 @@ typedef enum FONT_SIZE_24PT } fontSize_t; +typedef enum +{ + SYMBOLS_SIZE_5PT, + SYMBOLS_SIZE_6PT, + SYMBOLS_SIZE_8PT +} symbolSize_t; + typedef enum { TEXT_ALIGN_LEFT = 0, @@ -263,6 +271,19 @@ point_t gfx_printLine(uint8_t cur, uint8_t tot, int16_t startY, int16_t endY, */ void gfx_printError(const char *text, fontSize_t size); +/** + * Prints text on the screen at the specified coordinates. + * @param start: text line start point, in pixel coordinates. + * @param size: icon font size, defined as enum. + * @param alignment: text alignment type, defined as enum. DEPRECATED: in the + * future this will be always LEFT. + * @param color: text color, in color_t format. + * @param symbol: symbol to be printed. + * @return text width and height as point_t coordinates + */ +point_t gfx_drawSymbol(point_t start, symbolSize_t size, textAlign_t alignment, + color_t color, symbol_t symbol); + /** * Function to draw battery of arbitrary size. * Starting coordinates are relative to the top left point. diff --git a/openrtx/include/fonts/symbols/Symbols5pt7b.h b/openrtx/include/fonts/symbols/Symbols5pt7b.h new file mode 100644 index 00000000..1a77e572 --- /dev/null +++ b/openrtx/include/fonts/symbols/Symbols5pt7b.h @@ -0,0 +1,32 @@ +// This is a generated file, please do not edit it! Use generate_symbols.py +static const uint8_t Symbols5pt7bBitmaps[] PROGMEM = { +0x00, //space +0x00, 0x7e, 0x5a, 0x66, 0x66, 0x42, 0x7e, 0x00, //alpha-m-box-outline.svg +0x00, 0x18, 0x7e, 0x66, 0x66, 0x7e, 0x18, 0x00, //cog.svg +0x00, 0x3c, 0x42, 0x5a, 0x5a, 0x42, 0x3c, 0x00, //crosshairs-gps.svg +0x00, 0x3c, 0x42, 0x42, 0x42, 0x42, 0x3c, 0x00, //crosshairs.svg +0x18, 0x24, 0x24, 0x7e, 0x7e, 0x7e, 0x7e, 0x00, //lock.svg +0x00, 0x3c, 0x81, 0x42, 0x3c, 0x18, 0x18, 0x00, //wifi-strength-1.svg +0x00, 0x3c, 0x81, 0x5a, 0x3c, 0x18, 0x18, 0x00, //wifi-strength-2.svg +0x00, 0x3c, 0x81, 0x7e, 0x3c, 0x18, 0x18, 0x00, //wifi-strength-3.svg +0x00, 0x3c, 0xff, 0x7e, 0x3c, 0x18, 0x18, 0x00, //wifi-strength-4.svg +}; + +static const GFXglyph Symbols5pt7bGlyphs[] PROGMEM = { + //Index, W, H,xAdv,dX, dY +{ 0, 1, 1, 5, 0, -7}, // " " space +{ 1, 8, 8, 5, 0, -7}, // "!" alpha-m-box-outline.svg +{ 9, 8, 8, 5, 0, -7}, // """ cog.svg +{ 17, 8, 8, 5, 0, -7}, // "#" crosshairs-gps.svg +{ 25, 8, 8, 5, 0, -7}, // "$" crosshairs.svg +{ 33, 8, 8, 5, 0, -7}, // "%" lock.svg +{ 41, 8, 8, 5, 0, -7}, // "&" wifi-strength-1.svg +{ 49, 8, 8, 5, 0, -7}, // "'" wifi-strength-2.svg +{ 57, 8, 8, 5, 0, -7}, // "(" wifi-strength-3.svg +{ 65, 8, 8, 5, 0, -7}, // ")" wifi-strength-4.svg +}; +static const GFXfont Symbols5pt7b PROGMEM = { +(uint8_t *)Symbols5pt7bBitmaps, +(GFXglyph *)Symbols5pt7bGlyphs, +//ASCII start, ASCII stop,y Advance + 32, 41, 19 }; diff --git a/openrtx/include/fonts/symbols/Symbols6pt7b.h b/openrtx/include/fonts/symbols/Symbols6pt7b.h new file mode 100644 index 00000000..65b45cbc --- /dev/null +++ b/openrtx/include/fonts/symbols/Symbols6pt7b.h @@ -0,0 +1,32 @@ +// This is a generated file, please do not edit it! Use generate_symbols.py +static const uint8_t Symbols6pt7bBitmaps[] PROGMEM = { +0x00, //space +0x00, 0x0f, 0xc4, 0x09, 0x7a, 0x52, 0x94, 0xa5, 0x29, 0x02, 0x3f, 0x00, 0x00, //alpha-m-box-outline.svg +0x00, 0x03, 0x03, 0xf1, 0xfe, 0x33, 0x0c, 0xc7, 0xf8, 0xfc, 0x0c, 0x00, 0x00, //cog.svg +0x00, 0x03, 0x03, 0x30, 0xb4, 0x5e, 0x97, 0xa2, 0xd0, 0xcc, 0x0c, 0x00, 0x00, //crosshairs-gps.svg +0x00, 0x03, 0x03, 0x30, 0x84, 0x40, 0x90, 0x22, 0x10, 0xcc, 0x0c, 0x00, 0x00, //crosshairs.svg +0x0c, 0x04, 0x81, 0x20, 0xfc, 0x3f, 0x0f, 0xc3, 0x30, 0xfc, 0x3f, 0x00, 0x00, //lock.svg +0x00, 0x07, 0x86, 0x19, 0x02, 0x40, 0x8b, 0x41, 0xe0, 0x30, 0x00, 0x00, 0x00, //wifi-strength-1.svg +0x00, 0x07, 0x86, 0x19, 0x02, 0x7f, 0x8f, 0xc1, 0xe0, 0x30, 0x00, 0x00, 0x00, //wifi-strength-2.svg +0x00, 0x07, 0x86, 0x19, 0x32, 0x7f, 0x8f, 0xc1, 0xe0, 0x30, 0x00, 0x00, 0x00, //wifi-strength-3.svg +0x00, 0x07, 0x87, 0xf9, 0xfe, 0x7f, 0x8f, 0xc1, 0xe0, 0x30, 0x00, 0x00, 0x00, //wifi-strength-4.svg +}; + +static const GFXglyph Symbols6pt7bGlyphs[] PROGMEM = { + //Index, W, H,xAdv,dX, dY +{ 0, 1, 1, 6, 0, -8}, // " " space +{ 1, 10, 10, 6, 0, -8}, // "!" alpha-m-box-outline.svg +{ 14, 10, 10, 6, 0, -8}, // """ cog.svg +{ 27, 10, 10, 6, 0, -8}, // "#" crosshairs-gps.svg +{ 40, 10, 10, 6, 0, -8}, // "$" crosshairs.svg +{ 53, 10, 10, 6, 0, -8}, // "%" lock.svg +{ 66, 10, 10, 6, 0, -8}, // "&" wifi-strength-1.svg +{ 79, 10, 10, 6, 0, -8}, // "'" wifi-strength-2.svg +{ 92, 10, 10, 6, 0, -8}, // "(" wifi-strength-3.svg +{ 105, 10, 10, 6, 0, -8}, // ")" wifi-strength-4.svg +}; +static const GFXfont Symbols6pt7b PROGMEM = { +(uint8_t *)Symbols6pt7bBitmaps, +(GFXglyph *)Symbols6pt7bGlyphs, +//ASCII start, ASCII stop,y Advance + 32, 41, 22 }; diff --git a/openrtx/include/fonts/symbols/Symbols8pt7b.h b/openrtx/include/fonts/symbols/Symbols8pt7b.h new file mode 100644 index 00000000..6ef5339b --- /dev/null +++ b/openrtx/include/fonts/symbols/Symbols8pt7b.h @@ -0,0 +1,32 @@ +// This is a generated file, please do not edit it! Use generate_symbols.py +static const uint8_t Symbols8pt7bBitmaps[] PROGMEM = { +0x00, //space +0x00, 0x00, 0x00, 0x0f, 0xf8, 0x40, 0x42, 0xfa, 0x15, 0x50, 0xaa, 0x85, 0x54, 0x2a, 0xa1, 0x01, 0x0f, 0xf8, 0x00, 0x00, 0x00, 0x00, //alpha-m-box-outline.svg +0x00, 0x00, 0x38, 0x01, 0xc0, 0x7f, 0xc7, 0xff, 0x1c, 0x70, 0xe3, 0x87, 0x1c, 0x7f, 0xf1, 0xff, 0x01, 0xc0, 0x0e, 0x00, 0x00, 0x00, //cog.svg +0x00, 0x00, 0x10, 0x03, 0xe0, 0x20, 0x82, 0x22, 0x13, 0x91, 0xbe, 0xc4, 0xe4, 0x22, 0x20, 0x82, 0x03, 0xe0, 0x04, 0x00, 0x00, 0x00, //crosshairs-gps.svg +0x00, 0x00, 0x10, 0x03, 0xe0, 0x20, 0x82, 0x02, 0x10, 0x11, 0x80, 0xc4, 0x04, 0x20, 0x20, 0x82, 0x03, 0xe0, 0x04, 0x00, 0x00, 0x00, //crosshairs.svg +0x00, 0x00, 0x7c, 0x02, 0x20, 0x11, 0x01, 0xfc, 0x1f, 0xf0, 0xff, 0x87, 0xbc, 0x3d, 0xe1, 0xff, 0x0f, 0xf8, 0x7f, 0xc0, 0x00, 0x00, //lock.svg +0x00, 0x00, 0x00, 0x0f, 0xf8, 0xc0, 0x64, 0x01, 0x10, 0x10, 0xc1, 0x83, 0xf8, 0x0f, 0x80, 0x38, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, //wifi-strength-1.svg +0x00, 0x00, 0x00, 0x0f, 0xf8, 0xc0, 0x64, 0x01, 0x11, 0x10, 0xff, 0x83, 0xf8, 0x0f, 0x80, 0x38, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, //wifi-strength-2.svg +0x00, 0x00, 0x00, 0x0f, 0xf8, 0xc0, 0x64, 0x71, 0x1f, 0xf0, 0xff, 0x83, 0xf8, 0x0f, 0x80, 0x38, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, //wifi-strength-3.svg +0x00, 0x00, 0x00, 0x0f, 0xf8, 0xff, 0xe7, 0xff, 0x1f, 0xf0, 0xff, 0x83, 0xf8, 0x0f, 0x80, 0x38, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, //wifi-strength-4.svg +}; + +static const GFXglyph Symbols8pt7bGlyphs[] PROGMEM = { + //Index, W, H,xAdv,dX, dY +{ 0, 1, 1, 9, 0, -11}, // " " space +{ 1, 13, 13, 9, 0, -11}, // "!" alpha-m-box-outline.svg +{ 23, 13, 13, 9, 0, -11}, // """ cog.svg +{ 45, 13, 13, 9, 0, -11}, // "#" crosshairs-gps.svg +{ 67, 13, 13, 9, 0, -11}, // "$" crosshairs.svg +{ 89, 13, 13, 9, 0, -11}, // "%" lock.svg +{ 111, 13, 13, 9, 0, -11}, // "&" wifi-strength-1.svg +{ 133, 13, 13, 9, 0, -11}, // "'" wifi-strength-2.svg +{ 155, 13, 13, 9, 0, -11}, // "(" wifi-strength-3.svg +{ 177, 13, 13, 9, 0, -11}, // ")" wifi-strength-4.svg +}; +static const GFXfont Symbols8pt7b PROGMEM = { +(uint8_t *)Symbols8pt7bBitmaps, +(GFXglyph *)Symbols8pt7bGlyphs, +//ASCII start, ASCII stop,y Advance + 32, 41, 30 }; diff --git a/openrtx/include/fonts/symbols/sources/LICENSE b/openrtx/include/fonts/symbols/sources/LICENSE new file mode 100644 index 00000000..5431b476 --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/LICENSE @@ -0,0 +1,24 @@ +## Pictogrammers Free License + +Last Updated: February 1st, 2023 + +This package is released as free, open-source, and GPL friendly by +the [Pictogrammers](https://pictogrammers.com/). You may use it +for commercial projects, open-source projects, or anything really. + +# Icons: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + +Some of the icons are redistributed under the Apache 2.0 license. All other +icons are either redistributed under their respective licenses or are +distributed under the Apache 2.0 license. + +# Fonts: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + +All web and desktop fonts are distributed under the Apache 2.0 license. Web +and desktop fonts contain some icons that are redistributed under the Apache +2.0 license. All other icons are either redistributed under their respective +licenses or are distributed under the Apache 2.0 license. + +# Code: MIT (https://opensource.org/licenses/MIT) + +The MIT license applies to all non-font and non-icon files. diff --git a/openrtx/include/fonts/symbols/sources/alpha-m-box-outline.svg b/openrtx/include/fonts/symbols/sources/alpha-m-box-outline.svg new file mode 100644 index 00000000..2642a874 --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/alpha-m-box-outline.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/sources/cog.svg b/openrtx/include/fonts/symbols/sources/cog.svg new file mode 100644 index 00000000..3db1464a --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/cog.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/sources/crosshairs-gps.svg b/openrtx/include/fonts/symbols/sources/crosshairs-gps.svg new file mode 100644 index 00000000..7cb275d1 --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/crosshairs-gps.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/sources/crosshairs.svg b/openrtx/include/fonts/symbols/sources/crosshairs.svg new file mode 100644 index 00000000..4e267dc8 --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/crosshairs.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/sources/lock.svg b/openrtx/include/fonts/symbols/sources/lock.svg new file mode 100644 index 00000000..5c0eb3f6 --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/lock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/sources/wifi-strength-1.svg b/openrtx/include/fonts/symbols/sources/wifi-strength-1.svg new file mode 100644 index 00000000..44b128bc --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/wifi-strength-1.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/sources/wifi-strength-2.svg b/openrtx/include/fonts/symbols/sources/wifi-strength-2.svg new file mode 100644 index 00000000..ced46cf3 --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/wifi-strength-2.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/sources/wifi-strength-3.svg b/openrtx/include/fonts/symbols/sources/wifi-strength-3.svg new file mode 100644 index 00000000..06c186d4 --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/wifi-strength-3.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/sources/wifi-strength-4.svg b/openrtx/include/fonts/symbols/sources/wifi-strength-4.svg new file mode 100644 index 00000000..e92995c7 --- /dev/null +++ b/openrtx/include/fonts/symbols/sources/wifi-strength-4.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/openrtx/include/fonts/symbols/symbols.h b/openrtx/include/fonts/symbols/symbols.h new file mode 100644 index 00000000..9d624ce3 --- /dev/null +++ b/openrtx/include/fonts/symbols/symbols.h @@ -0,0 +1,13 @@ +// This is a generated file, please do not edit it! Use generate_symbols.py +typedef enum { + SYMBOL_SPACE = 32, + SYMBOL_ALPHA_M_BOX_OUTLINE = 33, + SYMBOL_COG = 34, + SYMBOL_CROSSHAIRS_GPS = 35, + SYMBOL_CROSSHAIRS = 36, + SYMBOL_LOCK = 37, + SYMBOL_WIFI_STRENGTH_1 = 38, + SYMBOL_WIFI_STRENGTH_2 = 39, + SYMBOL_WIFI_STRENGTH_3 = 40, + SYMBOL_WIFI_STRENGTH_4 = 41, +} symbol_t; diff --git a/openrtx/include/ui/ui_default.h b/openrtx/include/ui/ui_default.h index 755302a2..76e08b4f 100644 --- a/openrtx/include/ui/ui_default.h +++ b/openrtx/include/ui/ui_default.h @@ -164,6 +164,7 @@ typedef struct layout_t point_t line3_pos; point_t bottom_pos; fontSize_t top_font; + symbolSize_t top_symbol_size; fontSize_t line1_font; fontSize_t line2_font; fontSize_t line3_font; diff --git a/openrtx/include/ui/ui_mod17.h b/openrtx/include/ui/ui_mod17.h index 9df0d417..10f17765 100644 --- a/openrtx/include/ui/ui_mod17.h +++ b/openrtx/include/ui/ui_mod17.h @@ -170,6 +170,7 @@ typedef struct layout_t point_t line5_pos; point_t bottom_pos; fontSize_t top_font; + fontSize_t top_symbol_font; fontSize_t line1_font; fontSize_t line2_font; fontSize_t line3_font; diff --git a/openrtx/src/core/graphics.c b/openrtx/src/core/graphics.c index c5733b29..f763b9e8 100644 --- a/openrtx/src/core/graphics.c +++ b/openrtx/src/core/graphics.c @@ -51,6 +51,10 @@ #include #include +#include +#include +#include + // Variable swap macro #define DEG_RAD 0.017453292519943295769236907684886 #define SIN(x) sinf((x) * DEG_RAD) @@ -68,7 +72,7 @@ static const GFXfont fonts[] = { TomThumb, // 5pt FreeSans12pt7b, // 12pt FreeSans16pt7b, // 16pt FreeSans18pt7b, // 16pt - FreeSans24pt7b // 24pt + FreeSans24pt7b, // 24pt #elif defined FONT_UBUNTU_REGULAR UbuntuRegular6pt7b, // 6pt UbuntuRegular8pt7b, // 8pt @@ -77,10 +81,13 @@ static const GFXfont fonts[] = { TomThumb, // 5pt UbuntuRegular12pt7b, // 12pt UbuntuRegular16pt7b, // 16pt UbuntuRegular18pt7b, // 16pt - UbuntuRegular24pt7b // 24pt + UbuntuRegular24pt7b, // 24pt #else #error Unsupported font family! #endif + Symbols5pt7b, // 5pt + Symbols6pt7b, // 6pt + Symbols8pt7b // 8pt }; #ifdef PIX_FMT_RGB565 @@ -616,6 +623,24 @@ void gfx_printError(const char *text, fontSize_t size) gfx_drawRect(box_start, text_size.x, text_size.y, red, false); } +point_t gfx_drawSymbol(point_t start, symbolSize_t size, textAlign_t alignment, + color_t color, symbol_t symbol) +{ + /* + * Symbol tables come immediately after fonts in the general font table. + * But, to prevent errors where symbol size is used instead of font size and + * vice-versa, their enums are separate. The trickery below is used to put + * together again the two enums in a single consecutive index. + * + * TODO: improve this. + */ + int symSize = size + FONT_SIZE_24PT + 1; + char buffer[2] = {0}; + + buffer[0] = (char) symbol; + return gfx_printBuffer(start, symSize, alignment, color, buffer); +} + /* * Function to draw battery of arbitrary size * starting coordinates are relative to the top left point. diff --git a/openrtx/src/ui/default/ui.c b/openrtx/src/ui/default/ui.c index ec34386c..411e3287 100644 --- a/openrtx/src/ui/default/ui.c +++ b/openrtx/src/ui/default/ui.c @@ -295,7 +295,8 @@ static layout_t _ui_calculateLayout() const uint16_t horizontal_pad = 4; // Top bar font: 8 pt - const fontSize_t top_font = FONT_SIZE_8PT; + const fontSize_t top_font = FONT_SIZE_8PT; + const symbolSize_t top_symbol_size = SYMBOLS_SIZE_8PT; // Text line font: 8 pt const fontSize_t line1_font = FONT_SIZE_8PT; const fontSize_t line2_font = FONT_SIZE_8PT; @@ -330,7 +331,8 @@ static layout_t _ui_calculateLayout() const uint16_t horizontal_pad = 4; // Top bar font: 6 pt - const fontSize_t top_font = FONT_SIZE_6PT; + const fontSize_t top_font = FONT_SIZE_6PT; + const symbolSize_t top_symbol_size = SYMBOLS_SIZE_6PT; // Middle line fonts: 5, 8, 8 pt const fontSize_t line1_font = FONT_SIZE_6PT; const fontSize_t line2_font = FONT_SIZE_6PT; @@ -363,8 +365,9 @@ static layout_t _ui_calculateLayout() const uint16_t big_line_v_pad = 0; const uint16_t horizontal_pad = 4; - // Top bar font: 8 pt - const fontSize_t top_font = FONT_SIZE_6PT; + // Top bar font: 6 pt + const fontSize_t top_font = FONT_SIZE_6PT; + const symbolSize_t top_symbol_size = SYMBOLS_SIZE_6PT; // Middle line fonts: 16, 16 const fontSize_t line2_font = FONT_SIZE_6PT; const fontSize_t line3_font = FONT_SIZE_12PT; @@ -410,6 +413,7 @@ static layout_t _ui_calculateLayout() line3_pos, bottom_pos, top_font, + top_symbol_size, line1_font, line2_font, line3_font, diff --git a/openrtx/src/ui/default/ui_menu.c b/openrtx/src/ui/default/ui_menu.c index 1151fb89..5bd7871e 100644 --- a/openrtx/src/ui/default/ui_menu.c +++ b/openrtx/src/ui/default/ui_menu.c @@ -872,16 +872,34 @@ void _ui_drawSettingsReset2Defaults(ui_state_t* ui_state) drawcnt++; } +void _ui_drawMacroTop() +{ + gfx_print(layout.top_pos, layout.top_font, TEXT_ALIGN_CENTER, + color_white, currentLanguage->macroMenu); + if (macro_latched) + { + gfx_drawSymbol(layout.top_pos, layout.top_symbol_size, TEXT_ALIGN_LEFT, + color_white, SYMBOL_ALPHA_M_BOX_OUTLINE); + } + if(last_state.settings.gps_enabled) + { + if(last_state.gps_data.fix_quality > 0) + { + gfx_drawSymbol(layout.top_pos, layout.top_symbol_size, TEXT_ALIGN_RIGHT, + color_white, SYMBOL_CROSSHAIRS_GPS); + } + else + { + gfx_drawSymbol(layout.top_pos, layout.top_symbol_size, TEXT_ALIGN_RIGHT, + color_white, SYMBOL_CROSSHAIRS); + } + } +} + bool _ui_drawMacroMenu() { // Header - gfx_print(layout.top_pos, layout.top_font, TEXT_ALIGN_CENTER, - color_white, currentLanguage->macroMenu); - if (macro_latched) - { - gfx_print(layout.top_pos, layout.top_font, TEXT_ALIGN_LEFT, - color_white, "L"); - } + _ui_drawMacroTop(); // First row if (last_state.channel.mode == OPMODE_FM) { diff --git a/openrtx/src/ui/module17/ui.c b/openrtx/src/ui/module17/ui.c index 146585f0..cb50b14d 100644 --- a/openrtx/src/ui/module17/ui.c +++ b/openrtx/src/ui/module17/ui.c @@ -224,7 +224,8 @@ layout_t _ui_calculateLayout() const uint16_t horizontal_pad = 4; // Top bar font: 6 pt - const fontSize_t top_font = FONT_SIZE_6PT; + const fontSize_t top_font = FONT_SIZE_6PT; + const symbolSize_t top_symbol_size = SYMBOLS_SIZE_6PT; // Middle line fonts: 5, 8, 8 pt const fontSize_t line1_font = FONT_SIZE_6PT; const fontSize_t line2_font = FONT_SIZE_6PT; @@ -274,6 +275,7 @@ layout_t _ui_calculateLayout() line5_pos, bottom_pos, top_font, + top_symbol_size, line1_font, line2_font, line3_font, diff --git a/requirements.txt b/requirements.txt index d2a958ff..3a0922b1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,5 @@ pyusb meson ffmpeg +cairosvg==2.7.1 +numpy==1.25.2 \ No newline at end of file diff --git a/scripts/generate_symbols.py b/scripts/generate_symbols.py new file mode 100755 index 00000000..dafce455 --- /dev/null +++ b/scripts/generate_symbols.py @@ -0,0 +1,164 @@ +#!/usr/bin/env python3 +# /*************************************************************************** +# * Copyright (C) 2023 by Ryan Turner K0RET * +# * * +# * This program is free software; you can redistribute it and/or modify * +# * it under the terms of the GNU General Public License as published by * +# * the Free Software Foundation; either version 3 of the License, or * +# * (at your option) any later version. * +# * * +# * This program is distributed in the hope that it will be useful, * +# * but WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +# * GNU General Public License for more details. * +# * * +# * You should have received a copy of the GNU General Public License * +# * along with this program; if not, see * +# ***************************************************************************/ +# +# Usage: +# +# 1. Find your source svg; https://pictogrammers.com/library/mdi/ is a good resource +# 2. Add your source svg to openrtx/include/fonts/symbols/sources +# 3. Execute this script; the corresponding `.h` files in the openrtx/include/fonts/symbols directory will regenerate +# 4. Refer to the `symbols/symbols.h` file to find the enum that corresponds with your new symbol +# 5. Utilize the `gfx_printSymbol()` method with your enum to access your symbol + +import cairosvg +import io +from PIL import Image +import numpy +import os + +absolute_path = os.path.dirname(__file__) + +symbol_source_dir = "../openrtx/include/fonts/symbols/sources/" + +debug = False +sizes = [5, 6, 8] +symbols = sorted([f for f in os.listdir(os.path.join(absolute_path, symbol_source_dir)) if "svg" in f]) +print(symbols) +################################################################### + + +def svgToBytes(filename, height): + # Make memory buffer + mem = io.BytesIO() + # Convert SVG to PNG in memory + cairosvg.svg2png( + url=filename, write_to=mem, parent_height=height, parent_width=height + ) + # Convert PNG to Numpy array + img = Image.open(mem) + # Split the channels, get just the alpha since that's what we need + red, green, blue, alpha = img.split() + # Convert the alpha to 1 and 0 (black and white) + alpha = alpha.point(lambda x: 0 if x < 128 else 255, "1") + if debug: + alpha.show() + return numpy.array(alpha) + + +first_ascii = 32 # Start at ascii d32 which is " " per https://www.rapidtables.com/code/text/ascii-table.html +dont_edit_banner = "// This is a generated file, please do not edit it! Use generate_symbols.py\n" + +class FontDefinition: + scalar = 1.6 # this number is used to roughly convert from pt to px + yadvance_scalar = ( + 7 / 3 + ) # this number is applied to the width to scale up the yadvance; this is naively linear + + def __init__(self, name, size): + # Prepopulate with a space character + self.bitmaps = [[0x00]] + self.glyphNames = ["space"] + self.initial_offset = 1 + + self.size = size + self.name = name + self.height = round(size * self.scalar) + self.width = round(size * self.scalar) + self.yadvance = round(size * self.scalar * self.yadvance_scalar) + self.xadvance = round(size * self.scalar * 2 / 3) + self.dY = round(-1 * self.height / 1.2) + + def addGlyph(self, filename, glyphName): + res = svgToBytes(filename, self.height) + packed = numpy.packbits(res) + charBytes = packed.tobytes() + + self.bitmaps.append(charBytes) + + self.glyphNames.append(glyphName) + + def __str__(self): + out = dont_edit_banner + out += "static const uint8_t {}{}pt7bBitmaps[] PROGMEM = {{\n".format( + self.name, self.size + ) + for i, bitmap in enumerate(self.bitmaps): + out += ( + (", ".join("0x{:02x}".format(x) for x in bitmap)) + + ", //" + + self.glyphNames[i] + + "\n" + ) + out += "};\n" + out += "\n" + out += ( + "static const GFXglyph {}{}pt7bGlyphs[] PROGMEM = {{".format( + self.name, self.size + ) + + "\n" + ) + out += " //Index, W, H,xAdv,dX, dY\n" + offset = 0 + for glyphNumber, glyphName in enumerate(self.glyphNames): + out += '{{ {}, {}, {}, {}, 0, {}}}, // "{}" {}\n'.format( + offset, + self.width if glyphNumber > 0 else 1, + self.height if glyphNumber > 0 else 1, + self.xadvance, + self.dY, + chr(first_ascii + glyphNumber), + glyphName, + ) + offset += len(self.bitmaps[glyphNumber]) + out += "};\n" + out += ( + "static const GFXfont {}{}pt7b PROGMEM = {{".format(self.name, self.size) + + "\n" + ) + out += "(uint8_t *){}{}pt7bBitmaps,".format(self.name, self.size) + "\n" + out += "(GFXglyph *){}{}pt7bGlyphs,".format(self.name, self.size) + "\n" + out += "//ASCII start, ASCII stop,y Advance \n" + out += ( + " {}, {}, {} }};".format( + first_ascii, + first_ascii + len(self.glyphNames) - 1, + round(self.yadvance), + ) + + "\n" + ) + return out + + +################################################################### + +# Generate the font definitions +for size in sizes: + font = FontDefinition("Symbols", size) + for symbol in symbols: + font.addGlyph(os.path.join(absolute_path, symbol_source_dir + symbol), symbol) + with open(os.path.join(absolute_path, "../openrtx/include/fonts/symbols/Symbols{}pt7b.h".format(size)), "w") as f: + f.write(str(font)) + +# Generate the enum for convenience +with open(os.path.join(absolute_path, "../openrtx/include/fonts/symbols/symbols.h".format(size)), "w") as f: + out = dont_edit_banner + out += "typedef enum {\n" + symbols.insert(0, "SPACE") + for symbolNumber, symbolName in enumerate(symbols): + out += " SYMBOL_{} = {},\n".format(symbolName.split(".")[0].replace("-", "_").upper(), symbolNumber + first_ascii) + out += "} symbol_t;\n" + f.write(out)