From 80b77cec384087b021012ae0ea4d3b422d75cf45 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 24 Oct 2020 17:03:39 +0200 Subject: [PATCH] LibGfx+FontEditor+Fonts: Add family, size and weight metadata to fonts This makes finding fonts from the same family much less difficult. :^) --- Applications/FontEditor/FontEditor.cpp | 69 ++++++++++++++++++++++++- Base/res/fonts/CsillaBold10.font | Bin 15822 -> 15822 bytes Base/res/fonts/CsillaBold12.font | Bin 18894 -> 18894 bytes Base/res/fonts/CsillaRegular10.font | Bin 15822 -> 15822 bytes Base/res/fonts/CsillaRegular12.font | Bin 18894 -> 18894 bytes Base/res/fonts/KaticaBold10.font | Bin 15822 -> 15822 bytes Base/res/fonts/KaticaBold12.font | Bin 20430 -> 20430 bytes Base/res/fonts/KaticaRegular10.font | Bin 15822 -> 15822 bytes Base/res/fonts/KaticaRegular12.font | Bin 20430 -> 20430 bytes Base/res/fonts/LizaBlack10.font | Bin 15822 -> 15822 bytes Base/res/fonts/LizaBlack24.font | Bin 37326 -> 37326 bytes Base/res/fonts/LizaBlack36.font | Bin 55758 -> 55758 bytes Base/res/fonts/LizaBold10.font | Bin 15822 -> 15822 bytes Base/res/fonts/LizaBold24.font | Bin 37326 -> 37326 bytes Base/res/fonts/LizaBold36.font | Bin 55758 -> 55758 bytes Base/res/fonts/LizaRegular10.font | Bin 15822 -> 15822 bytes Base/res/fonts/LizaRegular24.font | Bin 37326 -> 37326 bytes Base/res/fonts/LizaRegular36.font | Bin 55758 -> 55758 bytes Base/res/fonts/PebbletonBold14.font | Bin 21966 -> 21966 bytes Base/res/fonts/PebbletonRegular14.font | Bin 21966 -> 21966 bytes Libraries/LibGfx/Font.cpp | 53 +++++++++---------- Libraries/LibGfx/Font.h | 18 +++++-- 22 files changed, 106 insertions(+), 34 deletions(-) diff --git a/Applications/FontEditor/FontEditor.cpp b/Applications/FontEditor/FontEditor.cpp index ae7107686b..05d72fa5cb 100644 --- a/Applications/FontEditor/FontEditor.cpp +++ b/Applications/FontEditor/FontEditor.cpp @@ -121,7 +121,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& edite font_metadata_group_box.set_layout(); font_metadata_group_box.layout()->set_margins({ 5, 15, 5, 5 }); font_metadata_group_box.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); - font_metadata_group_box.set_preferred_size(0, 195); + font_metadata_group_box.set_preferred_size(0, 275); font_metadata_group_box.set_title("Font metadata"); //// Name Row @@ -143,6 +143,61 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& edite m_edited_font->set_name(name_textbox.text()); }; + //// Family Row + auto& family_container = font_metadata_group_box.add(); + family_container.set_layout(); + family_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); + family_container.set_preferred_size(0, 22); + + auto& family_label = family_container.add(); + family_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fill); + family_label.set_preferred_size(100, 0); + family_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + family_label.set_text("Family:"); + + auto& family_textbox = family_container.add(); + family_textbox.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fill); + family_textbox.set_text(m_edited_font->family()); + family_textbox.on_change = [&] { + m_edited_font->set_family(family_textbox.text()); + }; + + //// Presentation size Row + auto& presentation_size_container = font_metadata_group_box.add(); + presentation_size_container.set_layout(); + presentation_size_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); + presentation_size_container.set_preferred_size(0, 22); + + auto& presentation_size_label = presentation_size_container.add(); + presentation_size_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fill); + presentation_size_label.set_preferred_size(100, 0); + presentation_size_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + presentation_size_label.set_text("Presentation size:"); + + auto& presentation_size_spinbox = presentation_size_container.add(); + presentation_size_spinbox.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fill); + presentation_size_spinbox.set_min(0); + presentation_size_spinbox.set_max(255); + presentation_size_spinbox.set_value(m_edited_font->presentation_size()); + + //// Weight Row + auto& weight_container = font_metadata_group_box.add(); + weight_container.set_layout(); + weight_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); + weight_container.set_preferred_size(0, 22); + + auto& weight_label = weight_container.add(); + weight_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fill); + weight_label.set_preferred_size(100, 0); + weight_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + weight_label.set_text("Weight:"); + + auto& weight_spinbox = weight_container.add(); + weight_spinbox.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fill); + weight_spinbox.set_min(0); + weight_spinbox.set_max(65535); + weight_spinbox.set_value(m_edited_font->weight()); + //// Glyph spacing Row auto& glyph_spacing_container = font_metadata_group_box.add(); glyph_spacing_container.set_layout(); @@ -278,7 +333,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& edite right_site_width = max(right_site_width, m_glyph_map_widget->preferred_width()); m_preferred_width = m_glyph_editor_widget->width() + right_site_width + 20; - m_preferred_height = m_glyph_map_widget->relative_rect().height() + 2 * m_edited_font->glyph_height() + 300; + m_preferred_height = m_glyph_map_widget->relative_rect().height() + 2 * m_edited_font->glyph_height() + 380; }; m_glyph_editor_widget->on_glyph_altered = [this, update_demo](u8 glyph) { @@ -316,6 +371,16 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& edite update_demo(); }; + weight_spinbox.on_change = [this, update_demo](int value) { + m_edited_font->set_weight(value); + update_demo(); + }; + + presentation_size_spinbox.on_change = [this, update_demo](int value) { + m_edited_font->set_presentation_size(value); + update_demo(); + }; + spacing_spinbox.on_change = [this, update_demo](int value) { m_edited_font->set_glyph_spacing(value); update_demo(); diff --git a/Base/res/fonts/CsillaBold10.font b/Base/res/fonts/CsillaBold10.font index bf84f44d97c6565518f9ee7139196803f7f299c0..a69c20761a8ac8b980f39aadf205b6c613de143e 100644 GIT binary patch delta 42 ycmX?CeXg2M(Jilpor{ryfrE)_57R_G1vcm6%$%IWjfzgJllj;=HrKHRSO5S3Tnlml delta 36 rcmX?CeXg2M(Jilpor{ryfrE*Gfng$_!e#>z57x>QixSOY8otRM(? diff --git a/Base/res/fonts/CsillaBold12.font b/Base/res/fonts/CsillaBold12.font index 17f0d7d7636390a447e53d3113ac36ca6e9b5b93..0bd7090a7302429cceab7e851aa65056ac0de466 100644 GIT binary patch delta 40 wcmX>%nep6YMm|Niyb?|xMg|5>MxH%P6ZsU_oQpGaauPQxda-S;V+(Kw0ODE;4*&oF delta 34 qcmX>%nep6YMm|Niyb?|xMg|5>Mg|6kiF^v16(j=KHrKHQI0FEfIS2*- diff --git a/Base/res/fonts/CsillaRegular10.font b/Base/res/fonts/CsillaRegular10.font index 1b5b627caca95818c8351abb228c519488fde7e2..3ccee87d75b7e235c9114024d227b721e324f911 100644 GIT binary patch delta 64 zcmX?CeXiO>(Jilpor{ryfrE)_0;6+rW=>9`LQraYX-;Ah0|tP|PgHc;SQcRm00$%w A82|tP delta 37 scmX?CeXd$k(Jilpor{ryfrE*Gfx)>rGbbleAtWO+Z{oq&jb#zG0L&r_hX4Qo diff --git a/Base/res/fonts/CsillaRegular12.font b/Base/res/fonts/CsillaRegular12.font index acec48f9bb14aca59df5fe24689c94565a3e1f6c..bd52e33142f169ef258c3fddc9495c160d119e5d 100644 GIT binary patch delta 59 zcmX>%nep6YMr}p6yb?|xMg|5>MxF_b&c&HIIf)8Esp+LTiA4;kU?X=h+vYm90A~QY Cs0|+g delta 30 mcmX>%nep6YMs7v7yb?|xMg|5>#*Ny+Y!d?%HrKHQI0FEOdk8rI diff --git a/Base/res/fonts/KaticaBold10.font b/Base/res/fonts/KaticaBold10.font index 840a1deaeebe20ab3995fe55eb7fada32a78211c..93a3f8903044c7e0ccfdd8293be9ee0db2cdc6fa 100644 GIT binary patch delta 38 tcmX?CeXg2M(Jilpor{r?k%NhA57R_G1vc-*lFa19jfzgJo6A@uECAK$3b_CP delta 32 ncmX?CeXg2M(Jilpor{r?k%NhWfng$_!e#>z57y0PtPvIfju!{X diff --git a/Base/res/fonts/KaticaBold12.font b/Base/res/fonts/KaticaBold12.font index 55a67cc3f3b4983292af8a25e84ea95c126b6692..831ee25d1aa9bd7817cafa5b31cba4b5ae0b6514 100644 GIT binary patch delta 40 wcmX>%pYhy$Mm|Niyb>N>Mn*8USiwK#(u&B0O;=vu>b%7 delta 34 qcmX>%pYhy$Mm|Niyb>N>Mn*%pYhy$Mr}p6yb^9+Mn*%pYhy$Ms7v7yb^9+Mn*`coYlH;=JCF@z delta 38 tcmX?CeXd$u(JilpgNu=YfrE*Gfx#!UDpA2HKPP3gqDVaJ<}%g@3joc-3QGV0 diff --git a/Base/res/fonts/LizaBlack24.font b/Base/res/fonts/LizaBlack24.font index 997d9159ac0b9b0f284590858b0e8e60ea8866be..763cdbce3d43d8d9d9eadcc6e26fb4cc9ff15326 100644 GIT binary patch delta 56 zcmX@NnCaYNCJ9Biyb>V^Mg|69c8L~dpUkR61*e?E6)(EV^Mg|69b_NCppUkR61*iO+6a^!b&5j9kcqZS|Gni~AX0Ta| HcSj2Vb&n4^ diff --git a/Base/res/fonts/LizaBlack36.font b/Base/res/fonts/LizaBlack36.font index 1fca448335a4a7a794941be1d52dcee89ad899fb..05c9fe5ab0f140c029ccdad8f08922ca294142f1 100644 GIT binary patch delta 52 zcmX@NnfcsiW(h^Nyb>uDMg|61Zj}~hpUkR61*e?EuDMg|61ZUzPhpUkR61*iO+6a{0mjgG5?CI+Za?zaxvY%kn@ F3;<({4^998 diff --git a/Base/res/fonts/LizaBold10.font b/Base/res/fonts/LizaBold10.font index ab59a0f5838ee224c9ce1ee05f11cda3cae5a08e..7ee0a363a1242a54465d7ed9f34af2f95942cb01 100644 GIT binary patch delta 53 zcmX?CeXd$u(JilpgNu=YfrE)_50g)3Ric7Zeoo3nMR67oXQQGE>tri+p2>V10-GnX H+E@Spq8ASM delta 49 zcmX?CeXd$c(JilpgNu=YfrE*Gfx#!UDp4UQHN7+^v1qfRNDS*_D|Md9d>jIsC$ZXC F0032=4OIXD diff --git a/Base/res/fonts/LizaBold24.font b/Base/res/fonts/LizaBold24.font index 0dcc42764bc02409286f1f2b9d2d0822d30f1093..05f3a3f4384d929e4921a8724bb07b6e93b9f702 100644 GIT binary patch delta 55 zcmX@NnCaYNCUHf#yb>V^Mg|69c8NVqKABaC3QqYsDH9dNSwNhPiY+{o@97y#wi7eh JEXKQ|1pv=N5lR36 delta 54 zcmX@NnCaYNCRs(dyb>V^Mg|69b_NCppUkR6g`m{*(wxL11tXKqjtMh)Cg0ODm~1Cz Kuvv_EM+*R}t`Lg= diff --git a/Base/res/fonts/LizaBold36.font b/Base/res/fonts/LizaBold36.font index 1f37f20ccfe5c171c82337cdced6095018e8d7ed..9a14fc4112bf3499bdd9117a4db81d77fc591a65 100644 GIT binary patch delta 55 zcmX@NnfcsiW^qNgyb>uDMg|61Zk0VuKABaC3QqYsDH9dNSwNhPiaUiS_gjZd?w7LO JTqPWG3;^RR5?=rS delta 56 zcmX@NnfcsiW?4nIyb>uDMg|61ZUzPhpUkR6g`m{*(wxL11!J>~j;n+w2B=K#w+@-y MFJ-;CN;u>g0No=J761SM diff --git a/Base/res/fonts/LizaRegular10.font b/Base/res/fonts/LizaRegular10.font index d0ba1dfe41361a6e5b4eabd6bc04476bbe40af69..8f355d050a78050ddbbb939cccf699522c645e35 100644 GIT binary patch delta 48 zcmX?CeXd$c(JilpgNu=YfrE)_0;5l6RiZ*rYIV^Mg|69c8Lj$KABaC3PGvqr8$X36BR{RK>Ur0tvr+O>lsY8 M7t`M?#=D~h00v|dZ~y=R delta 51 zcmX@NnCaYNCMiX?yb>V^Mg|69b_NCppUkR6g^-NQJOv|@&5j9kc_!c2Gni~IroUN? HcSj2VcU=!o diff --git a/Base/res/fonts/LizaRegular36.font b/Base/res/fonts/LizaRegular36.font index 8bb9c5cc4c8ec3c2242db7ab8bca698d661bc91a..6ff5fca2d8b8686717fd13ed3050a2053ff8cde7 100644 GIT binary patch delta 58 zcmX@NnfcsiW+_Ftyb>uDMg|61Zj}j)KABaC3PGvqr8$X36BR{RK>Ur0JB23qTZc^U Mm$KemB^+`L02?3^g8%>k delta 53 zcmX@NnfcsiW+_Ftyb>uDMg|61ZUzPhpUkR6g^-NQJOyL3jgG5?CI+Za?zaw^+%ILl Jxk@NhMn*<1CcZsP6ZsT415%Tca#Bn3^EN8_vrm2}pt5-tyNVwG DOD+yq delta 38 ucmX@Nn(^FfMm|Niyb>NhMn*<1CI$wEiF^v11!N-FC%+R=*}RHf#SZ|+y9xaO diff --git a/Base/res/fonts/PebbletonRegular14.font b/Base/res/fonts/PebbletonRegular14.font index e708fe990cd5ab10ae5f308f91eddda3c7485cf0..3ec833539056f333e08c565b3eda3c9b6ac0f468 100644 GIT binary patch delta 37 tcmX@Nn(^FfMm|Niyb>NhMn*<1CcX)b6ZsT2@NhMn*<1rj6Rs>=OeNCchI<*}RHf#SZ|spb9(y diff --git a/Libraries/LibGfx/Font.cpp b/Libraries/LibGfx/Font.cpp index dba9d9feb4..f17ab9a9dc 100644 --- a/Libraries/LibGfx/Font.cpp +++ b/Libraries/LibGfx/Font.cpp @@ -53,8 +53,10 @@ struct [[gnu::packed]] FontFileHeader u8 glyph_spacing; u8 baseline; u8 mean_line; - u8 unused[3]; - char name[64]; + u8 presentation_size; + u16 weight; + char name[32]; + char family[32]; }; Font& Font::default_font() @@ -112,7 +114,7 @@ NonnullRefPtr Font::clone() const memcpy(new_widths, m_glyph_widths, m_glyph_count); else 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, m_baseline, m_mean_line)); + return adopt(*new Font(m_name, m_family, new_rows, new_widths, m_fixed_width, m_glyph_width, m_glyph_height, m_glyph_spacing, m_type, m_baseline, m_mean_line, m_presentation_size, m_weight)); } NonnullRefPtr Font::create(u8 glyph_height, u8 glyph_width, bool fixed, FontTypes type) @@ -124,11 +126,12 @@ NonnullRefPtr Font::create(u8 glyph_height, u8 glyph_width, bool fixed, Fo 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, 0, 0)); + return adopt(*new Font("Untitled", "Untitled", new_rows, new_widths, fixed, glyph_width, glyph_height, 1, type, 0, 0, 0, 400)); } -Font::Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing, FontTypes type, u8 baseline, u8 mean_line) +Font::Font(String name, String family, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing, FontTypes type, u8 baseline, u8 mean_line, u8 presentation_size, u16 weight) : m_name(name) + , m_family(family) , m_type(type) , m_rows(rows) , m_glyph_widths(widths) @@ -139,6 +142,8 @@ Font::Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_wid , m_glyph_spacing(glyph_spacing) , m_baseline(baseline) , m_mean_line(mean_line) + , m_presentation_size(presentation_size) + , m_weight(weight) , m_fixed_width(is_fixed_width) { update_x_height(); @@ -170,11 +175,16 @@ RefPtr Font::load_from_memory(const u8* data) dbgprintf("header.magic != '!Fnt', instead it's '%c%c%c%c'\n", header.magic[0], header.magic[1], header.magic[2], header.magic[3]); return nullptr; } - if (header.name[63] != '\0') { + if (header.name[sizeof(header.name) - 1] != '\0') { dbgprintf("Font name not fully null-terminated\n"); return nullptr; } + if (header.family[sizeof(header.family) - 1] != '\0') { + dbgprintf("Font family not fully null-terminated\n"); + return nullptr; + } + FontTypes type; if (header.type == 0) type = FontTypes::Default; @@ -190,7 +200,7 @@ RefPtr Font::load_from_memory(const u8* data) u8* widths = nullptr; if (header.is_variable_width) 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, header.baseline, header.mean_line)); + return adopt(*new Font(String(header.name), String(header.family), rows, widths, !header.is_variable_width, header.glyph_width, header.glyph_height, header.glyph_spacing, type, header.baseline, header.mean_line, header.presentation_size, header.weight)); } size_t Font::glyph_count_by_type(FontTypes type) @@ -231,7 +241,10 @@ bool Font::write_to_file(const StringView& path) header.mean_line = m_mean_line; 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)); + header.presentation_size = m_presentation_size; + header.weight = m_weight; + memcpy(header.name, m_name.characters(), min(m_name.length(), sizeof(header.name) - 1)); + memcpy(header.family, m_family.characters(), min(m_family.length(), sizeof(header.family) - 1)); size_t bytes_per_glyph = sizeof(unsigned) * m_glyph_height; size_t count = glyph_count_by_type(m_type); @@ -339,32 +352,14 @@ void Font::set_type(FontTypes type) void Font::set_family_fonts() { - String typeface; - String weight; - StringBuilder size; - - auto parts = this->name().split(' '); - if (parts.size() < 2) { - typeface = this->name(); - } else { - typeface = parts[0]; - weight = parts[1]; - } - - if (this->is_fixed_width()) { - size.appendf("%d", this->m_max_glyph_width); - size.append("x"); - } - size.appendf("%d", this->m_glyph_height); - StringBuilder path; - if (weight != "Bold") { - path.appendf("/res/fonts/%sBold%s.font", &typeface[0], &size.to_string()[0]); + if (weight() != 700) { + path.appendff("/res/fonts/{}Bold{}.font", family(), presentation_size()); + auto spath = path.to_string(); m_bold_family_font = Font::load_from_file(path.to_string()); if (m_bold_family_font) set_boldface(true); - path.clear(); } } diff --git a/Libraries/LibGfx/Font.h b/Libraries/LibGfx/Font.h index c9e2d07bd9..0302338978 100644 --- a/Libraries/LibGfx/Font.h +++ b/Libraries/LibGfx/Font.h @@ -89,6 +89,12 @@ public: ~Font(); + u8 presentation_size() const { return m_presentation_size; } + void set_presentation_size(u8 size) { m_presentation_size = size; } + + u16 weight() const { return m_weight; } + void set_weight(u16 weight) { m_weight = weight; } + GlyphBitmap glyph_bitmap(u32 code_point) const; u8 glyph_width(size_t ch) const { return m_fixed_width ? m_glyph_width : m_glyph_widths[ch]; } @@ -118,8 +124,8 @@ public: int width(const Utf8View&) const; int width(const Utf32View&) const; - String name() const { return m_name; } - void set_name(const StringView& name) { m_name = name; } + const String& name() const { return m_name; } + void set_name(String name) { m_name = move(name); } bool is_fixed_width() const { return m_fixed_width; } void set_fixed_width(bool b) { m_fixed_width = b; } @@ -142,8 +148,11 @@ public: FontTypes type() { return m_type; } void set_type(FontTypes type); + const String& family() const { return m_family; } + void set_family(String family) { m_family = move(family); } + private: - Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing, FontTypes type, u8 baseline, u8 mean_line); + Font(String name, String family, unsigned* rows, u8* widths, bool is_fixed_width, u8 glyph_width, u8 glyph_height, u8 glyph_spacing, FontTypes type, u8 baseline, u8 mean_line, u8 presentation_size, u16 weight); static RefPtr load_from_memory(const u8*); static size_t glyph_count_by_type(FontTypes type); @@ -154,6 +163,7 @@ private: RefPtr m_bold_family_font; String m_name; + String m_family; FontTypes m_type; size_t m_glyph_count { 256 }; @@ -169,6 +179,8 @@ private: u8 m_glyph_spacing { 0 }; u8 m_baseline { 0 }; u8 m_mean_line { 0 }; + u8 m_presentation_size { 0 }; + u16 m_weight { 0 }; bool m_fixed_width { false }; bool m_boldface { false };