From fd1fbad1d26f59c8b1cb142c84b367d3acbd2299 Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Wed, 1 Mar 2023 08:43:22 -0500 Subject: [PATCH] LibGfx+LibUnicode: Support specifying the path to search for emoji Similar to the FontDatabase, this will be needed for Ladybird to find emoji images. We now generate just the file name of emoji image in LibUnicode, and look for that file in the specified path (defaulting to /res/emoji) at runtime. --- Meta/CMake/unicode_data.cmake | 5 ++-- .../LibUnicode/GenerateEmojiData.cpp | 13 ++++----- Userland/Libraries/LibGfx/Font/Emoji.cpp | 27 ++++++++++++++----- Userland/Libraries/LibGfx/Font/Emoji.h | 3 +++ 4 files changed, 31 insertions(+), 17 deletions(-) diff --git a/Meta/CMake/unicode_data.cmake b/Meta/CMake/unicode_data.cmake index 680ebdaa4bc..dc97c6362b3 100644 --- a/Meta/CMake/unicode_data.cmake +++ b/Meta/CMake/unicode_data.cmake @@ -64,8 +64,7 @@ set(SENTENCE_BREAK_PROP_PATH "${UCD_PATH}/${SENTENCE_BREAK_PROP_SOURCE}") string(REGEX REPLACE "([0-9]+\\.[0-9]+)\\.[0-9]+" "\\1" EMOJI_VERSION "${UCD_VERSION}") set(EMOJI_TEST_URL "https://www.unicode.org/Public/emoji/${EMOJI_VERSION}/emoji-test.txt") set(EMOJI_TEST_PATH "${UCD_PATH}/emoji-test.txt") -set(EMOJI_BASE_PATH "${SerenityOS_SOURCE_DIR}/Base") -set(EMOJI_RES_PATH "${EMOJI_BASE_PATH}/res/emoji") +set(EMOJI_RES_PATH "${SerenityOS_SOURCE_DIR}/Base/res/emoji") set(EMOJI_SERENITY_PATH "${SerenityOS_SOURCE_DIR}/Base/home/anon/Documents/emoji-serenity.txt") set(EMOJI_INSTALL_PATH "${CMAKE_BINARY_DIR}/Root/home/anon/Documents/emoji.txt") @@ -118,7 +117,7 @@ if (ENABLE_UNICODE_DATABASE_DOWNLOAD) "${UCD_VERSION_FILE}" "${EMOJI_DATA_HEADER}" "${EMOJI_DATA_IMPLEMENTATION}" - arguments "${EMOJI_INSTALL_ARG}" -e "${EMOJI_TEST_PATH}" -s "${EMOJI_SERENITY_PATH}" -b "${EMOJI_BASE_PATH}" -r "${EMOJI_RES_PATH}" + arguments "${EMOJI_INSTALL_ARG}" -e "${EMOJI_TEST_PATH}" -s "${EMOJI_SERENITY_PATH}" -r "${EMOJI_RES_PATH}" # This will make this command only run when the modified time of the directory changes, # which only happens if files within it are added or deleted, but not when a file is modified. diff --git a/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateEmojiData.cpp b/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateEmojiData.cpp index c98bf276408..428aba01499 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateEmojiData.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateEmojiData.cpp @@ -32,7 +32,7 @@ struct EmojiData { Vector emojis; }; -static void set_image_path_for_emoji(StringView emoji_base_path, StringView emoji_resource_path, EmojiData& emoji_data, Emoji& emoji) +static void set_image_path_for_emoji(StringView emoji_resource_path, EmojiData& emoji_data, Emoji& emoji) { StringBuilder builder; @@ -44,12 +44,12 @@ static void set_image_path_for_emoji(StringView emoji_base_path, StringView emoj builder.appendff("U+{:X}", code_point); } - auto path = DeprecatedString::formatted("{}/{}.png", emoji_resource_path, builder.to_deprecated_string()); + auto file = DeprecatedString::formatted("{}.png", builder.to_deprecated_string()); + auto path = DeprecatedString::formatted("{}/{}", emoji_resource_path, file); if (!Core::DeprecatedFile::exists(path)) return; - auto installed_image_path = path.replace(emoji_base_path, {}, ReplaceMode::FirstOnly); - emoji.image_path = emoji_data.unique_strings.ensure(move(installed_image_path)); + emoji.image_path = emoji_data.unique_strings.ensure(move(file)); } static ErrorOr parse_emoji_test_data(Core::BufferedFile& file, EmojiData& emoji_data) @@ -335,7 +335,6 @@ ErrorOr serenity_main(Main::Arguments arguments) StringView generated_installation_path; StringView emoji_test_path; StringView emoji_serenity_path; - StringView emoji_base_path; StringView emoji_resource_path; Core::ArgsParser args_parser; @@ -344,11 +343,9 @@ ErrorOr serenity_main(Main::Arguments arguments) args_parser.add_option(generated_installation_path, "Path to the emoji.txt file to generate", "generated-installation-path", 'i', "generated-installation-path"); args_parser.add_option(emoji_test_path, "Path to emoji-test.txt file", "emoji-test-path", 'e', "emoji-test-path"); args_parser.add_option(emoji_serenity_path, "Path to emoji-serenity.txt file", "emoji-serenity-path", 's', "emoji-serenity-path"); - args_parser.add_option(emoji_base_path, "Path to the Base directory", "emoji-base-path", 'b', "emoji-base-path"); args_parser.add_option(emoji_resource_path, "Path to the /res/emoji directory", "emoji-resource-path", 'r', "emoji-resource-path"); args_parser.parse(arguments); - VERIFY(!emoji_base_path.is_empty() && Core::DeprecatedFile::exists(emoji_base_path)); VERIFY(!emoji_resource_path.is_empty() && Core::DeprecatedFile::exists(emoji_resource_path)); auto emoji_test_file = TRY(open_file(emoji_test_path, Core::File::OpenMode::Read)); @@ -366,7 +363,7 @@ ErrorOr serenity_main(Main::Arguments arguments) emoji.code_point_array_index = code_point_array_index; code_point_array_index += emoji.code_points.size(); - set_image_path_for_emoji(emoji_base_path, emoji_resource_path, emoji_data, emoji); + set_image_path_for_emoji(emoji_resource_path, emoji_data, emoji); } if (!generated_header_path.is_empty()) { diff --git a/Userland/Libraries/LibGfx/Font/Emoji.cpp b/Userland/Libraries/LibGfx/Font/Emoji.cpp index 51f6c6d85b6..9c11cc93b52 100644 --- a/Userland/Libraries/LibGfx/Font/Emoji.cpp +++ b/Userland/Libraries/LibGfx/Font/Emoji.cpp @@ -8,9 +8,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -23,6 +25,17 @@ namespace Gfx { // https://unicode.org/emoji/charts/emoji-zwj-sequences.html static HashMap> s_emojis; +static Variant s_emoji_lookup_path = "/res/emoji"sv; + +static StringView emoji_lookup_path() +{ + return s_emoji_lookup_path.visit([](auto const& path) -> StringView { return path; }); +} + +void Emoji::set_emoji_lookup_path(String emoji_lookup_path) +{ + s_emoji_lookup_path = move(emoji_lookup_path); +} Bitmap const* Emoji::emoji_for_code_point(u32 code_point) { @@ -35,19 +48,21 @@ Bitmap const* Emoji::emoji_for_code_points(ReadonlySpan const& code_points) if (!emoji.has_value() || !emoji->image_path.has_value()) return nullptr; - auto emoji_path = emoji->image_path.value(); - if (auto it = s_emojis.find(emoji_path); it != s_emojis.end()) + auto emoji_file = emoji->image_path.value(); + if (auto it = s_emojis.find(emoji_file); it != s_emojis.end()) return it->value.ptr(); - auto bitmap_or_error = Bitmap::load_from_file(emoji_path); + auto emoji_path = LexicalPath::join(emoji_lookup_path(), emoji_file); + auto bitmap_or_error = Bitmap::load_from_file(emoji_path.string()); + if (bitmap_or_error.is_error()) { - dbgln_if(EMOJI_DEBUG, "Generated emoji data has path {}, but could not load image: {}", emoji_path, bitmap_or_error.error()); - s_emojis.set(emoji_path, nullptr); + dbgln_if(EMOJI_DEBUG, "Generated emoji data has file {}, but could not load image: {}", emoji_file, bitmap_or_error.error()); + s_emojis.set(emoji_file, nullptr); return nullptr; } auto bitmap = bitmap_or_error.release_value(); - s_emojis.set(emoji_path, bitmap); + s_emojis.set(emoji_file, bitmap); return bitmap.ptr(); } diff --git a/Userland/Libraries/LibGfx/Font/Emoji.h b/Userland/Libraries/LibGfx/Font/Emoji.h index e59ca8a6b0e..ee8fa9a8957 100644 --- a/Userland/Libraries/LibGfx/Font/Emoji.h +++ b/Userland/Libraries/LibGfx/Font/Emoji.h @@ -9,6 +9,7 @@ #include #include +#include #include namespace Gfx { @@ -17,6 +18,8 @@ class Bitmap; class Emoji { public: + static void set_emoji_lookup_path(String); + static Gfx::Bitmap const* emoji_for_code_point(u32 code_point); static Gfx::Bitmap const* emoji_for_code_points(ReadonlySpan const&); static Gfx::Bitmap const* emoji_for_code_point_iterator(Utf8CodePointIterator&);