Browse Source

sdf: handle input string as utf8

K. Lange 1 year ago
parent
commit
dd180b33c0
4 changed files with 198 additions and 350 deletions
  1. 1 167
      apps/terminal-vga.c
  2. 3 171
      apps/terminal.c
  3. 167 0
      apps/ununicode.h
  4. 27 12
      lib/sdf.c

+ 1 - 167
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(

+ 3 - 171
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);

+ 167 - 0
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;
+}
+

+ 27 - 12
lib/sdf.c

@@ -14,6 +14,9 @@
 #include <toaru/hashmap.h>
 #include <toaru/sdf.h>
 #include <toaru/spinlock.h>
+#include <toaru/decodeutf8.h>
+
+#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++;
 	}