From 11688cf348f283dc1f95957338137fe8dd958c71 Mon Sep 17 00:00:00 2001 From: Mikhail Burakov Date: Wed, 13 Jan 2021 14:27:14 +0100 Subject: Add text rendering and update pui interface types --- .gitignore | 2 +- font.c | 128 +++++++ font.h | 37 +++ font_cp00.c | 1069 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ font_cp04.c | 761 ++++++++++++++++++++++++++++++++++++++++++ main.c | 31 +- makefile | 8 +- pui.c | 33 +- pui.h | 12 +- 9 files changed, 2043 insertions(+), 38 deletions(-) create mode 100644 font.c create mode 100644 font.h create mode 100644 font_cp00.c create mode 100644 font_cp04.c 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 . + */ + +#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 . + */ + +#ifndef CHRAND_FONT_H_ +#define CHRAND_FONT_H_ + +#include +#include + +#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 . + */ + +#include + +#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 . + */ + +#include + +#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 . */ -#include -#include - #include #include +#include +#include #include #include #include #include +#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 + #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_ -- cgit v1.2.3