From dd180b33c09b0d6d8b284853974603ed92e09c20 Mon Sep 17 00:00:00 2001 From: "K. Lange" Date: Thu, 5 Dec 2019 19:13:16 +0900 Subject: [PATCH] sdf: handle input string as utf8 --- apps/terminal-vga.c | 168 +----------------------------------------- apps/terminal.c | 174 +------------------------------------------- apps/ununicode.h | 167 ++++++++++++++++++++++++++++++++++++++++++ lib/sdf.c | 39 +++++++--- 4 files changed, 198 insertions(+), 350 deletions(-) create mode 100644 apps/ununicode.h diff --git a/apps/terminal-vga.c b/apps/terminal-vga.c index 0af71032..627e8a42 100644 --- a/apps/terminal-vga.c +++ b/apps/terminal-vga.c @@ -408,173 +408,7 @@ char vga_to_ansi[] = { 8,12,10,14, 9,13,11,15 }; -uint32_t ununicode(uint32_t c) { - switch (c) { - case L'☺': return 1; - case L'☻': return 2; - case L'♥': return 3; - case L'♦': return 4; - case L'♣': return 5; - case L'♠': return 6; - case L'•': return 7; - case L'◘': return 8; - case L'○': return 9; - case L'◙': return 10; - case L'♂': return 11; - case L'♀': return 12; - case L'♪': return 13; - case L'♫': return 14; - case L'☼': return 15; - case L'►': return 16; - case L'◄': return 17; - case L'↕': return 18; - case L'‼': return 19; - case L'¶': return 20; - case L'§': return 21; - case L'▬': return 22; - case L'↨': return 23; - case L'↑': return 24; - case L'↓': return 25; - case L'→': return 26; - case L'←': return 27; - case L'∟': return 28; - case L'↔': return 29; - case L'▲': return 30; - case L'▼': return 31; - /* ASCII text */ - case L'⌂': return 127; - case L'Ç': return 128; - case L'ü': return 129; - case L'é': return 130; - case L'â': return 131; - case L'ä': return 132; - case L'à': return 133; - case L'å': return 134; - case L'ç': return 135; - case L'ê': return 136; - case L'ë': return 137; - case L'è': return 138; - case L'ï': return 139; - case L'î': return 140; - case L'ì': return 141; - case L'Ä': return 142; - case L'Å': return 143; - case L'É': return 144; - case L'æ': return 145; - case L'Æ': return 146; - case L'ô': return 147; - case L'ö': return 148; - case L'ò': return 149; - case L'û': return 150; - case L'ù': return 151; - case L'ÿ': return 152; - case L'Ö': return 153; - case L'Ü': return 154; - case L'¢': return 155; - case L'£': return 156; - case L'¥': return 157; - case L'₧': return 158; - case L'ƒ': return 159; - case L'á': return 160; - case L'í': return 161; - case L'ó': return 162; - case L'ú': return 163; - case L'ñ': return 164; - case L'Ñ': return 165; - case L'ª': return 166; - case L'º': return 167; - case L'¿': return 168; - case L'⌐': return 169; - case L'¬': return 170; - case L'½': return 171; - case L'¼': return 172; - case L'¡': return 173; - case L'«': return 174; - case L'»': return 175; - case L'░': return 176; - case L'▒': return 177; - case L'▓': return 178; - case L'│': return 179; - case L'┤': return 180; - case L'╡': return 181; - case L'╢': return 182; - case L'╖': return 183; - case L'╕': return 184; - case L'╣': return 185; - case L'║': return 186; - case L'╗': return 187; - case L'╝': return 188; - case L'╜': return 189; - case L'╛': return 190; - case L'┐': return 191; - case L'└': return 192; - case L'┴': return 193; - case L'┬': return 194; - case L'├': return 195; - case L'─': return 196; - case L'┼': return 197; - case L'╞': return 198; - case L'╟': return 199; - case L'╚': return 200; - case L'╔': return 201; - case L'╩': return 202; - case L'╦': return 203; - case L'╠': return 204; - case L'═': return 205; - case L'╬': return 206; - case L'╧': return 207; - case L'╨': return 208; - case L'╤': return 209; - case L'╥': return 210; - case L'╙': return 211; - case L'╘': return 212; - case L'╒': return 213; - case L'╓': return 214; - case L'╫': return 215; - case L'╪': return 216; - case L'┘': return 217; - case L'┌': return 218; - case L'█': return 219; - case L'▄': return 220; - case L'▌': return 221; - case L'▐': return 222; - case L'▀': return 223; - case L'α': return 224; - case L'ß': return 225; - case L'Γ': return 226; - case L'π': return 227; - case L'Σ': return 228; - case L'σ': return 229; - case L'µ': return 230; - case L'τ': return 231; - case L'Φ': return 232; - case L'Θ': return 233; - case L'Ω': return 234; - case L'δ': return 235; - case L'∞': return 236; - case L'φ': return 237; - case L'ε': return 238; - case L'∩': return 239; - case L'≡': return 240; - case L'±': return 241; - case L'≥': return 242; - case L'≤': return 243; - case L'⌠': return 244; - case L'⌡': return 245; - case L'÷': return 246; - case L'≈': return 247; - case L'°': return 248; - case L'∙': return 249; - case L'·': return 250; - case L'√': return 251; - case L'ⁿ': return 252; - case L'²': return 253; - case L'■': return 254; - /* Special cases */ - case L'▏': return 179; /* Replace with vertical bar to support bim better */ - } - return 4; -} +#include "ununicode.h" void term_write_char( diff --git a/apps/terminal.c b/apps/terminal.c index c8ca0b4c..5684ec87 100644 --- a/apps/terminal.c +++ b/apps/terminal.c @@ -597,172 +597,7 @@ static void draw_semi_block(int c, int x, int y, uint32_t fg, uint32_t bg) { } } -/* Convert unicode codepoint to fallback codepage codepoint */ -static uint32_t ununicode(uint32_t c) { - switch (c) { - case L'☺': return 1; - case L'☻': return 2; - case L'♥': return 3; - case L'♦': return 4; - case L'♣': return 5; - case L'♠': return 6; - case L'•': return 7; - case L'◘': return 8; - case L'○': return 9; - case L'◙': return 10; - case L'♂': return 11; - case L'♀': return 12; - case L'♪': return 13; - case L'♫': return 14; - case L'☼': return 15; - case L'►': return 16; - case L'◄': return 17; - case L'↕': return 18; - case L'‼': return 19; - case L'¶': return 20; - case L'§': return 21; - case L'▬': return 22; - case L'↨': return 23; - case L'↑': return 24; - case L'↓': return 25; - case L'→': return 26; - case L'←': return 27; - case L'∟': return 28; - case L'↔': return 29; - case L'▲': return 30; - case L'▼': return 31; - /* ASCII text */ - case L'⌂': return 127; - case L'Ç': return 128; - case L'ü': return 129; - case L'é': return 130; - case L'â': return 131; - case L'ä': return 132; - case L'à': return 133; - case L'å': return 134; - case L'ç': return 135; - case L'ê': return 136; - case L'ë': return 137; - case L'è': return 138; - case L'ï': return 139; - case L'î': return 140; - case L'ì': return 141; - case L'Ä': return 142; - case L'Å': return 143; - case L'É': return 144; - case L'æ': return 145; - case L'Æ': return 146; - case L'ô': return 147; - case L'ö': return 148; - case L'ò': return 149; - case L'û': return 150; - case L'ù': return 151; - case L'ÿ': return 152; - case L'Ö': return 153; - case L'Ü': return 154; - case L'¢': return 155; - case L'£': return 156; - case L'¥': return 157; - case L'₧': return 158; - case L'ƒ': return 159; - case L'á': return 160; - case L'í': return 161; - case L'ó': return 162; - case L'ú': return 163; - case L'ñ': return 164; - case L'Ñ': return 165; - case L'ª': return 166; - case L'º': return 167; - case L'¿': return 168; - case L'⌐': return 169; - case L'¬': return 170; - case L'½': return 171; - case L'¼': return 172; - case L'¡': return 173; - case L'«': return 174; - case L'»': return 175; - case L'░': return 176; - case L'▒': return 177; - case L'▓': return 178; - case L'│': return 179; - case L'┤': return 180; - case L'╡': return 181; - case L'╢': return 182; - case L'╖': return 183; - case L'╕': return 184; - case L'╣': return 185; - case L'║': return 186; - case L'╗': return 187; - case L'╝': return 188; - case L'╜': return 189; - case L'╛': return 190; - case L'┐': return 191; - case L'└': return 192; - case L'┴': return 193; - case L'┬': return 194; - case L'├': return 195; - case L'─': return 196; - case L'┼': return 197; - case L'╞': return 198; - case L'╟': return 199; - case L'╚': return 200; - case L'╔': return 201; - case L'╩': return 202; - case L'╦': return 203; - case L'╠': return 204; - case L'═': return 205; - case L'╬': return 206; - case L'╧': return 207; - case L'╨': return 208; - case L'╤': return 209; - case L'╥': return 210; - case L'╙': return 211; - case L'╘': return 212; - case L'╒': return 213; - case L'╓': return 214; - case L'╫': return 215; - case L'╪': return 216; - case L'┘': return 217; - case L'┌': return 218; - case L'█': return 219; - case L'▄': return 220; - case L'▌': return 221; - case L'▐': return 222; - case L'▀': return 223; - case L'α': return 224; - case L'ß': return 225; - case L'Γ': return 226; - case L'π': return 227; - case L'Σ': return 228; - case L'σ': return 229; - case L'µ': return 230; - case L'τ': return 231; - case L'Φ': return 232; - case L'Θ': return 233; - case L'Ω': return 234; - case L'δ': return 235; - case L'∞': return 236; - case L'φ': return 237; - case L'ε': return 238; - case L'∩': return 239; - case L'≡': return 240; - case L'±': return 241; - case L'≥': return 242; - case L'≤': return 243; - case L'⌠': return 244; - case L'⌡': return 245; - case L'÷': return 246; - case L'≈': return 247; - case L'°': return 248; - case L'∙': return 249; - case L'·': return 250; - case L'√': return 251; - case L'ⁿ': return 252; - case L'²': return 253; - case L'■': return 254; - } - return 4; -} +#include "apps/ununicode.h" /* Write a character to the window. */ static void term_write_char(uint32_t val, uint16_t x, uint16_t y, uint32_t fg, uint32_t bg, uint8_t flags) { @@ -801,12 +636,9 @@ static void term_write_char(uint32_t val, uint16_t x, uint16_t y, uint32_t fg, u /* Draw glyphs */ if (_use_aa && !_have_freetype) { - /* Convert other unicode characters. */ - if (val > 128) { - val = ununicode(val); - } /* Draw using the Toaru SDF rendering library */ - char tmp[2] = {val,0}; + char tmp[7]; + to_eight(val, tmp); for (uint8_t i = 0; i < char_height; ++i) { for (uint8_t j = 0; j < char_width; ++j) { term_set_point(x+j,y+i,_bg); diff --git a/apps/ununicode.h b/apps/ununicode.h new file mode 100644 index 00000000..c7a185f4 --- /dev/null +++ b/apps/ununicode.h @@ -0,0 +1,167 @@ +/* Commonly used by a few different things. */ +static uint32_t ununicode(uint32_t c) { + switch (c) { + case L'☺': return 1; + case L'☻': return 2; + case L'♥': return 3; + case L'♦': return 4; + case L'♣': return 5; + case L'♠': return 6; + case L'•': return 7; + case L'◘': return 8; + case L'○': return 9; + case L'◙': return 10; + case L'♂': return 11; + case L'♀': return 12; + case L'♪': return 13; + case L'♫': return 14; + case L'☼': return 15; + case L'►': return 16; + case L'◄': return 17; + case L'↕': return 18; + case L'‼': return 19; + case L'¶': return 20; + case L'§': return 21; + case L'▬': return 22; + case L'↨': return 23; + case L'↑': return 24; + case L'↓': return 25; + case L'→': return 26; + case L'←': return 27; + case L'∟': return 28; + case L'↔': return 29; + case L'▲': return 30; + case L'▼': return 31; + /* ASCII text */ + case L'⌂': return 127; + case L'Ç': return 128; + case L'ü': return 129; + case L'é': return 130; + case L'â': return 131; + case L'ä': return 132; + case L'à': return 133; + case L'å': return 134; + case L'ç': return 135; + case L'ê': return 136; + case L'ë': return 137; + case L'è': return 138; + case L'ï': return 139; + case L'î': return 140; + case L'ì': return 141; + case L'Ä': return 142; + case L'Å': return 143; + case L'É': return 144; + case L'æ': return 145; + case L'Æ': return 146; + case L'ô': return 147; + case L'ö': return 148; + case L'ò': return 149; + case L'û': return 150; + case L'ù': return 151; + case L'ÿ': return 152; + case L'Ö': return 153; + case L'Ü': return 154; + case L'¢': return 155; + case L'£': return 156; + case L'¥': return 157; + case L'₧': return 158; + case L'ƒ': return 159; + case L'á': return 160; + case L'í': return 161; + case L'ó': return 162; + case L'ú': return 163; + case L'ñ': return 164; + case L'Ñ': return 165; + case L'ª': return 166; + case L'º': return 167; + case L'¿': return 168; + case L'⌐': return 169; + case L'¬': return 170; + case L'½': return 171; + case L'¼': return 172; + case L'¡': return 173; + case L'«': return 174; + case L'»': return 175; + case L'░': return 176; + case L'▒': return 177; + case L'▓': return 178; + case L'│': return 179; + case L'┤': return 180; + case L'╡': return 181; + case L'╢': return 182; + case L'╖': return 183; + case L'╕': return 184; + case L'╣': return 185; + case L'║': return 186; + case L'╗': return 187; + case L'╝': return 188; + case L'╜': return 189; + case L'╛': return 190; + case L'┐': return 191; + case L'└': return 192; + case L'┴': return 193; + case L'┬': return 194; + case L'├': return 195; + case L'─': return 196; + case L'┼': return 197; + case L'╞': return 198; + case L'╟': return 199; + case L'╚': return 200; + case L'╔': return 201; + case L'╩': return 202; + case L'╦': return 203; + case L'╠': return 204; + case L'═': return 205; + case L'╬': return 206; + case L'╧': return 207; + case L'╨': return 208; + case L'╤': return 209; + case L'╥': return 210; + case L'╙': return 211; + case L'╘': return 212; + case L'╒': return 213; + case L'╓': return 214; + case L'╫': return 215; + case L'╪': return 216; + case L'┘': return 217; + case L'┌': return 218; + case L'█': return 219; + case L'▄': return 220; + case L'▌': return 221; + case L'▐': return 222; + case L'▀': return 223; + case L'α': return 224; + case L'ß': return 225; + case L'Γ': return 226; + case L'π': return 227; + case L'Σ': return 228; + case L'σ': return 229; + case L'µ': return 230; + case L'τ': return 231; + case L'Φ': return 232; + case L'Θ': return 233; + case L'Ω': return 234; + case L'δ': return 235; + case L'∞': return 236; + case L'φ': return 237; + case L'ε': return 238; + case L'∩': return 239; + case L'≡': return 240; + case L'±': return 241; + case L'≥': return 242; + case L'≤': return 243; + case L'⌠': return 244; + case L'⌡': return 245; + case L'÷': return 246; + case L'≈': return 247; + case L'°': return 248; + case L'∙': return 249; + case L'·': return 250; + case L'√': return 251; + case L'ⁿ': return 252; + case L'²': return 253; + case L'■': return 254; + } + return 4; +} + diff --git a/lib/sdf.c b/lib/sdf.c index 14c9bd98..b9b6e3e7 100644 --- a/lib/sdf.c +++ b/lib/sdf.c @@ -14,6 +14,9 @@ #include #include #include +#include + +#include "apps/ununicode.h" #define BASE_WIDTH 50 #define BASE_HEIGHT 50 @@ -135,25 +138,26 @@ static sprite_t * _select_font(int font) { } } -static int _select_width(char ch, int font) { +static int _select_width(int _ch, int font) { + int ch = (_ch >= 0 && _ch <= 128) ? _ch : (int)ununicode(_ch); switch (font) { case SDF_FONT_BOLD: case SDF_FONT_BOLD_OBLIQUE: - return _char_data[(int)ch].width_bold; + return _char_data[ch].width_bold; case SDF_FONT_MONO: case SDF_FONT_MONO_BOLD: case SDF_FONT_MONO_OBLIQUE: case SDF_FONT_MONO_BOLD_OBLIQUE: - return _char_data[(int)ch].width_mono; + return _char_data[ch].width_mono; case SDF_FONT_OBLIQUE: case SDF_FONT_THIN: default: - return _char_data[(int)ch].width_thin; + return _char_data[ch].width_thin; } } -static int draw_sdf_character(gfx_context_t * ctx, int32_t x, int32_t y, int ch, int size, uint32_t color, sprite_t * tmp, int font, sprite_t * _font_data, double buffer) { - if (ch < 0 || ch > 255) return 0; +static int draw_sdf_character(gfx_context_t * ctx, int32_t x, int32_t y, int _ch, int size, uint32_t color, sprite_t * tmp, int font, sprite_t * _font_data, double buffer) { + int ch = (_ch >= 0 && _ch <= 128) ? _ch : (int)ununicode(_ch); double scale = (double)size / 50.0; int width = _select_width(ch, font) * scale; @@ -212,12 +216,16 @@ int draw_sdf_string_stroke(gfx_context_t * ctx, int32_t x, int32_t y, const char tmp = hashmap_get(_font_cache, (void *)(scale_height | (font << 16))); } + uint32_t state = 0; + uint32_t c = 0; int32_t out_width = 0; gamma = _gamma; while (*str) { - int w = draw_sdf_character(ctx,x,y,*((uint8_t *)str),size,color,tmp,font,_font_data, stroke); - out_width += w; - x += w; + if (!decode(&state, &c, (unsigned char)*str)) { + int w = draw_sdf_character(ctx,x,y,c,size,color,tmp,font,_font_data, stroke); + out_width += w; + x += w; + } str++; } spin_unlock(&_sdf_lock); @@ -233,7 +241,7 @@ int draw_sdf_string(gfx_context_t * ctx, int32_t x, int32_t y, const char * str, return draw_sdf_string_stroke(ctx,x,y,str,size,color,font,1.7, 0.75); } -static int char_width(char ch, int font) { +static int char_width(int ch, int font) { return _select_width(ch, font); } @@ -241,10 +249,17 @@ static int char_width(char ch, int font) { int draw_sdf_string_width(const char * str, int size, int font) { double scale = (double)size / 50.0; + uint32_t state = 0; + uint32_t c = 0; + int32_t out_width = 0; while (*str) { - int w = char_width(*str,font) * scale; - out_width += w; + if (!decode(&state, &c, (unsigned char)*str)) { + int w = char_width(c,font) * scale; + out_width += w; + } else if (state == UTF8_REJECT) { + state = 0; + } str++; }