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
This commit is contained in:
Luke 2020-10-05 16:19:37 +01:00 committed by Andreas Kling
parent 043b31ad9a
commit 52c31bb743
Notes: sideshowbarker 2024-07-19 02:01:59 +09:00
19 changed files with 55 additions and 13 deletions

View file

@ -121,7 +121,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr<Gfx::Font>&& edite
font_metadata_group_box.set_layout<GUI::VerticalBoxLayout>();
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<Gfx::Font>&& edite
baseline_label.set_text("Baseline:");
auto& baseline_spinbox = baseline_container.add<GUI::SpinBox>();
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<GUI::Widget>();
mean_line_container.set_layout<GUI::HorizontalBoxLayout>();
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<GUI::Label>();
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<GUI::SpinBox>();
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<GUI::CheckBox>();
fixed_width_checkbox.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed);
@ -259,7 +278,7 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr<Gfx::Font>&& 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<Gfx::Font>&& 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');

View file

@ -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);
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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> 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> Font::create(u8 glyph_height, u8 glyph_width, bool fixed, FontTypes type)
@ -123,10 +124,10 @@ NonnullRefPtr<Font> Font::create(u8 glyph_height, u8 glyph_width, bool fixed, Fo
memset(new_rows, 0, bytes_per_glyph * count);
auto* new_widths = static_cast<u8*>(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> 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));

View file

@ -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<Font> 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<Font> 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 };