/* * Copyright (c) 2023-2024, Aliaksandr Kalenik * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include namespace Gfx { class FontCascadeList : public RefCounted { public: using SystemFontFallbackCallback = Function(u32, Font const&)>; static NonnullRefPtr create() { return adopt_ref(*new FontCascadeList()); } size_t size() const { return m_fonts.size(); } bool is_empty() const { return m_fonts.is_empty() && !m_last_resort_font; } Font const& first() const { return !m_fonts.is_empty() ? *m_fonts.first().font : *m_last_resort_font; } template void for_each_font_entry(Callback callback) const { for (auto const& font : m_fonts) callback(font); } void add(NonnullRefPtr font); void add(NonnullRefPtr font, Vector unicode_ranges); void extend(FontCascadeList const& other); Gfx::Font const& font_for_code_point(u32 code_point) const; bool equals(FontCascadeList const& other) const; struct Entry { NonnullRefPtr font; struct RangeData { // The enclosing range is the union of all Unicode ranges. Used for fast skipping. UnicodeRange enclosing_range; Vector unicode_ranges; }; Optional range_data; }; void set_last_resort_font(NonnullRefPtr font) { m_last_resort_font = move(font); } void set_system_font_fallback_callback(SystemFontFallbackCallback callback) { m_system_font_fallback_callback = move(callback); } Font const& first_text_face() const { for (auto const& entry : m_fonts) if (!entry.font->is_emoji_font()) return *entry.font; return first(); } private: RefPtr m_last_resort_font; mutable Vector m_fonts; SystemFontFallbackCallback m_system_font_fallback_callback; }; }