From 0501f3bd99847aa0b477528258ab2235af5f1e67 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Fri, 31 May 2024 10:47:05 +0300 Subject: [PATCH] Kernel: Move font code to its own library LibFont --- CMakeLists.txt | 3 + LibFont/CMakeLists.txt | 24 ++++ {kernel/kernel => LibFont}/Font.cpp | 80 +++++++++----- .../kernel => LibFont/include/LibFont}/Font.h | 12 +- kernel/CMakeLists.txt | 6 +- kernel/include/kernel/Terminal/TTY.h | 2 +- .../include/kernel/Terminal/TerminalDriver.h | 103 +++++++++--------- kernel/include/kernel/Terminal/VirtualTTY.h | 2 +- kernel/kernel/Debug.cpp | 4 +- kernel/kernel/Terminal/VirtualTTY.cpp | 2 +- kernel/kernel/kernel.cpp | 2 +- 11 files changed, 155 insertions(+), 85 deletions(-) create mode 100644 LibFont/CMakeLists.txt rename {kernel/kernel => LibFont}/Font.cpp (76%) rename {kernel/include/kernel => LibFont/include/LibFont}/Font.h (68%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4987a9a3..020cfb8c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ add_subdirectory(bootloader) add_subdirectory(BAN) add_subdirectory(libc) add_subdirectory(LibELF) +add_subdirectory(LibFont) add_subdirectory(LibGUI) add_subdirectory(LibInput) add_subdirectory(userspace) @@ -35,6 +36,7 @@ add_custom_target(headers DEPENDS ban-headers DEPENDS libc-headers DEPENDS libelf-headers + DEPENDS libfont-headers DEPENDS libgui-headers DEPENDS libinput-headers ) @@ -45,6 +47,7 @@ add_custom_target(install-sysroot DEPENDS libc-install DEPENDS userspace-install DEPENDS libelf-install + DEPENDS libfont-install DEPENDS libgui-install DEPENDS libinput-install ) diff --git a/LibFont/CMakeLists.txt b/LibFont/CMakeLists.txt new file mode 100644 index 00000000..3f48a852 --- /dev/null +++ b/LibFont/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.26) + +project(libfont CXX) + +set(LIBGUI_SOURCES + Font.cpp +) + +add_custom_target(libfont-headers + COMMAND ${CMAKE_COMMAND} -E copy_directory_if_different ${CMAKE_CURRENT_SOURCE_DIR}/include/ ${BANAN_INCLUDE}/ + DEPENDS sysroot +) + +add_library(libfont ${LIBGUI_SOURCES}) +add_dependencies(libfont headers libc-install) +target_link_libraries(libfont PUBLIC libc) + +add_custom_target(libfont-install + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_BINARY_DIR}/libfont.a ${BANAN_LIB}/ + DEPENDS libfont + BYPRODUCTS ${BANAN_LIB}/libfont.a +) + +set(CMAKE_STATIC_LIBRARY_PREFIX "") diff --git a/kernel/kernel/Font.cpp b/LibFont/Font.cpp similarity index 76% rename from kernel/kernel/Font.cpp rename to LibFont/Font.cpp index ccfc8d46..6a3a742b 100644 --- a/kernel/kernel/Font.cpp +++ b/LibFont/Font.cpp @@ -1,9 +1,13 @@ +#include #include #include #include -#include + +#include + +#if __is_kernel #include -#include +#endif #include @@ -23,59 +27,86 @@ #define PSF2_STARTSEQ 0xFE #define PSF2_SEPARATOR 0xFF +#if __is_kernel extern uint8_t _binary_font_prefs_psf_start[]; extern uint8_t _binary_font_prefs_psf_end[]; +#endif -namespace Kernel +namespace LibFont { +#if __is_kernel BAN::ErrorOr Font::prefs() { size_t font_data_size = _binary_font_prefs_psf_end - _binary_font_prefs_psf_start; - BAN::Span font_data(_binary_font_prefs_psf_start, font_data_size); - return parse_psf1(font_data); + return parse_psf1(BAN::ConstByteSpan(_binary_font_prefs_psf_start, font_data_size)); } +#endif BAN::ErrorOr Font::load(BAN::StringView path) { - auto inode = TRY(VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, O_RDONLY)).inode; - BAN::Vector file_data; - TRY(file_data.resize(inode->size())); - TRY(inode->read(0, file_data.span())); +#if __is_kernel + auto inode = TRY(Kernel::VirtualFileSystem::get().file_from_absolute_path({ 0, 0, 0, 0 }, path, O_RDONLY)).inode; + TRY(file_data.resize(inode->size())); + TRY(inode->read(0, BAN::ByteSpan(file_data.span()))); +#else + char path_buffer[PATH_MAX]; + strncpy(path_buffer, path.data(), path.size()); + path_buffer[path.size()] = '\0'; + + int fd = open(path_buffer, O_RDONLY); + if (fd == -1) + return BAN::Error::from_errno(errno); + BAN::ScopeGuard file_closer([fd] { close(fd); }); + + struct stat st; + if (fstat(fd, &st) == -1) + return BAN::Error::from_errno(errno); + TRY(file_data.resize(st.st_size)); + + ssize_t total_read = 0; + while (total_read < st.st_size) + { + ssize_t nread = read(fd, file_data.data() + total_read, st.st_size - total_read); + if (nread == -1) + return BAN::Error::from_errno(errno); + total_read += nread; + } +#endif if (file_data.size() < 4) - return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); + return BAN::Error::from_errno(EINVAL); if (file_data[0] == PSF1_MAGIC0 && file_data[1] == PSF1_MAGIC1) - return TRY(parse_psf1(file_data.span())); + return TRY(parse_psf1(BAN::ConstByteSpan(file_data.span()))); 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(BAN::ConstByteSpan(file_data.span()))); - return BAN::Error::from_error_code(ErrorCode::Font_Unsupported); + return BAN::Error::from_errno(ENOTSUP); } - BAN::ErrorOr Font::parse_psf1(BAN::Span font_data) + BAN::ErrorOr Font::parse_psf1(BAN::ConstByteSpan font_data) { - if (font_data.size() < 4) - return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); - struct PSF1Header { uint8_t magic[2]; uint8_t mode; uint8_t char_size; }; - const PSF1Header& header = *(const PSF1Header*)font_data.data(); + + if (font_data.size() < sizeof(PSF1Header)) + return BAN::Error::from_errno(EINVAL); + const auto& header = font_data.as(); uint32_t glyph_count = header.mode & PSF1_MODE512 ? 512 : 256; uint32_t glyph_size = header.char_size; uint32_t glyph_data_size = glyph_size * glyph_count; if (font_data.size() < sizeof(PSF1Header) + glyph_data_size) - return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); + return BAN::Error::from_errno(EINVAL); BAN::Vector glyph_data; TRY(glyph_data.resize(glyph_data_size)); @@ -125,7 +156,7 @@ namespace Kernel } if (codepoint_redef) - dwarnln("Font contsins multiple definitions for same codepoint(s)"); + dwarnln("Font contains multiple definitions for same codepoint(s)"); if (codepoint_sequence) dwarnln("Font contains codepoint sequences (not supported)"); @@ -138,7 +169,7 @@ namespace Kernel return result; } - BAN::ErrorOr Font::parse_psf2(BAN::Span font_data) + BAN::ErrorOr Font::parse_psf2(BAN::ConstByteSpan font_data) { struct PSF2Header { @@ -153,14 +184,13 @@ namespace Kernel }; if (font_data.size() < sizeof(PSF2Header)) - return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); - - const PSF2Header& header = *(const PSF2Header*)font_data.data(); + return BAN::Error::from_errno(EINVAL); + const auto& header = font_data.as(); uint32_t glyph_data_size = header.glyph_count * header.glyph_size; if (font_data.size() < glyph_data_size + header.header_size) - return BAN::Error::from_error_code(ErrorCode::Font_FileTooSmall); + return BAN::Error::from_errno(EINVAL); BAN::Vector glyph_data; TRY(glyph_data.resize(glyph_data_size)); diff --git a/kernel/include/kernel/Font.h b/LibFont/include/LibFont/Font.h similarity index 68% rename from kernel/include/kernel/Font.h rename to LibFont/include/LibFont/Font.h index a534dfb6..87d6ad8a 100644 --- a/kernel/include/kernel/Font.h +++ b/LibFont/include/LibFont/Font.h @@ -1,17 +1,19 @@ #pragma once +#include #include -#include #include -namespace Kernel +namespace LibFont { class Font { public: - static BAN::ErrorOr load(BAN::StringView); + static BAN::ErrorOr load(BAN::StringView path); +#if __is_kernel static BAN::ErrorOr prefs(); +#endif uint32_t width() const { return m_width; } uint32_t height() const { return m_height; } @@ -21,8 +23,8 @@ namespace Kernel const uint8_t* glyph(uint32_t) const; private: - static BAN::ErrorOr parse_psf1(BAN::Span); - static BAN::ErrorOr parse_psf2(BAN::Span); + static BAN::ErrorOr parse_psf1(BAN::ConstByteSpan); + static BAN::ErrorOr parse_psf2(BAN::ConstByteSpan); private: BAN::HashMap m_glyph_offsets; diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 62446c3a..f9236e6d 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -29,7 +29,6 @@ set(KERNEL_SOURCES kernel/Device/NullDevice.cpp kernel/Device/ZeroDevice.cpp kernel/Errors.cpp - kernel/Font.cpp kernel/FS/DevFS/FileSystem.cpp kernel/FS/Ext2/FileSystem.cpp kernel/FS/Ext2/Inode.cpp @@ -149,6 +148,10 @@ set(LIBELF_SOURCES ../LibELF/LibELF/LoadableELF.cpp ) +set(LIBFONT_SOURCES + ../LibFont/Font.cpp +) + set(LIBINPUT_SOURCE ../LibInput/KeyboardLayout.cpp ../LibInput/KeyEvent.cpp @@ -160,6 +163,7 @@ set(KERNEL_SOURCES ${BAN_SOURCES} ${KLIBC_SOURCES} ${LIBELF_SOURCES} + ${LIBFONT_SOURCES} ${LIBINPUT_SOURCE} ) diff --git a/kernel/include/kernel/Terminal/TTY.h b/kernel/include/kernel/Terminal/TTY.h index 1fbbe0f6..8615ca16 100644 --- a/kernel/include/kernel/Terminal/TTY.h +++ b/kernel/include/kernel/Terminal/TTY.h @@ -16,7 +16,7 @@ namespace Kernel public: void set_termios(const termios& termios) { m_termios = termios; } termios get_termios() const { return m_termios; } - virtual void set_font(const Font&) {}; + virtual void set_font(const LibFont::Font&) {}; void set_foreground_pgrp(pid_t pgrp) { m_foreground_pgrp = pgrp; } pid_t foreground_pgrp() const { return m_foreground_pgrp; } diff --git a/kernel/include/kernel/Terminal/TerminalDriver.h b/kernel/include/kernel/Terminal/TerminalDriver.h index e31133c0..f66609f6 100644 --- a/kernel/include/kernel/Terminal/TerminalDriver.h +++ b/kernel/include/kernel/Terminal/TerminalDriver.h @@ -1,61 +1,66 @@ #pragma once -#include +#include #include -class TerminalDriver +namespace Kernel { -public: - struct Color + + class TerminalDriver { - constexpr Color(uint32_t rgb) - : rgb(rgb) - { } - constexpr Color(uint8_t r, uint8_t g, uint8_t b) - : rgb(((uint32_t)r << 16) | ((uint32_t)g << 8) | b) - { } - uint8_t red() const { return (rgb >> 0x10) & 0xFF; } - uint8_t green() const { return (rgb >> 0x08) & 0xFF; } - uint8_t blue() const { return (rgb >> 0x00) & 0xFF; } - uint32_t rgb; + public: + struct Color + { + constexpr Color(uint32_t rgb) + : rgb(rgb) + { } + constexpr Color(uint8_t r, uint8_t g, uint8_t b) + : rgb(((uint32_t)r << 16) | ((uint32_t)g << 8) | b) + { } + uint8_t red() const { return (rgb >> 0x10) & 0xFF; } + uint8_t green() const { return (rgb >> 0x08) & 0xFF; } + uint8_t blue() const { return (rgb >> 0x00) & 0xFF; } + uint32_t rgb; + }; + + public: + TerminalDriver() : m_font(MUST(LibFont::Font::prefs())) {} + virtual ~TerminalDriver() {} + virtual uint32_t width() const = 0; + virtual uint32_t height() const = 0; + + virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) = 0; + virtual void clear(Color) = 0; + + virtual void set_cursor_position(uint32_t, uint32_t) = 0; + + void set_font(const LibFont::Font& font) { m_font = font; }; + const LibFont::Font& font() const { return m_font; } + + private: + LibFont::Font m_font; }; -public: - TerminalDriver() : m_font(MUST(Kernel::Font::prefs())) {} - virtual ~TerminalDriver() {} - virtual uint32_t width() const = 0; - virtual uint32_t height() const = 0; + namespace TerminalColor + { + static constexpr TerminalDriver::Color BLACK = 0x000000; + static constexpr TerminalDriver::Color BLUE = 0x0000AA; + static constexpr TerminalDriver::Color GREEN = 0x00AA00; + static constexpr TerminalDriver::Color CYAN = 0x00AAAA; + static constexpr TerminalDriver::Color RED = 0xAA0000; + static constexpr TerminalDriver::Color MAGENTA = 0xAA00AA; + static constexpr TerminalDriver::Color YELLOW = 0xAA5500; + static constexpr TerminalDriver::Color WHITE = 0xAAAAAA; - virtual void putchar_at(uint16_t, uint32_t, uint32_t, Color, Color) = 0; - virtual void clear(Color) = 0; + static constexpr TerminalDriver::Color BRIGHT_BLACK = 0x555555; + static constexpr TerminalDriver::Color BRIGHT_BLUE = 0x5555FF; + static constexpr TerminalDriver::Color BRIGHT_GREEN = 0x55FF55; + static constexpr TerminalDriver::Color BRIGHT_CYAN = 0x55FFFF; + static constexpr TerminalDriver::Color BRIGHT_RED = 0xFF5555; + static constexpr TerminalDriver::Color BRIGHT_MAGENTA = 0xFF55FF; + static constexpr TerminalDriver::Color BRIGHT_YELLOW = 0xFFFF55; + static constexpr TerminalDriver::Color BRIGHT_WHITE = 0xFFFFFF; + } - virtual void set_cursor_position(uint32_t, uint32_t) = 0; - - void set_font(const Kernel::Font& font) { m_font = font; }; - const Kernel::Font& font() const { return m_font; } - -private: - Kernel::Font m_font; -}; - -namespace TerminalColor -{ - static constexpr TerminalDriver::Color BLACK = 0x000000; - static constexpr TerminalDriver::Color BLUE = 0x0000AA; - static constexpr TerminalDriver::Color GREEN = 0x00AA00; - static constexpr TerminalDriver::Color CYAN = 0x00AAAA; - static constexpr TerminalDriver::Color RED = 0xAA0000; - static constexpr TerminalDriver::Color MAGENTA = 0xAA00AA; - static constexpr TerminalDriver::Color YELLOW = 0xAA5500; - static constexpr TerminalDriver::Color WHITE = 0xAAAAAA; - - static constexpr TerminalDriver::Color BRIGHT_BLACK = 0x555555; - static constexpr TerminalDriver::Color BRIGHT_BLUE = 0x5555FF; - static constexpr TerminalDriver::Color BRIGHT_GREEN = 0x55FF55; - static constexpr TerminalDriver::Color BRIGHT_CYAN = 0x55FFFF; - static constexpr TerminalDriver::Color BRIGHT_RED = 0xFF5555; - static constexpr TerminalDriver::Color BRIGHT_MAGENTA = 0xFF55FF; - static constexpr TerminalDriver::Color BRIGHT_YELLOW = 0xFFFF55; - static constexpr TerminalDriver::Color BRIGHT_WHITE = 0xFFFFFF; } diff --git a/kernel/include/kernel/Terminal/VirtualTTY.h b/kernel/include/kernel/Terminal/VirtualTTY.h index a85cb490..781495a7 100644 --- a/kernel/include/kernel/Terminal/VirtualTTY.h +++ b/kernel/include/kernel/Terminal/VirtualTTY.h @@ -15,7 +15,7 @@ namespace Kernel public: static BAN::ErrorOr> create(TerminalDriver*); - virtual void set_font(const Font&) override; + virtual void set_font(const LibFont::Font&) override; virtual uint32_t height() const override { return m_height; } virtual uint32_t width() const override { return m_width; } diff --git a/kernel/kernel/Debug.cpp b/kernel/kernel/Debug.cpp index bbf4b683..08a3640e 100644 --- a/kernel/kernel/Debug.cpp +++ b/kernel/kernel/Debug.cpp @@ -8,7 +8,7 @@ #include -extern TerminalDriver* g_terminal_driver; +extern Kernel::TerminalDriver* g_terminal_driver; namespace Debug { @@ -68,6 +68,8 @@ namespace Debug void putchar(char ch) { + using namespace Kernel; + if (Kernel::Serial::has_devices()) return Kernel::Serial::putchar_any(ch); if (Kernel::TTY::is_initialized()) diff --git a/kernel/kernel/Terminal/VirtualTTY.cpp b/kernel/kernel/Terminal/VirtualTTY.cpp index 0fb90b7c..014a099a 100644 --- a/kernel/kernel/Terminal/VirtualTTY.cpp +++ b/kernel/kernel/Terminal/VirtualTTY.cpp @@ -62,7 +62,7 @@ namespace Kernel m_terminal_driver->clear(m_background); } - void VirtualTTY::set_font(const Kernel::Font& font) + void VirtualTTY::set_font(const LibFont::Font& font) { m_terminal_driver->set_font(font); diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 89c5ee3a..1d87fa3b 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -77,7 +77,7 @@ static void parse_command_line() } } -TerminalDriver* g_terminal_driver = nullptr; +Kernel::TerminalDriver* g_terminal_driver = nullptr; static void init2(void*);