From 33e997309e153c706a149f8102bd5909d51ff164 Mon Sep 17 00:00:00 2001 From: James Lambert Date: Thu, 20 Apr 2023 08:32:19 -0600 Subject: [PATCH] Start work on font rendering --- .editorconfig | 0 assets/fonts/dejavu_sans.png | Bin 0 -> 3417 bytes assets/fonts/dejavu_sans_book_8.json | 730 ++++++++++++++++++++++++ src/font/dejavusans.c | 792 +++++++++++++++++++++++++++ src/font/font.c | 23 + src/font/font.h | 29 + tools/font_converter.js | 144 +++++ 7 files changed, 1718 insertions(+) create mode 100644 .editorconfig create mode 100644 assets/fonts/dejavu_sans.png create mode 100644 assets/fonts/dejavu_sans_book_8.json create mode 100644 src/font/dejavusans.c create mode 100644 src/font/font.c create mode 100644 src/font/font.h create mode 100644 tools/font_converter.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..e69de29 diff --git a/assets/fonts/dejavu_sans.png b/assets/fonts/dejavu_sans.png new file mode 100644 index 0000000000000000000000000000000000000000..67b77bc1f7b0a22ee69b5b522b2a46692f0ede7c GIT binary patch literal 3417 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 literal 0 HcmV?d00001 diff --git a/assets/fonts/dejavu_sans_book_8.json b/assets/fonts/dejavu_sans_book_8.json new file mode 100644 index 0000000..a306b3c --- /dev/null +++ b/assets/fonts/dejavu_sans_book_8.json @@ -0,0 +1,730 @@ +{ + "config": { + "base": 10, + "bold": 0, + "charHeight": 12, + "charSpacing": 0, + "face": "DejaVu Sans", + "italic": 0, + "lineSpacing": 0, + "size": 8, + "smooth": 1, + "textureFile": "dejavu_sans_book_8.PNG", + "textureHeight": 64, + "textureWidth": 128 + }, + "kerning": [ + { + "amount": -1, + "first": 76, + "second": 84 + }, + { + "amount": -1, + "first": 76, + "second": 86 + }, + { + "amount": -1, + "first": 76, + "second": 89 + }, + { + "amount": -1, + "first": 84, + "second": 97 + }, + { + "amount": -1, + "first": 84, + "second": 99 + }, + { + "amount": -1, + "first": 84, + "second": 101 + }, + { + "amount": -1, + "first": 84, + "second": 111 + }, + { + "amount": -1, + "first": 84, + "second": 114 + }, + { + "amount": -1, + "first": 84, + "second": 115 + }, + { + "amount": -1, + "first": 84, + "second": 117 + }, + { + "amount": -1, + "first": 84, + "second": 119 + }, + { + "amount": -1, + "first": 84, + "second": 121 + }, + { + "amount": -1, + "first": 89, + "second": 97 + }, + { + "amount": -1, + "first": 89, + "second": 101 + }, + { + "amount": -1, + "first": 89, + "second": 111 + }, + { + "amount": -1, + "first": 89, + "second": 117 + } + ], + "symbols": [ + { + "height": 1, + "id": 32, + "width": 1, + "x": 1, + "xadvance": 4, + "xoffset": 0, + "y": 10, + "yoffset": 10 + }, + { + "height": 10, + "id": 108, + "width": 3, + "x": 3, + "xadvance": 3, + "xoffset": 1, + "y": 1, + "yoffset": 1 + }, + { + "height": 9, + "id": 73, + "width": 3, + "x": 7, + "xadvance": 3, + "xoffset": 1, + "y": 2, + "yoffset": 2 + }, + { + "height": 9, + "id": 105, + "width": 3, + "x": 11, + "xadvance": 3, + "xoffset": 1, + "y": 2, + "yoffset": 2 + }, + { + "height": 7, + "id": 114, + "width": 5, + "x": 15, + "xadvance": 5, + "xoffset": 1, + "y": 4, + "yoffset": 4 + }, + { + "height": 10, + "id": 102, + "width": 6, + "x": 21, + "xadvance": 4, + "xoffset": 0, + "y": 1, + "yoffset": 1 + }, + { + "height": 9, + "id": 49, + "width": 6, + "x": 28, + "xadvance": 7, + "xoffset": 1, + "y": 2, + "yoffset": 2 + }, + { + "height": 9, + "id": 70, + "width": 6, + "x": 35, + "xadvance": 6, + "xoffset": 1, + "y": 2, + "yoffset": 2 + }, + { + "height": 9, + "id": 116, + "width": 6, + "x": 42, + "xadvance": 4, + "xoffset": 0, + "y": 2, + "yoffset": 2 + }, + { + "height": 10, + "id": 98, + "width": 7, + "x": 49, + "xadvance": 7, + "xoffset": 1, + "y": 1, + "yoffset": 1 + }, + { + "height": 10, + "id": 100, + "width": 7, + "x": 57, + "xadvance": 7, + "xoffset": 0, + "y": 1, + "yoffset": 1 + }, + { + "height": 10, + "id": 104, + "width": 7, + "x": 65, + "xadvance": 7, + "xoffset": 1, + "y": 1, + "yoffset": 1 + }, + { + "height": 10, + "id": 107, + "width": 7, + "x": 73, + "xadvance": 6, + "xoffset": 1, + "y": 1, + "yoffset": 1 + }, + { + "height": 9, + "id": 50, + "width": 7, + "x": 81, + "xadvance": 7, + "xoffset": 0, + "y": 2, + "yoffset": 2 + }, + { + "height": 9, + "id": 66, + "width": 7, + "x": 89, + "xadvance": 8, + "xoffset": 1, + "y": 2, + "yoffset": 2 + }, + { + "height": 9, + "id": 69, + "width": 7, + "x": 97, + "xadvance": 7, + "xoffset": 1, + "y": 2, + "yoffset": 2 + }, + { + "height": 9, + "id": 76, + "width": 7, + "x": 105, + "xadvance": 6, + "xoffset": 1, + "y": 2, + "yoffset": 2 + }, + { + "height": 9, + "id": 80, + "width": 7, + "x": 113, + "xadvance": 7, + "xoffset": 1, + "y": 2, + "yoffset": 2 + }, + { + "height": 7, + "id": 97, + "width": 7, + "x": 1, + "xadvance": 7, + "xoffset": 0, + "y": 14, + "yoffset": 4 + }, + { + "height": 7, + "id": 99, + "width": 7, + "x": 9, + "xadvance": 6, + "xoffset": 0, + "y": 14, + "yoffset": 4 + }, + { + "height": 7, + "id": 110, + "width": 7, + "x": 17, + "xadvance": 7, + "xoffset": 1, + "y": 14, + "yoffset": 4 + }, + { + "height": 7, + "id": 115, + "width": 7, + "x": 25, + "xadvance": 6, + "xoffset": 0, + "y": 14, + "yoffset": 4 + }, + { + "height": 7, + "id": 117, + "width": 7, + "x": 33, + "xadvance": 7, + "xoffset": 0, + "y": 14, + "yoffset": 4 + }, + { + "height": 7, + "id": 122, + "width": 7, + "x": 41, + "xadvance": 6, + "xoffset": 0, + "y": 14, + "yoffset": 4 + }, + { + "height": 9, + "id": 48, + "width": 8, + "x": 49, + "xadvance": 7, + "xoffset": 0, + "y": 12, + "yoffset": 2 + }, + { + "height": 9, + "id": 51, + "width": 8, + "x": 58, + "xadvance": 7, + "xoffset": 0, + "y": 12, + "yoffset": 2 + }, + { + "height": 9, + "id": 52, + "width": 8, + "x": 67, + "xadvance": 7, + "xoffset": 0, + "y": 12, + "yoffset": 2 + }, + { + "height": 9, + "id": 53, + "width": 8, + "x": 76, + "xadvance": 7, + "xoffset": 0, + "y": 12, + "yoffset": 2 + }, + { + "height": 9, + "id": 54, + "width": 8, + "x": 85, + "xadvance": 7, + "xoffset": 0, + "y": 12, + "yoffset": 2 + }, + { + "height": 9, + "id": 55, + "width": 8, + "x": 94, + "xadvance": 7, + "xoffset": 0, + "y": 12, + "yoffset": 2 + }, + { + "height": 9, + "id": 56, + "width": 8, + "x": 103, + "xadvance": 7, + "xoffset": 0, + "y": 12, + "yoffset": 2 + }, + { + "height": 9, + "id": 57, + "width": 8, + "x": 112, + "xadvance": 7, + "xoffset": 0, + "y": 12, + "yoffset": 2 + }, + { + "height": 9, + "id": 68, + "width": 8, + "x": 1, + "xadvance": 8, + "xoffset": 1, + "y": 22, + "yoffset": 2 + }, + { + "height": 9, + "id": 72, + "width": 8, + "x": 10, + "xadvance": 8, + "xoffset": 1, + "y": 22, + "yoffset": 2 + }, + { + "height": 9, + "id": 75, + "width": 8, + "x": 19, + "xadvance": 7, + "xoffset": 1, + "y": 22, + "yoffset": 2 + }, + { + "height": 9, + "id": 78, + "width": 8, + "x": 28, + "xadvance": 8, + "xoffset": 1, + "y": 22, + "yoffset": 2 + }, + { + "height": 9, + "id": 82, + "width": 8, + "x": 37, + "xadvance": 8, + "xoffset": 1, + "y": 22, + "yoffset": 2 + }, + { + "height": 9, + "id": 83, + "width": 8, + "x": 46, + "xadvance": 7, + "xoffset": 0, + "y": 22, + "yoffset": 2 + }, + { + "height": 7, + "id": 101, + "width": 8, + "x": 55, + "xadvance": 7, + "xoffset": 0, + "y": 24, + "yoffset": 4 + }, + { + "height": 7, + "id": 111, + "width": 8, + "x": 64, + "xadvance": 7, + "xoffset": 0, + "y": 24, + "yoffset": 4 + }, + { + "height": 7, + "id": 118, + "width": 8, + "x": 73, + "xadvance": 7, + "xoffset": 0, + "y": 24, + "yoffset": 4 + }, + { + "height": 7, + "id": 120, + "width": 8, + "x": 82, + "xadvance": 7, + "xoffset": 0, + "y": 24, + "yoffset": 4 + }, + { + "height": 9, + "id": 65, + "width": 9, + "x": 91, + "xadvance": 8, + "xoffset": 0, + "y": 22, + "yoffset": 2 + }, + { + "height": 9, + "id": 67, + "width": 9, + "x": 101, + "xadvance": 8, + "xoffset": 0, + "y": 22, + "yoffset": 2 + }, + { + "height": 9, + "id": 71, + "width": 9, + "x": 111, + "xadvance": 9, + "xoffset": 0, + "y": 22, + "yoffset": 2 + }, + { + "height": 9, + "id": 77, + "width": 9, + "x": 1, + "xadvance": 9, + "xoffset": 1, + "y": 32, + "yoffset": 2 + }, + { + "height": 9, + "id": 84, + "width": 9, + "x": 11, + "xadvance": 7, + "xoffset": -1, + "y": 32, + "yoffset": 2 + }, + { + "height": 9, + "id": 85, + "width": 9, + "x": 21, + "xadvance": 8, + "xoffset": 0, + "y": 32, + "yoffset": 2 + }, + { + "height": 9, + "id": 86, + "width": 9, + "x": 31, + "xadvance": 8, + "xoffset": 0, + "y": 32, + "yoffset": 2 + }, + { + "height": 9, + "id": 88, + "width": 9, + "x": 41, + "xadvance": 8, + "xoffset": 0, + "y": 32, + "yoffset": 2 + }, + { + "height": 9, + "id": 89, + "width": 9, + "x": 51, + "xadvance": 7, + "xoffset": -1, + "y": 32, + "yoffset": 2 + }, + { + "height": 9, + "id": 90, + "width": 9, + "x": 61, + "xadvance": 8, + "xoffset": 0, + "y": 32, + "yoffset": 2 + }, + { + "height": 9, + "id": 79, + "width": 10, + "x": 71, + "xadvance": 9, + "xoffset": 0, + "y": 32, + "yoffset": 2 + }, + { + "height": 7, + "id": 109, + "width": 10, + "x": 82, + "xadvance": 11, + "xoffset": 1, + "y": 34, + "yoffset": 4 + }, + { + "height": 7, + "id": 119, + "width": 10, + "x": 93, + "xadvance": 9, + "xoffset": 0, + "y": 34, + "yoffset": 4 + }, + { + "height": 9, + "id": 87, + "width": 12, + "x": 104, + "xadvance": 11, + "xoffset": 0, + "y": 32, + "yoffset": 2 + }, + { + "height": 10, + "id": 81, + "width": 10, + "x": 1, + "xadvance": 9, + "xoffset": 0, + "y": 42, + "yoffset": 2 + }, + { + "height": 11, + "id": 74, + "width": 5, + "x": 12, + "xadvance": 3, + "xoffset": -1, + "y": 42, + "yoffset": 2 + }, + { + "height": 11, + "id": 106, + "width": 5, + "x": 18, + "xadvance": 3, + "xoffset": -1, + "y": 42, + "yoffset": 2 + }, + { + "height": 9, + "id": 103, + "width": 7, + "x": 24, + "xadvance": 7, + "xoffset": 0, + "y": 44, + "yoffset": 4 + }, + { + "height": 9, + "id": 112, + "width": 7, + "x": 32, + "xadvance": 7, + "xoffset": 1, + "y": 44, + "yoffset": 4 + }, + { + "height": 9, + "id": 113, + "width": 7, + "x": 40, + "xadvance": 7, + "xoffset": 0, + "y": 44, + "yoffset": 4 + }, + { + "height": 9, + "id": 121, + "width": 8, + "x": 48, + "xadvance": 7, + "xoffset": 0, + "y": 44, + "yoffset": 4 + } + ] +} diff --git a/src/font/dejavusans.c b/src/font/dejavusans.c new file mode 100644 index 0000000..78e3638 --- /dev/null +++ b/src/font/dejavusans.c @@ -0,0 +1,792 @@ + + +#include "font.h" + +struct FontKerning gDejaVuSansKerning[] = { + {.amount = -1, .first = 76, .second = 84}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = -1, .first = 76, .second = 86}, + {.amount = -1, .first = 84, .second = 111}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = -1, .first = 76, .second = 89}, + {.amount = -1, .first = 84, .second = 114}, + {.amount = -1, .first = 84, .second = 115}, + {.amount = -1, .first = 89, .second = 111}, + {.amount = -1, .first = 84, .second = 117}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = -1, .first = 84, .second = 119}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = -1, .first = 84, .second = 121}, + {.amount = -1, .first = 89, .second = 117}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = -1, .first = 84, .second = 97}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = -1, .first = 84, .second = 99}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = -1, .first = 84, .second = 101}, + {.amount = -1, .first = 89, .second = 97}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = 0, .first = 0, .second = 0}, + {.amount = -1, .first = 89, .second = 101}, + {.amount = 0, .first = 0, .second = 0}, +}; + + +struct FontSymbol gDejaVuSansSymbols[] = { + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 1, .y = 10, + .width = 1, .height = 1, + .xoffset = 0, .yoffset = 10, + .xadvance = 4, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 49, .y = 12, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 28, .y = 2, + .width = 6, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 81, .y = 2, + .width = 7, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 58, .y = 12, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 67, .y = 12, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 76, .y = 12, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 85, .y = 12, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 94, .y = 12, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 103, .y = 12, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 112, .y = 12, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 91, .y = 22, + .width = 9, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 89, .y = 2, + .width = 7, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 101, .y = 22, + .width = 9, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 1, .y = 22, + .width = 8, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 97, .y = 2, + .width = 7, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 35, .y = 2, + .width = 6, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 6, + }, + { + .x = 111, .y = 22, + .width = 9, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 9, + }, + { + .x = 10, .y = 22, + .width = 8, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 7, .y = 2, + .width = 3, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 3, + }, + { + .x = 12, .y = 42, + .width = 5, .height = 11, + .xoffset = -1, .yoffset = 2, + .xadvance = 3, + }, + { + .x = 19, .y = 22, + .width = 8, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 105, .y = 2, + .width = 7, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 6, + }, + { + .x = 1, .y = 32, + .width = 9, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 9, + }, + { + .x = 28, .y = 22, + .width = 8, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 71, .y = 32, + .width = 10, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 9, + }, + { + .x = 113, .y = 2, + .width = 7, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 1, .y = 42, + .width = 10, .height = 10, + .xoffset = 0, .yoffset = 2, + .xadvance = 9, + }, + { + .x = 37, .y = 22, + .width = 8, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 46, .y = 22, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 11, .y = 32, + .width = 9, .height = 9, + .xoffset = -1, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 21, .y = 32, + .width = 9, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 31, .y = 32, + .width = 9, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 104, .y = 32, + .width = 12, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 11, + }, + { + .x = 41, .y = 32, + .width = 9, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 51, .y = 32, + .width = 9, .height = 9, + .xoffset = -1, .yoffset = 2, + .xadvance = 7, + }, + { + .x = 61, .y = 32, + .width = 9, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 8, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 0, .y = 0, + .width = 0, .height = 0, + .xoffset = 0, .yoffset = 0, + .xadvance = 0, + }, + { + .x = 1, .y = 14, + .width = 7, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 49, .y = 1, + .width = 7, .height = 10, + .xoffset = 1, .yoffset = 1, + .xadvance = 7, + }, + { + .x = 9, .y = 14, + .width = 7, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 6, + }, + { + .x = 57, .y = 1, + .width = 7, .height = 10, + .xoffset = 0, .yoffset = 1, + .xadvance = 7, + }, + { + .x = 55, .y = 24, + .width = 8, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 21, .y = 1, + .width = 6, .height = 10, + .xoffset = 0, .yoffset = 1, + .xadvance = 4, + }, + { + .x = 24, .y = 44, + .width = 7, .height = 9, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 65, .y = 1, + .width = 7, .height = 10, + .xoffset = 1, .yoffset = 1, + .xadvance = 7, + }, + { + .x = 11, .y = 2, + .width = 3, .height = 9, + .xoffset = 1, .yoffset = 2, + .xadvance = 3, + }, + { + .x = 18, .y = 42, + .width = 5, .height = 11, + .xoffset = -1, .yoffset = 2, + .xadvance = 3, + }, + { + .x = 73, .y = 1, + .width = 7, .height = 10, + .xoffset = 1, .yoffset = 1, + .xadvance = 6, + }, + { + .x = 3, .y = 1, + .width = 3, .height = 10, + .xoffset = 1, .yoffset = 1, + .xadvance = 3, + }, + { + .x = 82, .y = 34, + .width = 10, .height = 7, + .xoffset = 1, .yoffset = 4, + .xadvance = 11, + }, + { + .x = 17, .y = 14, + .width = 7, .height = 7, + .xoffset = 1, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 64, .y = 24, + .width = 8, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 32, .y = 44, + .width = 7, .height = 9, + .xoffset = 1, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 40, .y = 44, + .width = 7, .height = 9, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 15, .y = 4, + .width = 5, .height = 7, + .xoffset = 1, .yoffset = 4, + .xadvance = 5, + }, + { + .x = 25, .y = 14, + .width = 7, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 6, + }, + { + .x = 42, .y = 2, + .width = 6, .height = 9, + .xoffset = 0, .yoffset = 2, + .xadvance = 4, + }, + { + .x = 33, .y = 14, + .width = 7, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 73, .y = 24, + .width = 8, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 93, .y = 34, + .width = 10, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 9, + }, + { + .x = 82, .y = 24, + .width = 8, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 48, .y = 44, + .width = 8, .height = 9, + .xoffset = 0, .yoffset = 4, + .xadvance = 7, + }, + { + .x = 41, .y = 14, + .width = 7, .height = 7, + .xoffset = 0, .yoffset = 4, + .xadvance = 6, + }, +}; + +struct Font gDejaVuSansFont = { + .kerning = &gDejaVuSansKerning[0], + .symbols = &gDejaVuSansSymbols[0], + .base = 10, + .charHeight = 12, + .symbolCount = 123, + .kerningMultiplier = 1, + .kerningMask = 0x1f, + .maxCollisions = 0, +}; + diff --git a/src/font/font.c b/src/font/font.c new file mode 100644 index 0000000..371cc4e --- /dev/null +++ b/src/font/font.c @@ -0,0 +1,23 @@ +#include "font.h" + +int fontDetermineKerning(struct Font* font, char first, char second) { + unsigned index = ((unsigned)first * (unsigned)font->kerningMultiplier + (unsigned)second) & (unsigned)font->kerningMask; + int maxIterations = font->maxCollisions; + + do { + struct FontKerning* kerning = &font->kerning[index]; + + if (kerning->amount == 0) { + return 0; + } + + if (kerning->first == first && kerning->second == second) { + return kerning->amount; + } + + ++index; + --maxIterations; + } while (maxIterations >= 0); + + return 0; +} \ No newline at end of file diff --git a/src/font/font.h b/src/font/font.h new file mode 100644 index 0000000..408d156 --- /dev/null +++ b/src/font/font.h @@ -0,0 +1,29 @@ +#ifndef __FONT_FONT_H__ +#define __FONT_FONT_H__ + +struct FontKerning { + char amount; + char first; + char second; +}; + +struct FontSymbol { + char x, y; + char width, height; + char xoffset, yoffset; + char xadvance; +}; + +struct Font { + struct FontKerning* kerning; + struct FontSymbol* symbols; + + char base; + char charHeight; + unsigned short symbolCount; + unsigned short kerningMultiplier; + unsigned short kerningMask; + unsigned short maxCollisions; +}; + +#endif \ No newline at end of file diff --git a/tools/font_converter.js b/tools/font_converter.js new file mode 100644 index 0000000..d671091 --- /dev/null +++ b/tools/font_converter.js @@ -0,0 +1,144 @@ +// this tool takes a the json output from https://github.com/andryblack/fontbuilder and create a font usabe in portal64 + +const fs = require('fs'); + +const name = process.argv[2]; +const input = JSON.parse(fs.readFileSync(process.argv[3])); + +function hashFunction(first, second, multiplier, arraySize) { + return ((first * multiplier) + second) % arraySize; +} + +function checkForCollisions(kerningList, multiplier, arraySize) { + const sparseArray = []; + sparseArray.length = arraySize; + + if (arraySize < kerningList.length) { + return null; + } + + let totalCollisions = 0; + let maxCollisions = 0; + + for (const kerning of kerningList) { + let index = hashFunction(kerning.first, kerning.second, multiplier, arraySize); + + let currentCollisions = 0; + + while (sparseArray[index]) { + index = (index + 1) % arraySize; + totalCollisions = totalCollisions + 1; + currentCollisions = currentCollisions + 1; + } + + maxCollisions = Math.max(maxCollisions, currentCollisions); + + sparseArray[index] = kerning; + } + + for (let i = 0; i < arraySize; ++i) { + if (!sparseArray[i]) { + sparseArray[i] = {amount: 0, first: 0, second: 0}; + } + } + + return {sparseArray, totalCollisions, maxCollisions}; +} + +function searchForBestKerning(kerningList) { + let result; + let multiplier; + + let arraySize = 1; + let mask = 2; + + while (arraySize < kerningList.length) { + arraySize *= 2; + mask <<= 1; + } + + arraySize *= 2; + + for (let i = 1; i < 0x10000; ++i) { + const check = checkForCollisions(kerningList, i, arraySize); + + if (!result || check.totalCollisions < result.totalCollisions) { + result = check + multiplier = i; + } + } + + console.log(`totalCollisions = ${result.totalCollisions}`); + + mask -= 1; + + return {result: result.sparseArray, multiplier: multiplier, mask: mask, totalCollisions: result.totalCollisions, maxCollisions: result.maxCollisions}; +} + +function buildKerning(kerningList) { + return `struct FontKerning g${name}Kerning[] = { +${kerningList.map(kerning => ` {.amount = ${kerning.amount}, .first = ${kerning.first}, .second = ${kerning.second}},`).join('\n')} +}; +` +} + +function buildFont(multiplier, mask, symbolCount, maxCollisions) { + return `struct Font g${name}Font = { + .kerning = &g${name}Kerning[0], + .symbols = &g${name}Symbols[0], + .base = ${input.config.base}, + .charHeight = ${input.config.charHeight}, + .symbolCount = ${symbolCount}, + .kerningMultiplier = ${multiplier}, + .kerningMask = 0x${mask.toString(16)}, + .maxCollisions = ${maxCollisions}, +}; +` +} + +function sparseSymbols(symbols) { + const result = []; + + for (let i = 0; i < symbols.length; ++i) { + result[symbols[i].id] = symbols[i]; + } + + for (let i = 0; i < result.length; ++i) { + if (!result[i]) { + result[i] = { + x: 0, y: 0, + width: 0, height: 0, + xoffset: 0, yoffset: 0, + xadvance: 0, + }; + } + } + + return result; +} + +function buildSymbol(symbol) { + return ` { + .x = ${symbol.x}, .y = ${symbol.y}, + .width = ${symbol.width}, .height = ${symbol.height}, + .xoffset = ${symbol.xoffset}, .yoffset = ${symbol.yoffset}, + .xadvance = ${symbol.xadvance}, + },` +} + +const kerningResult = searchForBestKerning(input.kerning); + +const symbols = sparseSymbols(input.symbols); + +fs.writeFileSync(process.argv[4], ` + +#include "font.h" + +${buildKerning(kerningResult.result)} + +struct FontSymbol g${name}Symbols[] = { +${symbols.map(buildSymbol).join('\n')} +}; + +${buildFont(kerningResult.multiplier, kerningResult.mask, symbols.length, kerningResult.maxCollisions)} +`); \ No newline at end of file