mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 02:17:35 +00:00
LibGfx: Use LibUnicode to filter code points that cannot start an emoji
This commit is contained in:
parent
392c8c99aa
commit
8be43cd3bf
2 changed files with 7 additions and 37 deletions
|
@ -51,35 +51,10 @@ Bitmap const* Emoji::emoji_for_code_points(ReadonlySpan<u32> const& code_points)
|
||||||
return bitmap.ptr();
|
return bitmap.ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename CodePointIterator>
|
|
||||||
static bool could_be_emoji(CodePointIterator const& it)
|
|
||||||
{
|
|
||||||
if (it.done())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
static constexpr u32 supplementary_private_use_area_b_first_code_point = 0x100000;
|
|
||||||
if (*it >= supplementary_private_use_area_b_first_code_point) {
|
|
||||||
// We use Supplementary Private Use Area-B for custom Serenity emoji.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static auto const emoji_property = Unicode::property_from_string("Emoji"sv);
|
|
||||||
if (!emoji_property.has_value()) {
|
|
||||||
// This means Unicode data generation is disabled. Always check the disk in that case.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Unicode::code_point_has_property(*it, *emoji_property);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename CodePointIterator>
|
template<typename CodePointIterator>
|
||||||
static Bitmap const* emoji_for_code_point_iterator_impl(CodePointIterator& it)
|
static Bitmap const* emoji_for_code_point_iterator_impl(CodePointIterator& it)
|
||||||
{
|
{
|
||||||
// NOTE: I'm sure this could be more efficient, e.g. by checking if each code point falls
|
if (!Unicode::could_be_start_of_emoji_sequence(it))
|
||||||
// into a certain range in the loop below (emojis, modifiers, variation selectors, ZWJ),
|
|
||||||
// and bailing out early if not. Current worst case is 10 file lookups for any sequence of
|
|
||||||
// code points (if the first glyph isn't part of the font in regular text rendering).
|
|
||||||
if (!could_be_emoji(it))
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
constexpr size_t max_emoji_code_point_sequence_length = 10;
|
constexpr size_t max_emoji_code_point_sequence_length = 10;
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include <LibGfx/TextDirection.h>
|
#include <LibGfx/TextDirection.h>
|
||||||
#include <LibGfx/TextLayout.h>
|
#include <LibGfx/TextLayout.h>
|
||||||
#include <LibUnicode/CharacterTypes.h>
|
#include <LibUnicode/CharacterTypes.h>
|
||||||
|
#include <LibUnicode/Emoji.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#if defined(AK_COMPILER_GCC)
|
#if defined(AK_COMPILER_GCC)
|
||||||
|
@ -1396,13 +1397,14 @@ 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)
|
void Painter::draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, Font const& font, Color color)
|
||||||
{
|
{
|
||||||
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);
|
|
||||||
|
|
||||||
u32 code_point = *it;
|
u32 code_point = *it;
|
||||||
auto next_code_point = it.peek(1);
|
auto next_code_point = it.peek(1);
|
||||||
|
|
||||||
ScopeGuard consume_variation_selector = [&, initial_it = it] {
|
ScopeGuard consume_variation_selector = [&, initial_it = it] {
|
||||||
|
static auto const variation_selector = Unicode::property_from_string("Variation_Selector"sv);
|
||||||
|
if (!variation_selector.has_value())
|
||||||
|
return;
|
||||||
|
|
||||||
// If we advanced the iterator to consume an emoji sequence, don't look for another variation selector.
|
// If we advanced the iterator to consume an emoji sequence, don't look for another variation selector.
|
||||||
if (initial_it != it)
|
if (initial_it != it)
|
||||||
return;
|
return;
|
||||||
|
@ -1413,14 +1415,7 @@ void Painter::draw_glyph_or_emoji(FloatPoint point, Utf8CodePointIterator& it, F
|
||||||
};
|
};
|
||||||
|
|
||||||
auto font_contains_glyph = font.contains_glyph(code_point);
|
auto font_contains_glyph = font.contains_glyph(code_point);
|
||||||
auto check_for_emoji = false;
|
auto check_for_emoji = Unicode::could_be_start_of_emoji_sequence(it);
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
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 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) {
|
if (font_contains_glyph && !check_for_emoji) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue