Kernel: Cleanup font parsing

We use now the LittleEndian<> wrapper for PSF2 header and no more
magic constants in code
This commit is contained in:
Bananymous 2023-03-20 19:46:37 +02:00
parent 9c744dfc44
commit ae9d618803
1 changed files with 38 additions and 34 deletions

View File

@ -1,3 +1,4 @@
#include <BAN/Endianness.h>
#include <BAN/ScopeGuard.h> #include <BAN/ScopeGuard.h>
#include <BAN/UTF8.h> #include <BAN/UTF8.h>
#include <kernel/Font.h> #include <kernel/Font.h>
@ -5,11 +6,21 @@
#include <fcntl.h> #include <fcntl.h>
#define PSF1_MODE_512 0x01 #define PSF1_MAGIC0 0x36
#define PSF1_MODE_HASTAB 0x02 #define PSF1_MAGIC1 0x04
#define PSF1_MODE_SEQ 0x02 #define PSF1_MODE512 0x01
#define PSF1_MODEHASTAB 0x02
#define PSF1_MODEHASSEQ 0x04
#define PSF1_STARTSEQ 0xFFFE
#define PSF1_SEPARATOR 0xFFFF
#define PSF2_HAS_UNICODE_TABLE 0x00000001 #define PSF2_MAGIC0 0x72
#define PSF2_MAGIC1 0xB5
#define PSF2_MAGIC2 0x4A
#define PSF2_MAGIC3 0x86
#define PSF2_HAS_UNICODE_TABLE 0x01
#define PSF2_STARTSEQ 0xFE
#define PSF2_SEPARATOR 0xFF
extern uint8_t _binary_font_prefs_psf_start[]; extern uint8_t _binary_font_prefs_psf_start[];
extern uint8_t _binary_font_prefs_psf_end[]; extern uint8_t _binary_font_prefs_psf_end[];
@ -37,10 +48,10 @@ namespace Kernel
if (file_data.size() < 4) if (file_data.size() < 4)
return BAN::Error::from_c_string("Font file is too small"); return BAN::Error::from_c_string("Font file is too small");
if (file_data[0] == 0x36 && file_data[1] == 0x04) if (file_data[0] == PSF1_MAGIC0 && file_data[1] == PSF1_MAGIC1)
return TRY(parse_psf1(file_data.span())); return TRY(parse_psf1(file_data.span()));
if (file_data[0] == 0x72 && file_data[1] == 0xB5 && file_data[2] == 0x4A && file_data[3] == 0x86) if (file_data[0] == PSF2_MAGIC0 && file_data[1] == PSF2_MAGIC1 && file_data[2] == PSF2_MAGIC2 && file_data[3] == PSF2_MAGIC3)
return TRY(parse_psf2(file_data.span())); return TRY(parse_psf2(file_data.span()));
return BAN::Error::from_c_string("Unsupported font format"); return BAN::Error::from_c_string("Unsupported font format");
@ -54,14 +65,14 @@ namespace Kernel
struct PSF1Header struct PSF1Header
{ {
uint16_t magic; uint8_t magic[2];
uint8_t mode; uint8_t mode;
uint8_t char_size; uint8_t char_size;
}; };
auto* header = (const PSF1Header*)(font_data.data()); const PSF1Header& header = *(const PSF1Header*)font_data.data();
uint32_t glyph_count = header->mode & PSF1_MODE_512 ? 512 : 256; uint32_t glyph_count = header.mode & PSF1_MODE512 ? 512 : 256;
uint32_t glyph_size = header->char_size; uint32_t glyph_size = header.char_size;
uint32_t glyph_data_size = glyph_size * glyph_count; uint32_t glyph_data_size = glyph_size * glyph_count;
if (font_data.size() < sizeof(PSF1Header) + glyph_data_size) if (font_data.size() < sizeof(PSF1Header) + glyph_data_size)
@ -77,7 +88,7 @@ namespace Kernel
bool codepoint_redef = false; bool codepoint_redef = false;
bool codepoint_sequence = false; bool codepoint_sequence = false;
if (header->magic & (PSF1_MODE_HASTAB | PSF1_MODE_SEQ)) if (header.mode & (PSF1_MODEHASTAB | PSF1_MODEHASSEQ))
{ {
uint32_t current_index = sizeof(PSF1Header) + glyph_data_size; uint32_t current_index = sizeof(PSF1Header) + glyph_data_size;
@ -88,12 +99,12 @@ namespace Kernel
uint16_t hi = font_data[current_index + 1]; uint16_t hi = font_data[current_index + 1];
uint16_t codepoint = (hi << 8) | lo; uint16_t codepoint = (hi << 8) | lo;
if (codepoint == 0xFFFE) if (codepoint == PSF1_STARTSEQ)
{ {
codepoint_sequence = true; codepoint_sequence = true;
break; break;
} }
else if (codepoint == 0xFFFF) else if (codepoint == PSF1_SEPARATOR)
{ {
glyph_index++; glyph_index++;
} }
@ -123,7 +134,7 @@ namespace Kernel
result.m_glyph_offsets = BAN::move(glyph_offsets); result.m_glyph_offsets = BAN::move(glyph_offsets);
result.m_glyph_data = BAN::move(glyph_data); result.m_glyph_data = BAN::move(glyph_data);
result.m_width = 8; result.m_width = 8;
result.m_height = header->char_size; result.m_height = header.char_size;
result.m_pitch = 1; result.m_pitch = 1;
return result; return result;
} }
@ -132,28 +143,20 @@ namespace Kernel
{ {
struct PSF2Header struct PSF2Header
{ {
uint32_t magic; uint8_t magic[4];
uint32_t version; BAN::LittleEndian<uint32_t> version;
uint32_t header_size; BAN::LittleEndian<uint32_t> header_size;
uint32_t flags; BAN::LittleEndian<uint32_t> flags;
uint32_t glyph_count; BAN::LittleEndian<uint32_t> glyph_count;
uint32_t glyph_size; BAN::LittleEndian<uint32_t> glyph_size;
uint32_t height; BAN::LittleEndian<uint32_t> height;
uint32_t width; BAN::LittleEndian<uint32_t> width;
}; };
if (font_data.size() < sizeof(PSF2Header)) if (font_data.size() < sizeof(PSF2Header))
return BAN::Error::from_c_string("Font file is too small"); return BAN::Error::from_c_string("Font file is too small");
PSF2Header header; const PSF2Header& header = *(const PSF2Header*)font_data.data();
header.magic = BAN::Math::little_endian_to_host<uint32_t>(font_data.data() + 0);
header.version = BAN::Math::little_endian_to_host<uint32_t>(font_data.data() + 4);
header.header_size = BAN::Math::little_endian_to_host<uint32_t>(font_data.data() + 8);
header.flags = BAN::Math::little_endian_to_host<uint32_t>(font_data.data() + 12);
header.glyph_count = BAN::Math::little_endian_to_host<uint32_t>(font_data.data() + 16);
header.glyph_size = BAN::Math::little_endian_to_host<uint32_t>(font_data.data() + 20);
header.height = BAN::Math::little_endian_to_host<uint32_t>(font_data.data() + 24);
header.width = BAN::Math::little_endian_to_host<uint32_t>(font_data.data() + 28);
uint32_t glyph_data_size = header.glyph_count * header.glyph_size; uint32_t glyph_data_size = header.glyph_count * header.glyph_size;
@ -180,12 +183,12 @@ namespace Kernel
{ {
uint8_t byte = font_data[i]; uint8_t byte = font_data[i];
if (byte == 0xFE) if (byte == PSF2_STARTSEQ)
{ {
codepoint_sequence = true; codepoint_sequence = true;
break; break;
} }
else if (byte == 0xFF) else if (byte == PSF2_SEPARATOR)
{ {
if (byte_index) if (byte_index)
{ {
@ -198,6 +201,7 @@ namespace Kernel
{ {
ASSERT(byte_index < 4); ASSERT(byte_index < 4);
bytes[byte_index++] = byte; bytes[byte_index++] = byte;
uint32_t len = BAN::utf8_byte_length(bytes[0]); uint32_t len = BAN::utf8_byte_length(bytes[0]);
if (len == 0) if (len == 0)
@ -228,7 +232,7 @@ namespace Kernel
if (invalid_utf) if (invalid_utf)
dwarnln("Font contains invalid UTF-8 codepoint(s)"); dwarnln("Font contains invalid UTF-8 codepoint(s)");
if (codepoint_redef) if (codepoint_redef)
dwarnln("Font contsins multiple definitions for same codepoint(s)"); dwarnln("Font contains multiple definitions for same codepoint(s)");
if (codepoint_sequence) if (codepoint_sequence)
dwarnln("Font contains codepoint sequences (not supported)"); dwarnln("Font contains codepoint sequences (not supported)");