LibGfx: Pass font width to FontDatabase::get()

Width need to be passed to `FontDatabase::get()` to resolve font name
unambiguously.
This commit is contained in:
Aliaksandr Kalenik 2023-02-04 23:00:34 +03:00 committed by Sam Atkins
parent 79006c03b4
commit 1f4106842d
Notes: sideshowbarker 2024-07-17 00:46:13 +09:00
21 changed files with 71 additions and 21 deletions

View File

@ -34,11 +34,11 @@ FontPluginQt::FontPluginQt()
update_generic_fonts();
auto default_font_name = generic_font_name(Web::Platform::GenericFont::UiSansSerif);
m_default_font = Gfx::FontDatabase::the().get(default_font_name, 12.0, 400, 0);
m_default_font = Gfx::FontDatabase::the().get(default_font_name, 12.0, 400, Gfx::FontWidth::Normal, 0);
VERIFY(m_default_font);
auto default_fixed_width_font_name = generic_font_name(Web::Platform::GenericFont::UiMonospace);
m_default_fixed_width_font = Gfx::FontDatabase::the().get(default_fixed_width_font_name, 12.0, 400, 0);
m_default_fixed_width_font = Gfx::FontDatabase::the().get(default_fixed_width_font_name, 12.0, 400, Gfx::FontWidth::Normal, 0);
VERIFY(m_default_fixed_width_font);
}
@ -73,10 +73,10 @@ void FontPluginQt::update_generic_fonts()
QFontInfo qt_info(qt_font);
auto qt_font_family = qt_info.family();
auto gfx_font = Gfx::FontDatabase::the().get(qt_font_family.toUtf8().data(), 16, 400, 0, Gfx::Font::AllowInexactSizeMatch::Yes);
auto gfx_font = Gfx::FontDatabase::the().get(qt_font_family.toUtf8().data(), 16, 400, Gfx::FontWidth::Normal, 0, Gfx::Font::AllowInexactSizeMatch::Yes);
if (!gfx_font) {
for (auto& fallback : fallbacks) {
gfx_font = Gfx::FontDatabase::the().get(fallback, 16, 400, 0, Gfx::Font::AllowInexactSizeMatch::Yes);
gfx_font = Gfx::FontDatabase::the().get(fallback, 16, 400, Gfx::FontWidth::Normal, 0, Gfx::Font::AllowInexactSizeMatch::Yes);
if (gfx_font)
break;
}

View File

@ -31,7 +31,7 @@ TEST_CASE(test_fontdatabase_get)
{
Gfx::FontDatabase::set_default_fonts_lookup_path(TEST_INPUT(""));
auto& font_database = Gfx::FontDatabase::the();
EXPECT(!font_database.get("Family", 12, 400, 0)->name().is_null());
EXPECT(!font_database.get("Family", 12, 400, Gfx::FontWidth::Normal, 0)->name().is_null());
}
TEST_CASE(test_fontdatabase_for_each_font)

View File

@ -409,7 +409,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
auto adjust_font_size = [&](float adjustment) {
auto& font = terminal->font();
auto new_size = max(5, font.presentation_size() + adjustment);
if (auto new_font = Gfx::FontDatabase::the().get(font.family(), new_size, font.weight(), font.slope())) {
if (auto new_font = Gfx::FontDatabase::the().get(font.family(), new_size, font.weight(), font.width(), font.slope())) {
terminal->set_font_and_resize_to_fit(*new_font);
terminal->apply_size_increments_to_window(*window);
window->resize(terminal->size());

View File

@ -638,7 +638,7 @@ void TextEditor::paint_event(PaintEvent& event)
}
auto font = unspanned_font;
if (span.attributes.bold) {
if (auto bold_font = Gfx::FontDatabase::the().get(font->family(), font->presentation_size(), 700, 0))
if (auto bold_font = Gfx::FontDatabase::the().get(font->family(), font->presentation_size(), 700, font->width(), 0))
font = bold_font;
}
draw_text_helper(span_start, span_end, font, span.attributes);

View File

@ -815,25 +815,25 @@ void Widget::set_font(Gfx::Font const* font)
void Widget::set_font_family(DeprecatedString const& family)
{
set_font(Gfx::FontDatabase::the().get(family, m_font->presentation_size(), m_font->weight(), m_font->slope()));
set_font(Gfx::FontDatabase::the().get(family, m_font->presentation_size(), m_font->weight(), m_font->width(), m_font->slope()));
}
void Widget::set_font_size(unsigned size)
{
set_font(Gfx::FontDatabase::the().get(m_font->family(), size, m_font->weight(), m_font->slope()));
set_font(Gfx::FontDatabase::the().get(m_font->family(), size, m_font->weight(), m_font->width(), m_font->slope()));
}
void Widget::set_font_weight(unsigned weight)
{
set_font(Gfx::FontDatabase::the().get(m_font->family(), m_font->presentation_size(), weight, m_font->slope()));
set_font(Gfx::FontDatabase::the().get(m_font->family(), m_font->presentation_size(), weight, m_font->width(), m_font->slope()));
}
void Widget::set_font_fixed_width(bool fixed_width)
{
if (fixed_width)
set_font(Gfx::FontDatabase::the().get(Gfx::FontDatabase::the().default_fixed_width_font().family(), m_font->presentation_size(), m_font->weight(), m_font->slope()));
set_font(Gfx::FontDatabase::the().get(Gfx::FontDatabase::the().default_fixed_width_font().family(), m_font->presentation_size(), m_font->weight(), m_font->width(), m_font->slope()));
else
set_font(Gfx::FontDatabase::the().get(Gfx::FontDatabase::the().default_font().family(), m_font->presentation_size(), m_font->weight(), m_font->slope()));
set_font(Gfx::FontDatabase::the().get(Gfx::FontDatabase::the().default_font().family(), m_font->presentation_size(), m_font->weight(), m_font->width(), m_font->slope()));
}
void Widget::set_min_size(UISize const& size)

View File

@ -28,7 +28,7 @@ CoverWizardPage::CoverWizardPage()
m_content_widget->layout()->set_margins(20);
m_header_label = m_content_widget->add<Label>();
m_header_label->set_font(Gfx::FontDatabase::the().get("Pebbleton", 14, 700, 0));
m_header_label->set_font(Gfx::FontDatabase::the().get("Pebbleton", 14, 700, Gfx::FontWidth::Normal, 0));
m_header_label->set_text_alignment(Gfx::TextAlignment::TopLeft);
m_header_label->set_fixed_height(48);

View File

@ -385,7 +385,7 @@ Font const& Font::bold_variant() const
{
if (m_bold_variant)
return *m_bold_variant;
m_bold_variant = Gfx::FontDatabase::the().get(family(), presentation_size(), 700, 0);
m_bold_variant = Gfx::FontDatabase::the().get(family(), presentation_size(), 700, Gfx::FontWidth::Normal, 0);
if (!m_bold_variant)
m_bold_variant = this;
return *m_bold_variant;

View File

@ -44,6 +44,8 @@ public:
virtual float pixel_size() const override { return m_glyph_height; }
u16 width() const override { return FontWidth::Normal; }
u16 weight() const override { return m_weight; }
void set_weight(u16 weight) { m_weight = weight; }

View File

@ -127,6 +127,19 @@ struct FontPixelMetrics {
float line_spacing() const { return ascent + descent + line_gap; }
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/os2#uswidthclass
enum FontWidth {
UltraCondensed = 1,
ExtraCondensed = 2,
Condensed = 3,
SemiCondensed = 4,
Normal = 5,
SemiExpanded = 6,
Expanded = 7,
ExtraExpanded = 8,
UltraExpanded = 9
};
class Font : public RefCounted<Font> {
public:
enum class AllowInexactSizeMatch {
@ -144,6 +157,8 @@ public:
virtual float pixel_size() const = 0;
virtual u8 slope() const = 0;
virtual u16 width() const = 0;
virtual u16 weight() const = 0;
virtual Glyph glyph(u32 code_point) const = 0;
virtual Glyph glyph(u32 code_point, GlyphSubpixelOffset) const = 0;

View File

@ -206,7 +206,7 @@ RefPtr<Gfx::Font> FontDatabase::get_by_name(StringView name)
auto weight = parts.take_last().to_int().value_or(0);
auto size = parts.take_last().to_int().value_or(0);
auto family = DeprecatedString::join(' ', parts);
return get(family, size, weight, slope);
return get(family, size, weight, Gfx::FontWidth::Normal, slope);
}
dbgln("Font lookup failed: '{}'", name);
return nullptr;
@ -214,13 +214,13 @@ RefPtr<Gfx::Font> FontDatabase::get_by_name(StringView name)
return it->value;
}
RefPtr<Gfx::Font> FontDatabase::get(DeprecatedFlyString const& family, float point_size, unsigned weight, unsigned slope, Font::AllowInexactSizeMatch allow_inexact_size_match)
RefPtr<Gfx::Font> FontDatabase::get(DeprecatedFlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope, Font::AllowInexactSizeMatch allow_inexact_size_match)
{
auto it = m_private->typefaces.find(family);
if (it == m_private->typefaces.end())
return nullptr;
for (auto const& typeface : it->value) {
if (typeface->weight() == weight && typeface->slope() == slope)
if (typeface->weight() == weight && typeface->width() == width && typeface->slope() == slope)
return typeface->get_font(point_size, allow_inexact_size_match);
}
return nullptr;

View File

@ -48,7 +48,7 @@ public:
static void set_fixed_width_font_query(DeprecatedString);
static void set_default_fonts_lookup_path(DeprecatedString);
RefPtr<Gfx::Font> get(DeprecatedFlyString const& family, float point_size, unsigned weight, unsigned slope, Font::AllowInexactSizeMatch = Font::AllowInexactSizeMatch::No);
RefPtr<Gfx::Font> get(DeprecatedFlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope, Font::AllowInexactSizeMatch = Font::AllowInexactSizeMatch::No);
RefPtr<Gfx::Font> get(DeprecatedFlyString const& family, DeprecatedFlyString const& variant, float point_size, Font::AllowInexactSizeMatch = Font::AllowInexactSizeMatch::No);
RefPtr<Gfx::Font> get_by_name(StringView);
void for_each_font(Function<void(Gfx::Font const&)>);

View File

@ -650,6 +650,15 @@ u16 Font::weight() const
return 400;
}
u16 Font::width() const
{
if (m_os2.has_value()) {
return m_os2->width_class();
}
return Gfx::FontWidth::Normal;
}
u8 Font::slope() const
{
// https://docs.microsoft.com/en-us/typography/opentype/spec/os2
@ -680,6 +689,11 @@ u16 OS2::weight_class() const
return header().us_weight_class;
}
u16 OS2::width_class() const
{
return header().us_width_class;
}
u16 OS2::selection() const
{
return header().fs_selection;

View File

@ -37,6 +37,7 @@ public:
virtual DeprecatedString family() const override;
virtual DeprecatedString variant() const override;
virtual u16 weight() const override;
virtual u16 width() const override;
virtual u8 slope() const override;
virtual bool is_fixed_width() const override;

View File

@ -231,6 +231,7 @@ private:
class OS2 {
public:
u16 weight_class() const;
u16 width_class() const;
u16 selection() const;
i16 typographic_ascender() const;
i16 typographic_descender() const;

View File

@ -38,6 +38,7 @@ public:
virtual float pixel_size() const override { return m_point_height * 1.33333333f; }
virtual Gfx::FontPixelMetrics pixel_metrics() const override;
virtual u8 slope() const override { return m_font->slope(); }
virtual u16 width() const override { return m_font->width(); }
virtual u16 weight() const override { return m_font->weight(); }
virtual Gfx::Glyph glyph(u32 code_point) const override;
virtual float glyph_left_bearing(u32 code_point) const override;

View File

@ -19,6 +19,16 @@ unsigned Typeface::weight() const
return m_vector_font->weight();
}
unsigned Typeface::width() const
{
VERIFY(m_vector_font || m_bitmap_fonts.size() > 0);
if (is_fixed_size())
return Gfx::FontWidth::Normal;
return m_vector_font->width();
}
u8 Typeface::slope() const
{
VERIFY(m_vector_font || m_bitmap_fonts.size() > 0);

View File

@ -27,6 +27,7 @@ public:
DeprecatedFlyString const& family() const { return m_family; }
DeprecatedFlyString const& variant() const { return m_variant; }
unsigned weight() const;
unsigned width() const;
u8 slope() const;
bool is_fixed_width() const;

View File

@ -44,6 +44,7 @@ public:
virtual DeprecatedString family() const = 0;
virtual DeprecatedString variant() const = 0;
virtual u16 weight() const = 0;
virtual u16 width() const = 0;
virtual u8 slope() const = 0;
virtual bool is_fixed_width() const = 0;
};

View File

@ -33,6 +33,7 @@ public:
virtual DeprecatedString family() const override { return m_input_font->family(); }
virtual DeprecatedString variant() const override { return m_input_font->variant(); }
virtual u16 weight() const override { return m_input_font->weight(); }
virtual u16 width() const override { return m_input_font->width(); }
virtual u8 slope() const override { return m_input_font->slope(); }
virtual bool is_fixed_width() const override { return m_input_font->is_fixed_width(); }

View File

@ -998,6 +998,8 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
auto font_style = style.property(CSS::PropertyID::FontStyle);
auto font_weight = style.property(CSS::PropertyID::FontWeight);
int width = Gfx::FontWidth::Normal;
int weight = Gfx::FontWeight::Regular;
if (font_weight->is_identifier()) {
switch (static_cast<IdentifierStyleValue const&>(*font_weight).id()) {
@ -1133,7 +1135,7 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
auto find_font = [&](DeprecatedString const& family) -> RefPtr<Gfx::Font> {
float font_size_in_pt = font_size_in_px * 0.75f;
font_selector = { family, font_size_in_pt, weight, slope };
font_selector = { family, font_size_in_pt, weight, width, slope };
if (auto it = m_loaded_fonts.find(family); it != m_loaded_fonts.end()) {
auto& loader = *it->value;
@ -1144,7 +1146,7 @@ void StyleComputer::compute_font(StyleProperties& style, DOM::Element const* ele
if (auto found_font = FontCache::the().get(font_selector))
return found_font;
if (auto found_font = Gfx::FontDatabase::the().get(family, font_size_in_pt, weight, slope, Gfx::Font::AllowInexactSizeMatch::Yes))
if (auto found_font = Gfx::FontDatabase::the().get(family, font_size_in_pt, weight, width, slope, Gfx::Font::AllowInexactSizeMatch::Yes))
return found_font;
return {};

View File

@ -16,11 +16,12 @@ struct FontSelector {
DeprecatedFlyString family;
float point_size { 0 };
int weight { 0 };
int width { 0 };
int slope { 0 };
bool operator==(FontSelector const& other) const
{
return family == other.family && point_size == other.point_size && weight == other.weight && slope == other.slope;
return family == other.family && point_size == other.point_size && weight == other.weight && width == other.width && slope == other.slope;
}
};