123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- /*
- * (c) Philippe G. 2019, philippe_44@outlook.com
- *
- * This software is released under the MIT License.
- * https://opensource.org/licenses/MIT
- *
- */
- #include <string.h>
- #include <ctype.h>
- #include <stdint.h>
- #include <arpa/inet.h>
- #include "esp_log.h"
- #include "gds_private.h"
- #include "gds.h"
- #include "gds_draw.h"
- #include "gds_text.h"
- #define max(a,b) (((a) > (b)) ? (a) : (b))
- static char TAG[] = "gds";
- /****************************************************************************************
- * Set fonts for each line in text mode
- */
- static const struct GDS_FontDef *GuessFont( struct GDS_Device *Device, int FontType) {
- switch(FontType) {
- case GDS_FONT_DEFAULT:
- return Device->Font;
- case GDS_FONT_LINE_1:
- return &Font_line_1;
- case GDS_FONT_LINE_2:
- return &Font_line_2;
- case GDS_FONT_MEDIUM:
- //return &Font_droid_sans_fallback_15x17;
- case GDS_FONT_SMALL:
- default:
- return &Font_droid_sans_fallback_11x13;
- #ifdef USE_LARGE_FONTS
- case GDS_FONT_LARGE:
- return &Font_droid_sans_fallback_24x28;
- case GDS_FONT_SEGMENT:
- if (Device->Height == 32) return &Font_Tarable7Seg_16x32;
- else return &Font_Tarable7Seg_32x64;
- #else
- case GDS_FONT_LARGE:
- case GDS_FONT_SEGMENT:
- ESP_LOGW(TAG, "large fonts disabled");
- //return &Font_droid_sans_fallback_15x17;
- return &Font_droid_sans_fallback_11x13;
- #endif
- }
- }
- /****************************************************************************************
- * Set fonts for each line in text mode
- */
- bool GDS_TextSetFontAuto(struct GDS_Device* Device, int N, int FontType, int Space) {
- const struct GDS_FontDef *Font = GuessFont( Device, FontType );
- return GDS_TextSetFont( Device, N, Font, Space );
- }
- /****************************************************************************************
- * Set fonts for each line in text mode
- */
- bool GDS_TextSetFont(struct GDS_Device* Device, int N, const struct GDS_FontDef *Font, int Space) {
- if (--N >= MAX_LINES) return false;
- Device->Lines[N].Font = Font;
-
- // re-calculate lines absolute position
- Device->Lines[N].Space = Space;
- Device->Lines[0].Y = Device->Lines[0].Space;
- for (int i = 1; i <= N; i++) Device->Lines[i].Y = Device->Lines[i-1].Y + Device->Lines[i-1].Font->Height + Device->Lines[i].Space;
-
- ESP_LOGI(TAG, "Adding line %u at %d (height:%u)", N + 1, Device->Lines[N].Y, Device->Lines[N].Font->Height);
-
- if (Device->Lines[N].Y + Device->Lines[N].Font->Height > Device->Height) {
- ESP_LOGW(TAG, "line does not fit display");
- return false;
- }
-
- return true;
- }
- /****************************************************************************************
- *
- */
- bool GDS_TextLine(struct GDS_Device* Device, int N, int Pos, int Attr, char *Text) {
- int Width, X = Pos;
- // counting 1..n
- N--;
-
- GDS_SetFont( Device, Device->Lines[N].Font );
- if (Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace( Device, true );
-
- Width = GDS_FontMeasureString( Device, Text );
-
- // adjusting position, erase only EoL for rigth-justified
- if (Pos == GDS_TEXT_RIGHT) X = Device->TextWidth - Width - 1;
- else if (Pos == GDS_TEXT_CENTER) X = (Device->TextWidth - Width) / 2;
-
- // erase if requested
- if (Attr & GDS_TEXT_CLEAR) {
- int Y_min = max(0, Device->Lines[N].Y), Y_max = max(0, Device->Lines[N].Y + Device->Lines[N].Font->Height);
- for (int c = (Attr & GDS_TEXT_CLEAR_EOL) ? X : 0; c < Device->TextWidth; c++)
- for (int y = Y_min; y < Y_max; y++)
- DrawPixelFast( Device, c, y, GDS_COLOR_BLACK );
- }
-
- GDS_FontDrawString( Device, X, Device->Lines[N].Y, Text, GDS_COLOR_WHITE );
-
- ESP_LOGD(TAG, "displaying %s line %u (x:%d, attr:%u)", Text, N+1, X, Attr);
-
- // update whole display if requested
- Device->Dirty = true;
- if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device );
-
- return Width + X < Device->TextWidth;
- }
- /****************************************************************************************
- *
- */
- int GDS_GetTextWidth(struct GDS_Device* Device, int N, int Attr, char *Text) {
- const struct GDS_FontDef *Font = GDS_SetFont( Device, Device->Lines[N-1].Font );
- if (Attr & GDS_TEXT_MONOSPACE) GDS_FontForceMonospace( Device, true );
- int Width = GDS_FontMeasureString( Device, Text );
- GDS_SetFont( Device, Font );
- return Width;
- }
- /****************************************************************************************
- * Try to align string for better scrolling visual. there is probably much better to do
- */
- int GDS_TextStretch(struct GDS_Device* Device, int N, char *String, int Max) {
- char Space[] = " ";
- int Len = strlen(String), Extra = 0, Boundary;
-
- N--;
-
- // we might already fit
- GDS_SetFont( Device, Device->Lines[N].Font );
- if (GDS_FontMeasureString( Device, String ) <= Device->TextWidth) return 0;
-
- // add some space for better visual
- strncat(String, Space, Max-Len);
- String[Max] = '\0';
- Len = strlen(String);
-
- // mark the end of the extended string
- Boundary = GDS_FontMeasureString( Device, String );
-
- // add a full display width
- while (Len < Max && GDS_FontMeasureString( Device, String ) - Boundary < Device->TextWidth) {
- String[Len++] = String[Extra++];
- String[Len] = '\0';
- }
-
- return Boundary;
- }
- /****************************************************************************************
- *
- */
- void GDS_TextPos(struct GDS_Device* Device, int FontType, int Where, int Attr, char *Text, ...) {
- va_list args;
- TextAnchor Anchor = TextAnchor_Center;
-
- if (Attr & GDS_TEXT_CLEAR) GDS_Clear( Device, GDS_COLOR_BLACK );
-
- if (!Text) return;
-
- va_start(args, Text);
-
- switch(Where) {
- case GDS_TEXT_TOP_LEFT:
- default:
- Anchor = TextAnchor_NorthWest;
- break;
- case GDS_TEXT_MIDDLE_LEFT:
- Anchor = TextAnchor_West;
- break;
- case GDS_TEXT_BOTTOM_LEFT:
- Anchor = TextAnchor_SouthWest;
- break;
- case GDS_TEXT_CENTERED:
- Anchor = TextAnchor_Center;
- break;
- }
-
- ESP_LOGD(TAG, "Displaying %s at %u with attribute %u", Text, Anchor, Attr);
-
- GDS_SetFont( Device, GuessFont( Device, FontType ) );
- GDS_FontDrawAnchoredString( Device, Anchor, Text, GDS_COLOR_WHITE );
-
- Device->Dirty = true;
- if (Attr & GDS_TEXT_UPDATE) GDS_Update( Device );
-
- va_end(args);
- }
|