| /* |
| * Copyright (C) 2011 Google Inc. All rights reserved. |
| * Copyright (C) 2016 Apple Inc. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #pragma once |
| |
| #include <array> |
| #include <wtf/HashTraits.h> |
| #include <wtf/Vector.h> |
| |
| namespace WTF { |
| class TextStream; |
| } |
| |
| namespace WebCore { |
| |
| typedef std::array<char, 4> FontTag; |
| |
| inline FontTag fontFeatureTag(const char arr[4]) { return {{ arr[0], arr[1], arr[2], arr[3] }}; } |
| |
| struct FourCharacterTagHash { |
| static unsigned hash(const FontTag& characters) { return (characters[0] << 24) | (characters[1] << 16) | (characters[2] << 8) | characters[3]; } |
| static bool equal(const FontTag& a, const FontTag& b) { return a == b; } |
| static const bool safeToCompareToEmptyOrDeleted = true; |
| }; |
| |
| struct FourCharacterTagHashTraits : WTF::GenericHashTraits<FontTag> { |
| static const bool emptyValueIsZero = true; |
| static void constructDeletedValue(FontTag& slot) { new (NotNull, std::addressof(slot)) FontTag({{ ff, ff, ff, ff }}); } |
| static bool isDeletedValue(const FontTag& value) { return value == FontTag({{ ff, ff, ff, ff }}); } |
| |
| private: |
| static constexpr char ff = static_cast<char>(0xFF); |
| }; |
| |
| template <typename T> |
| class FontTaggedSetting { |
| public: |
| FontTaggedSetting() = delete; |
| FontTaggedSetting(const FontTag&, T value); |
| FontTaggedSetting(FontTag&&, T value); |
| |
| bool operator==(const FontTaggedSetting<T>& other) const; |
| bool operator!=(const FontTaggedSetting<T>& other) const { return !(*this == other); } |
| bool operator<(const FontTaggedSetting<T>& other) const; |
| |
| const FontTag& tag() const { return m_tag; } |
| T value() const { return m_value; } |
| bool enabled() const { return value(); } |
| |
| template<class Encoder> void encode(Encoder&) const; |
| template<class Decoder> static Optional<FontTaggedSetting<T>> decode(Decoder&); |
| |
| private: |
| FontTag m_tag; |
| T m_value; |
| }; |
| |
| template <typename T> |
| FontTaggedSetting<T>::FontTaggedSetting(const FontTag& tag, T value) |
| : m_tag(tag) |
| , m_value(value) |
| { |
| } |
| |
| template <typename T> |
| FontTaggedSetting<T>::FontTaggedSetting(FontTag&& tag, T value) |
| : m_tag(WTFMove(tag)) |
| , m_value(value) |
| { |
| } |
| |
| template <typename T> |
| bool FontTaggedSetting<T>::operator==(const FontTaggedSetting<T>& other) const |
| { |
| return m_tag == other.m_tag && m_value == other.m_value; |
| } |
| |
| template <typename T> |
| bool FontTaggedSetting<T>::operator<(const FontTaggedSetting<T>& other) const |
| { |
| return (m_tag < other.m_tag) || (m_tag == other.m_tag && m_value < other.m_value); |
| } |
| |
| template <typename T> |
| template <class Encoder> |
| void FontTaggedSetting<T>::encode(Encoder& encoder) const |
| { |
| encoder << static_cast<uint8_t>(m_tag[0]); |
| encoder << static_cast<uint8_t>(m_tag[1]); |
| encoder << static_cast<uint8_t>(m_tag[2]); |
| encoder << static_cast<uint8_t>(m_tag[3]); |
| encoder << m_value; |
| } |
| |
| template <typename T> |
| template <class Decoder> |
| Optional<FontTaggedSetting<T>> FontTaggedSetting<T>::decode(Decoder& decoder) |
| { |
| Optional<uint8_t> char0; |
| decoder >> char0; |
| if (!char0) |
| return WTF::nullopt; |
| |
| Optional<uint8_t> char1; |
| decoder >> char1; |
| if (!char1) |
| return WTF::nullopt; |
| |
| Optional<uint8_t> char2; |
| decoder >> char2; |
| if (!char2) |
| return WTF::nullopt; |
| |
| Optional<uint8_t> char3; |
| decoder >> char3; |
| if (!char3) |
| return WTF::nullopt; |
| |
| Optional<T> value; |
| decoder >> value; |
| if (!value) |
| return WTF::nullopt; |
| |
| return FontTaggedSetting<T>({{ |
| static_cast<char>(*char0), |
| static_cast<char>(*char1), |
| static_cast<char>(*char2), |
| static_cast<char>(*char3) |
| }}, *value); |
| } |
| |
| template <typename T> |
| class FontTaggedSettings { |
| public: |
| void insert(FontTaggedSetting<T>&&); |
| bool operator==(const FontTaggedSettings<T>& other) const { return m_list == other.m_list; } |
| bool operator!=(const FontTaggedSettings<T>& other) const { return !(*this == other); } |
| |
| bool isEmpty() const { return !size(); } |
| size_t size() const { return m_list.size(); } |
| const FontTaggedSetting<T>& operator[](int index) const { return m_list[index]; } |
| const FontTaggedSetting<T>& at(size_t index) const { return m_list.at(index); } |
| |
| typename Vector<FontTaggedSetting<T>>::const_iterator begin() const { return m_list.begin(); } |
| typename Vector<FontTaggedSetting<T>>::const_iterator end() const { return m_list.end(); } |
| |
| unsigned hash() const; |
| |
| template<class Encoder> void encode(Encoder&) const; |
| template<class Decoder> static Optional<FontTaggedSettings<T>> decode(Decoder&); |
| |
| private: |
| Vector<FontTaggedSetting<T>> m_list; |
| }; |
| |
| template <typename T> |
| void FontTaggedSettings<T>::insert(FontTaggedSetting<T>&& feature) |
| { |
| // This vector will almost always have 0 or 1 items in it. Don't bother with the overhead of a binary search or a hash set. |
| size_t i; |
| for (i = 0; i < m_list.size(); ++i) { |
| if (!(feature < m_list[i])) |
| break; |
| } |
| if (i < m_list.size() && feature.tag() == m_list[i].tag()) |
| m_list.remove(i); |
| m_list.insert(i, WTFMove(feature)); |
| } |
| |
| template <typename T> |
| template <class Encoder> |
| void FontTaggedSettings<T>::encode(Encoder& encoder) const |
| { |
| encoder << m_list; |
| } |
| |
| template <typename T> |
| template <class Decoder> |
| Optional<FontTaggedSettings<T>> FontTaggedSettings<T>::decode(Decoder& decoder) |
| { |
| Optional<Vector<FontTaggedSetting<T>>> list; |
| decoder >> list; |
| if (!list) |
| return WTF::nullopt; |
| |
| FontTaggedSettings result; |
| result.m_list = WTFMove(*list); |
| return result; |
| } |
| |
| typedef FontTaggedSetting<int> FontFeature; |
| typedef FontTaggedSettings<int> FontFeatureSettings; |
| |
| template <> unsigned FontFeatureSettings::hash() const; |
| |
| #if ENABLE(VARIATION_FONTS) |
| |
| typedef FontTaggedSettings<float> FontVariationSettings; |
| WTF::TextStream& operator<<(WTF::TextStream&, const FontVariationSettings&); |
| |
| template <> unsigned FontVariationSettings::hash() const; |
| |
| #else |
| |
| struct FontVariationSettings { |
| bool isEmpty() const { return true; } |
| }; |
| |
| #endif |
| |
| } |