new UTF8 decoder

This commit is contained in:
olikraus 2016-05-05 22:21:28 +02:00
parent 3c484fd2fd
commit 8950aa9ce3
5 changed files with 171 additions and 53 deletions

View File

@ -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); }

View File

@ -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);
}

View File

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

View File

@ -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;
}

View File

@ -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 */