From 52c31bb743ce5baa6358f1db34c5341833b8cdf1 Mon Sep 17 00:00:00 2001 From: Luke Date: Mon, 5 Oct 2020 16:19:37 +0100 Subject: [PATCH] LibGfx+FontEditor+Fonts: Add "mean line" value to all fonts The main inspiration behind this was to have a correct ex CSS unit. The mean line is based off what it shows in the CSS Values and Units Level 4 specification, section 6.1.1. https://www.w3.org/TR/css-values-4/#font-relative-lengths --- Applications/FontEditor/FontEditor.cpp | 31 ++++++++++++++++-- Applications/FontEditor/GlyphEditorWidget.cpp | 3 +- Base/res/fonts/CsillaBold7x10.font | Bin 15822 -> 15822 bytes Base/res/fonts/CsillaThin7x10.font | Bin 15822 -> 15822 bytes Base/res/fonts/Katica10.font | Bin 15822 -> 15822 bytes Base/res/fonts/KaticaBold10.font | Bin 15822 -> 15822 bytes Base/res/fonts/LizaBold18x24.font | Bin 37326 -> 37326 bytes Base/res/fonts/LizaBold26x36.font | Bin 55758 -> 55758 bytes Base/res/fonts/LizaBold8x10.font | Bin 15822 -> 15822 bytes Base/res/fonts/LizaRegular18x24.font | Bin 37326 -> 37326 bytes Base/res/fonts/LizaRegular26x36.font | Bin 55758 -> 55758 bytes Base/res/fonts/LizaRegular8x10.font | Bin 15822 -> 15822 bytes Base/res/fonts/LizaThin18x24.font | Bin 37326 -> 37326 bytes Base/res/fonts/LizaThin26x36.font | Bin 55758 -> 55758 bytes Base/res/fonts/LizaThin8x10.font | Bin 15822 -> 15822 bytes Base/res/fonts/Pebbleton14.font | Bin 21966 -> 21966 bytes Base/res/fonts/PebbletonBold14.font | Bin 21966 -> 21966 bytes Libraries/LibGfx/Font.cpp | 16 +++++---- Libraries/LibGfx/Font.h | 18 ++++++++-- 19 files changed, 55 insertions(+), 13 deletions(-) diff --git a/Applications/FontEditor/FontEditor.cpp b/Applications/FontEditor/FontEditor.cpp index bf16c83312..ae7107686b 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, 165); + font_metadata_group_box.set_preferred_size(0, 195); font_metadata_group_box.set_title("Font metadata"); //// Name Row @@ -212,12 +212,31 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& edite baseline_label.set_text("Baseline:"); auto& baseline_spinbox = baseline_container.add(); - baseline_spinbox.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fill); + baseline_spinbox.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fill); baseline_spinbox.set_preferred_size(100, 0); baseline_spinbox.set_min(0); baseline_spinbox.set_max(m_edited_font->glyph_height() - 1); baseline_spinbox.set_value(m_edited_font->baseline()); + //// Mean line Row + auto& mean_line_container = font_metadata_group_box.add(); + mean_line_container.set_layout(); + mean_line_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); + mean_line_container.set_preferred_size(0, 22); + + auto& mean_line_label = mean_line_container.add(); + mean_line_label.set_size_policy(GUI::SizePolicy::Fixed, GUI::SizePolicy::Fill); + mean_line_label.set_preferred_size(100, 0); + mean_line_label.set_text_alignment(Gfx::TextAlignment::CenterLeft); + mean_line_label.set_text("Mean Line:"); + + auto& mean_line_spinbox = mean_line_container.add(); + mean_line_spinbox.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fill); + mean_line_spinbox.set_preferred_size(100, 0); + mean_line_spinbox.set_min(0); + mean_line_spinbox.set_max(m_edited_font->glyph_height() - 1); + mean_line_spinbox.set_value(m_edited_font->mean_line()); + //// Fixed checkbox Row auto& fixed_width_checkbox = font_metadata_group_box.add(); fixed_width_checkbox.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed); @@ -259,7 +278,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() + 270; + m_preferred_height = m_glyph_map_widget->relative_rect().height() + 2 * m_edited_font->glyph_height() + 300; }; m_glyph_editor_widget->on_glyph_altered = [this, update_demo](u8 glyph) { @@ -308,6 +327,12 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr&& edite update_demo(); }; + mean_line_spinbox.on_change = [this, update_demo](int value) { + m_edited_font->set_mean_line(value); + m_glyph_editor_widget->update(); + update_demo(); + }; + // init widget calculate_prefed_sizes(); m_glyph_map_widget->set_selected_glyph('A'); diff --git a/Applications/FontEditor/GlyphEditorWidget.cpp b/Applications/FontEditor/GlyphEditorWidget.cpp index 32d4e08dca..57cbed8058 100644 --- a/Applications/FontEditor/GlyphEditorWidget.cpp +++ b/Applications/FontEditor/GlyphEditorWidget.cpp @@ -59,7 +59,8 @@ void GlyphEditorWidget::paint_event(GUI::PaintEvent& event) painter.translate(-1, -1); for (int y = 1; y < font().glyph_height(); ++y) { - bool bold_line = (y - 1) == font().baseline(); + int y_below = y - 1; + bool bold_line = y_below == font().baseline() || y_below == font().mean_line(); painter.draw_line({ 0, y * m_scale }, { font().max_glyph_width() * m_scale, y * m_scale }, palette().threed_shadow2(), bold_line ? 2 : 1); } diff --git a/Base/res/fonts/CsillaBold7x10.font b/Base/res/fonts/CsillaBold7x10.font index 1af5564228a1803609f5055b046cbf152629a1a6..bf84f44d97c6565518f9ee7139196803f7f299c0 100644 GIT binary patch delta 20 bcmX?CeXg2Y(Jilpor{ryfrDuy_hDNAM+pVL delta 20 bcmX?CeXg2Y(Jilpor{ryfrDWq_hDNAM*ju9 diff --git a/Base/res/fonts/CsillaThin7x10.font b/Base/res/fonts/CsillaThin7x10.font index 463c9397c46df0917aecf6adf41b47e47dc16335..1b5b627caca95818c8351abb228c519488fde7e2 100644 GIT binary patch delta 20 bcmX?CeXg2Y(Jilpor{ryfrDuy_hDNAM+pVL delta 20 bcmX?CeXg2Y(Jilpor{ryfrDWq_hDNAM*ju9 diff --git a/Base/res/fonts/Katica10.font b/Base/res/fonts/Katica10.font index 7655bbbc6fb4ff14c4b5e7bbecc96a32b92394ac..6e4a68066f17b0521d26d74f299ec6384a596dcf 100644 GIT binary patch delta 20 bcmX?CeXg2Y(Jilpor{r?k%MU?_hDNAM;Hac delta 20 bcmX?CeXg2Y(Jilpor{r?k%M6)_hDNAM-BzQ diff --git a/Base/res/fonts/KaticaBold10.font b/Base/res/fonts/KaticaBold10.font index 089abeb7fbf56d0190d930edc31790eb5b89f8a1..840a1deaeebe20ab3995fe55eb7fada32a78211c 100644 GIT binary patch delta 20 bcmX?CeXg2Y(Jilpor{r?k%MU?_hDNAM;Hac delta 20 bcmX?CeXg2Y(Jilpor{r?k%M6)_hDNAM-BzQ diff --git a/Base/res/fonts/LizaBold18x24.font b/Base/res/fonts/LizaBold18x24.font index e090c4d0c405d997a3491edb32fc71dc65d8eff6..997d9159ac0b9b0f284590858b0e8e60ea8866be 100644 GIT binary patch delta 26 icmX@NnCaYNCT>Nyyb>V^Mg|69_Kn=m6DKE3XaE3jNC*=E delta 25 hcmX@NnCaYNCT>Nyyb>V^Mg|69hK=0L6DKM*003rb2Ri@& diff --git a/Base/res/fonts/LizaBold26x36.font b/Base/res/fonts/LizaBold26x36.font index 057b1d013dd5219a287b9dd6f16c2966a9d96228..1fca448335a4a7a794941be1d52dcee89ad899fb 100644 GIT binary patch delta 26 icmX@NnfcsiW^P5dyb>uDMg|61?v32eHzz0DXaE3q1qkN= delta 25 hcmX@NnfcsiW^P5dyb>uDMg|5shK=0LHzz7K003+A2gCpX diff --git a/Base/res/fonts/LizaBold8x10.font b/Base/res/fonts/LizaBold8x10.font index 9620a3e9de1a31da62fe2d85c78c27d989196492..0331e41a9753965454cfee70a57060bedc36f4ed 100644 GIT binary patch delta 24 fcmX?CeXg2Y(JilpgNu=YfrDuyx3lf!1e*o`Uw8)Z delta 23 ecmX?CeXg2Y(JilpgNu=YfrDWqx3ld;#RdRaIRNyyb>V^Mg|69_Kn=m6DKE3XaE3jNC*=E delta 25 hcmX@NnCaYNCT>Nyyb>V^Mg|69hK=0L6DKM*003rb2Ri@& diff --git a/Base/res/fonts/LizaRegular26x36.font b/Base/res/fonts/LizaRegular26x36.font index a8e57fb08643ce2fb7974e8a3a697fadf1e615f7..1f37f20ccfe5c171c82337cdced6095018e8d7ed 100644 GIT binary patch delta 26 icmX@NnfcsiW^P5dyb>uDMg|61?v32eHzz0DXaE3q1qkN= delta 25 hcmX@NnfcsiW^P5dyb>uDMg|5shK=0LHzz7K003+A2gCpX diff --git a/Base/res/fonts/LizaRegular8x10.font b/Base/res/fonts/LizaRegular8x10.font index 8f993d13851ee5ec480927e813b7dc607991df33..ab59a0f5838ee224c9ce1ee05f11cda3cae5a08e 100644 GIT binary patch delta 24 fcmX?CeXg2Y(JilpgNu=YfrDuyx3lf!1e*o`Uw8)Z delta 23 ecmX?CeXg2Y(JilpgNu=YfrDWqx3ld;#RdRaIRNyyb>V^Mg|69_Kn=m6DKE3XaE3jNC*=E delta 25 hcmX@NnCaYNCT>Nyyb>V^Mg|69hK=0L6DKM*003rb2Ri@& diff --git a/Base/res/fonts/LizaThin26x36.font b/Base/res/fonts/LizaThin26x36.font index cbc9ba51fd3d0a01c329e5e997d4d2b1539ad4bd..8bb9c5cc4c8ec3c2242db7ab8bca698d661bc91a 100644 GIT binary patch delta 26 icmX@NnfcsiW^P5dyb>uDMg|61?v32eHzz0DXaE3q1qkN= delta 25 hcmX@NnfcsiW^P5dyb>uDMg|5shK=0LHzz7K003+A2gCpX diff --git a/Base/res/fonts/LizaThin8x10.font b/Base/res/fonts/LizaThin8x10.font index 5371128edd356294aa288bd13255996165627d84..d0ba1dfe41361a6e5b4eabd6bc04476bbe40af69 100644 GIT binary patch delta 24 fcmX?CeXg2Y(JilpgNu=YfrDuyx3lf!1e*o`Uw8)Z delta 23 ecmX?CeXg2Y(JilpgNu=YfrDWqx3ld;#RdRaIRNhMn*<1rj6W(Ljh9l21Wn? delta 22 dcmX@Nn(^FfMs7v7yb>NhMn*<1hK<~ZLjh9b21Eb= diff --git a/Base/res/fonts/PebbletonBold14.font b/Base/res/fonts/PebbletonBold14.font index c4ab28f30fb19dd4bd43bfb11b1d7dbbed503199..4aaa37d1fbad53fc37dcfcac96689b3e0ddd7246 100644 GIT binary patch delta 22 dcmX@Nn(^FfMs7v7yb>NhMn*<1rj6W(Ljh9l21Wn? delta 22 dcmX@Nn(^FfMs7v7yb>NhMn*<1hK<~ZLjh9b21Eb= diff --git a/Libraries/LibGfx/Font.cpp b/Libraries/LibGfx/Font.cpp index 98824308b3..eb8f187753 100644 --- a/Libraries/LibGfx/Font.cpp +++ b/Libraries/LibGfx/Font.cpp @@ -52,7 +52,8 @@ struct [[gnu::packed]] FontFileHeader u8 is_variable_width; u8 glyph_spacing; u8 baseline; - u8 unused[4]; + u8 mean_line; + u8 unused[3]; char name[64]; }; @@ -111,7 +112,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)); + 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)); } NonnullRefPtr Font::create(u8 glyph_height, u8 glyph_width, bool fixed, FontTypes type) @@ -123,10 +124,10 @@ 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)); + return adopt(*new Font("Untitled", new_rows, new_widths, fixed, glyph_width, glyph_height, 1, type, 0, 0)); } -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) +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) : m_name(name) , m_type(type) , m_rows(rows) @@ -137,10 +138,10 @@ Font::Font(const StringView& name, unsigned* rows, u8* widths, bool is_fixed_wid , m_max_glyph_width(glyph_width) , m_glyph_spacing(glyph_spacing) , m_baseline(baseline) + , m_mean_line(mean_line) , m_fixed_width(is_fixed_width) { - // FIXME: This is just a dumb guess. It would be cool to know the actual x-height of the font! - m_x_height = glyph_height / 2; + update_x_height(); m_glyph_count = glyph_count_by_type(m_type); @@ -189,7 +190,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)); + 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)); } size_t Font::glyph_count_by_type(FontTypes type) @@ -227,6 +228,7 @@ bool Font::write_to_file(const StringView& path) header.glyph_height = m_glyph_height; header.type = m_type; header.baseline = m_baseline; + 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)); diff --git a/Libraries/LibGfx/Font.h b/Libraries/LibGfx/Font.h index 1d465668b2..c9e2d07bd9 100644 --- a/Libraries/LibGfx/Font.h +++ b/Libraries/LibGfx/Font.h @@ -101,7 +101,18 @@ public: u8 glyph_fixed_width() const { return m_glyph_width; } u8 baseline() const { return m_baseline; } - void set_baseline(u8 baseline) { m_baseline = baseline; } + void set_baseline(u8 baseline) + { + m_baseline = baseline; + update_x_height(); + } + + u8 mean_line() const { return m_mean_line; } + void set_mean_line(u8 mean_line) + { + m_mean_line = mean_line; + update_x_height(); + } int width(const StringView&) const; int width(const Utf8View&) const; @@ -132,11 +143,13 @@ public: 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, FontTypes type, u8 baseline); + 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); static RefPtr load_from_memory(const u8*); static size_t glyph_count_by_type(FontTypes type); + void update_x_height() { m_x_height = m_mean_line - m_baseline; }; + void set_family_fonts(); RefPtr m_bold_family_font; @@ -155,6 +168,7 @@ private: u8 m_max_glyph_width { 0 }; u8 m_glyph_spacing { 0 }; u8 m_baseline { 0 }; + u8 m_mean_line { 0 }; bool m_fixed_width { false }; bool m_boldface { false };