new UTF8 decoder
This commit is contained in:
parent
3c484fd2fd
commit
8950aa9ce3
|
@ -125,6 +125,13 @@ class U8G2 : public Print
|
|||
void drawEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt = U8G2_DRAW_ALL) { u8g2_DrawEllipse(&u8g2, x0, y0, rx, ry, opt); }
|
||||
void drawFilledEllipse(u8g2_uint_t x0, u8g2_uint_t y0, u8g2_uint_t rx, u8g2_uint_t ry, uint8_t opt = U8G2_DRAW_ALL) { u8g2_DrawFilledEllipse(&u8g2, x0, y0, rx, ry, opt); }
|
||||
|
||||
/* u8g2_bitmap.c */
|
||||
void drawBitmap(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t cnt, u8g2_uint_t h, const uint8_t *bitmap)
|
||||
{ u8g2_DrawBitmap(&u8g2, x, y, cnt, h, bitmap); }
|
||||
void drawXBM(u8g2_uint_t x, u8g2_uint_t y, u8g2_uint_t w, u8g2_uint_t h, const uint8_t *bitmap)
|
||||
{ u8g2_DrawXBM(&u8g2, x, y, w, h, bitmap); }
|
||||
|
||||
|
||||
/* u8g2_polygon.c */
|
||||
void drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2)
|
||||
{ u8g2_DrawTriangle(&u8g2, x0, y0, x1, y1, x2, y2); }
|
||||
|
|
|
@ -713,41 +713,46 @@ static u8g2_uint_t u8g2_draw_string(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y,
|
|||
{
|
||||
uint16_t e;
|
||||
u8g2_uint_t delta, sum;
|
||||
u8x8_utf8_init(u8g2_GetU8x8(u8g2));
|
||||
sum = 0;
|
||||
for(;;)
|
||||
{
|
||||
e = u8g2->u8x8.char_cb(&str);
|
||||
if ( e == 0 )
|
||||
e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
|
||||
if ( e == 0x0ffff )
|
||||
break;
|
||||
delta = u8g2_DrawGlyph(u8g2, x, y, e);
|
||||
str++;
|
||||
if ( e != 0x0fffe )
|
||||
{
|
||||
delta = u8g2_DrawGlyph(u8g2, x, y, e);
|
||||
|
||||
#ifdef U8G2_WITH_FONT_ROTATION
|
||||
switch(u8g2->font_decode.dir)
|
||||
{
|
||||
case 0:
|
||||
x += delta;
|
||||
break;
|
||||
case 1:
|
||||
y += delta;
|
||||
break;
|
||||
case 2:
|
||||
x -= delta;
|
||||
break;
|
||||
case 3:
|
||||
y -= delta;
|
||||
break;
|
||||
}
|
||||
switch(u8g2->font_decode.dir)
|
||||
{
|
||||
case 0:
|
||||
x += delta;
|
||||
break;
|
||||
case 1:
|
||||
y += delta;
|
||||
break;
|
||||
case 2:
|
||||
x -= delta;
|
||||
break;
|
||||
case 3:
|
||||
y -= delta;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
x += delta;
|
||||
x += delta;
|
||||
#endif
|
||||
sum += delta;
|
||||
sum += delta;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
u8g2_uint_t u8g2_DrawStr(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
|
||||
{
|
||||
u8g2->u8x8.char_cb = u8x8_get_char_from_string;
|
||||
u8g2->u8x8.next_cb = u8x8_ascii_next;
|
||||
return u8g2_draw_string(u8g2, x, y, str);
|
||||
}
|
||||
|
||||
|
@ -763,7 +768,7 @@ Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
|
|||
*/
|
||||
u8g2_uint_t u8g2_DrawUTF8(u8g2_t *u8g2, u8g2_uint_t x, u8g2_uint_t y, const char *str)
|
||||
{
|
||||
u8g2->u8x8.char_cb = u8x8_get_encoding_from_utf8_string;
|
||||
u8g2->u8x8.next_cb = u8x8_utf8_next;
|
||||
return u8g2_draw_string(u8g2, x, y, str);
|
||||
}
|
||||
|
||||
|
@ -940,23 +945,28 @@ static u8g2_uint_t u8g2_string_width(u8g2_t *u8g2, const char *str)
|
|||
uint16_t e;
|
||||
u8g2_uint_t w;
|
||||
|
||||
u8x8_utf8_init(u8g2_GetU8x8(u8g2));
|
||||
|
||||
/* reset the total width to zero, this will be expanded during calculation */
|
||||
w = 0;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
e = u8g2->u8x8.char_cb(&str);
|
||||
if ( e == 0 )
|
||||
e = u8g2->u8x8.next_cb(u8g2_GetU8x8(u8g2), (uint8_t)*str);
|
||||
if ( e == 0x0ffff )
|
||||
break;
|
||||
w += u8g2_GetGlyphWidth(u8g2, e);
|
||||
|
||||
str++;
|
||||
if ( e != 0x0fffe )
|
||||
{
|
||||
w += u8g2_GetGlyphWidth(u8g2, e);
|
||||
}
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
u8g2_uint_t u8g2_GetStrWidth(u8g2_t *u8g2, const char *s)
|
||||
{
|
||||
u8g2->u8x8.char_cb = u8x8_get_char_from_string;
|
||||
u8g2->u8x8.next_cb = u8x8_ascii_next;
|
||||
return u8g2_string_width(u8g2, s);
|
||||
}
|
||||
|
||||
|
@ -972,7 +982,7 @@ Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
|
|||
*/
|
||||
u8g2_uint_t u8g2_GetUTF8Width(u8g2_t *u8g2, const char *str)
|
||||
{
|
||||
u8g2->u8x8.char_cb = u8x8_get_encoding_from_utf8_string;
|
||||
u8g2->u8x8.next_cb = u8x8_utf8_next;
|
||||
return u8g2_string_width(u8g2, str);
|
||||
}
|
||||
|
||||
|
|
16
csrc/u8x8.h
16
csrc/u8x8.h
|
@ -162,7 +162,8 @@ typedef struct u8x8_display_info_struct u8x8_display_info_t;
|
|||
typedef struct u8x8_tile_struct u8x8_tile_t;
|
||||
|
||||
typedef uint8_t (*u8x8_msg_cb)(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
typedef uint16_t (*u8x8_char_cb)(const char **s);
|
||||
typedef uint16_t (*u8x8_char_cb)(u8x8_t *u8x8, uint8_t b);
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -247,12 +248,13 @@ struct u8x8_display_info_struct
|
|||
struct u8x8_struct
|
||||
{
|
||||
const u8x8_display_info_t *display_info;
|
||||
u8x8_char_cb next_cb; /* procedure, which will be used to get the next char from the string */
|
||||
u8x8_msg_cb display_cb;
|
||||
u8x8_msg_cb cad_cb;
|
||||
u8x8_msg_cb byte_cb;
|
||||
u8x8_msg_cb gpio_and_delay_cb;
|
||||
const uint8_t *font;
|
||||
u8x8_char_cb char_cb; /* procedure, which will be used to get the next char from the string */
|
||||
uint16_t encoding; /* encoding result for utf8 decoder in next_cb */
|
||||
uint8_t x_offset; /* copied from info struct, can be modified in flip mode */
|
||||
uint8_t is_font_inverse_mode; /* 0: normal, 1: font glyphs are inverted */
|
||||
uint8_t i2c_address; /* a valid i2c adr. Initially this is 255, but this is set to something usefull during DISPLAY_INIT */
|
||||
|
@ -260,6 +262,7 @@ struct u8x8_struct
|
|||
/* usually, the lowest bit must be zero for a valid address */
|
||||
uint8_t i2c_started; /* for i2c interface */
|
||||
uint8_t device_address; /* this is the device address, replacement for U8X8_MSG_CAD_SET_DEVICE */
|
||||
uint8_t utf8_state; /* number of chars which are still to scan */
|
||||
#ifdef U8X8_USE_PINS
|
||||
uint8_t pins[U8X8_PIN_CNT]; /* defines a pinlist: Mainly a list of pins for the Arduino Envionment, use U8X8_PIN_xxx to access */
|
||||
#endif
|
||||
|
@ -621,8 +624,13 @@ uint8_t u8x8_d_st7920_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *a
|
|||
|
||||
/*==========================================*/
|
||||
/* u8x8_8x8.c */
|
||||
uint16_t u8x8_get_encoding_from_utf8_string(const char **str);
|
||||
uint16_t u8x8_get_char_from_string(const char **str);
|
||||
|
||||
void u8x8_utf8_init(u8x8_t *u8x8);
|
||||
uint16_t u8x8_ascii_next(u8x8_t *u8x8, uint8_t b);
|
||||
uint16_t u8x8_utf8_next(u8x8_t *u8x8, uint8_t b);
|
||||
// the following two functions are replaced by the init/next functions
|
||||
//uint16_t u8x8_get_encoding_from_utf8_string(const char **str);
|
||||
//uint16_t u8x8_get_char_from_string(const char **str);
|
||||
|
||||
void u8x8_SetFont(u8x8_t *u8x8, const uint8_t *font_8x8);
|
||||
void u8x8_DrawGlyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding);
|
||||
|
|
133
csrc/u8x8_8x8.c
133
csrc/u8x8_8x8.c
|
@ -95,6 +95,7 @@ Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
|
|||
This function returns 0x0ffff for end of string (0x0ffff is not a unicode glyph)
|
||||
|
||||
*/
|
||||
#ifdef OBSOLETE
|
||||
uint16_t u8x8_get_encoding_from_utf8_string(const char **str)
|
||||
{
|
||||
uint16_t e;
|
||||
|
@ -133,7 +134,82 @@ uint16_t u8x8_get_encoding_from_utf8_string(const char **str)
|
|||
}
|
||||
return e;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* reset the internal state machine */
|
||||
void u8x8_utf8_init(u8x8_t *u8x8)
|
||||
{
|
||||
u8x8->utf8_state = 0;
|
||||
}
|
||||
|
||||
uint16_t u8x8_ascii_next(u8x8_t *u8x8, uint8_t b)
|
||||
{
|
||||
if ( b == 0 )
|
||||
return 0x0ffff; /* end of string detected*/
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
pass a byte from an utf8 encoded string to the utf8 decoder state machine
|
||||
returns
|
||||
0x0fffe: no glyph, just continue
|
||||
0x0ffff: end of string
|
||||
anything else: The decoded encoding
|
||||
*/
|
||||
uint16_t u8x8_utf8_next(u8x8_t *u8x8, uint8_t b)
|
||||
{
|
||||
if ( b == 0 )
|
||||
return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
|
||||
if ( u8x8->utf8_state == 0 )
|
||||
{
|
||||
if ( b >= 0xfc ) /* 6 byte sequence */
|
||||
{
|
||||
u8x8->utf8_state = 5;
|
||||
b &= 1;
|
||||
}
|
||||
else if ( b >= 0xf8 )
|
||||
{
|
||||
u8x8->utf8_state = 4;
|
||||
b &= 3;
|
||||
}
|
||||
else if ( b >= 0xf0 )
|
||||
{
|
||||
u8x8->utf8_state = 3;
|
||||
b &= 7;
|
||||
}
|
||||
else if ( b >= 0xe0 )
|
||||
{
|
||||
u8x8->utf8_state = 2;
|
||||
b &= 15;
|
||||
}
|
||||
else if ( b >= 0xc0 )
|
||||
{
|
||||
u8x8->utf8_state = 1;
|
||||
b &= 0x01f;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do nothing, just use the value as encoding */
|
||||
return b;
|
||||
}
|
||||
u8x8->encoding = b;
|
||||
return 0x0fffe;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8->utf8_state--;
|
||||
/* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
|
||||
u8x8->encoding<<=6;
|
||||
b &= 0x03f;
|
||||
u8x8->encoding |= b;
|
||||
if ( u8x8->utf8_state != 0 )
|
||||
return 0x0fffe; /* nothing to do yet */
|
||||
}
|
||||
return u8x8->encoding;
|
||||
}
|
||||
|
||||
|
||||
#ifdef OBSOLETE
|
||||
uint16_t u8x8_get_char_from_string(const char **str)
|
||||
{
|
||||
uint8_t b = **str;
|
||||
|
@ -160,41 +236,58 @@ static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *
|
|||
}
|
||||
return cnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t u8x8_DrawString(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
|
||||
static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
u8x8->char_cb = u8x8_get_char_from_string;
|
||||
return u8x8_draw_string(u8x8, x, y, s);
|
||||
}
|
||||
|
||||
uint8_t u8x8_DrawUTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
u8x8->char_cb = u8x8_get_encoding_from_utf8_string;
|
||||
return u8x8_draw_string(u8x8, x, y, s);
|
||||
}
|
||||
|
||||
static uint8_t u8x8_strlen(u8x8_t *u8x8, const char *s) U8X8_NOINLINE;
|
||||
static uint8_t u8x8_strlen(u8x8_t *u8x8, const char *s)
|
||||
{
|
||||
uint16_t c;
|
||||
uint16_t e;
|
||||
uint8_t cnt = 0;
|
||||
u8x8_utf8_init(u8x8);
|
||||
for(;;)
|
||||
{
|
||||
c = u8x8->char_cb(&s);
|
||||
if ( c == 0 )
|
||||
e = u8x8->next_cb(u8x8, (uint8_t)*s);
|
||||
if ( e == 0x0ffff )
|
||||
break;
|
||||
if ( c <= 255 )
|
||||
s++;
|
||||
if ( e != 0x0fffe )
|
||||
{
|
||||
u8x8_DrawGlyph(u8x8, x, y, e);
|
||||
x++;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
uint8_t u8x8_DrawString(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
u8x8->next_cb = u8x8_ascii_next;
|
||||
return u8x8_draw_string(u8x8, x, y, s);
|
||||
}
|
||||
|
||||
uint8_t u8x8_DrawUTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
u8x8->next_cb = u8x8_utf8_next;
|
||||
return u8x8_draw_string(u8x8, x, y, s);
|
||||
}
|
||||
|
||||
uint8_t u8x8_GetUTF8Len(u8x8_t *u8x8, const char *s)
|
||||
{
|
||||
u8x8->char_cb = u8x8_get_encoding_from_utf8_string;
|
||||
return u8x8_strlen(u8x8, s);
|
||||
uint16_t e;
|
||||
uint8_t cnt = 0;
|
||||
u8x8_utf8_init(u8x8);
|
||||
for(;;)
|
||||
{
|
||||
e = u8x8_utf8_next(u8x8, *s);
|
||||
if ( e == 0x0ffff )
|
||||
break;
|
||||
s++;
|
||||
if ( e != 0x0fffe )
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ int main(void)
|
|||
u8x8_Setup_SDL_128x64(&u8g2);
|
||||
u8x8_InitDisplay(&u8g2);
|
||||
|
||||
u8x8_SetFont(&u8g2, u8x8_font_amstrad_cpc_f);
|
||||
u8x8_SetFont(&u8g2, u8x8_font_amstrad_cpc_extended_f);
|
||||
u8x8_DrawString(&u8g2, 0, 0, "UTF-8 Test");
|
||||
|
||||
u8x8_DrawString(&u8g2, 0, 1, "M\xfcnchen");/* works: select umlaut-u directly with code 0xfc */
|
||||
|
|
Loading…
Reference in New Issue