diff --git a/radio/src/fonts.h b/radio/src/fonts.h index 44f8bbc42..c1ca10f6e 100644 --- a/radio/src/fonts.h +++ b/radio/src/fonts.h @@ -26,6 +26,9 @@ extern const uint16_t * const fontspecsTable[16]; extern const uint8_t * const fontsTable[16]; +extern BitmapBuffer * fontCache[2]; +void loadFontCache(); + #else extern const pm_uchar font_5x7[]; diff --git a/radio/src/gui/horus/bitmapbuffer.cpp b/radio/src/gui/horus/bitmapbuffer.cpp index a35c0504f..93c9764d5 100644 --- a/radio/src/gui/horus/bitmapbuffer.cpp +++ b/radio/src/gui/horus/bitmapbuffer.cpp @@ -247,8 +247,7 @@ void BitmapBuffer::drawBitmapPattern(coord_t x, coord_t y, const uint8_t * bmp, } } -#define FONT_MAX_HEIGHT 42 -void BitmapBuffer::drawFontPattern(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, int index, LcdFlags flags) +void BitmapBuffer::drawCharWithoutCache(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, int index, LcdFlags flags) { coord_t offset = spec[index]; coord_t width = spec[index+1] - offset; @@ -256,6 +255,14 @@ void BitmapBuffer::drawFontPattern(coord_t x, coord_t y, const uint8_t * font, c lcdNextPos = x + width; } +void BitmapBuffer::drawCharWithCache(coord_t x, coord_t y, const BitmapBuffer * font, const uint16_t * spec, int index, LcdFlags flags) +{ + coord_t offset = spec[index]; + coord_t width = spec[index+1] - offset; + drawBitmap(x, y, font, offset, 0, width); + lcdNextPos = x + width; +} + void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const char * s, uint8_t len, LcdFlags flags) { int width = getTextWidth(s, len, flags); @@ -263,6 +270,7 @@ void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const char * s, uint8_t l int fontindex = FONTSIZE(flags) >> 8; const pm_uchar * font = fontsTable[fontindex]; const uint16_t * fontspecs = fontspecsTable[fontindex]; + BitmapBuffer * fontcache = NULL; if (flags & RIGHT) x -= width; @@ -271,12 +279,32 @@ void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const char * s, uint8_t l if ((flags&INVERS) && ((~flags & BLINK) || BLINK_ON_PHASE)) { flags = TEXT_INVERTED_COLOR | (flags & 0x0ffff); - if (FONTSIZE(flags) == TINSIZE) + if (fontindex == TINSIZE_INDEX) { drawSolidFilledRect(x-INVERT_HORZ_MARGIN+2, y-INVERT_VERT_MARGIN+2, width+2*INVERT_HORZ_MARGIN-5, INVERT_LINE_HEIGHT-7, TEXT_INVERTED_BGCOLOR); - else if (FONTSIZE(flags) == SMLSIZE) + } + else if (fontindex == SMLSIZE_INDEX) { drawSolidFilledRect(x-INVERT_HORZ_MARGIN, y+1, width+2*INVERT_HORZ_MARGIN-2, INVERT_LINE_HEIGHT-5, TEXT_INVERTED_BGCOLOR); - else - drawSolidFilledRect(x-INVERT_HORZ_MARGIN, y, width+2*INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR); + } + else if (fontindex == STDSIZE_INDEX) { + drawSolidFilledRect(x-INVERT_HORZ_MARGIN, y, INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR); + drawSolidFilledRect(x+width, y, INVERT_HORZ_MARGIN, INVERT_LINE_HEIGHT, TEXT_INVERTED_BGCOLOR); + fontcache = fontCache[1]; + } + } + else if (!(flags & NO_FONTCACHE)) { + if (fontindex == STDSIZE_INDEX) { + uint16_t fgColor = lcdColorTable[COLOR_IDX(flags)]; + uint16_t bgColor = *getPixelPtr(x, y); + if (fgColor == lcdColorTable[TEXT_COLOR_INDEX] && bgColor == lcdColorTable[TEXT_BGCOLOR_INDEX]) { + fontcache = fontCache[0]; + } + else if (fgColor == lcdColorTable[TEXT_INVERTED_COLOR_INDEX] && bgColor == lcdColorTable[TEXT_INVERTED_BGCOLOR_INDEX]) { + fontcache = fontCache[1]; + } + else { + // TRACE("No cache for \"%s\"", s); + } + } } const coord_t orig_x = x; @@ -295,7 +323,12 @@ void BitmapBuffer::drawSizedText(coord_t x, coord_t y, const char * s, uint8_t l break; } else if (c >= 0x20) { - drawFontPattern(x, y, font, fontspecs, getMappedChar(c), flags); + if (fontcache) { + drawCharWithCache(x, y, fontcache, fontspecs, getMappedChar(c), flags); + } + else { + drawCharWithoutCache(x, y, font, fontspecs, getMappedChar(c), flags); + } x = lcdNextPos; } else if (c == 0x1F) { // X-coord prefix diff --git a/radio/src/gui/horus/bitmapbuffer.h b/radio/src/gui/horus/bitmapbuffer.h index 913d39e28..2dc6a350e 100644 --- a/radio/src/gui/horus/bitmapbuffer.h +++ b/radio/src/gui/horus/bitmapbuffer.h @@ -176,7 +176,9 @@ class BitmapBuffer: public BitmapBufferBase void drawBitmapPattern(coord_t x, coord_t y, const uint8_t * bmp, LcdFlags flags, coord_t offset=0, coord_t width=0); - void drawFontPattern(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, int index, LcdFlags flags); + void drawCharWithoutCache(coord_t x, coord_t y, const uint8_t * font, const uint16_t * spec, int index, LcdFlags flags); + + void drawCharWithCache(coord_t x, coord_t y, const BitmapBuffer * font, const uint16_t * spec, int index, LcdFlags flags); void drawText(coord_t x, coord_t y, const char * s, LcdFlags flags) { diff --git a/radio/src/gui/horus/fonts.cpp b/radio/src/gui/horus/fonts.cpp index 14f1801bd..7e68afd22 100644 --- a/radio/src/gui/horus/fonts.cpp +++ b/radio/src/gui/horus/fonts.cpp @@ -78,3 +78,23 @@ pm_uchar font_stdsizebold[] = { const uint16_t * const fontspecsTable[16] = { font_stdsize_specs, font_tinsize_specs, font_smlsize_specs, font_midsize_specs, font_dblsize_specs, font_xxlsize_specs, font_stdsizebold_specs }; const uint8_t * const fontsTable[16] = { font_stdsize, font_tinsize, font_smlsize, font_midsize, font_dblsize, font_xxlsize, font_stdsizebold }; + +BitmapBuffer * fontCache[2]; + +BitmapBuffer * createFontCache(const uint8_t * font, LcdFlags fg, LcdFlags bg) +{ + coord_t width = *((uint16_t *)font); + coord_t height = *(((uint16_t *)font)+1); + + BitmapBuffer * buffer = new BitmapBuffer(BMP_RGB565, width, height); + buffer->clear(bg); + buffer->drawBitmapPattern(0, 0, font, fg); + + return buffer; +} + +void loadFontCache() +{ + fontCache[0] = createFontCache(fontsTable[0], TEXT_COLOR, TEXT_BGCOLOR); + fontCache[1] = createFontCache(fontsTable[0], TEXT_INVERTED_COLOR, TEXT_INVERTED_BGCOLOR); +} diff --git a/radio/src/gui/horus/lcd.h b/radio/src/gui/horus/lcd.h index d90382835..b97775e93 100644 --- a/radio/src/gui/horus/lcd.h +++ b/radio/src/gui/horus/lcd.h @@ -24,58 +24,67 @@ #include "bitmapbuffer.h" #if defined(PCBHORUS) - #define LCD_W 480 - #define LCD_H 272 - #define LCD_COLS 30 + #define LCD_W 480 + #define LCD_H 272 + #define LCD_COLS 30 #else - #define LCD_W 800 - #define LCD_H 480 - #define LCD_COLS 40 + #define LCD_W 800 + #define LCD_H 480 + #define LCD_COLS 40 #endif #define CENTER -#define lcdint_t int32_t +#define lcdint_t int32_t -#define BSS 0x00 +#define BSS 0x00 /* lcd common flags */ -#define BLINK 0x01 +#define BLINK 0x01 /* drawText flags */ -#define INVERS 0x02 -#define LEFT 0x00 -#define CENTERED 0x04 /* align left */ -#define RIGHT 0x08 /* align left */ +#define INVERS 0x02 +#define LEFT 0x00 +#define CENTERED 0x04 /* align left */ +#define RIGHT 0x08 /* align left */ /* drawNumber flags */ -#define LEADING0 0x10 -#define PREC1 0x20 -#define PREC2 0x30 -#define MODE(flags) ((((int8_t)(flags) & 0x30) - 0x10) >> 4) +#define LEADING0 0x10 +#define PREC1 0x20 +#define PREC2 0x30 +#define MODE(flags) ((((int8_t)(flags) & 0x30) - 0x10) >> 4) -#define ZCHAR 0x10 +#define ZCHAR 0x10 /* rect, square flags */ -#define ROUND 0x04 +#define ROUND 0x04 /* telemetry flags */ -#define NO_UNIT 0x40 +#define NO_UNIT 0x40 -#define FONTSIZE(x) ((x) & 0x0700) -#define TINSIZE 0x0100 -#define SMLSIZE 0x0200 -#define MIDSIZE 0x0300 -#define DBLSIZE 0x0400 -#define XXLSIZE 0x0500 -#define BOLD 0x0600 -#define VERTICAL 0x0800 +enum FontSizeIndex { + STDSIZE_INDEX, + TINSIZE_INDEX, + SMLSIZE_INDEX, + MIDSIZE_INDEX, + DBLSIZE_INDEX, + XXLSIZE_INDEX +}; -#define TIMEBLINK 0x1000 -#define TIMEHOUR 0x2000 -#define STREXPANDED 0x4000 +#define FONTSIZE(x) ((x) & 0x0700) +#define TINSIZE (TINSIZE_INDEX << 8) +#define SMLSIZE (SMLSIZE_INDEX << 8) +#define MIDSIZE (MIDSIZE_INDEX << 8) +#define DBLSIZE (DBLSIZE_INDEX << 8) +#define XXLSIZE (XXLSIZE_INDEX << 8) +#define BOLD 0x0600 +#define VERTICAL 0x0800 +#define TIMEBLINK 0x1000 +#define TIMEHOUR 0x2000 +#define NO_FONTCACHE 0x8000 #include "colors.h" + #define DISPLAY_PIXELS_COUNT (LCD_W*LCD_H) #define DISPLAY_BUFFER_SIZE (sizeof(display_t)*DISPLAY_PIXELS_COUNT) diff --git a/radio/src/gui/horus/menu_model_inputs.cpp b/radio/src/gui/horus/menu_model_inputs.cpp index 58458fb93..45dcb4f56 100644 --- a/radio/src/gui/horus/menu_model_inputs.cpp +++ b/radio/src/gui/horus/menu_model_inputs.cpp @@ -233,7 +233,7 @@ bool menuModelExpoOne(evt_t event) case EXPO_FIELD_SOURCE: lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_SOURCE)); - putsMixerSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, STREXPANDED|(menuHorizontalPosition==0?attr:0)); + putsMixerSource(EXPO_ONE_2ND_COLUMN, y, ed->srcRaw, menuHorizontalPosition==0 ? attr : 0); if (attr && menuHorizontalPosition==0) ed->srcRaw = checkIncDec(event, ed->srcRaw, INPUTSRC_FIRST, INPUTSRC_LAST, EE_MODEL|INCDEC_SOURCE|NO_INCDEC_MARKS, isInputSourceAvailable); if (ed->srcRaw >= MIXSRC_FIRST_TELEM) { putsTelemetryChannelValue(EXPO_ONE_2ND_COLUMN+60, y, (ed->srcRaw - MIXSRC_FIRST_TELEM)/3, convertTelemValue(ed->srcRaw - MIXSRC_FIRST_TELEM + 1, ed->scale), LEFT|(menuHorizontalPosition==1?attr:0)); diff --git a/radio/src/gui/horus/menu_model_mixes.cpp b/radio/src/gui/horus/menu_model_mixes.cpp index fb2cfe776..d3801282f 100644 --- a/radio/src/gui/horus/menu_model_mixes.cpp +++ b/radio/src/gui/horus/menu_model_mixes.cpp @@ -201,7 +201,7 @@ bool menuModelMixOne(evt_t event) break; case MIX_FIELD_SOURCE: lcdDrawText(MENUS_MARGIN_LEFT, y, NO_INDENT(STR_SOURCE)); - putsMixerSource(MIXES_2ND_COLUMN, y, md2->srcRaw, STREXPANDED|attr); + putsMixerSource(MIXES_2ND_COLUMN, y, md2->srcRaw, attr); if (attr) CHECK_INCDEC_MODELSOURCE(event, md2->srcRaw, 1, MIXSRC_LAST); break; case MIX_FIELD_WEIGHT: diff --git a/radio/src/gui/horus/menu_model_setup.cpp b/radio/src/gui/horus/menu_model_setup.cpp index f5b5b64f0..1948b6962 100644 --- a/radio/src/gui/horus/menu_model_setup.cpp +++ b/radio/src/gui/horus/menu_model_setup.cpp @@ -105,7 +105,7 @@ void editTimerMode(int timerIdx, coord_t y, LcdFlags attr, evt_t event) } drawStringWithIndex(MENUS_MARGIN_LEFT, y, STR_TIMER, timerIdx+1); putsTimerMode(MODEL_SETUP_2ND_COLUMN, y, timer->mode, (menuHorizontalPosition<=0 ? attr : 0)); - putsTimer(MODEL_SETUP_2ND_COLUMN+50, y, timer->start, (menuHorizontalPosition==1 ? attr|TIMEHOUR : TIMEHOUR)); + putsTimer(MODEL_SETUP_2ND_COLUMN+50, y, timer->start, (menuHorizontalPosition!=0 ? attr|TIMEHOUR : TIMEHOUR)); if (attr && s_editMode>0) { switch (menuHorizontalPosition) { case 0: @@ -203,14 +203,10 @@ bool menuModelSetup(evt_t event) IF_EXTERNAL_MODULE_XJT(FAILSAFE_ROWS(EXTERNAL_MODULE)), LABEL(Trainer), 0, TRAINER_CHANNELS_ROWS(), IF_TRAINER_ON(2) }); -#if (defined(DSM2) || defined(PXX)) if (menuEvent) { moduleFlag[0] = 0; -#if NUM_MODULES > 1 moduleFlag[1] = 0; -#endif } -#endif int sub = menuVerticalPosition; diff --git a/radio/src/opentx.cpp b/radio/src/opentx.cpp index daf92bd33..10830210d 100644 --- a/radio/src/opentx.cpp +++ b/radio/src/opentx.cpp @@ -2609,6 +2609,7 @@ void opentxInit(OPENTX_INIT_ARGS) #if defined(COLORLCD) loadTheme(); + loadFontCache(); #endif if (g_eeGeneral.backlightMode != e_backlight_mode_off) backlightOn(); // on Tx start turn the light on