diff options
author | Timothy Flynn <trflynn89@pm.me> | 2023-02-21 07:50:41 -0500 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-02-22 10:14:36 +0100 |
commit | 2bc7c11e8d9c6aae561a9e34c6bcf9bc29fd9917 (patch) | |
tree | 5f03ef7f810d61e60b19910ef076dd404e802df2 /Userland/Libraries/LibGfx | |
parent | 2eb2207f5049e6b154e3601faca1b7d69b62bf8a (diff) | |
download | serenity-2bc7c11e8d9c6aae561a9e34c6bcf9bc29fd9917.zip |
LibGfx: Consult Unicode data to decode emoji sequences
For example, consider the Pirate Flag emoji, which is the code point
sequence U+1F3F4 U+200D U+2620 U+FE0F. Our current emoji resolution does
not consider U+200D (Zero Width Joiner) as part of an emoji sequence.
Therefore fonts like Katica, which have a glyph for U+1F3F4, will draw
that glyph without checking if we have an emoji bitmap.
This removes some hard-coded code points and consults the UCD's code
point properties for emoji sequence components and variation selectors.
This recognizes the ZWJ code point as part of an emoji sequence.
Diffstat (limited to 'Userland/Libraries/LibGfx')
-rw-r--r-- | Userland/Libraries/LibGfx/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibGfx/Painter.cpp | 30 |
2 files changed, 14 insertions, 18 deletions
diff --git a/Userland/Libraries/LibGfx/CMakeLists.txt b/Userland/Libraries/LibGfx/CMakeLists.txt index 3f5073ec8e..9e5ac10092 100644 --- a/Userland/Libraries/LibGfx/CMakeLists.txt +++ b/Userland/Libraries/LibGfx/CMakeLists.txt @@ -59,4 +59,4 @@ set(SOURCES ) serenity_lib(LibGfx gfx) -target_link_libraries(LibGfx PRIVATE LibCompress LibCore LibCrypto LibTextCodec LibIPC) +target_link_libraries(LibGfx PRIVATE LibCompress LibCore LibCrypto LibTextCodec LibIPC LibUnicode) diff --git a/Userland/Libraries/LibGfx/Painter.cpp b/Userland/Libraries/LibGfx/Painter.cpp index b7ee81fda1..ee85d60752 100644 --- a/Userland/Libraries/LibGfx/Painter.cpp +++ b/Userland/Libraries/LibGfx/Painter.cpp @@ -33,6 +33,7 @@ #include <LibGfx/Quad.h> #include <LibGfx/TextDirection.h> #include <LibGfx/TextLayout.h> +#include <LibUnicode/CharacterTypes.h> #include <stdio.h> #if defined(AK_COMPILER_GCC) @@ -1395,36 +1396,31 @@ void Painter::draw_glyph_or_emoji(FloatPoint point, u32 code_point, Font const& void Painter::draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font, Color color) { - // FIXME: These should live somewhere else. - constexpr u32 text_variation_selector = 0xFE0E; - constexpr u32 emoji_variation_selector = 0xFE0F; - constexpr u32 regional_indicator_symbol_a = 0x1F1E6; - constexpr u32 regional_indicator_symbol_z = 0x1F1FF; + static auto const emoji_component_property = Unicode::property_from_string("Emoji_Component"sv); + static auto const variation_selector = Unicode::property_from_string("Variation_Selector"sv); - auto initial_it = it; u32 code_point = *it; auto next_code_point = it.peek(1); - ScopeGuard consume_variation_selector = [&] { + ScopeGuard consume_variation_selector = [&, initial_it = it] { // If we advanced the iterator to consume an emoji sequence, don't look for another variation selector. if (initial_it != it) return; + // Otherwise, discard one code point if it's a variation selector. - auto next_code_point = it.peek(1); - if (next_code_point == text_variation_selector || next_code_point == emoji_variation_selector) + if (next_code_point.has_value() && Unicode::code_point_has_property(*next_code_point, *variation_selector)) ++it; }; - auto code_point_is_regional_indicator = code_point >= regional_indicator_symbol_a && code_point <= regional_indicator_symbol_z; auto font_contains_glyph = font.contains_glyph(code_point); + auto check_for_emoji = false; + + if (emoji_component_property.has_value()) { + auto code_point_is_emoji_component = Unicode::code_point_has_property(code_point, *emoji_component_property); + auto next_code_point_is_emoji_component = next_code_point.has_value() && Unicode::code_point_has_property(*next_code_point, *emoji_component_property); - auto check_for_emoji = false - // Flag emojis consist of two regional indicators. - || code_point_is_regional_indicator - // U+00A9 (copyright) or U+00AE (registered) are text glyphs by default, - // keycap emojis ({#,*,0-9} U+FE0F U+20E3) start with a regular ASCII character. - // Both cases are handled by peeking for the variation selector. - || next_code_point == emoji_variation_selector; + check_for_emoji = code_point_is_emoji_component || next_code_point_is_emoji_component; + } // If the font contains the glyph, and we know it's not the start of an emoji, draw a text glyph. if (font_contains_glyph && !check_for_emoji) { |