LibGfx+FontEditor+Fonts: Add family, size and weight metadata to fonts

This makes finding fonts from the same family much less difficult. :^)
This commit is contained in:
Andreas Kling 2020-10-24 17:03:39 +02:00
parent 5abc03db0d
commit 80b77cec38
Notes: sideshowbarker 2024-07-19 01:45:52 +09:00
22 changed files with 106 additions and 34 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, 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<Gfx::Font>&& edite
m_edited_font->set_name(name_textbox.text());
};
//// Family Row
auto& family_container = font_metadata_group_box.add<GUI::Widget>();
family_container.set_layout<GUI::HorizontalBoxLayout>();
family_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed);
family_container.set_preferred_size(0, 22);
auto& family_label = family_container.add<GUI::Label>();
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<GUI::TextBox>();
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<GUI::Widget>();
presentation_size_container.set_layout<GUI::HorizontalBoxLayout>();
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<GUI::Label>();
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<GUI::SpinBox>();
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<GUI::Widget>();
weight_container.set_layout<GUI::HorizontalBoxLayout>();
weight_container.set_size_policy(GUI::SizePolicy::Fill, GUI::SizePolicy::Fixed);
weight_container.set_preferred_size(0, 22);
auto& weight_label = weight_container.add<GUI::Label>();
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<GUI::SpinBox>();
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<GUI::Widget>();
glyph_spacing_container.set_layout<GUI::HorizontalBoxLayout>();
@ -278,7 +333,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() + 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<Gfx::Font>&& 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();

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.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -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> 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> Font::create(u8 glyph_height, u8 glyph_width, bool fixed, FontTypes type)
@ -124,11 +126,12 @@ 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, 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> 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> 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();
}
}

View file

@ -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<Font> load_from_memory(const u8*);
static size_t glyph_count_by_type(FontTypes type);
@ -154,6 +163,7 @@ private:
RefPtr<Font> 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 };