mirror of
https://github.com/RGBCube/serenity
synced 2025-06-01 11:08:12 +00:00
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:
parent
5abc03db0d
commit
80b77cec38
22 changed files with 106 additions and 34 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.set_layout<GUI::VerticalBoxLayout>();
|
||||||
font_metadata_group_box.layout()->set_margins({ 5, 15, 5, 5 });
|
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_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");
|
font_metadata_group_box.set_title("Font metadata");
|
||||||
|
|
||||||
//// Name Row
|
//// Name Row
|
||||||
|
@ -143,6 +143,61 @@ FontEditorWidget::FontEditorWidget(const String& path, RefPtr<Gfx::Font>&& edite
|
||||||
m_edited_font->set_name(name_textbox.text());
|
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
|
//// Glyph spacing Row
|
||||||
auto& glyph_spacing_container = font_metadata_group_box.add<GUI::Widget>();
|
auto& glyph_spacing_container = font_metadata_group_box.add<GUI::Widget>();
|
||||||
glyph_spacing_container.set_layout<GUI::HorizontalBoxLayout>();
|
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());
|
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_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) {
|
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();
|
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) {
|
spacing_spinbox.on_change = [this, update_demo](int value) {
|
||||||
m_edited_font->set_glyph_spacing(value);
|
m_edited_font->set_glyph_spacing(value);
|
||||||
update_demo();
|
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.
Binary file not shown.
|
@ -53,8 +53,10 @@ struct [[gnu::packed]] FontFileHeader
|
||||||
u8 glyph_spacing;
|
u8 glyph_spacing;
|
||||||
u8 baseline;
|
u8 baseline;
|
||||||
u8 mean_line;
|
u8 mean_line;
|
||||||
u8 unused[3];
|
u8 presentation_size;
|
||||||
char name[64];
|
u16 weight;
|
||||||
|
char name[32];
|
||||||
|
char family[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
Font& Font::default_font()
|
Font& Font::default_font()
|
||||||
|
@ -112,7 +114,7 @@ NonnullRefPtr<Font> Font::clone() const
|
||||||
memcpy(new_widths, m_glyph_widths, m_glyph_count);
|
memcpy(new_widths, m_glyph_widths, m_glyph_count);
|
||||||
else
|
else
|
||||||
memset(new_widths, m_glyph_width, m_glyph_count);
|
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)
|
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);
|
memset(new_rows, 0, bytes_per_glyph * count);
|
||||||
auto* new_widths = static_cast<u8*>(malloc(count));
|
auto* new_widths = static_cast<u8*>(malloc(count));
|
||||||
memset(new_widths, glyph_width, 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_name(name)
|
||||||
|
, m_family(family)
|
||||||
, m_type(type)
|
, m_type(type)
|
||||||
, m_rows(rows)
|
, m_rows(rows)
|
||||||
, m_glyph_widths(widths)
|
, 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_glyph_spacing(glyph_spacing)
|
||||||
, m_baseline(baseline)
|
, m_baseline(baseline)
|
||||||
, m_mean_line(mean_line)
|
, m_mean_line(mean_line)
|
||||||
|
, m_presentation_size(presentation_size)
|
||||||
|
, m_weight(weight)
|
||||||
, m_fixed_width(is_fixed_width)
|
, m_fixed_width(is_fixed_width)
|
||||||
{
|
{
|
||||||
update_x_height();
|
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]);
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (header.name[63] != '\0') {
|
if (header.name[sizeof(header.name) - 1] != '\0') {
|
||||||
dbgprintf("Font name not fully null-terminated\n");
|
dbgprintf("Font name not fully null-terminated\n");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header.family[sizeof(header.family) - 1] != '\0') {
|
||||||
|
dbgprintf("Font family not fully null-terminated\n");
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
FontTypes type;
|
FontTypes type;
|
||||||
if (header.type == 0)
|
if (header.type == 0)
|
||||||
type = FontTypes::Default;
|
type = FontTypes::Default;
|
||||||
|
@ -190,7 +200,7 @@ RefPtr<Font> Font::load_from_memory(const u8* data)
|
||||||
u8* widths = nullptr;
|
u8* widths = nullptr;
|
||||||
if (header.is_variable_width)
|
if (header.is_variable_width)
|
||||||
widths = (u8*)(rows) + count * bytes_per_glyph;
|
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)
|
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.mean_line = m_mean_line;
|
||||||
header.is_variable_width = !m_fixed_width;
|
header.is_variable_width = !m_fixed_width;
|
||||||
header.glyph_spacing = m_glyph_spacing;
|
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 bytes_per_glyph = sizeof(unsigned) * m_glyph_height;
|
||||||
size_t count = glyph_count_by_type(m_type);
|
size_t count = glyph_count_by_type(m_type);
|
||||||
|
@ -339,32 +352,14 @@ void Font::set_type(FontTypes type)
|
||||||
|
|
||||||
void Font::set_family_fonts()
|
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;
|
StringBuilder path;
|
||||||
|
|
||||||
if (weight != "Bold") {
|
if (weight() != 700) {
|
||||||
path.appendf("/res/fonts/%sBold%s.font", &typeface[0], &size.to_string()[0]);
|
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());
|
m_bold_family_font = Font::load_from_file(path.to_string());
|
||||||
if (m_bold_family_font)
|
if (m_bold_family_font)
|
||||||
set_boldface(true);
|
set_boldface(true);
|
||||||
path.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -89,6 +89,12 @@ public:
|
||||||
|
|
||||||
~Font();
|
~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;
|
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]; }
|
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 Utf8View&) const;
|
||||||
int width(const Utf32View&) const;
|
int width(const Utf32View&) const;
|
||||||
|
|
||||||
String name() const { return m_name; }
|
const String& name() const { return m_name; }
|
||||||
void set_name(const StringView& name) { m_name = name; }
|
void set_name(String name) { m_name = move(name); }
|
||||||
|
|
||||||
bool is_fixed_width() const { return m_fixed_width; }
|
bool is_fixed_width() const { return m_fixed_width; }
|
||||||
void set_fixed_width(bool b) { m_fixed_width = b; }
|
void set_fixed_width(bool b) { m_fixed_width = b; }
|
||||||
|
@ -142,8 +148,11 @@ public:
|
||||||
FontTypes type() { return m_type; }
|
FontTypes type() { return m_type; }
|
||||||
void set_type(FontTypes type);
|
void set_type(FontTypes type);
|
||||||
|
|
||||||
|
const String& family() const { return m_family; }
|
||||||
|
void set_family(String family) { m_family = move(family); }
|
||||||
|
|
||||||
private:
|
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 RefPtr<Font> load_from_memory(const u8*);
|
||||||
static size_t glyph_count_by_type(FontTypes type);
|
static size_t glyph_count_by_type(FontTypes type);
|
||||||
|
@ -154,6 +163,7 @@ private:
|
||||||
RefPtr<Font> m_bold_family_font;
|
RefPtr<Font> m_bold_family_font;
|
||||||
|
|
||||||
String m_name;
|
String m_name;
|
||||||
|
String m_family;
|
||||||
FontTypes m_type;
|
FontTypes m_type;
|
||||||
size_t m_glyph_count { 256 };
|
size_t m_glyph_count { 256 };
|
||||||
|
|
||||||
|
@ -169,6 +179,8 @@ private:
|
||||||
u8 m_glyph_spacing { 0 };
|
u8 m_glyph_spacing { 0 };
|
||||||
u8 m_baseline { 0 };
|
u8 m_baseline { 0 };
|
||||||
u8 m_mean_line { 0 };
|
u8 m_mean_line { 0 };
|
||||||
|
u8 m_presentation_size { 0 };
|
||||||
|
u16 m_weight { 0 };
|
||||||
|
|
||||||
bool m_fixed_width { false };
|
bool m_fixed_width { false };
|
||||||
bool m_boldface { false };
|
bool m_boldface { false };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue