TestFontHandling.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * Copyright (c) 2020, the SerenityOS developers.
  3. * Copyright (c) 2021, Brian Gianforcaro <bgianf@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Utf8View.h>
  8. #include <LibCore/ResourceImplementationFile.h>
  9. #include <LibGfx/Font/BitmapFont.h>
  10. #include <LibGfx/Font/FontDatabase.h>
  11. #include <LibGfx/Font/OpenType/Glyf.h>
  12. #include <LibTest/TestCase.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <unistd.h>
  16. #ifdef AK_OS_SERENITY
  17. # define TEST_INPUT(x) ("/usr/Tests/LibGfx/test-inputs/" x)
  18. #else
  19. # define TEST_INPUT(x) ("test-inputs/" x)
  20. #endif
  21. static void init_font_database()
  22. {
  23. Core::ResourceImplementation::install(make<Core::ResourceImplementationFile>(TEST_INPUT(""_string)));
  24. Gfx::FontDatabase::the().load_all_fonts_from_uri("resource:///"sv);
  25. }
  26. TEST_CASE(test_fontdatabase_get_by_name)
  27. {
  28. init_font_database();
  29. auto& font_database = Gfx::FontDatabase::the();
  30. auto name = "Family 12 400 0"sv;
  31. EXPECT(!font_database.get_by_name(name)->name().is_empty());
  32. }
  33. TEST_CASE(test_fontdatabase_get)
  34. {
  35. init_font_database();
  36. auto& font_database = Gfx::FontDatabase::the();
  37. EXPECT(!font_database.get("Family"_fly_string, 12, 400, Gfx::FontWidth::Normal, 0)->name().is_empty());
  38. }
  39. TEST_CASE(test_fontdatabase_for_each_font)
  40. {
  41. init_font_database();
  42. auto& font_database = Gfx::FontDatabase::the();
  43. font_database.for_each_font([&](Gfx::Font const& font) {
  44. EXPECT(!font.name().is_empty());
  45. EXPECT(!font.qualified_name().is_empty());
  46. EXPECT(!font.family().is_empty());
  47. EXPECT(font.glyph_count() > 0);
  48. });
  49. }
  50. TEST_CASE(test_clone)
  51. {
  52. u8 glyph_height = 1;
  53. u8 glyph_width = 1;
  54. auto font = MUST(Gfx::BitmapFont::create(glyph_height, glyph_width, true, 256));
  55. auto new_font = font->clone();
  56. EXPECT(!new_font->name().is_empty());
  57. EXPECT(!new_font->qualified_name().is_empty());
  58. EXPECT(!new_font->family().is_empty());
  59. EXPECT(new_font->glyph_count() > 0);
  60. }
  61. TEST_CASE(test_set_name)
  62. {
  63. u8 glyph_height = 1;
  64. u8 glyph_width = 1;
  65. auto font = MUST(Gfx::BitmapFont::create(glyph_height, glyph_width, true, 256));
  66. auto name = "my newly created font"_string;
  67. font->set_name(name);
  68. EXPECT(!font->name().is_empty());
  69. EXPECT(font->name().contains(name));
  70. }
  71. TEST_CASE(test_set_family)
  72. {
  73. u8 glyph_height = 1;
  74. u8 glyph_width = 1;
  75. auto font = MUST(Gfx::BitmapFont::create(glyph_height, glyph_width, true, 256));
  76. auto family = "my newly created font family"_string;
  77. font->set_family(family);
  78. EXPECT(!font->family().is_empty());
  79. EXPECT(font->family().contains(family));
  80. }
  81. TEST_CASE(test_set_glyph_width)
  82. {
  83. u8 glyph_height = 1;
  84. u8 glyph_width = 1;
  85. auto font = MUST(Gfx::BitmapFont::create(glyph_height, glyph_width, true, 256));
  86. size_t ch = 123;
  87. font->set_glyph_width(ch, glyph_width);
  88. EXPECT(font->glyph_width(ch) == glyph_width);
  89. }
  90. TEST_CASE(test_set_glyph_spacing)
  91. {
  92. u8 glyph_height = 1;
  93. u8 glyph_width = 1;
  94. auto font = MUST(Gfx::BitmapFont::create(glyph_height, glyph_width, true, 256));
  95. u8 glyph_spacing = 8;
  96. font->set_glyph_spacing(glyph_spacing);
  97. EXPECT(font->glyph_spacing() == glyph_spacing);
  98. }
  99. TEST_CASE(test_width)
  100. {
  101. u8 glyph_height = 1;
  102. u8 glyph_width = 1;
  103. auto font = MUST(Gfx::BitmapFont::create(glyph_height, glyph_width, true, 256));
  104. EXPECT(font->width("A"sv) == glyph_width);
  105. }
  106. TEST_CASE(test_glyph_or_emoji_width)
  107. {
  108. u8 glyph_height = 1;
  109. u8 glyph_width = 1;
  110. auto font = MUST(Gfx::BitmapFont::create(glyph_height, glyph_width, true, 256));
  111. Utf8View view { " "sv };
  112. auto it = view.begin();
  113. EXPECT(font->glyph_or_emoji_width(it));
  114. }
  115. TEST_CASE(test_load_from_file)
  116. {
  117. auto font = Gfx::BitmapFont::load_from_file(TEST_INPUT("TestFont.font"sv));
  118. EXPECT(!font->name().is_empty());
  119. }
  120. TEST_CASE(test_write_to_file)
  121. {
  122. u8 glyph_height = 1;
  123. u8 glyph_width = 1;
  124. auto font = MUST(Gfx::BitmapFont::create(glyph_height, glyph_width, true, 256));
  125. char path[] = "/tmp/new.font.XXXXXX";
  126. EXPECT(mkstemp(path) != -1);
  127. TRY_OR_FAIL(font->write_to_file(path));
  128. unlink(path);
  129. }
  130. TEST_CASE(test_character_set_masking)
  131. {
  132. auto font = TRY_OR_FAIL(Gfx::BitmapFont::try_load_from_file(TEST_INPUT("TestFont.font"sv)));
  133. auto unmasked_font = TRY_OR_FAIL(font->unmasked_character_set());
  134. EXPECT(unmasked_font->glyph_index(0x0041).value() == 0x0041);
  135. EXPECT(unmasked_font->glyph_index(0x0100).value() == 0x0100);
  136. EXPECT(unmasked_font->glyph_index(0xFFFD).value() == 0xFFFD);
  137. auto masked_font = TRY_OR_FAIL(unmasked_font->masked_character_set());
  138. EXPECT(masked_font->glyph_index(0x0041).value() == 0x0041);
  139. EXPECT(!masked_font->glyph_index(0x0100).has_value());
  140. EXPECT(masked_font->glyph_index(0xFFFD).value() == 0x1FD);
  141. }
  142. TEST_CASE(rasterize_glyph_containing_single_off_curve_point)
  143. {
  144. Vector<u8> glyph_data {
  145. 0, 5, 0, 205, 255, 51, 7, 51, 6, 225, 0, 3, 0, 6, 0, 9, 0, 12, 0, 15, 0, 31, 64, 13, 13, 2, 15, 5, 7, 2, 8, 5, 10, 3, 0,
  146. 5, 3, 0, 47, 47, 51, 17, 51, 17, 51, 17, 51, 17, 51, 17, 51, 48, 49, 19, 33, 17, 33, 1, 33, 1, 1, 17, 1, 1, 33, 9, 3,
  147. 205, 6, 102, 249, 154, 5, 184, 250, 248, 2, 133, 2, 199, 253, 125, 253, 57, 5, 4, 253, 127, 253, 53, 2, 133, 253,
  148. 123, 6, 225, 248, 82, 7, 68, 252, 231, 252, 145, 6, 50, 252, 231, 252, 149, 3, 23, 253, 57, 3, 27, 3, 29, 0, 1, 0, 0,
  149. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 177, 2, 81, 43, 48, 49, 48, 0
  150. };
  151. OpenType::Glyf glyf(glyph_data.span());
  152. auto glyph = glyf.glyph(118);
  153. EXPECT(glyph.has_value());
  154. EXPECT_NO_CRASH("rasterizing glyph containing single off-curve point should not crash", [&] {
  155. (void)glyph->rasterize(0, 0, 1, 1, {}, [&](u16) -> Optional<OpenType::Glyf::Glyph> { VERIFY_NOT_REACHED(); });
  156. return Test::Crash::Failure::DidNotCrash;
  157. });
  158. }