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:
parent
043b31ad9a
commit
52c31bb743
Notes:
sideshowbarker
2024-07-19 02:01:59 +09:00
Author: https://github.com/Lubrsi Commit: https://github.com/SerenityOS/serenity/commit/52c31bb743c Pull-request: https://github.com/SerenityOS/serenity/pull/3694
19 changed files with 55 additions and 13 deletions
|
@ -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');
|
||||
|
|
|
@ -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.
|
@ -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));
|
||||
|
|
|
@ -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 };
|
||||
|
|
Loading…
Add table
Reference in a new issue