FontDatabase.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/DeprecatedFlyString.h>
  7. #include <AK/FlyString.h>
  8. #include <AK/LexicalPath.h>
  9. #include <AK/Queue.h>
  10. #include <LibCore/Resource.h>
  11. #include <LibGfx/Font/Font.h>
  12. #include <LibGfx/Font/FontDatabase.h>
  13. #include <LibGfx/Font/ScaledFont.h>
  14. #include <LibGfx/Font/WOFF/Loader.h>
  15. namespace Gfx {
  16. FontDatabase& FontDatabase::the()
  17. {
  18. static FontDatabase s_the;
  19. return s_the;
  20. }
  21. struct FontDatabase::Private {
  22. bool force_fontconfig { false };
  23. HashMap<FlyString, Vector<NonnullRefPtr<Typeface>>, AK::ASCIICaseInsensitiveFlyStringTraits> typeface_by_family;
  24. };
  25. void FontDatabase::set_force_fontconfig(bool force_fontconfig)
  26. {
  27. m_private->force_fontconfig = force_fontconfig;
  28. }
  29. bool FontDatabase::should_force_fontconfig() const
  30. {
  31. return m_private->force_fontconfig;
  32. }
  33. void FontDatabase::load_all_fonts_from_uri(StringView uri)
  34. {
  35. auto root_or_error = Core::Resource::load_from_uri(uri);
  36. if (root_or_error.is_error()) {
  37. if (root_or_error.error().is_errno() && root_or_error.error().code() == ENOENT) {
  38. return;
  39. }
  40. dbgln("FontDatabase::load_all_fonts_from_uri('{}'): {}", uri, root_or_error.error());
  41. return;
  42. }
  43. auto root = root_or_error.release_value();
  44. root->for_each_descendant_file([this](Core::Resource const& resource) -> IterationDecision {
  45. auto uri = resource.uri();
  46. auto path = LexicalPath(uri.bytes_as_string_view());
  47. if (path.has_extension(".ttf"sv)) {
  48. // FIXME: What about .otf
  49. if (auto font_or_error = Typeface::try_load_from_resource(resource); !font_or_error.is_error()) {
  50. auto font = font_or_error.release_value();
  51. auto& family = m_private->typeface_by_family.ensure(font->family(), [] {
  52. return Vector<NonnullRefPtr<Typeface>> {};
  53. });
  54. family.append(font);
  55. }
  56. } else if (path.has_extension(".woff"sv)) {
  57. if (auto font_or_error = WOFF::try_load_from_resource(resource); !font_or_error.is_error()) {
  58. auto font = font_or_error.release_value();
  59. auto& family = m_private->typeface_by_family.ensure(font->family(), [] {
  60. return Vector<NonnullRefPtr<Typeface>> {};
  61. });
  62. family.append(font);
  63. }
  64. }
  65. return IterationDecision::Continue;
  66. });
  67. }
  68. FontDatabase::FontDatabase()
  69. : m_private(make<Private>())
  70. {
  71. }
  72. RefPtr<Gfx::Font> FontDatabase::get(FlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope)
  73. {
  74. auto it = m_private->typeface_by_family.find(family);
  75. if (it == m_private->typeface_by_family.end())
  76. return nullptr;
  77. for (auto const& typeface : it->value) {
  78. if (typeface->weight() == weight && typeface->width() == width && typeface->slope() == slope)
  79. return typeface->scaled_font(point_size);
  80. }
  81. return nullptr;
  82. }
  83. void FontDatabase::for_each_typeface_with_family_name(FlyString const& family_name, Function<void(Typeface const&)> callback)
  84. {
  85. auto it = m_private->typeface_by_family.find(family_name);
  86. if (it == m_private->typeface_by_family.end())
  87. return;
  88. for (auto const& typeface : it->value)
  89. callback(*typeface);
  90. }
  91. }