LibGfx+LibWeb: Allow inexact size lookups when requesting scaled fonts

For bitmap fonts, we will often not have an exact match for requested
sizes. Return the closest match instead of a nullptr.

LibWeb is currently the only user of this API. If it needs to be
configurable in the future to only allow exact matches, we can add a
parameter or another method at that time.
This commit is contained in:
Timothy Flynn 2024-05-06 13:12:16 -04:00 committed by Alexander Kalenik
commit 464d7d5858
Notes: sideshowbarker 2024-07-16 22:14:49 +09:00
12 changed files with 17 additions and 18 deletions

View file

@ -410,9 +410,12 @@ String BitmapFont::variant() const
return MUST(builder.to_string()); return MUST(builder.to_string());
} }
RefPtr<Font> BitmapFont::with_size(float point_size) const NonnullRefPtr<Font> BitmapFont::with_size(float point_size) const
{ {
return Gfx::FontDatabase::the().get(family(), point_size, weight(), width(), slope()); auto scaled_font = Gfx::FontDatabase::the().get(family(), point_size, weight(), width(), slope(), AllowInexactSizeMatch::Yes);
VERIFY(scaled_font); // The inexact lookup should, at the very least, return `this` font.
return *scaled_font;
} }
Font const& Font::bold_variant() const Font const& Font::bold_variant() const

View file

@ -130,7 +130,7 @@ public:
virtual String qualified_name() const override; virtual String qualified_name() const override;
virtual String human_readable_name() const override { return MUST(String::formatted("{} {} {}", family(), variant(), presentation_size())); } virtual String human_readable_name() const override { return MUST(String::formatted("{} {} {}", family(), variant(), presentation_size())); }
virtual RefPtr<Font> with_size(float point_size) const override; virtual NonnullRefPtr<Font> with_size(float point_size) const override;
private: private:
BitmapFont(String name, String family, Bytes rows, Span<u8> widths, bool is_fixed_width, BitmapFont(String name, String family, Bytes rows, Span<u8> widths, bool is_fixed_width,

View file

@ -212,7 +212,7 @@ public:
virtual String qualified_name() const = 0; virtual String qualified_name() const = 0;
virtual String human_readable_name() const = 0; virtual String human_readable_name() const = 0;
virtual RefPtr<Font> with_size(float point_size) const = 0; virtual NonnullRefPtr<Font> with_size(float point_size) const = 0;
Font const& bold_variant() const; Font const& bold_variant() const;

View file

@ -159,7 +159,7 @@ NonnullRefPtr<ScaledFont> ScaledFont::scaled_with_size(float point_size) const
return m_font->scaled_font(point_size); return m_font->scaled_font(point_size);
} }
RefPtr<Font> ScaledFont::with_size(float point_size) const NonnullRefPtr<Font> ScaledFont::with_size(float point_size) const
{ {
return scaled_with_size(point_size); return scaled_with_size(point_size);
} }

View file

@ -70,7 +70,7 @@ public:
virtual String human_readable_name() const override { return MUST(String::formatted("{} {} {}", family(), variant(), presentation_size())); } virtual String human_readable_name() const override { return MUST(String::formatted("{} {} {}", family(), variant(), presentation_size())); }
virtual NonnullRefPtr<ScaledFont> scaled_with_size(float point_size) const; virtual NonnullRefPtr<ScaledFont> scaled_with_size(float point_size) const;
virtual RefPtr<Font> with_size(float point_size) const override; virtual NonnullRefPtr<Font> with_size(float point_size) const override;
virtual bool has_color_bitmaps() const override { return m_font->has_color_bitmaps(); } virtual bool has_color_bitmaps() const override { return m_font->has_color_bitmaps(); }

View file

@ -2089,11 +2089,7 @@ RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(
} }
auto found_font = StyleProperties::font_fallback(monospace, bold); auto found_font = StyleProperties::font_fallback(monospace, bold);
if (auto scaled_fallback_font = found_font->with_size(font_size_in_pt)) { font_list->add(found_font->with_size(font_size_in_pt));
font_list->add(*scaled_fallback_font);
} else {
font_list->add(*found_font);
}
return font_list; return font_list;
} }

View file

@ -272,7 +272,7 @@ inline Gfx::Font const& Node::scaled_font(PaintContext& context) const
inline Gfx::Font const& Node::scaled_font(float scale_factor) const inline Gfx::Font const& Node::scaled_font(float scale_factor) const
{ {
auto const& font = first_available_font(); auto const& font = first_available_font();
return *font.with_size(font.point_size() * scale_factor); return font.with_size(font.point_size() * scale_factor);
} }
inline const CSS::ImmutableComputedValues& Node::computed_values() const inline const CSS::ImmutableComputedValues& Node::computed_values() const

View file

@ -66,7 +66,7 @@ static Vector<Gfx::Path> compute_text_clip_paths(PaintContext& context, Paintabl
Gfx::Path glyph_run_path; Gfx::Path glyph_run_path;
for (auto glyph : fragment.glyph_run().glyphs()) { for (auto glyph : fragment.glyph_run().glyphs()) {
glyph.visit([&](auto& glyph) { glyph.visit([&](auto& glyph) {
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(context.device_pixels_per_css_pixel())); glyph.font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(context.device_pixels_per_css_pixel()));
glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel()); glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel());
}); });

View file

@ -31,7 +31,7 @@ CommandResult CommandExecutorCPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> c
auto transformed_glyph = glyph_or_emoji; auto transformed_glyph = glyph_or_emoji;
transformed_glyph.visit([&](auto& glyph) { transformed_glyph.visit([&](auto& glyph) {
glyph.position = glyph.position.scaled(scale).translated(translation); glyph.position = glyph.position.scaled(scale).translated(translation);
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale)); glyph.font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
}); });
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) { if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
auto& glyph = transformed_glyph.get<Gfx::DrawGlyph>(); auto& glyph = transformed_glyph.get<Gfx::DrawGlyph>();

View file

@ -39,7 +39,7 @@ CommandResult CommandExecutorGPU::draw_glyph_run(Vector<Gfx::DrawGlyphOrEmoji> c
auto transformed_glyph = glyph; auto transformed_glyph = glyph;
transformed_glyph.visit([&](auto& glyph) { transformed_glyph.visit([&](auto& glyph) {
glyph.position = glyph.position.scaled(scale).translated(translation); glyph.position = glyph.position.scaled(scale).translated(translation);
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale)); glyph.font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
}); });
transformed_glyph_run.append(transformed_glyph); transformed_glyph_run.append(transformed_glyph);
} }

View file

@ -89,8 +89,8 @@ void CommandList::execute(CommandExecutor& executor)
for (auto const& glyph_or_emoji : command.get<DrawGlyphRun>().glyph_run->glyphs()) { for (auto const& glyph_or_emoji : command.get<DrawGlyphRun>().glyph_run->glyphs()) {
if (glyph_or_emoji.has<Gfx::DrawGlyph>()) { if (glyph_or_emoji.has<Gfx::DrawGlyph>()) {
auto const& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>(); auto const& glyph = glyph_or_emoji.get<Gfx::DrawGlyph>();
auto const& font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale)); auto font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(scale));
unique_glyphs.ensure(&font, [] { return HashTable<u32> {}; }).set(glyph.code_point); unique_glyphs.ensure(font, [] { return HashTable<u32> {}; }).set(glyph.code_point);
} }
} }
} }

View file

@ -593,7 +593,7 @@ void paint_text_shadow(PaintContext& context, PaintableFragment const& fragment,
scaled_glyph_run.ensure_capacity(fragment.glyph_run().glyphs().size()); scaled_glyph_run.ensure_capacity(fragment.glyph_run().glyphs().size());
for (auto glyph : fragment.glyph_run().glyphs()) { for (auto glyph : fragment.glyph_run().glyphs()) {
glyph.visit([&](auto& glyph) { glyph.visit([&](auto& glyph) {
glyph.font = *glyph.font->with_size(glyph.font->point_size() * static_cast<float>(context.device_pixels_per_css_pixel())); glyph.font = glyph.font->with_size(glyph.font->point_size() * static_cast<float>(context.device_pixels_per_css_pixel()));
glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel()); glyph.position = glyph.position.scaled(context.device_pixels_per_css_pixel());
}); });
scaled_glyph_run.append(move(glyph)); scaled_glyph_run.append(move(glyph));