فهرست منبع

Text renderer

Kajetan Johannes Hammerle 22 ساعت پیش
والد
کامیت
fa21b1b2b1
7فایلهای تغییر یافته به همراه391 افزوده شده و 22 حذف شده
  1. 1 0
      CMakeLists.txt
  2. 5 0
      examples/window.basic
  3. 2 1
      src/Compiler.c
  4. 55 15
      src/SystemFunctions.c
  5. 18 6
      src/Window.c
  6. 3 0
      src/Window.h
  7. 307 0
      src/WindowCharacters.c

+ 1 - 0
CMakeLists.txt

@@ -14,6 +14,7 @@ set(SRC
     "src/SystemFunctions.c"
     "src/SystemFunctions.c"
     "src/Utils.c"
     "src/Utils.c"
     "src/Window.c"
     "src/Window.c"
+    "src/WindowCharacters.c"
 )
 )
 
 
 set(COMPILER_ARGUMENTS
 set(COMPILER_ARGUMENTS

+ 5 - 0
examples/window.basic

@@ -68,6 +68,11 @@ while !shouldClose()
     end
     end
 
 
     big(x, y)
     big(x, y)
+
+    render(0, 0, c, "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
+    render(0, 8, c, "abcdefghijklmnopqrstuvwxyz")
+    render(0, 16, c, "0123456789()[]{}<>/\\?")
+    render(0, 24, c, "\"$%^&*-_=+#~.,;:|")
 end
 end
 
 
 printLine("stop")
 printLine("stop")

+ 2 - 1
src/Compiler.c

@@ -563,7 +563,8 @@ static void compileCallFunction(Context* c, Token t) {
     if(index >= 0) {
     if(index >= 0) {
         i32 args = compileCallFunctionArguments(c);
         i32 args = compileCallFunctionArguments(c);
         i32 wantedArgs = getSystemFunctionArguments(index);
         i32 wantedArgs = getSystemFunctionArguments(index);
-        if(wantedArgs >= 0 && args != wantedArgs) {
+        if((wantedArgs >= 0 && args != wantedArgs) ||
+           (wantedArgs < 0 && args < -wantedArgs)) {
             THROW_ERROR(
             THROW_ERROR(
                 "System function '%s' called with invalid amount of arguments",
                 "System function '%s' called with invalid amount of arguments",
                 t.stringValue);
                 t.stringValue);

+ 55 - 15
src/SystemFunctions.c

@@ -19,41 +19,80 @@ static u32 seed = 0;
 static bool rawMode = false;
 static bool rawMode = false;
 static struct termios originalTerminal;
 static struct termios originalTerminal;
 
 
-static void printArray(Code* c, const Value* v) {
+static void append(char** buffer, size_t* n, int change) {
+    if(change > 0) {
+        *buffer += change;
+        *n -= (size_t)change;
+    }
+}
+
+static void printUnicode(const Value* v, char** buffer, size_t* n) {
+    UTF8 u = convertUnicodeToUTF8(v->data);
+    for(u32 l = 0; l < u.length && *n > 1; l++) {
+        **buffer = u.data[l];
+        append(buffer, n, 1);
+    }
+    if(*n > 0) {
+        **buffer = '\0';
+    }
+}
+
+#define APPEND(b, n, format, ...)                                      \
+    append(b, n, snprintf(*b, *n, format __VA_OPT__(, ) __VA_ARGS__));
+
+static void printArray(
+    const Code* c, const Value* v, char** buffer, size_t* n) {
     if(v->data == -1) {
     if(v->data == -1) {
-        printf("null array");
+        APPEND(buffer, n, "null array");
         return;
         return;
     }
     }
     Allocation* a = memoryConvertToPointer(v->data);
     Allocation* a = memoryConvertToPointer(v->data);
     Value* end = a->values + a->values[0].data + 1;
     Value* end = a->values + a->values[0].data + 1;
     for(Value* i = a->values + 1; i != end; i++) {
     for(Value* i = a->values + 1; i != end; i++) {
         switch(i->type) {
         switch(i->type) {
-            case VT_INT32: {
-                UTF8 u = convertUnicodeToUTF8(i->data);
-                for(u32 l = 0; l < u.length; l++) {
-                    putchar(u.data[l]);
-                }
-                break;
-            }
-            case VT_ARRAY: printf("array"); break;
+            case VT_INT32: printUnicode(i, buffer, n); break;
+            case VT_ARRAY: APPEND(buffer, n, "array"); break;
             case VT_CONSTANT_STRING:
             case VT_CONSTANT_STRING:
-                printf("%s", c->code.data + i->data);
+                APPEND(buffer, n, "%s", c->code.data + i->data);
                 break;
                 break;
         }
         }
     }
     }
 }
 }
 
 
-static bool sfPrint(Code* c, Value* r, Value* vs, i32 n) {
+static void print(const Code* c, Value* vs, i32 n, char* buffer, size_t bn) {
     for(i32 i = 0; i < n; i++) {
     for(i32 i = 0; i < n; i++) {
         Value* v = vs + i;
         Value* v = vs + i;
         switch(v->type) {
         switch(v->type) {
-            case VT_INT32: printf("%d", v->data); break;
-            case VT_ARRAY: printArray(c, v); break;
+            case VT_INT32: APPEND(&buffer, &bn, "%d", v->data); break;
+            case VT_ARRAY: printArray(c, v, &buffer, &bn); break;
             case VT_CONSTANT_STRING:
             case VT_CONSTANT_STRING:
-                printf("%s", c->code.data + v->data);
+                APPEND(&buffer, &bn, "%s", c->code.data + v->data);
                 break;
                 break;
         }
         }
     }
     }
+}
+
+static bool sfPrint(Code* c, Value* r, Value* vs, i32 n) {
+    char buffer[1024];
+    print(c, vs, n, buffer, sizeof(buffer));
+    fputs(buffer, stdout);
+    RETURN_INT(0);
+}
+
+static bool sfRender(Code* c, Value* r, Value* vs, i32 n) {
+    i32 x = vs[0].data;
+    i32 y = vs[1].data;
+    Color color = (Color)vs[2].data;
+    char buffer[1024];
+    print(c, vs + 3, n - 3, buffer, sizeof(buffer));
+    char* s = buffer;
+    while(*s != 0) {
+        UTF8 u = {.data = {*s}, .length = 1};
+        i32 i = convertUTF8toUnicode(u);
+        windowSetCharacter(x, y, i, color);
+        x += 8;
+        s++;
+    }
     RETURN_INT(0);
     RETURN_INT(0);
 }
 }
 
 
@@ -326,6 +365,7 @@ static FunctionEntry systemFunctions[] = {
     {sfGetBlue, 1, "getBlue"},
     {sfGetBlue, 1, "getBlue"},
     {sfIsButtonDown, 1, "isButtonDown"},
     {sfIsButtonDown, 1, "isButtonDown"},
     {sfGetButtonDownTime, 1, "getButtonDownTime"},
     {sfGetButtonDownTime, 1, "getButtonDownTime"},
+    {sfRender, -4, "render"},
 };
 };
 static constexpr i32 amount = sizeof(systemFunctions) / sizeof(FunctionEntry);
 static constexpr i32 amount = sizeof(systemFunctions) / sizeof(FunctionEntry);
 
 

+ 18 - 6
src/Window.c

@@ -60,12 +60,11 @@ static const GLchar* VERTEX_SHADER_CODE =
     "out vec2 tex;\n"
     "out vec2 tex;\n"
     "void main(void) {\n"
     "void main(void) {\n"
     "    tex = pos;\n"
     "    tex = pos;\n"
-    //"    vec2 w = vec2(" STR(WIDTH) ", " STR(HEIGHT) ");\n"
-    //"    ivec2 f = ivec2(size / w);\n"
-    //"    f = ivec2(min(f.x, f.y), min(f.x, f.y));\n"
-    //"    vec2 f2 = (f * w) / size;\n"
-    //"    gl_Position = vec4(pos * f2, 0.0, 1.0);\n"
-    "    gl_Position = vec4(pos, 0.0, 1.0);\n"
+    "    vec2 w = vec2(" STR(WIDTH) ", " STR(HEIGHT) ");\n"
+    "    ivec2 f = ivec2(size / w);\n"
+    "    f = ivec2(min(f.x, f.y), min(f.x, f.y));\n"
+    "    vec2 f2 = (f * w) / size;\n"
+    "    gl_Position = vec4(pos * f2, 0.0, 1.0);\n"
     "}\n";
     "}\n";
 // clang-format on
 // clang-format on
 
 
@@ -287,3 +286,16 @@ void windowSetPixel(i32 x, i32 y, Color c) {
         pixels[y][x] = c;
         pixels[y][x] = c;
     }
     }
 }
 }
+
+void windowSetCharacter(i32 x, i32 y, i32 i, Color c) {
+    if(i < 0 || i > 255) {
+        i = 255;
+    }
+    for(int ax = 0; ax < 8; ax++) {
+        for(int ay = 0; ay < 8; ay++) {
+            if(CHARACTERS[i][ay] & (1 << (7 - ax))) {
+                windowSetPixel(x + ax, y + ay, c);
+            }
+        }
+    }
+}

+ 3 - 0
src/Window.h

@@ -29,5 +29,8 @@ typedef u16 Color;
 
 
 void windowClear(Color c);
 void windowClear(Color c);
 void windowSetPixel(i32 x, i32 y, Color c);
 void windowSetPixel(i32 x, i32 y, Color c);
+void windowSetCharacter(i32 x, i32 y, i32 i, Color c);
+
+extern const u8 CHARACTERS[256][8];
 
 
 #endif
 #endif

+ 307 - 0
src/WindowCharacters.c

@@ -0,0 +1,307 @@
+#include "Window.h"
+
+const u8 CHARACTERS[256][8] =
+    {['!'] =
+         {0b00001000, 0b00001000, 0b00001000, 0b00001000, 0b00001000,
+          0b00000000, 0b00001000, 0b00000000},
+     ['"'] =
+         {0b00010100, 0b00010100, 0b00010100, 0b00000000, 0b00000000,
+          0b00000000, 0b00000000, 0b00000000},
+     ['#'] =
+         {0b00010100, 0b00010100, 0b00111110, 0b00010100, 0b00111110,
+          0b00010100, 0b00010100, 0b00000000},
+     ['$'] =
+         {0b00001000, 0b00011110, 0b00101000, 0b00011100, 0b00001010,
+          0b00111100, 0b00001000, 0b00000000},
+     ['%'] =
+         {0b00110010, 0b00110100, 0b00000100, 0b00001000, 0b00010000,
+          0b00010110, 0b00100110, 0b00000000},
+     ['&'] =
+         {0b00001100, 0b00010100, 0b00010100, 0b00011000, 0b00110110,
+          0b00100010, 0b00011110, 0b00000000},
+     ['\''] =
+         {0b00001000, 0b00001000, 0b00001000, 0b00000000, 0b00000000,
+          0b00000000, 0b00000000, 0b00000000},
+     ['('] =
+         {0b00001100, 0b00010000, 0b00100000, 0b00100000, 0b00100000,
+          0b00010000, 0b00001100, 0b00000000},
+     [')'] =
+         {0b00110000, 0b00001000, 0b00000100, 0b00000100, 0b00000100,
+          0b00001000, 0b00110000, 0b00000000},
+     ['*'] =
+         {0b00000000, 0b00101010, 0b00011100, 0b00111110, 0b00011100,
+          0b00101010, 0b00000000, 0b00000000},
+     ['+'] =
+         {0b00000000, 0b00001000, 0b00001000, 0b00111110, 0b00001000,
+          0b00001000, 0b00000000, 0b00000000},
+     [','] =
+         {0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
+          0b00001000, 0b00001000, 0b00010000},
+     ['-'] =
+         {0b00000000, 0b00000000, 0b00000000, 0b00111110, 0b00000000,
+          0b00000000, 0b00000000, 0b00000000},
+     ['.'] =
+         {0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
+          0b00011000, 0b00011000, 0b00000000},
+     ['/'] =
+         {0b00000010, 0b00000100, 0b00000100, 0b00001000, 0b00010000,
+          0b00010000, 0b00100000, 0b00000000},
+     ['0'] =
+         {0b00011100, 0b00100010, 0b00100110, 0b00101010, 0b00110010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['1'] =
+         {0b00001000, 0b00011000, 0b00101000, 0b00001000, 0b00001000,
+          0b00001000, 0b00111100, 0b00000000},
+     ['2'] =
+         {0b00011100, 0b00100010, 0b00000010, 0b00001100, 0b00010000,
+          0b00100010, 0b00111110, 0b00000000},
+     ['3'] =
+         {0b00011100, 0b00100010, 0b00000010, 0b00011100, 0b00000010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['4'] =
+         {0b00000100, 0b00001100, 0b00010100, 0b00100100, 0b00111110,
+          0b00000100, 0b00000100, 0b00000000},
+     ['5'] =
+         {0b00111110, 0b00100000, 0b00111100, 0b00000010, 0b00000010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['6'] =
+         {0b00001110, 0b00010000, 0b00100000, 0b00111100, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['7'] =
+         {0b00111110, 0b00100010, 0b00000010, 0b00000100, 0b00001000,
+          0b00010000, 0b00100000, 0b00000000},
+     ['8'] =
+         {0b00011100, 0b00100010, 0b00100010, 0b00011100, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['9'] =
+         {0b00011100, 0b00100010, 0b00100010, 0b00011110, 0b00000010,
+          0b00000100, 0b00111000, 0b00000000},
+     [':'] =
+         {0b00000000, 0b00011000, 0b00011000, 0b00000000, 0b00000000,
+          0b00011000, 0b00011000, 0b00000000},
+     [';'] =
+         {0b00000000, 0b00011000, 0b00011000, 0b00000000, 0b00000000,
+          0b00001000, 0b00001000, 0b00010000},
+     ['<'] =
+         {0b00000100, 0b00001000, 0b00010000, 0b00100000, 0b00010000,
+          0b00001000, 0b00000100, 0b00000000},
+     ['='] =
+         {0b00000000, 0b00000000, 0b00111110, 0b00000000, 0b00000000,
+          0b00111110, 0b00000000, 0b00000000},
+     ['>'] =
+         {0b00100000, 0b00010000, 0b00001000, 0b00000100, 0b00001000,
+          0b00010000, 0b00100000, 0b00000000},
+     ['?'] =
+         {0b00011100, 0b00100010, 0b00000010, 0b00000100, 0b00001000,
+          0b00000000, 0b00001000, 0b00000000},
+     ['@'] =
+         {0b00000000, 0b00011100, 0b00100010, 0b00101010, 0b00101110,
+          0b00100000, 0b00011100, 0b00000000},
+     ['A'] =
+         {0b00011100, 0b00100010, 0b00100010, 0b00111110, 0b00100010,
+          0b00100010, 0b00100010, 0b00000000},
+     ['B'] =
+         {0b00111100, 0b00100010, 0b00100010, 0b00111100, 0b00100010,
+          0b00100010, 0b00111100, 0b00000000},
+     ['C'] =
+         {0b00011100, 0b00100010, 0b00100000, 0b00100000, 0b00100000,
+          0b00100010, 0b00011100, 0b00000000},
+     ['D'] =
+         {0b00111100, 0b00100010, 0b00100010, 0b00100010, 0b00100010,
+          0b00100010, 0b00111100, 0b00000000},
+     ['E'] =
+         {0b00111110, 0b00100000, 0b00111000, 0b00100000, 0b00100000,
+          0b00100000, 0b00111110, 0b00000000},
+     ['F'] =
+         {0b00111110, 0b00100000, 0b00111000, 0b00100000, 0b00100000,
+          0b00100000, 0b00100000, 0b00000000},
+     ['G'] =
+         {0b00011110, 0b00100000, 0b00100110, 0b00100010, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['H'] =
+         {0b00100010, 0b00100010, 0b00111110, 0b00100010, 0b00100010,
+          0b00100010, 0b00100010, 0b00000000},
+     ['I'] =
+         {0b00011100, 0b00001000, 0b00001000, 0b00001000, 0b00001000,
+          0b00001000, 0b00011100, 0b00000000},
+     ['J'] =
+         {0b00000010, 0b00000010, 0b00000010, 0b00000010, 0b00000010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['K'] =
+         {0b00100010, 0b00100100, 0b00101000, 0b00110000, 0b00101000,
+          0b00100100, 0b00100010, 0b00000000},
+     ['L'] =
+         {0b00100000, 0b00100000, 0b00100000, 0b00100000, 0b00100000,
+          0b00100000, 0b00111110, 0b00000000},
+     ['M'] =
+         {0b00100010, 0b00110110, 0b00101010, 0b00100010, 0b00100010,
+          0b00100010, 0b00100010, 0b00000000},
+     ['N'] =
+         {0b00100010, 0b00110010, 0b00101010, 0b00100110, 0b00100010,
+          0b00100010, 0b00100010, 0b00000000},
+     ['O'] =
+         {0b00011100, 0b00100010, 0b00100010, 0b00100010, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['P'] =
+         {0b00111100, 0b00100010, 0b00100010, 0b00111100, 0b00100000,
+          0b00100000, 0b00100000, 0b00000000},
+     ['Q'] =
+         {0b00011100, 0b00100010, 0b00100010, 0b00100010, 0b00100010,
+          0b00100100, 0b00011010, 0b00000000},
+     ['R'] =
+         {0b00111100, 0b00100010, 0b00100010, 0b00111100, 0b00101000,
+          0b00100100, 0b00100010, 0b00000000},
+     ['S'] =
+         {0b00011100, 0b00100010, 0b00100000, 0b00011100, 0b00000010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['T'] =
+         {0b00111110, 0b00001000, 0b00001000, 0b00001000, 0b00001000,
+          0b00001000, 0b00001000, 0b00000000},
+     ['U'] =
+         {0b00100010, 0b00100010, 0b00100010, 0b00100010, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['V'] =
+         {0b00100010, 0b00100010, 0b00010100, 0b00010100, 0b00010100,
+          0b00001000, 0b00001000, 0b00000000},
+     ['W'] =
+         {0b00100010, 0b00100010, 0b00100010, 0b00100010, 0b00101010,
+          0b00110110, 0b00100010, 0b00000000},
+     ['X'] =
+         {0b00100010, 0b00100010, 0b00010100, 0b00001000, 0b00010100,
+          0b00100010, 0b00100010, 0b00000000},
+     ['Y'] =
+         {0b00100010, 0b00100010, 0b00010100, 0b00010100, 0b00001000,
+          0b00001000, 0b00001000, 0b00000000},
+     ['Z'] =
+         {0b00111110, 0b00000010, 0b00000100, 0b00001000, 0b00010000,
+          0b00100000, 0b00111110, 0b00000000},
+     ['['] =
+         {0b00011100, 0b00010000, 0b00010000, 0b00010000, 0b00010000,
+          0b00010000, 0b00011100, 0b00000000},
+     ['\\'] =
+         {0b00100000, 0b00010000, 0b00010000, 0b00001000, 0b00000100,
+          0b00000100, 0b00000010, 0b00000000},
+     [']'] =
+         {0b00011100, 0b00000100, 0b00000100, 0b00000100, 0b00000100,
+          0b00000100, 0b00011100, 0b00000000},
+     ['^'] =
+         {0b00001000, 0b00010100, 0b00100010, 0b00000000, 0b00000000,
+          0b00000000, 0b00000000, 0b00000000},
+     ['_'] =
+         {0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
+          0b00000000, 0b00000000, 0b01111110},
+     ['`'] =
+         {0b00011000, 0b00011000, 0b00001100, 0b00000000, 0b00000000,
+          0b00000000, 0b00000000, 0b00000000},
+     ['a'] =
+         {0b00000000, 0b00000000, 0b00011010, 0b00100110, 0b00100010,
+          0b00100010, 0b00011110, 0b00000000},
+     ['b'] =
+         {0b00100000, 0b00100000, 0b00101100, 0b00110010, 0b00100010,
+          0b00100010, 0b00111100, 0b00000000},
+     ['c'] =
+         {0b00000000, 0b00000000, 0b00011100, 0b00100010, 0b00100000,
+          0b00100010, 0b00011100, 0b00000000},
+     ['d'] =
+         {0b00000010, 0b00000010, 0b00011010, 0b00100110, 0b00100010,
+          0b00100010, 0b00011110, 0b00000000},
+     ['e'] =
+         {0b00000000, 0b00000000, 0b00011100, 0b00100010, 0b00111110,
+          0b00100000, 0b00011110, 0b00000000},
+     ['f'] =
+         {0b00001100, 0b00010000, 0b00010000, 0b00111100, 0b00010000,
+          0b00010000, 0b00010000, 0b00000000},
+     ['g'] =
+         {0b00000000, 0b00000000, 0b00011110, 0b00100010, 0b00100010,
+          0b00011110, 0b00000010, 0b00111100},
+     ['h'] =
+         {0b00100000, 0b00100000, 0b00101100, 0b00110010, 0b00100010,
+          0b00100010, 0b00100010, 0b00000000},
+     ['i'] =
+         {0b00001000, 0b00000000, 0b00001000, 0b00001000, 0b00001000,
+          0b00001000, 0b00001000, 0b00000000},
+     ['j'] =
+         {0b00000010, 0b00000000, 0b00000010, 0b00000010, 0b00000010,
+          0b00100010, 0b00100010, 0b00011100},
+     ['k'] =
+         {0b00100000, 0b00100000, 0b00100100, 0b00101000, 0b00110000,
+          0b00101000, 0b00100100, 0b00000000},
+     ['l'] =
+         {0b00010000, 0b00010000, 0b00010000, 0b00010000, 0b00010000,
+          0b00010000, 0b00001100, 0b00000000},
+     ['m'] =
+         {0b00000000, 0b00000000, 0b00110100, 0b00101010, 0b00101010,
+          0b00100010, 0b00100010, 0b00000000},
+     ['n'] =
+         {0b00000000, 0b00000000, 0b00111100, 0b00100010, 0b00100010,
+          0b00100010, 0b00100010, 0b00000000},
+     ['o'] =
+         {0b00000000, 0b00000000, 0b00011100, 0b00100010, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['p'] =
+         {0b00000000, 0b00000000, 0b00101100, 0b00110010, 0b00100010,
+          0b00111100, 0b00100000, 0b00100000},
+     ['q'] =
+         {0b00000000, 0b00000000, 0b00011010, 0b00100110, 0b00100010,
+          0b00011110, 0b00000010, 0b00000010},
+     ['r'] =
+         {0b00000000, 0b00000000, 0b00101100, 0b00110010, 0b00100000,
+          0b00100000, 0b00100000, 0b00000000},
+     ['s'] =
+         {0b00000000, 0b00000000, 0b00011110, 0b00100000, 0b00011100,
+          0b00000010, 0b00111100, 0b00000000},
+     ['t'] =
+         {0b00001000, 0b00001000, 0b00111100, 0b00001000, 0b00001000,
+          0b00001000, 0b00001100, 0b00000000},
+     ['u'] =
+         {0b00000000, 0b00000000, 0b00100010, 0b00100010, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     ['v'] =
+         {0b00000000, 0b00000000, 0b00100010, 0b00100010, 0b00010100,
+          0b00010100, 0b00001000, 0b00000000},
+     ['w'] =
+         {0b00000000, 0b00000000, 0b00100010, 0b00100010, 0b00101010,
+          0b00101010, 0b00010100, 0b00000000},
+     ['x'] =
+         {0b00000000, 0b00000000, 0b00100010, 0b00010100, 0b00001000,
+          0b00010100, 0b00100010, 0b00000000},
+     ['y'] =
+         {0b00000000, 0b00000000, 0b00100010, 0b00100010, 0b00100010,
+          0b00011110, 0b00000010, 0b00111100},
+     ['z'] =
+         {0b00000000, 0b00000000, 0b00111110, 0b00000100, 0b00001000,
+          0b00010000, 0b00111110, 0b00000000},
+     ['{'] =
+         {0b00001100, 0b00010000, 0b00010000, 0b00100000, 0b00010000,
+          0b00010000, 0b00001100, 0b00000000},
+     ['|'] =
+         {0b00001000, 0b00001000, 0b00001000, 0b00001000, 0b00001000,
+          0b00001000, 0b00001000, 0b00000000},
+     ['}'] =
+         {0b00110000, 0b00001000, 0b00001000, 0b00000100, 0b00001000,
+          0b00001000, 0b00110000, 0b00000000},
+     ['~'] =
+         {0b00000000, 0b00000000, 0b00010010, 0b00101010, 0b00100100,
+          0b00000000, 0b00000000, 0b00000000},
+
+     [u'Ä'] =
+         {0b00100010, 0b00011100, 0b00100010, 0b00100010, 0b00111110,
+          0b00100010, 0b00100010, 0b00000000},
+     [u'Ö'] =
+         {0b00100010, 0b00011100, 0b00100010, 0b00100010, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     [u'Ü'] =
+         {0b00100010, 0b00000000, 0b00100010, 0b00100010, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     [u'ß'] =
+         {0b00011100, 0b00100010, 0b00100010, 0b00101100, 0b00100010,
+          0b00100010, 0b00101100, 0b00000000},
+     [u'ä'] =
+         {0b00010100, 0b00000000, 0b00011010, 0b00100110, 0b00100010,
+          0b00100010, 0b00011110, 0b00000000},
+     [u'ö'] =
+         {0b00010100, 0b00000000, 0b00011100, 0b00100010, 0b00100010,
+          0b00100010, 0b00011100, 0b00000000},
+     [u'ü'] = {
+         0b00000000, 0b00010100, 0b00000000, 0b00100010, 0b00100010, 0b00100010,
+         0b00011100, 0b00000000}};