summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Burakov <mburakov@mailbox.org>2021-01-13 14:27:14 +0100
committerMikhail Burakov <mburakov@mailbox.org>2021-01-13 14:27:14 +0100
commit11688cf348f283dc1f95957338137fe8dd958c71 (patch)
tree572be35a19fd41b1895a093a216609f666b20135
parentf65e4f5502d88125f145dc257ec7a012e08dd6d6 (diff)
Add text rendering and update pui interface types
-rw-r--r--.gitignore2
-rw-r--r--font.c128
-rw-r--r--font.h37
-rw-r--r--font_cp00.c1069
-rw-r--r--font_cp04.c761
-rw-r--r--main.c31
-rw-r--r--makefile8
-rw-r--r--pui.c33
-rw-r--r--pui.h12
9 files changed, 2043 insertions, 38 deletions
diff --git a/.gitignore b/.gitignore
index 07b9b75..81a908f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
*.o
.clang-format
-.clangd/
+.cache/
compile_commands.json
compile_flags.txt
convert
diff --git a/font.c b/font.c
new file mode 100644
index 0000000..f7c7380
--- /dev/null
+++ b/font.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2020 Mikhail Burakov. This file is part of Chrand.
+ *
+ * Chrand is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrand is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrand. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "font.h"
+
+extern uint32_t kCp00[256 * 3];
+extern uint32_t kCp04[256 * 3];
+
+static int GetUnicode(const char** str) {
+ const char* character = *str;
+ if ((character[0] & 0xf8) == 0xf0 && (character[1] & 0xc0) == 0x80 &&
+ (character[2] & 0xc0) == 0x80 && (character[3] & 0xc0) == 0x80) {
+ (*str) += 4;
+ return ((character[0] & 0x07) << 18) | ((character[1] & 0x3f) << 12) |
+ ((character[2] & 0x3f) << 6) | (character[3] & 0x3f);
+ }
+ if ((character[0] & 0xf0) == 0xe0 && (character[1] & 0xc0) == 0x80 &&
+ (character[2] & 0xc0) == 0x80) {
+ (*str) += 3;
+ return ((character[0] & 0x0f) << 12) | ((character[1] & 0x3f) << 6) |
+ (character[2] & 0x3f);
+ }
+ if ((character[0] & 0xe0) == 0xc0 && (character[1] & 0xc0) == 0x80) {
+ (*str) += 2;
+ return ((character[0] & 0x1f) << 6) | (character[1] & 0x3f);
+ }
+ if ((character[0] & 0x80) == 0x00) {
+ (*str) += 1;
+ return character[0];
+ }
+ return -1;
+}
+
+static size_t GlyphWidth(int point) {
+ const uint32_t* page;
+ switch (point >> 8) {
+ case 0:
+ if (point == 0x20) return 4;
+ page = kCp00;
+ break;
+ case 4:
+ page = kCp04;
+ point &= 0xff;
+ break;
+ default:
+ return 0;
+ }
+ uint32_t glyph = page[point * 3];
+ return (glyph >> 24) + 1;
+}
+
+static void BlockRender(uint32_t block, uint32_t* buffer, size_t stride,
+ uint32_t color) {
+ for (size_t counter = 31; block; block >>= 1, counter--) {
+ if (!(block & 1)) continue;
+ size_t x = counter & 0x7u;
+ size_t y = counter >> 3u;
+ buffer[x + y * stride] = color;
+ }
+}
+
+static void GlyphRender(int point, uint32_t* buffer, size_t stride,
+ uint32_t color) {
+ const uint32_t* page;
+ switch (point >> 8) {
+ case 0:
+ if (point == 0x20) return;
+ page = kCp00;
+ break;
+ case 4:
+ page = kCp04;
+ point &= 0xff;
+ break;
+ default:
+ return;
+ }
+ const uint32_t* glyph = page + point * 3;
+ BlockRender(glyph[2], buffer + stride * 7, stride, color);
+ BlockRender(glyph[1], buffer + stride * 3, stride, color);
+ BlockRender(glyph[0] & 0xffffff, buffer - stride, stride, color);
+}
+
+size_t PuiStringWidth(const char* str) {
+ size_t result = 0;
+ for (;;) {
+ int cp = GetUnicode(&str);
+ if (cp < 1) break;
+ result += GlyphWidth(cp);
+ }
+ return result;
+}
+
+size_t PuiStringCut(const char* str, size_t width) {
+ size_t result = 0;
+ for (size_t current = 0;;) {
+ const char* before = str;
+ int cp = GetUnicode(&str);
+ if (cp < 1) break;
+ current += GlyphWidth(cp);
+ if (current >= width) break;
+ result += (size_t)(str - before);
+ }
+ return result;
+}
+
+void PuiStringRender(const char* str, void* buffer, size_t stride,
+ uint32_t color) {
+ for (uint32_t* ptr = buffer;;) {
+ int cp = GetUnicode(&str);
+ if (cp < 1) break;
+ GlyphRender(cp, ptr, stride, color);
+ ptr += GlyphWidth(cp);
+ }
+}
diff --git a/font.h b/font.h
new file mode 100644
index 0000000..7bc6732
--- /dev/null
+++ b/font.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 Mikhail Burakov. This file is part of Pui.
+ *
+ * Pui is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Pui is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pui. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef CHRAND_FONT_H_
+#define CHRAND_FONT_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+size_t PuiStringWidth(const char* str);
+size_t PuiStringCut(const char* str, size_t width);
+void PuiStringRender(const char* str, void* buffer, size_t stride,
+ uint32_t color);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif // __cplusplus
+
+#endif // CHRAND_FONT_H_
diff --git a/font_cp00.c b/font_cp00.c
new file mode 100644
index 0000000..1cf9555
--- /dev/null
+++ b/font_cp00.c
@@ -0,0 +1,1069 @@
+/*
+ * Copyright (C) 2020 Mikhail Burakov. This file is part of Chrand.
+ *
+ * Chrand is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrand is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrand. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+
+#define PIXEL(op) ((uint32_t) !!(op - ' '))
+
+#define LINE(str) \
+ (PIXEL(str[0]) << 7 | PIXEL(str[1]) << 6 | PIXEL(str[2]) << 5 | \
+ PIXEL(str[3]) << 4 | PIXEL(str[4]) << 3 | PIXEL(str[5]) << 2 | \
+ PIXEL(str[6]) << 1 | PIXEL(str[7]))
+
+#define GLYPH(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, width) \
+ width << 24 | LINE(_0) << 16 | LINE(_1) << 8 | LINE(_2), \
+ LINE(_3) << 24 | LINE(_4) << 16 | LINE(_5) << 8 | LINE(_6), \
+ LINE(_7) << 24 | LINE(_8) << 16 | LINE(_9) << 8 | LINE(_a)
+
+extern const uint32_t kCp00[256 * 3];
+
+const uint32_t kCp00[256 * 3] = {
+ [0x21 * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", //
+ "# ", //
+ " ", //
+ " ", 1),
+ [0x22 * 3] = GLYPH(" ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", 3),
+ [0x23 * 3] = GLYPH(" ", //
+ " ", //
+ " # # ", //
+ "###### ", //
+ " # # ", //
+ " # # ", //
+ " # # ", //
+ "###### ", //
+ " # # ", //
+ " ", //
+ " ", 6),
+ [0x24 * 3] = GLYPH(" ", //
+ " # ", //
+ " ### ", //
+ "# # # ", //
+ "# # ", //
+ " ### ", //
+ " # # ", //
+ "# # # ", //
+ " ### ", //
+ " # ", //
+ " ", 5),
+ [0x25 * 3] = GLYPH(" ", //
+ " ", //
+ " ## # ", //
+ "# # # ", //
+ "## # ", //
+ " ", //
+ " # ## ", //
+ " # # # ", //
+ "# ## ", //
+ " ", //
+ " ", 6),
+ [0x26 * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " # # ", //
+ " # ", //
+ " # # ", //
+ "# # ", //
+ "# ## ", //
+ " ### ", //
+ " ", //
+ " ", 6),
+ [0x27 * 3] = GLYPH(" ", //
+ "## ", //
+ " # ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", 2),
+ [0x28 * 3] = GLYPH(" ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " # ", //
+ " # ", //
+ " ", 3),
+ [0x29 * 3] = GLYPH(" ", //
+ "# ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ " ", 3),
+ [0x2a * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ " # ", //
+ "# # ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", 3),
+ [0x2b * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " # ", //
+ " # ", //
+ "##### ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", //
+ " ", 5),
+ [0x2c * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ "## ", //
+ " # ", //
+ " ", 2),
+ [0x2d * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ "#### ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", 4),
+ [0x2e * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ "# ", //
+ " ", //
+ " ", 1),
+ [0x2f * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ "# ", //
+ " ", 4),
+ [0x30 * 3] = GLYPH(" ", //
+ " ", //
+ " ### ", //
+ "# # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # ", //
+ " ### ", //
+ " ", //
+ " ", 5),
+ [0x31 * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " ## ", //
+ "# # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ### ", //
+ " ", //
+ " ", 4),
+ [0x32 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ "#### ", //
+ " ", //
+ " ", 4),
+ [0x33 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x34 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "#### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 4),
+ [0x35 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ " # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x36 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x37 * 3] = GLYPH(" ", //
+ " ", //
+ "#### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 4),
+ [0x38 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x39 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x3a * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ "# ", //
+ " ", //
+ " ", 1),
+ [0x3b * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ "## ", //
+ " # ", //
+ " ", 2),
+ [0x3c * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", //
+ " ", 3),
+ [0x3d * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "#### ", //
+ " ", //
+ "#### ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", 4),
+ [0x3e * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ "# ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ " ", //
+ " ", //
+ " ", 3),
+ [0x3f * 3] = GLYPH(" ", //
+ " ", //
+ " ### ", //
+ "# # ", //
+ " # ", //
+ " ## ", //
+ " # ", //
+ " ", //
+ " # ", //
+ " ", //
+ " ", 5),
+ [0x40 * 3] = GLYPH(" ", //
+ " ", //
+ " #### ", //
+ "# # ", //
+ "# ## # ", //
+ "# ## # ", //
+ "# #### ", //
+ "# ", //
+ " #### ", //
+ " ", //
+ " ", 6),
+ [0x41 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "#### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x42 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x43 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x44 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x45 * 3] = GLYPH(" ", //
+ " ", //
+ "#### ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "#### ", //
+ " ", //
+ " ", 4),
+ [0x46 * 3] = GLYPH(" ", //
+ " ", //
+ "#### ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", //
+ " ", 4),
+ [0x47 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# ", //
+ "# ## ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " ", //
+ " ", 4),
+ [0x48 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "#### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x49 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "### ", //
+ " ", //
+ " ", 3),
+ [0x4a * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x4b * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x4c * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "#### ", //
+ " ", //
+ " ", 4),
+ [0x4d * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "## ## ", //
+ "# # # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 5),
+ [0x4e * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "## # ", //
+ "# # # ", //
+ "# ## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 5),
+ [0x4f * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x50 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", //
+ " ", 4),
+ [0x51 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " # ", //
+ " # ", 4),
+ [0x52 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x53 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# ", //
+ " ## ", //
+ " # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x54 * 3] = GLYPH(" ", //
+ " ", //
+ "##### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 5),
+ [0x55 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x56 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " # ", //
+ " ", //
+ " ", 4),
+ [0x57 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ " # # ", //
+ " ", //
+ " ", 5),
+ [0x58 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x59 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x5a * 3] = GLYPH(" ", //
+ " ", //
+ "##### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ "##### ", //
+ " ", //
+ " ", 5),
+ [0x5b * 3] = GLYPH(" ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ " ", 3),
+ [0x5c * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ "# ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", 4),
+ [0x5d * 3] = GLYPH(" ", //
+ "### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "### ", //
+ " ", 3),
+ [0x5e * 3] = GLYPH(" ", //
+ " # ", //
+ " # # ", //
+ "# # ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", 5),
+ [0x5f * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ "#### ", //
+ " ", //
+ " ", 4),
+ [0x60 * 3] = GLYPH(" ", //
+ "## ", //
+ "# ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", 2),
+ [0x61 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " ", //
+ " ", 4),
+ [0x62 * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x63 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x64 * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " # ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " ", //
+ " ", 4),
+ [0x65 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "#### ", //
+ "# ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x66 * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " # ", //
+ "### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 3),
+ [0x67 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " ## ", 4),
+ [0x68 * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x69 * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", //
+ " ", 1),
+ [0x6a * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# ", 2),
+ [0x6b * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "# # ", //
+ "# # ", //
+ "## ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x6c * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", //
+ " ", 1),
+ [0x6d * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "## # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ " ", //
+ " ", 5),
+ [0x6e * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x6f * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x70 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ "# ", //
+ "# ", 4),
+ [0x71 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " # ", 4),
+ [0x72 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", //
+ " ", 3),
+ [0x73 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# ", //
+ " ## ", //
+ " # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x74 * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " # ", //
+ "### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 3),
+ [0x75 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x76 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " # ", //
+ " ", //
+ " ", 4),
+ [0x77 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # # ", //
+ "# # # ", //
+ " # # ", //
+ " ", //
+ " ", 5),
+ [0x78 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x79 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " ## ", 4),
+ [0x7a * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "### ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ "### ", //
+ " ", //
+ " ", 3),
+ [0x7b * 3] = GLYPH(" ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", 3),
+ [0x7c * 3] = GLYPH(" ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", 1),
+ [0x7d * 3] = GLYPH(" ", //
+ "# ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# ", //
+ " ", 3),
+ [0x7e * 3] = GLYPH(" ", //
+ " ## # ", //
+ "# ## ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", //
+ " ", 6),
+};
diff --git a/font_cp04.c b/font_cp04.c
new file mode 100644
index 0000000..a657f52
--- /dev/null
+++ b/font_cp04.c
@@ -0,0 +1,761 @@
+/*
+ * Copyright (C) 2020 Mikhail Burakov. This file is part of Chrand.
+ *
+ * Chrand is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrand is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Chrand. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <stdint.h>
+
+#define PIXEL(op) ((uint32_t) !!(op - ' '))
+
+#define LINE(str) \
+ (PIXEL(str[0]) << 7 | PIXEL(str[1]) << 6 | PIXEL(str[2]) << 5 | \
+ PIXEL(str[3]) << 4 | PIXEL(str[4]) << 3 | PIXEL(str[5]) << 2 | \
+ PIXEL(str[6]) << 1 | PIXEL(str[7]))
+
+#define GLYPH(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _a, width) \
+ width << 24 | LINE(_0) << 16 | LINE(_1) << 8 | LINE(_2), \
+ LINE(_3) << 24 | LINE(_4) << 16 | LINE(_5) << 8 | LINE(_6), \
+ LINE(_7) << 24 | LINE(_8) << 16 | LINE(_9) << 8 | LINE(_a)
+
+extern const uint32_t kCp04[256 * 3];
+
+const uint32_t kCp04[256 * 3] = {
+ [0x01 * 3] = GLYPH("# # ", //
+ " ", //
+ "#### ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "#### ", //
+ " ", //
+ " ", 4),
+ [0x10 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "#### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x11 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x12 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x13 * 3] = GLYPH(" ", //
+ " ", //
+ "#### ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", //
+ " ", 4),
+ [0x14 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ " # # ", //
+ " # # ", //
+ " # # ", //
+ " # # ", //
+ "###### ", //
+ "# # ", //
+ " ", //
+ " ", 6),
+ [0x15 * 3] = GLYPH(" ", //
+ " ", //
+ "#### ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "#### ", //
+ " ", //
+ " ", 4),
+ [0x16 * 3] = GLYPH(" ", //
+ " ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ " ### ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ " ", //
+ " ", 5),
+ [0x17 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x18 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# ## ", //
+ "# # # ", //
+ "## # ", //
+ "# # ", //
+ " ", //
+ " ", 5),
+ [0x19 * 3] = GLYPH(" ### ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# ## ", //
+ "# # # ", //
+ "## # ", //
+ "# # ", //
+ " ", //
+ " ", 5),
+ [0x1a * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x1b * 3] = GLYPH(" ", //
+ " ", //
+ " # ", //
+ " # # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x1c * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "## ## ", //
+ "# # # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 5),
+ [0x1d * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "#### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x1e * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x1f * 3] = GLYPH(" ", //
+ " ", //
+ "#### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x20 * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ " ", //
+ " ", 4),
+ [0x21 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x22 * 3] = GLYPH(" ", //
+ " ", //
+ "##### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 5),
+ [0x23 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x24 * 3] = GLYPH(" ", //
+ " ", //
+ " ### ", //
+ "# # # ", //
+ "# # # ", //
+ " ### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 5),
+ [0x25 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x26 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "##### ", //
+ " # ", //
+ " ", 5),
+ [0x27 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 4),
+ [0x28 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ "##### ", //
+ " ", //
+ " ", 5),
+ [0x29 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ "###### ", //
+ " # ", //
+ " ", 6),
+ [0x2a * 3] = GLYPH(" ", //
+ " ", //
+ "### ", //
+ " # ", //
+ " # ", //
+ " ### ", //
+ " # # ", //
+ " # # ", //
+ " ### ", //
+ " ", //
+ " ", 6),
+ [0x2b * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "### # ", //
+ "# # # ", //
+ "# # # ", //
+ "### # ", //
+ " ", //
+ " ", 6),
+ [0x2c * 3] = GLYPH(" ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x2d * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ " # ", //
+ " ### ", //
+ " # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x2e * 3] = GLYPH(" ", //
+ " ", //
+ "# ## ", //
+ "# # # ", //
+ "# # # ", //
+ "### # ", //
+ "# # # ", //
+ "# # # ", //
+ "# ## ", //
+ " ", //
+ " ", 6),
+ [0x2f * 3] = GLYPH(" ", //
+ " ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x30 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " ", //
+ " ", 4),
+ [0x31 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ "# ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x32 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "## ", //
+ "# # ", //
+ "### ", //
+ "# # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x33 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ " # ", //
+ " ## ", //
+ "# ", //
+ " ### ", //
+ " ", //
+ " ", 4),
+ [0x34 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ " # ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x35 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "#### ", //
+ "# ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x36 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # # ", //
+ "# # # ", //
+ " ### ", //
+ "# # # ", //
+ "# # # ", //
+ " ", //
+ " ", 5),
+ [0x37 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ " # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x38 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " ", //
+ " ", 4),
+ [0x39 * 3] = GLYPH(" ", //
+ " ", //
+ " ## ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " ", //
+ " ", 4),
+ [0x3a * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "## ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x3b * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " # ", //
+ " # # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x3c * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "## ## ", //
+ "# # # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 5),
+ [0x3d * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "#### ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x3e * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x3f * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x40 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "### ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "### ", //
+ "# ", //
+ "# ", 4),
+ [0x41 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "# ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x42 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "### ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 3),
+ [0x43 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " ## ", 4),
+ [0x44 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ### ", //
+ "# # # ", //
+ "# # # ", //
+ "# # # ", //
+ " ### ", //
+ " # ", //
+ " # ", 5),
+ [0x45 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ " ## ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x46 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "# # ", //
+ "##### ", //
+ " # ", //
+ " ", 5),
+ [0x47 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ " ### ", //
+ " # ", //
+ " # ", //
+ " ", //
+ " ", 4),
+ [0x48 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # # ", //
+ "# # # ", //
+ "##### ", //
+ " ", //
+ " ", 5),
+ [0x49 * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "# # # ", //
+ "# # # ", //
+ "###### ", //
+ " # ", //
+ " ", 6),
+ [0x4a * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "## ", //
+ " # ", //
+ " ### ", //
+ " # # ", //
+ " ### ", //
+ " ", //
+ " ", 5),
+ [0x4b * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# # ", //
+ "# # ", //
+ "### # ", //
+ "# # # ", //
+ "### # ", //
+ " ", //
+ " ", 6),
+ [0x4c * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# ", //
+ "# ", //
+ "### ", //
+ "# # ", //
+ "### ", //
+ " ", //
+ " ", 4),
+ [0x4d * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ " ## ", //
+ "# # ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+ [0x4e * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ "# ## ", //
+ "# # # ", //
+ "### # ", //
+ "# # # ", //
+ "# ## ", //
+ " ", //
+ " ", 6),
+ [0x4f * 3] = GLYPH(" ", //
+ " ", //
+ " ", //
+ " ", //
+ " ### ", //
+ "# # ", //
+ " ### ", //
+ "# # ", //
+ "# # ", //
+ " ", //
+ " ", 4),
+ [0x51 * 3] = GLYPH(" ", //
+ " ", //
+ "# # ", //
+ " ", //
+ " ## ", //
+ "# # ", //
+ "#### ", //
+ "# ", //
+ " ## ", //
+ " ", //
+ " ", 4),
+};
diff --git a/main.c b/main.c
index 5cc4299..f29f9aa 100644
--- a/main.c
+++ b/main.c
@@ -15,16 +15,16 @@
* along with Pui. If not, see <https://www.gnu.org/licenses/>.
*/
-#include <stdlib.h>
-#include <string.h>
-
#include <err.h>
#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <wayland-client.h>
+#include "font.h"
#include "pui.h"
#include "xdg-shell.h"
@@ -113,38 +113,39 @@ static const void* CreatePui(const char* filename) {
return result;
}
-static int CreateShm(int size) {
+static int CreateShm(size_t size) {
static const char kShmName[] = "/wl_shm-pui";
int fd = shm_open(kShmName, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd == -1) err(1, "Failed to create shm");
shm_unlink(kShmName);
- if (ftruncate(fd, size)) err(1, "Failed to truncate shm");
+ if (ftruncate(fd, (off_t)size)) err(1, "Failed to truncate shm");
return fd;
}
static void RenderPui(const void* pui, int fd) {
- int width = PuiGetWidth(pui);
- int height = PuiGetHeight(pui);
- size_t size = (size_t)width * (size_t)height * 4;
+ size_t width = PuiGetWidth(pui);
+ size_t height = PuiGetHeight(pui);
+ size_t size = width * height * 4;
void* buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buffer == MAP_FAILED) err(1, "Failed to map shm");
PuiRender(pui, buffer, width, 0);
- for (int i = 0; i < width * height; i++) {
+ for (size_t i = 0; i < width * height; i++) {
uint32_t* ptr = (uint32_t*)buffer + i;
*ptr = (*ptr << 16 & 0xff0000) | (*ptr >> 16 & 0xff) | (*ptr & 0xff00);
}
+ PuiStringRender("This is just a test string", buffer, width, 0);
munmap(buffer, size);
}
static struct wl_buffer* PrepareBuffer(struct Context* ctx) {
- int width = PuiGetWidth(ctx->pui);
- int height = PuiGetHeight(ctx->pui);
- int stride = width * 4;
- int size = stride * height;
+ size_t width = PuiGetWidth(ctx->pui);
+ size_t height = PuiGetHeight(ctx->pui);
+ size_t stride = width * 4;
+ size_t size = stride * height;
int fd = CreateShm(size);
- struct wl_shm_pool* pool = wl_shm_create_pool(ctx->shm, fd, size);
+ struct wl_shm_pool* pool = wl_shm_create_pool(ctx->shm, fd, (int)size);
struct wl_buffer* buffer = wl_shm_pool_create_buffer(
- pool, 0, width, height, stride, WL_SHM_FORMAT_XRGB8888);
+ pool, 0, (int)width, (int)height, (int)stride, WL_SHM_FORMAT_XRGB8888);
wl_shm_pool_destroy(pool);
RenderPui(ctx->pui, fd);
close(fd);
diff --git a/makefile b/makefile
index b5ad669..6fd608a 100644
--- a/makefile
+++ b/makefile
@@ -1,5 +1,11 @@
target:=pui
-objects:=main.o pui.o xdg-shell.o
+objects:=\
+ font.o \
+ font_cp00.o \
+ font_cp04.o \
+ main.o \
+ pui.o \
+ xdg-shell.o
protocols:=/usr/share/wayland-protocols
wl_headers:=xdg-shell.h
diff --git a/pui.c b/pui.c
index cb89991..660ac4b 100644
--- a/pui.c
+++ b/pui.c
@@ -33,19 +33,19 @@ struct PuiElement {
static_assert(sizeof(struct PuiHeader) == 4, "Invalid PuiHeader size");
static_assert(sizeof(struct PuiElement) == 4, "Invalid PuiElement size");
-int PuiGetWidth(const void* pui_data) {
+size_t PuiGetWidth(const void* pui_data) {
const struct PuiHeader* pui_header = pui_data;
- int sx = pui_header->scale >> 4;
- return pui_header->w << sx;
+ size_t sx = pui_header->scale >> 4;
+ return (size_t)pui_header->w << sx;
}
-int PuiGetHeight(const void* pui_data) {
+size_t PuiGetHeight(const void* pui_data) {
const struct PuiHeader* pui_header = pui_data;
- int sy = pui_header->scale & 0xf;
- return pui_header->h << sy;
+ size_t sy = pui_header->scale & 0xf;
+ return (size_t)pui_header->h << sy;
}
-int PuiHitTest(const void* pui_data, int x, int y) {
+int PuiHitTest(const void* pui_data, size_t x, size_t y) {
int result = 0;
const struct PuiHeader* pui_header = pui_data;
x >>= pui_header->scale >> 4;
@@ -61,28 +61,29 @@ int PuiHitTest(const void* pui_data, int x, int y) {
return result;
}
-void PuiRender(const void* pui_data, void* buffer, int stride, int active) {
+void PuiRender(const void* pui_data, void* buffer, size_t stride, int active) {
const struct PuiHeader* pui_header = pui_data;
- int width = pui_header->w << (pui_header->scale >> 4);
- int height = pui_header->h << (pui_header->scale & 0xf);
- int elements = pui_header->count >> 4;
- int colors = pui_header->count & 0xf;
+ size_t width = PuiGetWidth(pui_data);
+ size_t height = PuiGetHeight(pui_data);
+ size_t size = width * height;
+ size_t elements = pui_header->count >> 4;
+ size_t colors = pui_header->count & 0xf;
const uint32_t* palettes[] = {
(const uint32_t*)pui_data + 1 + elements,
(const uint32_t*)pui_data + 1 + elements + colors,
};
const uint8_t* bitmap_data =
(const uint8_t*)pui_data + 4 * (1 + elements + 2 * colors);
- for (int idx = 0, counter = 0, offset = 0; offset < width * height; idx++) {
- int value = bitmap_data[idx >> 1];
+ for (size_t idx = 0, counter = 0, offset = 0; offset < size; idx++) {
+ uint8_t value = bitmap_data[idx >> 1];
if (~idx & 1) value = value >> 4;
if (value & 0x8) {
counter = counter << 3 | (value & 0x7);
continue;
}
for (counter = counter ? counter + 2 : 1; counter-- > 0; offset++) {
- int x = offset % width;
- int y = offset / width;
+ size_t x = offset % width;
+ size_t y = offset / width;
int palette = !!(PuiHitTest(pui_data, x, y) & active);
((uint32_t*)buffer)[x + y * stride] = palettes[palette][value & 0x7];
}
diff --git a/pui.h b/pui.h
index a959795..1cce5aa 100644
--- a/pui.h
+++ b/pui.h
@@ -18,17 +18,19 @@
#ifndef PUI_PUI_H_
#define PUI_PUI_H_
+#include <stddef.h>
+
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
-int PuiGetWidth(const void* pui_data);
-int PuiGetHeight(const void* pui_data);
-int PuiHitTest(const void* pui_data, int x, int y);
-void PuiRender(const void* pui_data, void* buffer, int stride, int active);
+size_t PuiGetWidth(const void* pui_data);
+size_t PuiGetHeight(const void* pui_data);
+int PuiHitTest(const void* pui_data, size_t x, size_t y);
+void PuiRender(const void* pui_data, void* buffer, size_t stride, int active);
#ifdef __cplusplus
-}
+} // extern "C"
#endif // __cplusplus
#endif // PUI_PUI_H_