Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
|
eae
2015/08/04 18:23:28
This should retain the copyright header from FontF
| |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "config.h" | |
| 6 #include "core/css/FontStyleMatcher.h" | |
| 7 | |
| 8 #include "core/css/CSSSegmentedFontFace.h" | |
| 9 #include "wtf/Assertions.h" | |
| 10 | |
| 11 namespace blink { | |
| 12 | |
| 13 static inline unsigned stretchDistanceToDesired(FontTraits desired, FontTraits c andidate) | |
| 14 { | |
| 15 return std::abs(desired.stretch() - candidate.stretch()); | |
| 16 } | |
| 17 | |
| 18 static inline unsigned styleScore(FontTraits desired, FontTraits candidate) | |
| 19 { | |
| 20 static_assert(FontStyleNormal == 0 && FontStyleItalic == 2, | |
| 21 "Enumeration values need to match lookup table."); | |
| 22 unsigned styleScoreLookupTable[][FontStyleItalic + 1] = { | |
| 23 // "If the value is normal, normal faces are checked first, then oblique faces, then italic faces." | |
| 24 // i.e. normal has the highest score, then oblique, then italic. | |
| 25 { 2, 1, 0 }, | |
| 26 // "If the value is oblique, oblique faces are checked first, then itali c faces and then normal faces." | |
| 27 // i.e. normal gets the lowest score, oblique gets the highest, italic s econd best. | |
| 28 { 0, 2, 1 }, | |
| 29 // "If the value of font-style is italic, italic faces are checked first , then oblique, then normal faces" | |
| 30 // i.e. normal gets the lowest score, oblique is second best, italic hig hest. | |
| 31 { 0, 1, 2 } | |
| 32 }; | |
| 33 | |
| 34 ASSERT_WITH_SECURITY_IMPLICATION(desired.style() < FontStyleItalic + 1); | |
| 35 ASSERT_WITH_SECURITY_IMPLICATION(candidate.style() < FontStyleItalic + 1); | |
| 36 | |
| 37 return styleScoreLookupTable[desired.style()][candidate.style()]; | |
| 38 } | |
| 39 | |
| 40 static inline unsigned weightScore(FontTraits desired, FontTraits candidate) | |
| 41 { | |
| 42 static_assert(FontWeight100 == 0 && FontWeight900 - FontWeight100 == 8, | |
| 43 "Enumeration values need to match lookup table."); | |
| 44 static const unsigned scoreLookupSize = FontWeight900 + 1; | |
| 45 // https://drafts.csswg.org/css-fonts/#font-style-matching | |
| 46 // "..if the desired weight is available that face matches. " | |
| 47 static const unsigned weightScoreLookup[scoreLookupSize][scoreLookupSize] = { | |
| 48 // "If the desired weight is less than 400, weights below the desired | |
| 49 // weight are checked in descending order followed by weights above the | |
| 50 // desired weight in ascending order until a match is found." | |
| 51 { 9, 8, 7, 6, 5, 4, 3, 2, 1 }, // FontWeight100 desired | |
| 52 { 8, 9, 7, 6, 5, 4, 3, 2, 1 }, // FontWeight200 desired | |
| 53 { 7, 8, 9, 6, 5, 4, 3, 2, 1 }, // FontWeight300 desired | |
| 54 | |
| 55 // "If the desired weight is 400, 500 is checked first and then the rule | |
| 56 // for desired weights less than 400 is used." | |
| 57 { 5, 6, 7, 9, 8, 4, 3, 2, 1 }, // FontWeight400 desired | |
| 58 | |
| 59 // "If the desired weight is 500, 400 is checked first and then the rule | |
| 60 // for desired weights less than 400 is used." | |
| 61 { 5, 6, 7, 8, 9, 4, 3, 2, 1 }, // FontWeight500 desired | |
| 62 | |
| 63 // "If the desired weight is greater than 500, weights above the desired | |
| 64 // weight are checked in ascending order followed by weights below the | |
| 65 // desired weight in descending order until a match is found." | |
| 66 { 1, 2, 3, 4, 5, 9, 8, 7, 6 }, // FontWeight600 desired | |
| 67 { 1, 2, 3, 4, 5, 6, 9, 8, 7 }, // FontWeight700 desired | |
| 68 { 1, 2, 3, 4, 5, 6, 7, 9, 8 }, // FontWeight800 desired | |
| 69 { 1, 2, 3, 4, 5, 6, 7, 8, 9 } // FontWeight900 desired | |
| 70 }; | |
| 71 | |
| 72 unsigned desiredScoresLookup = static_cast<unsigned>(desired.weight()); | |
| 73 unsigned candidateScoreLookup = static_cast<unsigned>(candidate.weight()); | |
| 74 ASSERT_WITH_SECURITY_IMPLICATION(desiredScoresLookup < scoreLookupSize); | |
| 75 ASSERT_WITH_SECURITY_IMPLICATION(candidateScoreLookup < scoreLookupSize); | |
| 76 | |
| 77 return weightScoreLookup[desiredScoresLookup][candidateScoreLookup]; | |
| 78 } | |
| 79 | |
| 80 bool FontStyleMatcher::isCandidateBetter(CSSSegmentedFontFace *candidate, CSSSeg mentedFontFace *current) | |
| 81 { | |
| 82 const FontTraits& candidateTraits = candidate->traits(); | |
| 83 const FontTraits& currentTraits = current->traits(); | |
| 84 | |
| 85 // According to CSS3 Fonts Font Style matching, there is a precedence for ma tching: | |
| 86 // A better stretch match wins over a better style match, a better style mat ch | |
| 87 // wins over a better weight match, where "better" means closer to the desir ed | |
| 88 // traits. | |
| 89 int stretchComparison = 0, styleComparison = 0, weightComparison = 0; | |
| 90 | |
| 91 // 1. Compare stretch | |
| 92 stretchComparison = stretchDistanceToDesired(m_fontTraits, candidateTraits) - | |
| 93 stretchDistanceToDesired(m_fontTraits, currentTraits); | |
| 94 | |
| 95 if (stretchComparison > 0) | |
| 96 return false; | |
| 97 if (stretchComparison < 0) | |
| 98 return true; | |
| 99 | |
| 100 // 2. Compare style | |
| 101 styleComparison = styleScore(m_fontTraits, candidateTraits) - | |
| 102 styleScore(m_fontTraits, currentTraits); | |
| 103 | |
| 104 if (styleComparison > 0) | |
| 105 return true; | |
| 106 if (styleComparison < 0) | |
| 107 return false; | |
| 108 | |
| 109 weightComparison = weightScore(m_fontTraits, candidateTraits) - | |
| 110 weightScore(m_fontTraits, currentTraits); | |
| 111 | |
| 112 if (weightComparison > 0) | |
| 113 return true; | |
| 114 | |
| 115 return false; | |
| 116 } | |
| 117 | |
| 118 } | |
| OLD | NEW |