FontDatabase.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  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/OpenType/Font.h>
  14. #include <LibGfx/Font/ScaledFont.h>
  15. #include <LibGfx/Font/WOFF/Font.h>
  16. namespace Gfx {
  17. FontDatabase& FontDatabase::the()
  18. {
  19. static FontDatabase s_the;
  20. return s_the;
  21. }
  22. struct FontDatabase::Private {
  23. HashMap<FlyString, Vector<NonnullRefPtr<VectorFont>>, AK::ASCIICaseInsensitiveFlyStringTraits> typeface_by_family;
  24. };
  25. void FontDatabase::load_all_fonts_from_uri(StringView uri)
  26. {
  27. auto root_or_error = Core::Resource::load_from_uri(uri);
  28. if (root_or_error.is_error()) {
  29. if (root_or_error.error().is_errno() && root_or_error.error().code() == ENOENT) {
  30. return;
  31. }
  32. dbgln("FontDatabase::load_all_fonts_from_uri('{}'): {}", uri, root_or_error.error());
  33. return;
  34. }
  35. auto root = root_or_error.release_value();
  36. root->for_each_descendant_file([this](Core::Resource const& resource) -> IterationDecision {
  37. auto uri = resource.uri();
  38. auto path = LexicalPath(uri.bytes_as_string_view());
  39. if (path.has_extension(".ttf"sv)) {
  40. // FIXME: What about .otf
  41. if (auto font_or_error = OpenType::Font::try_load_from_resource(resource); !font_or_error.is_error()) {
  42. auto font = font_or_error.release_value();
  43. auto& family = m_private->typeface_by_family.ensure(font->family(), [] {
  44. return Vector<NonnullRefPtr<VectorFont>> {};
  45. });
  46. family.append(font);
  47. }
  48. } else if (path.has_extension(".woff"sv)) {
  49. if (auto font_or_error = WOFF::Font::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<VectorFont>> {};
  53. });
  54. family.append(font);
  55. }
  56. }
  57. return IterationDecision::Continue;
  58. });
  59. }
  60. FontDatabase::FontDatabase()
  61. : m_private(make<Private>())
  62. {
  63. load_all_fonts_from_uri("resource://fonts"sv);
  64. }
  65. RefPtr<Gfx::Font> FontDatabase::get(FlyString const& family, float point_size, unsigned weight, unsigned width, unsigned slope)
  66. {
  67. auto it = m_private->typeface_by_family.find(family);
  68. if (it == m_private->typeface_by_family.end())
  69. return nullptr;
  70. for (auto const& typeface : it->value) {
  71. if (typeface->weight() == weight && typeface->width() == width && typeface->slope() == slope)
  72. return typeface->scaled_font(point_size);
  73. }
  74. return nullptr;
  75. }
  76. RefPtr<Gfx::Font> FontDatabase::get(FlyString const& family, FlyString const& variant, float point_size)
  77. {
  78. auto it = m_private->typeface_by_family.find(family);
  79. if (it == m_private->typeface_by_family.end())
  80. return nullptr;
  81. for (auto const& typeface : it->value) {
  82. if (typeface->variant() == variant)
  83. return typeface->scaled_font(point_size);
  84. }
  85. return nullptr;
  86. }
  87. void FontDatabase::for_each_typeface_with_family_name(FlyString const& family_name, Function<void(VectorFont const&)> callback)
  88. {
  89. auto it = m_private->typeface_by_family.find(family_name);
  90. if (it == m_private->typeface_by_family.end())
  91. return;
  92. for (auto const& typeface : it->value)
  93. callback(*typeface);
  94. }
  95. }