Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(222)

Side by Side Diff: Source/core/css/FontStyleMatcher.cpp

Issue 1270723002: Improve CSS Style matching spec compliance (Closed) Base URL: git@github.com:drott/blink-crosswalk.git@reimplementMatching
Patch Set: TODOs with bugs, redundant file removed, test expectations fix Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698