opuntiaOS - an operating system targeting x86 and ARMv7
at master 3.5 kB view raw
1/* 2 * Copyright (C) 2020-2022 The opuntiaOS Project Authors. 3 * + Contributed by Nikita Melekhin <nimelehin@gmail.com> 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#include <fcntl.h> 10#include <libfoundation/Logger.h> 11#include <libg/Font.h> 12#include <new> 13#include <string.h> 14#include <sys/mman.h> 15#include <sys/stat.h> 16#include <unistd.h> 17 18namespace LG { 19 20/* SerenityOS font header */ 21struct [[gnu::packed]] FontFileHeader { 22 char magic[4]; 23 uint8_t glyph_width; 24 uint8_t glyph_height; 25 uint16_t range_mask_size; 26 uint8_t is_variable_width; 27 uint8_t glyph_spacing; 28 uint8_t baseline; 29 uint8_t mean_line; 30 uint8_t presentation_size; 31 uint16_t weight; 32 uint8_t slope; 33 char name[32]; 34 char family[32]; 35}; 36 37Font& Font::system_font(int size) 38{ 39 const int buf_size = 40; 40 char buf[buf_size]; 41 static Font* s_system_font_ptr[SystemMaxSize + 1]; 42 const static char* s_system_font_path = "/res/fonts/system.font/%d/regular.font"; 43 snprintf(buf, buf_size, s_system_font_path, size); 44 if (!s_system_font_ptr[size]) { 45 s_system_font_ptr[size] = Font::load_from_file(buf); 46 } 47 return *s_system_font_ptr[size]; 48} 49 50Font& Font::system_bold_font(int size) 51{ 52 const int buf_size = 40; 53 char buf[buf_size]; 54 static Font* s_system_bold_font_ptr[SystemMaxSize + 1]; 55 const static char* s_system_bold_font_path = "/res/fonts/system.font/%d/bold.font"; 56 snprintf(buf, buf_size, s_system_bold_font_path, size); 57 if (!s_system_bold_font_ptr[size]) { 58 s_system_bold_font_ptr[size] = Font::load_from_file(buf); 59 } 60 return *s_system_bold_font_ptr[size]; 61} 62 63Font::Font(uint32_t* raw_data, uint8_t* width_data, uint8_t width, uint8_t height, size_t count, bool dynamic_width, uint8_t glyph_spacing) 64 : m_raw_data(raw_data) 65 , m_width_data(width_data) 66 , m_width(width) 67 , m_height(height) 68 , m_count(count) 69 , m_dynamic_width(dynamic_width) 70 , m_spacing(glyph_spacing) 71{ 72} 73 74Font* Font::load_from_file(const char* path) 75{ 76 int fd = open(path, O_RDONLY); 77 if (fd < 0) { 78 return nullptr; 79 } 80 81 fstat_t stat; 82 fstat(fd, &stat); 83 84 uint8_t* ptr = (uint8_t*)mmap(NULL, stat.size, PROT_READ, MAP_PRIVATE, fd, 0); 85 auto* res = Font::load_from_mem(ptr); 86 87 close(fd); 88 return res; 89} 90 91Font* Font::load_from_mem(uint8_t* font_data) 92{ 93 if (!font_data) { 94 return nullptr; 95 } 96 97 FontFileHeader& header = *(FontFileHeader*)font_data; 98 99 if (memcmp((uint8_t*)header.magic, (const uint8_t*)"!Fnt", 4)) { 100 Logger::debug << "Font unsupported" << std::endl; 101 return nullptr; 102 } 103 104 size_t count = 0; 105 uint8_t* range_mask = const_cast<uint8_t*>(font_data + sizeof(FontFileHeader)); 106 for (size_t i = 0; i < header.range_mask_size; ++i) 107 count += 256 * __builtin_popcount(range_mask[i]); 108 109 size_t bytes_per_glyph = sizeof(uint32_t) * header.glyph_height; 110 111 uint32_t* raw_data = (uint32_t*)(range_mask + header.range_mask_size); 112 uint8_t* width_data = nullptr; 113 if (header.is_variable_width) { 114 width_data = (uint8_t*)((uint8_t*)(raw_data) + count * bytes_per_glyph); 115 } 116 117 return new Font(raw_data, width_data, header.glyph_width, header.glyph_height, count, header.is_variable_width, header.glyph_spacing); 118} 119 120GlyphBitmap Font::glyph_bitmap(size_t ch) const 121{ 122 return GlyphBitmap(&m_raw_data[ch * m_height], glyph_width(ch), m_height); 123} 124 125} // namespace LG