/* * Copyright (c) 2024, Johan Dahlin * Copyright (c) 2026, Callum Law * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include namespace Web::CSS { enum class FontFeatureValueType : u8 { Stylistic, Styleset, CharacterVariant, Swash, Ornaments, Annotation, }; struct FontFeatureValueKey { FontFeatureValueType type; FlyString name; bool operator==(FontFeatureValueKey const&) const = default; }; struct FontVariantAlternates { bool historical_forms = false; Vector font_feature_value_entries; bool operator==(FontVariantAlternates const&) const = default; }; struct FontVariantEastAsian { bool ruby = false; Optional variant; Optional width; bool operator==(FontVariantEastAsian const&) const = default; }; struct FontVariantLigatures { bool none = false; Optional common {}; Optional discretionary {}; Optional historical {}; Optional contextual {}; bool operator==(FontVariantLigatures const&) const = default; }; struct FontVariantNumeric { bool ordinal = false; bool slashed_zero = false; Optional figure {}; Optional spacing {}; Optional fraction {}; bool operator==(FontVariantNumeric const&) const = default; }; struct FontFeatureData { Optional font_variant_alternates; FontVariantCaps font_variant_caps; Optional font_variant_east_asian; FontVariantEmoji font_variant_emoji; Optional font_variant_ligatures; Optional font_variant_numeric; FontVariantPosition font_variant_position; HashMap font_feature_settings; FontKerning font_kerning; TextRendering text_rendering; Gfx::ShapeFeatures to_shape_features(HashMap> const& font_feature_values) const; bool operator==(FontFeatureData const& other) const = default; }; } namespace AK { template<> struct Traits : public DefaultTraits { static unsigned hash(Web::CSS::FontFeatureValueKey const& data) { return pair_int_hash(to_underlying(data.type), data.name.hash()); } }; template<> struct Traits : public DefaultTraits { static unsigned hash(Web::CSS::FontVariantAlternates const& data) { u32 hash = data.historical_forms ? 1 : 0; for (auto const& entry : data.font_feature_value_entries) hash = pair_int_hash(hash, Traits::hash(entry)); return hash; } }; template<> struct Traits : public DefaultTraits { static unsigned hash(Web::CSS::FontVariantEastAsian const& data) { u32 hash = data.ruby ? 1 : 0; hash = pair_int_hash(hash, data.variant.has_value() ? to_underlying(data.variant.value()) : -1); hash = pair_int_hash(hash, data.width.has_value() ? to_underlying(data.width.value()) : -1); return hash; } }; template<> struct Traits : public DefaultTraits { static unsigned hash(Web::CSS::FontVariantLigatures const& data) { u32 hash = data.none ? 1 : 0; hash = pair_int_hash(hash, data.common.has_value() ? to_underlying(data.common.value()) : -1); hash = pair_int_hash(hash, data.discretionary.has_value() ? to_underlying(data.discretionary.value()) : -1); hash = pair_int_hash(hash, data.historical.has_value() ? to_underlying(data.historical.value()) : -1); hash = pair_int_hash(hash, data.contextual.has_value() ? to_underlying(data.contextual.value()) : -1); return hash; } }; template<> struct Traits : public DefaultTraits { static unsigned hash(Web::CSS::FontVariantNumeric const& data) { u32 hash = data.ordinal ? 1 : 0; hash = pair_int_hash(hash, data.slashed_zero ? 1 : 0); hash = pair_int_hash(hash, data.figure.has_value() ? to_underlying(data.figure.value()) : -1); hash = pair_int_hash(hash, data.spacing.has_value() ? to_underlying(data.spacing.value()) : -1); hash = pair_int_hash(hash, data.fraction.has_value() ? to_underlying(data.fraction.value()) : -1); return hash; } }; template<> struct Traits : public DefaultTraits { static unsigned hash(Web::CSS::FontFeatureData const& data) { u32 hash = 0; hash = pair_int_hash(hash, data.font_variant_alternates.has_value() ? Traits::hash(data.font_variant_alternates.value()) : -1); hash = pair_int_hash(hash, to_underlying(data.font_variant_caps)); hash = pair_int_hash(hash, data.font_variant_east_asian.has_value() ? Traits::hash(data.font_variant_east_asian.value()) : -1); hash = pair_int_hash(hash, to_underlying(data.font_variant_emoji)); hash = pair_int_hash(hash, data.font_variant_ligatures.has_value() ? Traits::hash(data.font_variant_ligatures.value()) : -1); hash = pair_int_hash(hash, data.font_variant_numeric.has_value() ? Traits::hash(data.font_variant_numeric.value()) : -1); hash = pair_int_hash(hash, to_underlying(data.font_variant_position)); hash = pair_int_hash(hash, to_underlying(data.font_kerning)); hash = pair_int_hash(hash, to_underlying(data.text_rendering)); for (auto const& [key, value] : data.font_feature_settings) hash = pair_int_hash(hash, pair_int_hash(key.hash(), value)); return hash; } }; }