From 8b3bd1a54b77d17704a6b90fe508effa77494ae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=BCseyin=20ASLIT=C3=9CRK?= Date: Wed, 20 May 2020 22:48:22 +0300 Subject: [PATCH] LibGfx: Font, extend fonts to 384 character to support LatinExtendedA --- Libraries/LibGfx/Font.cpp | 110 ++++++++++++++++++++++++++++++-------- Libraries/LibGfx/Font.h | 23 +++++--- 2 files changed, 104 insertions(+), 29 deletions(-) diff --git a/Libraries/LibGfx/Font.cpp b/Libraries/LibGfx/Font.cpp index 75488bda3d0..1f882bace3b 100644 --- a/Libraries/LibGfx/Font.cpp +++ b/Libraries/LibGfx/Font.cpp @@ -103,29 +103,31 @@ NonnullRefPtr Font::clone() const { size_t bytes_per_glyph = sizeof(u32) * glyph_height(); // FIXME: This is leaked! - auto* new_rows = static_cast(kmalloc(bytes_per_glyph * 256)); - memcpy(new_rows, m_rows, bytes_per_glyph * 256); - auto* new_widths = static_cast(kmalloc(256)); + auto* new_rows = static_cast(kmalloc(bytes_per_glyph * m_glyph_count)); + memcpy(new_rows, m_rows, bytes_per_glyph * m_glyph_count); + auto* new_widths = static_cast(kmalloc(m_glyph_count)); if (m_glyph_widths) - memcpy(new_widths, m_glyph_widths, 256); + memcpy(new_widths, m_glyph_widths, m_glyph_count); else - memset(new_widths, m_glyph_width, 256); - return adopt(*new Font(m_name, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing)); + memset(new_widths, m_glyph_width, m_glyph_count); + return adopt(*new Font(m_name, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing, m_type)); } -NonnullRefPtr Font::create(u8 glyph_height, u8 glyph_width, bool fixed) +NonnullRefPtr Font::create(u8 glyph_height, u8 glyph_width, bool fixed, FontTypes type) { size_t bytes_per_glyph = sizeof(u32) * glyph_height; // FIXME: This is leaked! - auto* new_rows = static_cast(malloc(bytes_per_glyph * 256)); - memset(new_rows, 0, bytes_per_glyph * 256); - auto* new_widths = static_cast(malloc(256)); - memset(new_widths, glyph_width, 256); - return adopt(*new Font("Untitled", new_rows, new_widths, fixed, glyph_width, glyph_height, 1)); + size_t count = glyph_count_by_type(type); + auto* new_rows = static_cast(malloc(bytes_per_glyph * count)); + memset(new_rows, 0, bytes_per_glyph * count); + auto* new_widths = static_cast(malloc(count)); + memset(new_widths, glyph_width, count); + return adopt(*new Font("Untitled", new_rows, new_widths, fixed, glyph_width, glyph_height, 1, type)); } -Font::Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing) +Font::Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing, FontTypes type) : m_name(name) + , m_type(type) , m_rows(rows) , m_glyph_widths(widths) , m_glyph_width(glyph_width) @@ -135,10 +137,12 @@ Font::Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_wid , m_glyph_spacing(glyph_spacing) , m_fixed_width(is_fixed_width) { + m_glyph_count = glyph_count_by_type(m_type); + if (!m_fixed_width) { u8 maximum = 0; u8 minimum = 255; - for (int i = 0; i < 256; ++i) { + for (size_t i = 0; i < m_glyph_count; ++i) { minimum = min(minimum, m_glyph_widths[i]); maximum = max(maximum, m_glyph_widths[i]); } @@ -163,13 +167,34 @@ RefPtr Font::load_from_memory(const u8* data) return nullptr; } + FontTypes type; + if (header.type == 0) + type = FontTypes::Default; + else if (header.type == 1) + type = FontTypes::LatinExtendedA; + else + ASSERT_NOT_REACHED(); + + size_t count = glyph_count_by_type(type); size_t bytes_per_glyph = sizeof(unsigned) * header.glyph_height; auto* rows = const_cast((const unsigned*)(data + sizeof(FontFileHeader))); u8* widths = nullptr; if (header.is_variable_width) - widths = (u8*)(rows) + 256 * bytes_per_glyph; - return adopt(*new Font(String(header.name), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing)); + widths = (u8*)(rows) + count * bytes_per_glyph; + return adopt(*new Font(String(header.name), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing, type)); +} + +size_t Font::glyph_count_by_type(FontTypes type) +{ + if (type == FontTypes::Default) + return 256; + + if (type == FontTypes::LatinExtendedA) + return 384; + + dbg() << "Unknown font type:" << type; + ASSERT_NOT_REACHED(); } RefPtr Font::load_from_file(const StringView& path) @@ -199,19 +224,20 @@ bool Font::write_to_file(const StringView& path) memcpy(header.magic, "!Fnt", 4); header.glyph_width = m_glyph_width; header.glyph_height = m_glyph_height; - header.type = 0; + header.type = m_type; header.is_variable_width = !m_fixed_width; header.glyph_spacing = m_glyph_spacing; memcpy(header.name, m_name.characters(), min(m_name.length(), (size_t)63)); size_t bytes_per_glyph = sizeof(unsigned) * m_glyph_height; + size_t count = glyph_count_by_type(m_type); - auto buffer = ByteBuffer::create_uninitialized(sizeof(FontFileHeader) + (256 * bytes_per_glyph) + 256); + auto buffer = ByteBuffer::create_uninitialized(sizeof(FontFileHeader) + (count * bytes_per_glyph) + count); BufferStream stream(buffer); stream << ByteBuffer::wrap(&header, sizeof(FontFileHeader)); - stream << ByteBuffer::wrap(m_rows, (256 * bytes_per_glyph)); - stream << ByteBuffer::wrap(m_glyph_widths, 256); + stream << ByteBuffer::wrap(m_rows, (count * bytes_per_glyph)); + stream << ByteBuffer::wrap(m_glyph_widths, count); ASSERT(stream.at_end()); ssize_t nwritten = write(fd, buffer.data(), buffer.size()); @@ -221,10 +247,15 @@ bool Font::write_to_file(const StringView& path) return true; } +GlyphBitmap Font::glyph_bitmap(u32 codepoint) const +{ + return GlyphBitmap(&m_rows[codepoint * m_glyph_height], { glyph_width(codepoint), m_glyph_height }); +} + int Font::glyph_or_emoji_width(u32 codepoint) const { - if (codepoint < 256) - return glyph_width((char)codepoint); + if (codepoint < m_glyph_count) + return glyph_width(codepoint); if (m_fixed_width) return m_glyph_width; @@ -266,4 +297,39 @@ int Font::width(const Utf32View& view) const return width; } +void Font::set_type(FontTypes type) +{ + if (type == m_type) + return; + + if (type == FontTypes::Default) + return; + + size_t new_glyph_count = glyph_count_by_type(type); + if (new_glyph_count <= m_glyph_count) { + m_glyph_count = new_glyph_count; + return; + } + + int item_count_to_copy = min(m_glyph_count, new_glyph_count); + + size_t bytes_per_glyph = sizeof(u32) * glyph_height(); + + auto* new_rows = static_cast(kmalloc(bytes_per_glyph * new_glyph_count)); + memset(new_rows, (unsigned)0, bytes_per_glyph * new_glyph_count); + memcpy(new_rows, m_rows, bytes_per_glyph * item_count_to_copy); + + auto* new_widths = static_cast(kmalloc(new_glyph_count)); + memset(new_widths, (u8)0, new_glyph_count); + memcpy(new_widths, m_glyph_widths, item_count_to_copy); + + kfree(m_rows); + kfree(m_glyph_widths); + + m_type = type; + m_glyph_count = new_glyph_count; + m_rows = new_rows; + m_glyph_widths = new_widths; +} + } diff --git a/Libraries/LibGfx/Font.h b/Libraries/LibGfx/Font.h index 8bbec4c830c..2dae06f4b88 100644 --- a/Libraries/LibGfx/Font.h +++ b/Libraries/LibGfx/Font.h @@ -35,6 +35,11 @@ namespace Gfx { +enum FontTypes { + Default = 0, + LatinExtendedA = 1 +}; + // FIXME: Make a MutableGlyphBitmap buddy class for FontEditor instead? class GlyphBitmap { friend class Font; @@ -77,16 +82,16 @@ public: static Font& default_bold_fixed_width_font(); NonnullRefPtr clone() const; - static NonnullRefPtr create(u8 glyph_height, u8 glyph_width, bool fixed); + static NonnullRefPtr create(u8 glyph_height, u8 glyph_width, bool fixed, FontTypes type); static RefPtr load_from_file(const StringView& path); bool write_to_file(const StringView& path); ~Font(); - GlyphBitmap glyph_bitmap(char ch) const { return GlyphBitmap(&m_rows[(u8)ch * m_glyph_height], { glyph_width(ch), m_glyph_height }); } + GlyphBitmap glyph_bitmap(u32 codepoint) const; - u8 glyph_width(char ch) const { return m_fixed_width ? m_glyph_width : m_glyph_widths[(u8)ch]; } + u8 glyph_width(size_t ch) const { return m_fixed_width ? m_glyph_width : m_glyph_widths[ch]; } int glyph_or_emoji_width(u32 codepoint) const; u8 glyph_height() const { return m_glyph_height; } u8 min_glyph_width() const { return m_min_glyph_width; } @@ -106,20 +111,24 @@ public: u8 glyph_spacing() const { return m_glyph_spacing; } void set_glyph_spacing(u8 spacing) { m_glyph_spacing = spacing; } - void set_glyph_width(char ch, u8 width) + void set_glyph_width(size_t ch, u8 width) { ASSERT(m_glyph_widths); - m_glyph_widths[(u8)ch] = width; + m_glyph_widths[ch] = width; } - int glyph_count() { return m_glyph_count; } + int glyph_count() const { return m_glyph_count; } + FontTypes type() { return m_type; } + void set_type(FontTypes type); private: - Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing); + Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing, FontTypes type); static RefPtr load_from_memory(const u8*); + static size_t glyph_count_by_type(FontTypes type); String m_name; + FontTypes m_type; size_t m_glyph_count { 256 }; unsigned* m_rows { nullptr };