Changeset 225769 in webkit
- Timestamp:
- Dec 11, 2017, 7:50:06 PM (7 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r225766 r225769 1 2017-12-11 Darin Adler <darin@apple.com> 2 3 Improve FontSelectionAlgorithm, including moving from IntegerHasher to Hasher 4 https://bugs.webkit.org/show_bug.cgi?id=180340 5 6 Reviewed by Dan Bates. 7 8 * css/CSSFontFaceSet.h: Moved FontSelectionRequestKey and FontSelectionRequestKeyHash 9 here to be private members, and used a std::optional instead of a class for this. 10 Also use the new Hasher to compute the hash. Also added FontSelectionRequestKeyHashTraits. 11 12 * platform/graphics/FontDescription.cpp: 13 (WebCore::FontDescription::FontDescription): Updated since FontSelectionRequest 14 does not always have a constructor any more. 15 16 * platform/graphics/FontSelectionAlgorithm.h: Tweaked comments. Used "using" instead 17 of typedef. Formatted some trivial functions as single lines. Stopped using 18 NeverDestroyed for simple classes like FontSelectionValue; it's not needed unless 19 there is a destructor. Got rid of some incorrect use of const. Replaced some member 20 functions with non-member functions. Moved some function bodies out of class definitions. 21 Used a lot of constexpr functions. 22 (WebCore::FontSelectionRequest::tied const): Added so we can easily write both == and the 23 hash function without listing the data members. 24 (WebCore::add): Added an overload so we can hash things that include FontSelectionRequest. 25 (WebCore::FontSelectionRequestKey::FontSelectionRequestKey): Changed this class to 26 use std::optional instead of a separate boolean for deleted values. 27 (WebCore::FontSelectionRequestKey::isHashTableDeletedValue const): Ditto. 28 (WebCore::FontSelectionRequestKey::operator== const): Ditto. 29 (WebCore::FontSelectionRequestKeyHash::hash): Ditto. 30 (WebCore::FontSelectionRequestKeyHash::equal): Ditto. 31 (WebCore::FontSelectionCapabilities::tied const): Added so we can easily write both == 32 and the hash function without listing the data members. 33 (WebCore::FontSelectionSpecifiedCapabilities::tied const): Ditto. 34 (WebCore::FontSelectionAlgorithm::FontSelectionAlgorithm): Use make_unique instead of new. 35 36 * platform/graphics/cocoa/FontCacheCoreText.cpp: 37 (WebCore::findClosestFont): Move in the vector instead of copying it when creating a 38 FontSelectionAlgorithm object. 39 1 40 2017-12-11 Jer Noble <jer.noble@apple.com> 2 41 -
trunk/Source/WebCore/css/CSSFontFaceSet.h
r225414 r225769 1 1 /* 2 * Copyright (C) 2016 Apple Inc. All rights reserved.2 * Copyright (C) 2016-2017 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 98 98 static String familyNameFromPrimitive(const CSSPrimitiveValue&); 99 99 100 using FontSelectionKey = std::optional<FontSelectionRequest>; 101 struct FontSelectionKeyHash { 102 static unsigned hash(const FontSelectionKey& key) { return computeHash(key); } 103 static bool equal(const FontSelectionKey& a, const FontSelectionKey& b) { return a == b; } 104 static const bool safeToCompareToEmptyOrDeleted = true; 105 }; 106 struct FontSelectionKeyHashTraits : SimpleClassHashTraits<FontSelectionKey> { 107 static const bool emptyValueIsZero = false; 108 static FontSelectionKey emptyValue() { return FontSelectionRequest { }; } 109 static void constructDeletedValue(FontSelectionKey& slot) { slot = std::nullopt; } 110 static bool isDeletedValue(const FontSelectionKey& value) { return !value; } 111 }; 112 using FontSelectionHashMap = HashMap<FontSelectionKey, RefPtr<CSSSegmentedFontFace>, FontSelectionKeyHash, FontSelectionKeyHashTraits>; 113 100 114 // m_faces should hold all the same fonts as the ones inside inside m_facesLookupTable. 101 115 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. 102 116 HashMap<String, Vector<Ref<CSSFontFace>>, ASCIICaseInsensitiveHash> m_facesLookupTable; 103 117 HashMap<String, Vector<Ref<CSSFontFace>>, ASCIICaseInsensitiveHash> m_locallyInstalledFacesLookupTable; 104 typedef HashMap<FontSelectionRequestKey, RefPtr<CSSSegmentedFontFace>, FontSelectionRequestKeyHash, WTF::SimpleClassHashTraits<FontSelectionRequestKey>> FontSelectionHashMap;105 118 HashMap<String, FontSelectionHashMap, ASCIICaseInsensitiveHash> m_cache; 106 119 HashMap<StyleRuleFontFace*, CSSFontFace*> m_constituentCSSConnections; -
trunk/Source/WebCore/platform/graphics/FontDescription.cpp
r225641 r225769 56 56 57 57 FontDescription::FontDescription() 58 : m_fontSelectionRequest (FontCascadeDescription::initialWeight(), FontCascadeDescription::initialStretch(), FontCascadeDescription::initialItalic())58 : m_fontSelectionRequest { FontCascadeDescription::initialWeight(), FontCascadeDescription::initialStretch(), FontCascadeDescription::initialItalic() } 59 59 , m_orientation(Horizontal) 60 60 , m_nonCJKGlyphOrientation(static_cast<unsigned>(NonCJKGlyphOrientation::Mixed)) -
trunk/Source/WebCore/platform/graphics/FontSelectionAlgorithm.cpp
r221630 r225769 29 29 namespace WebCore { 30 30 31 auto FontSelectionAlgorithm::stretchDistance(FontSelectionCapabilities capabilities) const -> DistanceResult 31 FontSelectionAlgorithm::FontSelectionAlgorithm(FontSelectionRequest request, const Vector<Capabilities>& capabilities, std::optional<Capabilities> bounds) 32 : m_request(request) 33 , m_capabilities(capabilities) 34 { 35 ASSERT(!m_capabilities.isEmpty()); 36 if (bounds) 37 m_capabilitiesBounds = bounds.value(); 38 else { 39 for (auto& capabilities : m_capabilities) 40 m_capabilitiesBounds.expand(capabilities); 41 } 42 } 43 44 auto FontSelectionAlgorithm::stretchDistance(Capabilities capabilities) const -> DistanceResult 32 45 { 33 46 auto width = capabilities.width; … … 51 64 } 52 65 53 auto FontSelectionAlgorithm::styleDistance( FontSelectionCapabilities capabilities) const -> DistanceResult66 auto FontSelectionAlgorithm::styleDistance(Capabilities capabilities) const -> DistanceResult 54 67 { 55 68 auto slope = capabilities.slope; … … 93 106 } 94 107 95 auto FontSelectionAlgorithm::weightDistance( FontSelectionCapabilities capabilities) const -> DistanceResult108 auto FontSelectionAlgorithm::weightDistance(Capabilities capabilities) const -> DistanceResult 96 109 { 97 110 auto weight = capabilities.weight; … … 124 137 } 125 138 126 void FontSelectionAlgorithm::filterCapability(DistanceResult(FontSelectionAlgorithm::*computeDistance)(FontSelectionCapabilities) const, FontSelectionRange FontSelectionCapabilities::*inclusionRange) 139 FontSelectionValue FontSelectionAlgorithm::bestValue(const bool eliminated[], DistanceFunction computeDistance) const 127 140 { 128 std::optional<FontSelectionValue> smallestDistance; 129 FontSelectionValue closestValue; 130 iterateActiveCapabilities([&](FontSelectionCapabilities capabilities, size_t) { 131 auto distanceResult = (this->*computeDistance)(capabilities); 132 if (!smallestDistance || distanceResult.distance < smallestDistance.value()) { 133 smallestDistance = distanceResult.distance; 134 closestValue = distanceResult.value; 135 } 136 }); 137 ASSERT(smallestDistance); 138 iterateActiveCapabilities([&](auto& capabilities, size_t i) { 139 if (!(capabilities.*inclusionRange).includes(closestValue)) 140 m_filter[i] = false; 141 }); 141 std::optional<DistanceResult> smallestDistance; 142 for (size_t i = 0, size = m_capabilities.size(); i < size; ++i) { 143 if (eliminated[i]) 144 continue; 145 auto distanceResult = (this->*computeDistance)(m_capabilities[i]); 146 if (!smallestDistance || distanceResult.distance < smallestDistance.value().distance) 147 smallestDistance = distanceResult; 148 } 149 return smallestDistance.value().value; 150 } 151 152 void FontSelectionAlgorithm::filterCapability(bool eliminated[], DistanceFunction computeDistance, CapabilitiesRange inclusionRange) 153 { 154 auto value = bestValue(eliminated, computeDistance); 155 for (size_t i = 0, size = m_capabilities.size(); i < size; ++i) { 156 eliminated[i] = eliminated[i] 157 || !(m_capabilities[i].*inclusionRange).includes(value); 158 } 142 159 } 143 160 144 161 size_t FontSelectionAlgorithm::indexOfBestCapabilities() 145 162 { 146 filterCapability(&FontSelectionAlgorithm::stretchDistance, &FontSelectionCapabilities::width); 147 filterCapability(&FontSelectionAlgorithm::styleDistance, &FontSelectionCapabilities::slope); 148 filterCapability(&FontSelectionAlgorithm::weightDistance, &FontSelectionCapabilities::weight); 149 150 auto result = iterateActiveCapabilitiesWithReturn<size_t>([](FontSelectionCapabilities, size_t i) { 151 return i; 152 }); 153 ASSERT(result); 154 return result.value_or(0); 163 Vector<bool, 256> eliminated(m_capabilities.size(), false); 164 filterCapability(eliminated.data(), &FontSelectionAlgorithm::stretchDistance, &Capabilities::width); 165 filterCapability(eliminated.data(), &FontSelectionAlgorithm::styleDistance, &Capabilities::slope); 166 filterCapability(eliminated.data(), &FontSelectionAlgorithm::weightDistance, &Capabilities::weight); 167 return eliminated.find(false); 155 168 } 156 169 -
trunk/Source/WebCore/platform/graphics/FontSelectionAlgorithm.h
r221630 r225769 27 27 28 28 #include "TextFlags.h" 29 #include < wtf/Function.h>30 #include < wtf/GetPtr.h>29 #include <algorithm> 30 #include <tuple> 31 31 #include <wtf/Hasher.h> 32 #include <wtf/NeverDestroyed.h>33 32 #include <wtf/Optional.h> 34 #include <wtf/Vector.h>35 33 36 34 namespace WebCore { 37 35 38 36 // Unclamped, unchecked, signed fixed-point number representing a value used for font variations. 39 // Sixteen bits in total, one sign bit, two fractional bits, means the smallest positive representable value is 0.25,40 // the maximum representable value is 8191.75, and the minimum representablevalue is -8192.37 // Sixteen bits in total, one sign bit, two fractional bits, smallest positive value is 0.25, 38 // maximum value is 8191.75, and minimum value is -8192. 41 39 class FontSelectionValue { 42 40 public: 43 typedef int16_t BackingType;41 using BackingType = int16_t; 44 42 45 43 FontSelectionValue() = default; 46 44 47 // Explicit because it is lossy. 48 explicit FontSelectionValue(int x) 49 : m_backing(x * fractionalEntropy) 50 { 51 } 52 53 // Explicit because it is lossy. 54 explicit FontSelectionValue(float x) 55 : m_backing(x * fractionalEntropy) 56 { 57 } 58 59 operator float() const 60 { 61 // floats have 23 fractional bits, but only 14 fractional bits are necessary, so every value can be represented losslessly. 62 return m_backing / static_cast<float>(fractionalEntropy); 63 } 64 65 FontSelectionValue operator+(const FontSelectionValue other) const; 66 FontSelectionValue operator-(const FontSelectionValue other) const; 67 FontSelectionValue operator*(const FontSelectionValue other) const; 68 FontSelectionValue operator/(const FontSelectionValue other) const; 69 FontSelectionValue operator-() const; 70 bool operator==(const FontSelectionValue other) const; 71 bool operator!=(const FontSelectionValue other) const; 72 bool operator<(const FontSelectionValue other) const; 73 bool operator<=(const FontSelectionValue other) const; 74 bool operator>(const FontSelectionValue other) const; 75 bool operator>=(const FontSelectionValue other) const; 76 77 BackingType rawValue() const 78 { 79 return m_backing; 80 } 81 82 static FontSelectionValue maximumValue() 83 { 84 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(std::numeric_limits<BackingType>::max(), RawTag::RawTag); 85 return result.get(); 86 } 87 88 static FontSelectionValue minimumValue() 89 { 90 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(std::numeric_limits<BackingType>::min(), RawTag::RawTag); 91 return result.get(); 92 } 93 94 static FontSelectionValue clampFloat(float value) 95 { 96 if (value < static_cast<float>(FontSelectionValue::minimumValue())) 97 return FontSelectionValue::minimumValue(); 98 if (value > static_cast<float>(FontSelectionValue::maximumValue())) 99 return FontSelectionValue::maximumValue(); 100 return FontSelectionValue(value); 101 } 45 // Explicit because it won't work correctly for values outside the representable range. 46 explicit constexpr FontSelectionValue(int); 47 48 // Explicit because it won't work correctly for values outside the representable range and because precision can be lost. 49 explicit constexpr FontSelectionValue(float); 50 51 // Precision can be lost, but value will be clamped to the representable range. 52 static constexpr FontSelectionValue clampFloat(float); 53 54 // Since floats have 23 mantissa bits, every value can be represented losslessly. 55 constexpr operator float() const; 56 57 static constexpr FontSelectionValue maximumValue(); 58 static constexpr FontSelectionValue minimumValue(); 59 60 friend constexpr FontSelectionValue operator+(FontSelectionValue, FontSelectionValue); 61 friend constexpr FontSelectionValue operator-(FontSelectionValue, FontSelectionValue); 62 friend constexpr FontSelectionValue operator*(FontSelectionValue, FontSelectionValue); 63 friend constexpr FontSelectionValue operator/(FontSelectionValue, FontSelectionValue); 64 friend constexpr FontSelectionValue operator-(FontSelectionValue); 65 66 constexpr BackingType rawValue() const { return m_backing; } 102 67 103 68 private: 104 69 enum class RawTag { RawTag }; 105 106 FontSelectionValue(BackingType rawValue, RawTag) 107 : m_backing(rawValue) 108 { 109 } 70 constexpr FontSelectionValue(int, RawTag); 110 71 111 72 static constexpr int fractionalEntropy = 4; … … 113 74 }; 114 75 115 inline FontSelectionValue FontSelectionValue::operator+(const FontSelectionValue other) const 116 { 117 return FontSelectionValue(m_backing + other.m_backing, RawTag::RawTag); 118 } 119 120 inline FontSelectionValue FontSelectionValue::operator-(const FontSelectionValue other) const 121 { 122 return FontSelectionValue(m_backing - other.m_backing, RawTag::RawTag); 123 } 124 125 inline FontSelectionValue FontSelectionValue::operator*(const FontSelectionValue other) const 126 { 127 return FontSelectionValue(static_cast<int32_t>(m_backing) * other.m_backing / fractionalEntropy, RawTag::RawTag); 128 } 129 130 inline FontSelectionValue FontSelectionValue::operator/(const FontSelectionValue other) const 131 { 132 return FontSelectionValue(static_cast<int32_t>(m_backing) / other.m_backing * fractionalEntropy, RawTag::RawTag); 133 } 134 135 inline FontSelectionValue FontSelectionValue::operator-() const 136 { 137 return FontSelectionValue(-m_backing, RawTag::RawTag); 138 } 139 140 inline bool FontSelectionValue::operator==(const FontSelectionValue other) const 141 { 142 return m_backing == other.m_backing; 143 } 144 145 inline bool FontSelectionValue::operator!=(const FontSelectionValue other) const 146 { 147 return !operator==(other); 148 } 149 150 inline bool FontSelectionValue::operator<(const FontSelectionValue other) const 151 { 152 return m_backing < other.m_backing; 153 } 154 155 inline bool FontSelectionValue::operator<=(const FontSelectionValue other) const 156 { 157 return m_backing <= other.m_backing; 158 } 159 160 inline bool FontSelectionValue::operator>(const FontSelectionValue other) const 161 { 162 return m_backing > other.m_backing; 163 } 164 165 inline bool FontSelectionValue::operator>=(const FontSelectionValue other) const 166 { 167 return m_backing >= other.m_backing; 168 } 169 170 static inline FontSelectionValue italicThreshold() 171 { 172 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(20); 173 return result.get(); 174 } 175 176 static inline bool isItalic(FontSelectionValue fontWeight) 76 constexpr FontSelectionValue::FontSelectionValue(int x) 77 : m_backing(x * fractionalEntropy) 78 { 79 // FIXME: Should we assert the passed in value was in range? 80 } 81 82 constexpr FontSelectionValue::FontSelectionValue(float x) 83 : m_backing(x * fractionalEntropy) 84 { 85 // FIXME: Should we assert the passed in value was in range? 86 } 87 88 constexpr FontSelectionValue::operator float() const 89 { 90 return m_backing / static_cast<float>(fractionalEntropy); 91 } 92 93 constexpr FontSelectionValue FontSelectionValue::maximumValue() 94 { 95 return { std::numeric_limits<BackingType>::max(), RawTag::RawTag }; 96 } 97 98 constexpr FontSelectionValue FontSelectionValue::minimumValue() 99 { 100 return { std::numeric_limits<BackingType>::min(), RawTag::RawTag }; 101 } 102 103 constexpr FontSelectionValue FontSelectionValue::clampFloat(float value) 104 { 105 return FontSelectionValue { std::max<float>(minimumValue(), std::min<float>(value, maximumValue())) }; 106 } 107 108 constexpr FontSelectionValue::FontSelectionValue(int rawValue, RawTag) 109 : m_backing(rawValue) 110 { 111 } 112 113 constexpr FontSelectionValue operator+(FontSelectionValue a, FontSelectionValue b) 114 { 115 return { a.m_backing + b.m_backing, FontSelectionValue::RawTag::RawTag }; 116 } 117 118 constexpr FontSelectionValue operator-(FontSelectionValue a, FontSelectionValue b) 119 { 120 return { a.m_backing - b.m_backing, FontSelectionValue::RawTag::RawTag }; 121 } 122 123 constexpr FontSelectionValue operator*(FontSelectionValue a, FontSelectionValue b) 124 { 125 return { a.m_backing * b.m_backing / FontSelectionValue::fractionalEntropy, FontSelectionValue::RawTag::RawTag }; 126 } 127 128 constexpr FontSelectionValue operator/(FontSelectionValue a, FontSelectionValue b) 129 { 130 return { a.m_backing * FontSelectionValue::fractionalEntropy / b.m_backing, FontSelectionValue::RawTag::RawTag }; 131 } 132 133 constexpr FontSelectionValue operator-(FontSelectionValue value) 134 { 135 return { -value.m_backing, FontSelectionValue::RawTag::RawTag }; 136 } 137 138 constexpr bool operator==(FontSelectionValue a, FontSelectionValue b) 139 { 140 return a.rawValue() == b.rawValue(); 141 } 142 143 constexpr bool operator!=(FontSelectionValue a, FontSelectionValue b) 144 { 145 return a.rawValue() != b.rawValue(); 146 } 147 148 constexpr bool operator<(FontSelectionValue a, FontSelectionValue b) 149 { 150 return a.rawValue() < b.rawValue(); 151 } 152 153 constexpr bool operator<=(FontSelectionValue a, FontSelectionValue b) 154 { 155 return a.rawValue() <= b.rawValue(); 156 } 157 158 constexpr bool operator>(FontSelectionValue a, FontSelectionValue b) 159 { 160 return a.rawValue() > b.rawValue(); 161 } 162 163 constexpr bool operator>=(FontSelectionValue a, FontSelectionValue b) 164 { 165 return a.rawValue() >= b.rawValue(); 166 } 167 168 constexpr FontSelectionValue italicThreshold() 169 { 170 return FontSelectionValue { 20 }; 171 } 172 173 constexpr bool isItalic(FontSelectionValue fontWeight) 177 174 { 178 175 return fontWeight >= italicThreshold(); 179 176 } 180 177 181 static inline FontSelectionValue normalItalicValue() 182 { 183 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(); 184 return result.get(); 185 } 186 187 static inline FontSelectionValue italicValue() 188 { 189 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(20); 190 return result.get(); 191 } 192 193 static inline FontSelectionValue boldThreshold() 194 { 195 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(600); 196 return result.get(); 197 } 198 199 static inline FontSelectionValue boldWeightValue() 200 { 201 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(700); 202 return result.get(); 203 } 204 205 static inline FontSelectionValue normalWeightValue() 206 { 207 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(400); 208 return result.get(); 209 } 210 211 static inline FontSelectionValue lightWeightValue() 212 { 213 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(200); 214 return result.get(); 215 } 216 217 static inline bool isFontWeightBold(FontSelectionValue fontWeight) 178 constexpr FontSelectionValue normalItalicValue() 179 { 180 return FontSelectionValue { 0 }; 181 } 182 183 constexpr FontSelectionValue italicValue() 184 { 185 return FontSelectionValue { 20 }; 186 } 187 188 constexpr FontSelectionValue boldThreshold() 189 { 190 return FontSelectionValue { 600 }; 191 } 192 193 constexpr FontSelectionValue boldWeightValue() 194 { 195 return FontSelectionValue { 700 }; 196 } 197 198 constexpr FontSelectionValue normalWeightValue() 199 { 200 return FontSelectionValue { 400 }; 201 } 202 203 constexpr FontSelectionValue lightWeightValue() 204 { 205 return FontSelectionValue { 200 }; 206 } 207 208 constexpr bool isFontWeightBold(FontSelectionValue fontWeight) 218 209 { 219 210 return fontWeight >= boldThreshold(); 220 211 } 221 212 222 static inline FontSelectionValue lowerWeightSearchThreshold() 223 { 224 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(400); 225 return result.get(); 226 } 227 228 static inline FontSelectionValue upperWeightSearchThreshold() 229 { 230 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(500); 231 return result.get(); 232 } 233 234 static inline FontSelectionValue ultraCondensedStretchValue() 235 { 236 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(50); 237 return result.get(); 238 } 239 240 static inline FontSelectionValue extraCondensedStretchValue() 241 { 242 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(62.5f); 243 return result.get(); 244 } 245 246 static inline FontSelectionValue condensedStretchValue() 247 { 248 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(75); 249 return result.get(); 250 } 251 252 static inline FontSelectionValue semiCondensedStretchValue() 253 { 254 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(87.5f); 255 return result.get(); 256 } 257 258 static inline FontSelectionValue normalStretchValue() 259 { 260 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(100); 261 return result.get(); 262 } 263 264 static inline FontSelectionValue semiExpandedStretchValue() 265 { 266 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(112.5f); 267 return result.get(); 268 } 269 270 static inline FontSelectionValue expandedStretchValue() 271 { 272 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(125); 273 return result.get(); 274 } 275 276 static inline FontSelectionValue extraExpandedStretchValue() 277 { 278 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(150); 279 return result.get(); 280 } 281 282 static inline FontSelectionValue ultraExpandedStretchValue() 283 { 284 static NeverDestroyed<FontSelectionValue> result = FontSelectionValue(200); 285 return result.get(); 213 constexpr FontSelectionValue lowerWeightSearchThreshold() 214 { 215 return FontSelectionValue { 400 }; 216 } 217 218 constexpr FontSelectionValue upperWeightSearchThreshold() 219 { 220 return FontSelectionValue { 500 }; 221 } 222 223 constexpr FontSelectionValue ultraCondensedStretchValue() 224 { 225 return FontSelectionValue { 50 }; 226 } 227 228 constexpr FontSelectionValue extraCondensedStretchValue() 229 { 230 return FontSelectionValue { 62.5f }; 231 } 232 233 constexpr FontSelectionValue condensedStretchValue() 234 { 235 return FontSelectionValue { 75 }; 236 } 237 238 constexpr FontSelectionValue semiCondensedStretchValue() 239 { 240 return FontSelectionValue { 87.5f }; 241 } 242 243 constexpr FontSelectionValue normalStretchValue() 244 { 245 return FontSelectionValue { 100 }; 246 } 247 248 constexpr FontSelectionValue semiExpandedStretchValue() 249 { 250 return FontSelectionValue { 112.5f }; 251 } 252 253 constexpr FontSelectionValue expandedStretchValue() 254 { 255 return FontSelectionValue { 125 }; 256 } 257 258 constexpr FontSelectionValue extraExpandedStretchValue() 259 { 260 return FontSelectionValue { 150 }; 261 } 262 263 constexpr FontSelectionValue ultraExpandedStretchValue() 264 { 265 return FontSelectionValue { 200 }; 286 266 } 287 267 288 268 // [Inclusive, Inclusive] 289 269 struct FontSelectionRange { 290 FontSelectionRange(FontSelectionValue minimum, FontSelectionValue maximum) 270 using Value = FontSelectionValue; 271 272 constexpr FontSelectionRange(Value minimum, Value maximum) 291 273 : minimum(minimum) 292 274 , maximum(maximum) … … 294 276 } 295 277 296 bool operator==(const FontSelectionRange& other) const 297 { 298 return minimum == other.minimum 299 && maximum == other.maximum; 300 } 301 302 bool isValid() const 278 explicit constexpr FontSelectionRange(Value value) 279 : minimum(value) 280 , maximum(value) 281 { 282 } 283 284 constexpr bool operator==(const FontSelectionRange& other) const 285 { 286 return std::tie(minimum, maximum) == std::tie(other.minimum, other.maximum); 287 } 288 289 constexpr bool isValid() const 303 290 { 304 291 return minimum <= maximum; … … 317 304 } 318 305 319 bool includes(FontSelectionValue target) const306 constexpr bool includes(Value target) const 320 307 { 321 308 return target >= minimum && target <= maximum; 322 309 } 323 310 324 uint32_t uniqueValue() const 311 // FIXME: This name is not so great. Move this into the add function below 312 // once we move FontPlatformDataCacheKeyHash from IntegerHasher to Hasher, 313 // and then it doesn't need to have a name. 314 constexpr uint32_t uniqueValue() const 325 315 { 326 316 return minimum.rawValue() << 16 | maximum.rawValue(); 327 317 } 328 318 329 FontSelectionValue minimum { FontSelectionValue(1) }; 330 FontSelectionValue maximum { FontSelectionValue(0) }; 331 }; 319 Value minimum { 1 }; 320 Value maximum { 0 }; 321 }; 322 323 inline void add(Hasher& hasher, const FontSelectionRange& range) 324 { 325 add(hasher, range.uniqueValue()); 326 } 332 327 333 328 struct FontSelectionRequest { 329 using Value = FontSelectionValue; 330 331 Value weight; 332 Value width; 333 Value slope; 334 335 constexpr std::tuple<Value, Value, Value> tied() const 336 { 337 return std::tie(weight, width, slope); 338 } 339 340 #if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES) 334 341 FontSelectionRequest() = default; 335 342 336 FontSelectionRequest(FontSelectionValue weight, FontSelectionValue width, FontSelectionValue slope)343 constexpr FontSelectionRequest(Value weight, Value width, Value slope) 337 344 : weight(weight) 338 345 , width(width) … … 340 347 { 341 348 } 342 343 bool operator==(const FontSelectionRequest& other) const 344 { 345 return weight == other.weight 346 && width == other.width 347 && slope == other.slope; 348 } 349 350 bool operator!=(const FontSelectionRequest& other) const 351 { 352 return !operator==(other); 353 } 354 355 FontSelectionValue weight; 356 FontSelectionValue width; 357 FontSelectionValue slope; 358 }; 359 360 // Only used for HashMaps. We don't want to put the bool into FontSelectionRequest 361 // because FontSelectionRequest needs to be as small as possible because it's inside 362 // every FontDescription. 363 struct FontSelectionRequestKey { 364 FontSelectionRequestKey() = default; 365 366 FontSelectionRequestKey(FontSelectionRequest request) 367 : request(request) 368 { 369 } 370 371 explicit FontSelectionRequestKey(WTF::HashTableDeletedValueType) 372 : isDeletedValue(true) 373 { 374 } 375 376 bool isHashTableDeletedValue() const 377 { 378 return isDeletedValue; 379 } 380 381 bool operator==(const FontSelectionRequestKey& other) const 382 { 383 return request == other.request 384 && isDeletedValue == other.isDeletedValue; 385 } 386 387 FontSelectionRequest request; 388 bool isDeletedValue { false }; 389 }; 390 391 struct FontSelectionRequestKeyHash { 392 static unsigned hash(const FontSelectionRequestKey& key) 393 { 394 IntegerHasher hasher; 395 hasher.add(key.request.weight.rawValue()); 396 hasher.add(key.request.width.rawValue()); 397 hasher.add(key.request.slope.rawValue()); 398 hasher.add(key.isDeletedValue); 399 return hasher.hash(); 400 } 401 402 static bool equal(const FontSelectionRequestKey& a, const FontSelectionRequestKey& b) 403 { 404 return a == b; 405 } 406 407 static const bool safeToCompareToEmptyOrDeleted = true; 408 }; 349 #endif 350 }; 351 352 constexpr bool operator==(const FontSelectionRequest& a, const FontSelectionRequest& b) 353 { 354 return a.tied() == b.tied(); 355 } 356 357 constexpr bool operator!=(const FontSelectionRequest& a, const FontSelectionRequest& b) 358 { 359 return !(a == b); 360 } 361 362 inline void add(Hasher& hasher, const FontSelectionRequest& request) 363 { 364 add(hasher, request.tied()); 365 } 409 366 410 367 struct FontSelectionCapabilities { 411 FontSelectionCapabilities() 412 { 413 } 414 415 FontSelectionCapabilities(FontSelectionRange weight, FontSelectionRange width, FontSelectionRange slope) 368 using Range = FontSelectionRange; 369 370 FontSelectionCapabilities& operator=(const FontSelectionCapabilities&) = default; 371 372 constexpr std::tuple<Range, Range, Range> tied() const 373 { 374 return std::tie(weight, width, slope); 375 } 376 377 void expand(const FontSelectionCapabilities& capabilities) 378 { 379 weight.expand(capabilities.weight); 380 width.expand(capabilities.width); 381 slope.expand(capabilities.slope); 382 } 383 384 Range weight { normalWeightValue() }; 385 Range width { normalStretchValue() }; 386 Range slope { normalItalicValue() }; 387 388 #if !COMPILER_SUPPORTS(NSDMI_FOR_AGGREGATES) 389 FontSelectionCapabilities() = default; 390 391 constexpr FontSelectionCapabilities(Range weight, Range width, Range slope) 416 392 : weight(weight) 417 393 , width(width) … … 419 395 { 420 396 } 421 422 void expand(const FontSelectionCapabilities& capabilities) 423 { 424 weight.expand(capabilities.weight); 425 width.expand(capabilities.width); 426 slope.expand(capabilities.slope); 427 } 428 429 bool operator==(const FontSelectionCapabilities& other) const 430 { 431 return weight == other.weight 432 && width == other.width 433 && slope == other.slope; 434 } 435 436 bool operator!=(const FontSelectionCapabilities& other) const 437 { 438 return !(*this == other); 439 } 440 441 FontSelectionRange weight { normalWeightValue(), normalWeightValue() }; 442 FontSelectionRange width { normalStretchValue(), normalStretchValue() }; 443 FontSelectionRange slope { normalItalicValue(), normalItalicValue() }; 444 }; 397 #endif 398 }; 399 400 constexpr bool operator==(const FontSelectionCapabilities& a, const FontSelectionCapabilities& b) 401 { 402 return a.tied() == b.tied(); 403 } 404 405 constexpr bool operator!=(const FontSelectionCapabilities& a, const FontSelectionCapabilities& b) 406 { 407 return !(a == b); 408 } 445 409 446 410 struct FontSelectionSpecifiedCapabilities { 447 FontSelectionCapabilities computeFontSelectionCapabilities() const448 {449 return FontSelectionCapabilities(computeWeight(), computeWidth(), computeSlope());450 } 451 452 bool operator==(const FontSelectionSpecifiedCapabilities& other) const453 {454 return weight == other.weight455 && width == other.width 456 && slope == other.slope;457 }458 459 bool operator!=(const FontSelectionSpecifiedCapabilities& other) const460 { 461 return !(*this == other);462 }463 464 FontSelectionSpecifiedCapabilities& operator=(const FontSelectionCapabilities& other)465 { 466 weight = other.weight;467 width = other.width;468 slope = other.slope;411 using Capabilities = FontSelectionCapabilities; 412 using Range = FontSelectionRange; 413 using OptionalRange = std::optional<Range>; 414 415 constexpr Capabilities computeFontSelectionCapabilities() const 416 { 417 return { computeWeight(), computeWidth(), computeSlope() }; 418 } 419 420 constexpr std::tuple<OptionalRange&, OptionalRange&, OptionalRange&> tied() 421 { 422 return std::tie(weight, width, slope); 423 } 424 425 constexpr std::tuple<const OptionalRange&, const OptionalRange&, const OptionalRange&> tied() const 426 { 427 return std::tie(weight, width, slope); 428 } 429 430 FontSelectionSpecifiedCapabilities& operator=(const Capabilities& other) 431 { 432 tied() = other.tied(); 469 433 return *this; 470 434 } 471 435 472 FontSelectionRange computeWeight() const 473 { 474 return weight.value_or(FontSelectionRange({ normalWeightValue(), normalWeightValue() })); 475 } 476 477 FontSelectionRange computeWidth() const 478 { 479 return width.value_or(FontSelectionRange({ normalStretchValue(), normalStretchValue() })); 480 } 481 482 FontSelectionRange computeSlope() const 483 { 484 return slope.value_or(FontSelectionRange({ normalItalicValue(), normalItalicValue() })); 485 } 486 487 std::optional<FontSelectionRange> weight; 488 std::optional<FontSelectionRange> width; 489 std::optional<FontSelectionRange> slope; 490 }; 436 constexpr Range computeWeight() const 437 { 438 return weight.value_or(Range { normalWeightValue() }); 439 } 440 441 constexpr Range computeWidth() const 442 { 443 return width.value_or(Range { normalStretchValue() }); 444 } 445 446 constexpr Range computeSlope() const 447 { 448 return slope.value_or(Range { normalItalicValue() }); 449 } 450 451 OptionalRange weight; 452 OptionalRange width; 453 OptionalRange slope; 454 }; 455 456 constexpr bool operator==(const FontSelectionSpecifiedCapabilities& a, const FontSelectionSpecifiedCapabilities& b) 457 { 458 return a.tied() == b.tied(); 459 } 460 461 constexpr bool operator!=(const FontSelectionSpecifiedCapabilities& a, const FontSelectionSpecifiedCapabilities& b) 462 { 463 return !(a == b); 464 } 491 465 492 466 class FontSelectionAlgorithm { 493 467 public: 468 using Capabilities = FontSelectionCapabilities; 469 494 470 FontSelectionAlgorithm() = delete; 495 496 FontSelectionAlgorithm(FontSelectionRequest request, const Vector<FontSelectionCapabilities>& capabilities, std::optional<FontSelectionCapabilities> capabilitiesBounds = std::nullopt) 497 : m_request(request) 498 , m_capabilities(capabilities) 499 , m_filter(new bool[m_capabilities.size()]) 500 { 501 ASSERT(!m_capabilities.isEmpty()); 502 if (capabilitiesBounds) 503 m_capabilitiesBounds = capabilitiesBounds.value(); 504 else { 505 for (auto capabilities : m_capabilities) 506 m_capabilitiesBounds.expand(capabilities); 507 } 508 for (size_t i = 0; i < m_capabilities.size(); ++i) 509 m_filter[i] = true; 510 } 471 FontSelectionAlgorithm(FontSelectionRequest, const Vector<Capabilities>&, std::optional<Capabilities> capabilitiesBounds = std::nullopt); 511 472 512 473 struct DistanceResult { … … 514 475 FontSelectionValue value; 515 476 }; 516 517 DistanceResult stretchDistance(FontSelectionCapabilities) const; 518 DistanceResult styleDistance(FontSelectionCapabilities) const; 519 DistanceResult weightDistance(FontSelectionCapabilities) const; 477 DistanceResult stretchDistance(Capabilities) const; 478 DistanceResult styleDistance(Capabilities) const; 479 DistanceResult weightDistance(Capabilities) const; 520 480 521 481 size_t indexOfBestCapabilities(); 522 482 523 483 private: 524 template <typename T> 525 using IterateActiveCapabilitiesWithReturnCallback = WTF::Function<std::optional<T>(FontSelectionCapabilities, size_t)>; 526 527 template <typename T> 528 inline std::optional<T> iterateActiveCapabilitiesWithReturn(const IterateActiveCapabilitiesWithReturnCallback<T>& callback) 529 { 530 for (size_t i = 0; i < m_capabilities.size(); ++i) { 531 if (!m_filter[i]) 532 continue; 533 if (auto result = callback(m_capabilities[i], i)) 534 return result; 535 } 536 return std::nullopt; 537 } 538 539 template <typename T> 540 inline void iterateActiveCapabilities(T callback) 541 { 542 iterateActiveCapabilitiesWithReturn<int>([&](FontSelectionCapabilities capabilities, size_t i) -> std::optional<int> { 543 callback(capabilities, i); 544 return std::nullopt; 545 }); 546 } 547 548 void filterCapability(DistanceResult(FontSelectionAlgorithm::*computeDistance)(FontSelectionCapabilities) const, FontSelectionRange FontSelectionCapabilities::*inclusionRange); 484 using DistanceFunction = DistanceResult (FontSelectionAlgorithm::*)(Capabilities) const; 485 using CapabilitiesRange = FontSelectionRange Capabilities::*; 486 FontSelectionValue bestValue(const bool eliminated[], DistanceFunction) const; 487 void filterCapability(bool eliminated[], DistanceFunction, CapabilitiesRange); 549 488 550 489 FontSelectionRequest m_request; 551 FontSelectionCapabilities m_capabilitiesBounds; 552 const Vector<FontSelectionCapabilities>& m_capabilities; 553 std::unique_ptr<bool[]> m_filter; 554 }; 555 556 } 490 Capabilities m_capabilitiesBounds; 491 const Vector<Capabilities>& m_capabilities; 492 }; 493 494 }
Note:
See TracChangeset
for help on using the changeset viewer.