Modified: trunk/Source/WebCore/css/CSSFontFaceSet.h (225768 => 225769)
--- trunk/Source/WebCore/css/CSSFontFaceSet.h 2017-12-12 03:24:43 UTC (rev 225768)
+++ trunk/Source/WebCore/css/CSSFontFaceSet.h 2017-12-12 03:50:06 UTC (rev 225769)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -97,11 +97,24 @@
static String familyNameFromPrimitive(const CSSPrimitiveValue&);
+ using FontSelectionKey = std::optional<FontSelectionRequest>;
+ struct FontSelectionKeyHash {
+ static unsigned hash(const FontSelectionKey& key) { return computeHash(key); }
+ static bool equal(const FontSelectionKey& a, const FontSelectionKey& b) { return a == b; }
+ static const bool safeToCompareToEmptyOrDeleted = true;
+ };
+ struct FontSelectionKeyHashTraits : SimpleClassHashTraits<FontSelectionKey> {
+ static const bool emptyValueIsZero = false;
+ static FontSelectionKey emptyValue() { return FontSelectionRequest { }; }
+ static void constructDeletedValue(FontSelectionKey& slot) { slot = std::nullopt; }
+ static bool isDeletedValue(const FontSelectionKey& value) { return !value; }
+ };
+ using FontSelectionHashMap = HashMap<FontSelectionKey, RefPtr<CSSSegmentedFontFace>, FontSelectionKeyHash, FontSelectionKeyHashTraits>;
+
// m_faces should hold all the same fonts as the ones inside inside m_facesLookupTable.
Vector<Ref<CSSFontFace>> m_faces; // We should investigate moving m_faces to FontFaceSet and making it reference FontFaces. This may clean up the font loading design.
HashMap<String, Vector<Ref<CSSFontFace>>, ASCIICaseInsensitiveHash> m_facesLookupTable;
HashMap<String, Vector<Ref<CSSFontFace>>, ASCIICaseInsensitiveHash> m_locallyInstalledFacesLookupTable;
- typedef HashMap<FontSelectionRequestKey, RefPtr<CSSSegmentedFontFace>, FontSelectionRequestKeyHash, WTF::SimpleClassHashTraits<FontSelectionRequestKey>> FontSelectionHashMap;
HashMap<String, FontSelectionHashMap, ASCIICaseInsensitiveHash> m_cache;
HashMap<StyleRuleFontFace*, CSSFontFace*> m_constituentCSSConnections;
size_t m_facesPartitionIndex { 0 }; // All entries in m_faces before this index are CSS-connected.
Modified: trunk/Source/WebCore/platform/graphics/FontSelectionAlgorithm.cpp (225768 => 225769)
--- trunk/Source/WebCore/platform/graphics/FontSelectionAlgorithm.cpp 2017-12-12 03:24:43 UTC (rev 225768)
+++ trunk/Source/WebCore/platform/graphics/FontSelectionAlgorithm.cpp 2017-12-12 03:50:06 UTC (rev 225769)
@@ -28,8 +28,21 @@
namespace WebCore {
-auto FontSelectionAlgorithm::stretchDistance(FontSelectionCapabilities capabilities) const -> DistanceResult
+FontSelectionAlgorithm::FontSelectionAlgorithm(FontSelectionRequest request, const Vector<Capabilities>& capabilities, std::optional<Capabilities> bounds)
+ : m_request(request)
+ , m_capabilities(capabilities)
{
+ ASSERT(!m_capabilities.isEmpty());
+ if (bounds)
+ m_capabilitiesBounds = bounds.value();
+ else {
+ for (auto& capabilities : m_capabilities)
+ m_capabilitiesBounds.expand(capabilities);
+ }
+}
+
+auto FontSelectionAlgorithm::stretchDistance(Capabilities capabilities) const -> DistanceResult
+{
auto width = capabilities.width;
ASSERT(width.isValid());
if (width.includes(m_request.width))
@@ -50,7 +63,7 @@
return { width.minimum - threshold, width.minimum };
}
-auto FontSelectionAlgorithm::styleDistance(FontSelectionCapabilities capabilities) const -> DistanceResult
+auto FontSelectionAlgorithm::styleDistance(Capabilities capabilities) const -> DistanceResult
{
auto slope = capabilities.slope;
ASSERT(slope.isValid());
@@ -92,7 +105,7 @@
return { slope.minimum - threshold, slope.minimum };
}
-auto FontSelectionAlgorithm::weightDistance(FontSelectionCapabilities capabilities) const -> DistanceResult
+auto FontSelectionAlgorithm::weightDistance(Capabilities capabilities) const -> DistanceResult
{
auto weight = capabilities.weight;
ASSERT(weight.isValid());
@@ -123,35 +136,35 @@
return { threshold - weight.maximum, weight.maximum };
}
-void FontSelectionAlgorithm::filterCapability(DistanceResult(FontSelectionAlgorithm::*computeDistance)(FontSelectionCapabilities) const, FontSelectionRange FontSelectionCapabilities::*inclusionRange)
+FontSelectionValue FontSelectionAlgorithm::bestValue(const bool eliminated[], DistanceFunction computeDistance) const
{
- std::optional<FontSelectionValue> smallestDistance;
- FontSelectionValue closestValue;
- iterateActiveCapabilities([&](FontSelectionCapabilities capabilities, size_t) {
- auto distanceResult = (this->*computeDistance)(capabilities);
- if (!smallestDistance || distanceResult.distance < smallestDistance.value()) {
- smallestDistance = distanceResult.distance;
- closestValue = distanceResult.value;
- }
- });
- ASSERT(smallestDistance);
- iterateActiveCapabilities([&](auto& capabilities, size_t i) {
- if (!(capabilities.*inclusionRange).includes(closestValue))
- m_filter[i] = false;
- });
+ std::optional<DistanceResult> smallestDistance;
+ for (size_t i = 0, size = m_capabilities.size(); i < size; ++i) {
+ if (eliminated[i])
+ continue;
+ auto distanceResult = (this->*computeDistance)(m_capabilities[i]);
+ if (!smallestDistance || distanceResult.distance < smallestDistance.value().distance)
+ smallestDistance = distanceResult;
+ }
+ return smallestDistance.value().value;
}
+void FontSelectionAlgorithm::filterCapability(bool eliminated[], DistanceFunction computeDistance, CapabilitiesRange inclusionRange)
+{
+ auto value = bestValue(eliminated, computeDistance);
+ for (size_t i = 0, size = m_capabilities.size(); i < size; ++i) {
+ eliminated[i] = eliminated[i]
+ || !(m_capabilities[i].*inclusionRange).includes(value);
+ }
+}
+
size_t FontSelectionAlgorithm::indexOfBestCapabilities()
{
- filterCapability(&FontSelectionAlgorithm::stretchDistance, &FontSelectionCapabilities::width);
- filterCapability(&FontSelectionAlgorithm::styleDistance, &FontSelectionCapabilities::slope);
- filterCapability(&FontSelectionAlgorithm::weightDistance, &FontSelectionCapabilities::weight);
-
- auto result = iterateActiveCapabilitiesWithReturn<size_t>([](FontSelectionCapabilities, size_t i) {
- return i;
- });
- ASSERT(result);
- return result.value_or(0);
+ Vector<bool, 256> eliminated(m_capabilities.size(), false);
+ filterCapability(eliminated.data(), &FontSelectionAlgorithm::stretchDistance, &Capabilities::width);
+ filterCapability(eliminated.data(), &FontSelectionAlgorithm::styleDistance, &Capabilities::slope);
+ filterCapability(eliminated.data(), &FontSelectionAlgorithm::weightDistance, &Capabilities::weight);
+ return eliminated.find(false);
}
}
Modified: trunk/Source/WebCore/platform/graphics/FontSelectionAlgorithm.h (225768 => 225769)
--- trunk/Source/WebCore/platform/graphics/FontSelectionAlgorithm.h 2017-12-12 03:24:43 UTC (rev 225768)
+++ trunk/Source/WebCore/platform/graphics/FontSelectionAlgorithm.h 2017-12-12 03:50:06 UTC (rev 225769)
@@ -26,281 +26,268 @@
#pragma once
#include "TextFlags.h"
-#include <wtf/Function.h>
-#include <wtf/GetPtr.h>
+#include <algorithm>
+#include <tuple>
#include <wtf/Hasher.h>
-#include <wtf/NeverDestroyed.h>
#include <wtf/Optional.h>
-#include <wtf/Vector.h>
namespace WebCore {
// Unclamped, unchecked, signed fixed-point number representing a value used for font variations.
-// Sixteen bits in total, one sign bit, two fractional bits, means the smallest positive representable value is 0.25,
-// the maximum representable value is 8191.75, and the minimum representable value is -8192.
+// Sixteen bits in total, one sign bit, two fractional bits, smallest positive value is 0.25,
+// maximum value is 8191.75, and minimum value is -8192.
class FontSelectionValue {
public:
- typedef int16_t BackingType;
+ using BackingType = int16_t;
FontSelectionValue() = default;
- // Explicit because it is lossy.
- explicit FontSelectionValue(int x)
- : m_backing(x * fractionalEntropy)
- {
- }
+ // Explicit because it won't work correctly for values outside the representable range.
+ explicit constexpr FontSelectionValue(int);
- // Explicit because it is lossy.
- explicit FontSelectionValue(float x)
- : m_backing(x * fractionalEntropy)
- {
- }
+ // Explicit because it won't work correctly for values outside the representable range and because precision can be lost.
+ explicit constexpr FontSelectionValue(float);
- operator float() const
- {
- // floats have 23 fractional bits, but only 14 fractional bits are necessary, so every value can be represented losslessly.
- return m_backing / static_cast<float>(fractionalEntropy);
- }
+ // Precision can be lost, but value will be clamped to the representable range.
+ static constexpr FontSelectionValue clampFloat(float);
- FontSelectionValue operator+(const FontSelectionValue other) const;
- FontSelectionValue operator-(const FontSelectionValue other) const;
- FontSelectionValue operator*(const FontSelectionValue other) const;
- FontSelectionValue operator/(const FontSelectionValue other) const;
- FontSelectionValue operator-() const;
- bool operator==(const FontSelectionValue other) const;
- bool operator!=(const FontSelectionValue other) const;
- bool operator<(const FontSelectionValue other) const;
- bool operator<=(const FontSelectionValue other) const;
- bool operator>(const FontSelectionValue other) const;
- bool operator>=(const FontSelectionValue other) const;
+ // Since floats have 23 mantissa bits, every value can be represented losslessly.
+ constexpr operator float() const;
- BackingType rawValue() const
- {
- return m_backing;
- }
+ static constexpr FontSelectionValue maximumValue();
+ static constexpr FontSelectionValue minimumValue();
- static FontSelectionValue maximumValue()
- {
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(std::numeric_limits<BackingType>::max(), RawTag::RawTag);
- return result.get();
- }
+ friend constexpr FontSelectionValue operator+(FontSelectionValue, FontSelectionValue);
+ friend constexpr FontSelectionValue operator-(FontSelectionValue, FontSelectionValue);
+ friend constexpr FontSelectionValue operator*(FontSelectionValue, FontSelectionValue);
+ friend constexpr FontSelectionValue operator/(FontSelectionValue, FontSelectionValue);
+ friend constexpr FontSelectionValue operator-(FontSelectionValue);
- static FontSelectionValue minimumValue()
- {
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(std::numeric_limits<BackingType>::min(), RawTag::RawTag);
- return result.get();
- }
+ constexpr BackingType rawValue() const { return m_backing; }
- static FontSelectionValue clampFloat(float value)
- {
- if (value < static_cast<float>(FontSelectionValue::minimumValue()))
- return FontSelectionValue::minimumValue();
- if (value > static_cast<float>(FontSelectionValue::maximumValue()))
- return FontSelectionValue::maximumValue();
- return FontSelectionValue(value);
- }
-
private:
enum class RawTag { RawTag };
+ constexpr FontSelectionValue(int, RawTag);
- FontSelectionValue(BackingType rawValue, RawTag)
- : m_backing(rawValue)
- {
- }
-
static constexpr int fractionalEntropy = 4;
BackingType m_backing { 0 };
};
-inline FontSelectionValue FontSelectionValue::operator+(const FontSelectionValue other) const
+constexpr FontSelectionValue::FontSelectionValue(int x)
+ : m_backing(x * fractionalEntropy)
{
- return FontSelectionValue(m_backing + other.m_backing, RawTag::RawTag);
+ // FIXME: Should we assert the passed in value was in range?
}
-inline FontSelectionValue FontSelectionValue::operator-(const FontSelectionValue other) const
+constexpr FontSelectionValue::FontSelectionValue(float x)
+ : m_backing(x * fractionalEntropy)
{
- return FontSelectionValue(m_backing - other.m_backing, RawTag::RawTag);
+ // FIXME: Should we assert the passed in value was in range?
}
-inline FontSelectionValue FontSelectionValue::operator*(const FontSelectionValue other) const
+constexpr FontSelectionValue::operator float() const
{
- return FontSelectionValue(static_cast<int32_t>(m_backing) * other.m_backing / fractionalEntropy, RawTag::RawTag);
+ return m_backing / static_cast<float>(fractionalEntropy);
}
-inline FontSelectionValue FontSelectionValue::operator/(const FontSelectionValue other) const
+constexpr FontSelectionValue FontSelectionValue::maximumValue()
{
- return FontSelectionValue(static_cast<int32_t>(m_backing) / other.m_backing * fractionalEntropy, RawTag::RawTag);
+ return { std::numeric_limits<BackingType>::max(), RawTag::RawTag };
}
-inline FontSelectionValue FontSelectionValue::operator-() const
+constexpr FontSelectionValue FontSelectionValue::minimumValue()
{
- return FontSelectionValue(-m_backing, RawTag::RawTag);
+ return { std::numeric_limits<BackingType>::min(), RawTag::RawTag };
}
-inline bool FontSelectionValue::operator==(const FontSelectionValue other) const
+constexpr FontSelectionValue FontSelectionValue::clampFloat(float value)
{
- return m_backing == other.m_backing;
+ return FontSelectionValue { std::max<float>(minimumValue(), std::min<float>(value, maximumValue())) };
}
-inline bool FontSelectionValue::operator!=(const FontSelectionValue other) const
+constexpr FontSelectionValue::FontSelectionValue(int rawValue, RawTag)
+ : m_backing(rawValue)
{
- return !operator==(other);
}
-inline bool FontSelectionValue::operator<(const FontSelectionValue other) const
+constexpr FontSelectionValue operator+(FontSelectionValue a, FontSelectionValue b)
{
- return m_backing < other.m_backing;
+ return { a.m_backing + b.m_backing, FontSelectionValue::RawTag::RawTag };
}
-inline bool FontSelectionValue::operator<=(const FontSelectionValue other) const
+constexpr FontSelectionValue operator-(FontSelectionValue a, FontSelectionValue b)
{
- return m_backing <= other.m_backing;
+ return { a.m_backing - b.m_backing, FontSelectionValue::RawTag::RawTag };
}
-inline bool FontSelectionValue::operator>(const FontSelectionValue other) const
+constexpr FontSelectionValue operator*(FontSelectionValue a, FontSelectionValue b)
{
- return m_backing > other.m_backing;
+ return { a.m_backing * b.m_backing / FontSelectionValue::fractionalEntropy, FontSelectionValue::RawTag::RawTag };
}
-inline bool FontSelectionValue::operator>=(const FontSelectionValue other) const
+constexpr FontSelectionValue operator/(FontSelectionValue a, FontSelectionValue b)
{
- return m_backing >= other.m_backing;
+ return { a.m_backing * FontSelectionValue::fractionalEntropy / b.m_backing, FontSelectionValue::RawTag::RawTag };
}
-static inline FontSelectionValue italicThreshold()
+constexpr FontSelectionValue operator-(FontSelectionValue value)
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(20);
- return result.get();
+ return { -value.m_backing, FontSelectionValue::RawTag::RawTag };
}
-static inline bool isItalic(FontSelectionValue fontWeight)
+constexpr bool operator==(FontSelectionValue a, FontSelectionValue b)
{
+ return a.rawValue() == b.rawValue();
+}
+
+constexpr bool operator!=(FontSelectionValue a, FontSelectionValue b)
+{
+ return a.rawValue() != b.rawValue();
+}
+
+constexpr bool operator<(FontSelectionValue a, FontSelectionValue b)
+{
+ return a.rawValue() < b.rawValue();
+}
+
+constexpr bool operator<=(FontSelectionValue a, FontSelectionValue b)
+{
+ return a.rawValue() <= b.rawValue();
+}
+
+constexpr bool operator>(FontSelectionValue a, FontSelectionValue b)
+{
+ return a.rawValue() > b.rawValue();
+}
+
+constexpr bool operator>=(FontSelectionValue a, FontSelectionValue b)
+{
+ return a.rawValue() >= b.rawValue();
+}
+
+constexpr FontSelectionValue italicThreshold()
+{
+ return FontSelectionValue { 20 };
+}
+
+constexpr bool isItalic(FontSelectionValue fontWeight)
+{
return fontWeight >= italicThreshold();
}
-static inline FontSelectionValue normalItalicValue()
+constexpr FontSelectionValue normalItalicValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue();
- return result.get();
+ return FontSelectionValue { 0 };
}
-static inline FontSelectionValue italicValue()
+constexpr FontSelectionValue italicValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(20);
- return result.get();
+ return FontSelectionValue { 20 };
}
-static inline FontSelectionValue boldThreshold()
+constexpr FontSelectionValue boldThreshold()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(600);
- return result.get();
+ return FontSelectionValue { 600 };
}
-static inline FontSelectionValue boldWeightValue()
+constexpr FontSelectionValue boldWeightValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(700);
- return result.get();
+ return FontSelectionValue { 700 };
}
-static inline FontSelectionValue normalWeightValue()
+constexpr FontSelectionValue normalWeightValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(400);
- return result.get();
+ return FontSelectionValue { 400 };
}
-static inline FontSelectionValue lightWeightValue()
+constexpr FontSelectionValue lightWeightValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(200);
- return result.get();
+ return FontSelectionValue { 200 };
}
-static inline bool isFontWeightBold(FontSelectionValue fontWeight)
+constexpr bool isFontWeightBold(FontSelectionValue fontWeight)
{
return fontWeight >= boldThreshold();
}
-static inline FontSelectionValue lowerWeightSearchThreshold()
+constexpr FontSelectionValue lowerWeightSearchThreshold()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(400);
- return result.get();
+ return FontSelectionValue { 400 };
}
-static inline FontSelectionValue upperWeightSearchThreshold()
+constexpr FontSelectionValue upperWeightSearchThreshold()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(500);
- return result.get();
+ return FontSelectionValue { 500 };
}
-static inline FontSelectionValue ultraCondensedStretchValue()
+constexpr FontSelectionValue ultraCondensedStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(50);
- return result.get();
+ return FontSelectionValue { 50 };
}
-static inline FontSelectionValue extraCondensedStretchValue()
+constexpr FontSelectionValue extraCondensedStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(62.5f);
- return result.get();
+ return FontSelectionValue { 62.5f };
}
-static inline FontSelectionValue condensedStretchValue()
+constexpr FontSelectionValue condensedStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(75);
- return result.get();
+ return FontSelectionValue { 75 };
}
-static inline FontSelectionValue semiCondensedStretchValue()
+constexpr FontSelectionValue semiCondensedStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(87.5f);
- return result.get();
+ return FontSelectionValue { 87.5f };
}
-static inline FontSelectionValue normalStretchValue()
+constexpr FontSelectionValue normalStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(100);
- return result.get();
+ return FontSelectionValue { 100 };
}
-static inline FontSelectionValue semiExpandedStretchValue()
+constexpr FontSelectionValue semiExpandedStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(112.5f);
- return result.get();
+ return FontSelectionValue { 112.5f };
}
-static inline FontSelectionValue expandedStretchValue()
+constexpr FontSelectionValue expandedStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(125);
- return result.get();
+ return FontSelectionValue { 125 };
}
-static inline FontSelectionValue extraExpandedStretchValue()
+constexpr FontSelectionValue extraExpandedStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(150);
- return result.get();
+ return FontSelectionValue { 150 };
}
-static inline FontSelectionValue ultraExpandedStretchValue()
+constexpr FontSelectionValue ultraExpandedStretchValue()
{
- static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(200);
- return result.get();
+ return FontSelectionValue { 200 };
}
// [Inclusive, Inclusive]
struct FontSelectionRange {
- FontSelectionRange(FontSelectionValue minimum, FontSelectionValue maximum)
+ using Value = FontSelectionValue;
+
+ constexpr FontSelectionRange(Value minimum, Value maximum)
: minimum(minimum)
, maximum(maximum)
{
}
- bool operator==(const FontSelectionRange& other) const
+ explicit constexpr FontSelectionRange(Value value)
+ : minimum(value)
+ , maximum(value)
{
- return minimum == other.minimum
- && maximum == other.maximum;
}
- bool isValid() const
+ constexpr bool operator==(const FontSelectionRange& other) const
{
+ return std::tie(minimum, maximum) == std::tie(other.minimum, other.maximum);
+ }
+
+ constexpr bool isValid() const
+ {
return minimum <= maximum;
}
@@ -316,241 +303,192 @@
ASSERT(isValid());
}
- bool includes(FontSelectionValue target) const
+ constexpr bool includes(Value target) const
{
return target >= minimum && target <= maximum;
}
- uint32_t uniqueValue() const
+ // FIXME: This name is not so great. Move this into the add function below
+ // once we move FontPlatformDataCacheKeyHash from IntegerHasher to Hasher,
+ // and then it doesn't need to have a name.
+ constexpr uint32_t uniqueValue() const
{
return minimum.rawValue() << 16 | maximum.rawValue();
}
- FontSelectionValue minimum { FontSelectionValue(1) };
- FontSelectionValue maximum { FontSelectionValue(0) };
+ Value minimum { 1 };
+ Value maximum { 0 };
};
+inline void add(Hasher& hasher, const FontSelectionRange& range)
+{
+ add(hasher, range.uniqueValue());
+}
+
struct FontSelectionRequest {
+ using Value = FontSelectionValue;
+
+ Value weight;
+ Value width;
+ Value slope;
+
+ constexpr std::tuple<Value, Value, Value> tied() const
+ {
+ return std::tie(weight, width, slope);
+ }
+
+#if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES)
FontSelectionRequest() = default;
- FontSelectionRequest(FontSelectionValue weight, FontSelectionValue width, FontSelectionValue slope)
+ constexpr FontSelectionRequest(Value weight, Value width, Value slope)
: weight(weight)
, width(width)
, slope(slope)
{
}
-
- bool operator==(const FontSelectionRequest& other) const
- {
- return weight == other.weight
- && width == other.width
- && slope == other.slope;
- }
-
- bool operator!=(const FontSelectionRequest& other) const
- {
- return !operator==(other);
- }
-
- FontSelectionValue weight;
- FontSelectionValue width;
- FontSelectionValue slope;
+#endif
};
-// Only used for HashMaps. We don't want to put the bool into FontSelectionRequest
-// because FontSelectionRequest needs to be as small as possible because it's inside
-// every FontDescription.
-struct FontSelectionRequestKey {
- FontSelectionRequestKey() = default;
+constexpr bool operator==(const FontSelectionRequest& a, const FontSelectionRequest& b)
+{
+ return a.tied() == b.tied();
+}
- FontSelectionRequestKey(FontSelectionRequest request)
- : request(request)
- {
- }
+constexpr bool operator!=(const FontSelectionRequest& a, const FontSelectionRequest& b)
+{
+ return !(a == b);
+}
- explicit FontSelectionRequestKey(WTF::HashTableDeletedValueType)
- : isDeletedValue(true)
- {
- }
+inline void add(Hasher& hasher, const FontSelectionRequest& request)
+{
+ add(hasher, request.tied());
+}
- bool isHashTableDeletedValue() const
- {
- return isDeletedValue;
- }
+struct FontSelectionCapabilities {
+ using Range = FontSelectionRange;
- bool operator==(const FontSelectionRequestKey& other) const
- {
- return request == other.request
- && isDeletedValue == other.isDeletedValue;
- }
+ FontSelectionCapabilities& operator=(const FontSelectionCapabilities&) = default;
- FontSelectionRequest request;
- bool isDeletedValue { false };
-};
-
-struct FontSelectionRequestKeyHash {
- static unsigned hash(const FontSelectionRequestKey& key)
+ constexpr std::tuple<Range, Range, Range> tied() const
{
- IntegerHasher hasher;
- hasher.add(key.request.weight.rawValue());
- hasher.add(key.request.width.rawValue());
- hasher.add(key.request.slope.rawValue());
- hasher.add(key.isDeletedValue);
- return hasher.hash();
+ return std::tie(weight, width, slope);
}
- static bool equal(const FontSelectionRequestKey& a, const FontSelectionRequestKey& b)
+ void expand(const FontSelectionCapabilities& capabilities)
{
- return a == b;
+ weight.expand(capabilities.weight);
+ width.expand(capabilities.width);
+ slope.expand(capabilities.slope);
}
- static const bool safeToCompareToEmptyOrDeleted = true;
-};
+ Range weight { normalWeightValue() };
+ Range width { normalStretchValue() };
+ Range slope { normalItalicValue() };
-struct FontSelectionCapabilities {
- FontSelectionCapabilities()
- {
- }
+#if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES)
+ FontSelectionCapabilities() = default;
- FontSelectionCapabilities(FontSelectionRange weight, FontSelectionRange width, FontSelectionRange slope)
+ constexpr FontSelectionCapabilities(Range weight, Range width, Range slope)
: weight(weight)
, width(width)
, slope(slope)
{
}
+#endif
+};
- void expand(const FontSelectionCapabilities& capabilities)
- {
- weight.expand(capabilities.weight);
- width.expand(capabilities.width);
- slope.expand(capabilities.slope);
- }
+constexpr bool operator==(const FontSelectionCapabilities& a, const FontSelectionCapabilities& b)
+{
+ return a.tied() == b.tied();
+}
- bool operator==(const FontSelectionCapabilities& other) const
- {
- return weight == other.weight
- && width == other.width
- && slope == other.slope;
- }
+constexpr bool operator!=(const FontSelectionCapabilities& a, const FontSelectionCapabilities& b)
+{
+ return !(a == b);
+}
- bool operator!=(const FontSelectionCapabilities& other) const
- {
- return !(*this == other);
- }
+struct FontSelectionSpecifiedCapabilities {
+ using Capabilities = FontSelectionCapabilities;
+ using Range = FontSelectionRange;
+ using OptionalRange = std::optional<Range>;
- FontSelectionRange weight { normalWeightValue(), normalWeightValue() };
- FontSelectionRange width { normalStretchValue(), normalStretchValue() };
- FontSelectionRange slope { normalItalicValue(), normalItalicValue() };
-};
-
-struct FontSelectionSpecifiedCapabilities {
- FontSelectionCapabilities computeFontSelectionCapabilities() const
+ constexpr Capabilities computeFontSelectionCapabilities() const
{
- return FontSelectionCapabilities(computeWeight(), computeWidth(), computeSlope());
+ return { computeWeight(), computeWidth(), computeSlope() };
}
- bool operator==(const FontSelectionSpecifiedCapabilities& other) const
+ constexpr std::tuple<OptionalRange&, OptionalRange&, OptionalRange&> tied()
{
- return weight == other.weight
- && width == other.width
- && slope == other.slope;
+ return std::tie(weight, width, slope);
}
- bool operator!=(const FontSelectionSpecifiedCapabilities& other) const
+ constexpr std::tuple<const OptionalRange&, const OptionalRange&, const OptionalRange&> tied() const
{
- return !(*this == other);
+ return std::tie(weight, width, slope);
}
- FontSelectionSpecifiedCapabilities& operator=(const FontSelectionCapabilities& other)
+ FontSelectionSpecifiedCapabilities& operator=(const Capabilities& other)
{
- weight = other.weight;
- width = other.width;
- slope = other.slope;
+ tied() = other.tied();
return *this;
}
- FontSelectionRange computeWeight() const
+ constexpr Range computeWeight() const
{
- return weight.value_or(FontSelectionRange({ normalWeightValue(), normalWeightValue() }));
+ return weight.value_or(Range { normalWeightValue() });
}
- FontSelectionRange computeWidth() const
+ constexpr Range computeWidth() const
{
- return width.value_or(FontSelectionRange({ normalStretchValue(), normalStretchValue() }));
+ return width.value_or(Range { normalStretchValue() });
}
- FontSelectionRange computeSlope() const
+ constexpr Range computeSlope() const
{
- return slope.value_or(FontSelectionRange({ normalItalicValue(), normalItalicValue() }));
+ return slope.value_or(Range { normalItalicValue() });
}
- std::optional<FontSelectionRange> weight;
- std::optional<FontSelectionRange> width;
- std::optional<FontSelectionRange> slope;
+ OptionalRange weight;
+ OptionalRange width;
+ OptionalRange slope;
};
+constexpr bool operator==(const FontSelectionSpecifiedCapabilities& a, const FontSelectionSpecifiedCapabilities& b)
+{
+ return a.tied() == b.tied();
+}
+
+constexpr bool operator!=(const FontSelectionSpecifiedCapabilities& a, const FontSelectionSpecifiedCapabilities& b)
+{
+ return !(a == b);
+}
+
class FontSelectionAlgorithm {
public:
+ using Capabilities = FontSelectionCapabilities;
+
FontSelectionAlgorithm() = delete;
+ FontSelectionAlgorithm(FontSelectionRequest, const Vector<Capabilities>&, std::optional<Capabilities> capabilitiesBounds = std::nullopt);
- FontSelectionAlgorithm(FontSelectionRequest request, const Vector<FontSelectionCapabilities>& capabilities, std::optional<FontSelectionCapabilities> capabilitiesBounds = std::nullopt)
- : m_request(request)
- , m_capabilities(capabilities)
- , m_filter(new bool[m_capabilities.size()])
- {
- ASSERT(!m_capabilities.isEmpty());
- if (capabilitiesBounds)
- m_capabilitiesBounds = capabilitiesBounds.value();
- else {
- for (auto capabilities : m_capabilities)
- m_capabilitiesBounds.expand(capabilities);
- }
- for (size_t i = 0; i < m_capabilities.size(); ++i)
- m_filter[i] = true;
- }
-
struct DistanceResult {
FontSelectionValue distance;
FontSelectionValue value;
};
+ DistanceResult stretchDistance(Capabilities) const;
+ DistanceResult styleDistance(Capabilities) const;
+ DistanceResult weightDistance(Capabilities) const;
- DistanceResult stretchDistance(FontSelectionCapabilities) const;
- DistanceResult styleDistance(FontSelectionCapabilities) const;
- DistanceResult weightDistance(FontSelectionCapabilities) const;
-
size_t indexOfBestCapabilities();
private:
- template <typename T>
- using IterateActiveCapabilitiesWithReturnCallback = WTF::Function<std::optional<T>(FontSelectionCapabilities, size_t)>;
+ using DistanceFunction = DistanceResult (FontSelectionAlgorithm::*)(Capabilities) const;
+ using CapabilitiesRange = FontSelectionRange Capabilities::*;
+ FontSelectionValue bestValue(const bool eliminated[], DistanceFunction) const;
+ void filterCapability(bool eliminated[], DistanceFunction, CapabilitiesRange);
- template <typename T>
- inline std::optional<T> iterateActiveCapabilitiesWithReturn(const IterateActiveCapabilitiesWithReturnCallback<T>& callback)
- {
- for (size_t i = 0; i < m_capabilities.size(); ++i) {
- if (!m_filter[i])
- continue;
- if (auto result = callback(m_capabilities[i], i))
- return result;
- }
- return std::nullopt;
- }
-
- template <typename T>
- inline void iterateActiveCapabilities(T callback)
- {
- iterateActiveCapabilitiesWithReturn<int>([&](FontSelectionCapabilities capabilities, size_t i) -> std::optional<int> {
- callback(capabilities, i);
- return std::nullopt;
- });
- }
-
- void filterCapability(DistanceResult(FontSelectionAlgorithm::*computeDistance)(FontSelectionCapabilities) const, FontSelectionRange FontSelectionCapabilities::*inclusionRange);
-
FontSelectionRequest m_request;
- FontSelectionCapabilities m_capabilitiesBounds;
- const Vector<FontSelectionCapabilities>& m_capabilities;
- std::unique_ptr<bool[]> m_filter;
+ Capabilities m_capabilitiesBounds;
+ const Vector<Capabilities>& m_capabilities;
};
}