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

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

Issue 1270723002: Improve CSS Style matching spec compliance (Closed) Base URL: git@github.com:drott/blink-crosswalk.git@reimplementMatching
Patch Set: stdlib instead of MathExtras 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
1 /* 1 /*
2 * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved. 2 * Copyright (C) 2007, 2008, 2011 Apple Inc. All rights reserved.
3 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * Copyright (C) 2013 Google Inc. All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 14 matching lines...) Expand all
25 */ 25 */
26 26
27 27
28 #include "config.h" 28 #include "config.h"
29 #include "core/css/FontFaceCache.h" 29 #include "core/css/FontFaceCache.h"
30 30
31 #include "core/css/CSSFontSelector.h" 31 #include "core/css/CSSFontSelector.h"
32 #include "core/css/CSSSegmentedFontFace.h" 32 #include "core/css/CSSSegmentedFontFace.h"
33 #include "core/css/CSSValueList.h" 33 #include "core/css/CSSValueList.h"
34 #include "core/css/FontFace.h" 34 #include "core/css/FontFace.h"
35 #include "core/css/FontStyleMatcher.h"
35 #include "core/css/StyleRule.h" 36 #include "core/css/StyleRule.h"
36 #include "core/fetch/FontResource.h" 37 #include "core/fetch/FontResource.h"
37 #include "core/fetch/ResourceFetcher.h" 38 #include "core/fetch/ResourceFetcher.h"
38 #include "platform/FontFamilyNames.h" 39 #include "platform/FontFamilyNames.h"
39 #include "platform/fonts/FontDescription.h" 40 #include "platform/fonts/FontDescription.h"
40 #include "wtf/text/AtomicString.h" 41 #include "wtf/text/AtomicString.h"
41 42
43
42 namespace blink { 44 namespace blink {
43 45
44 FontFaceCache::FontFaceCache() 46 FontFaceCache::FontFaceCache()
45 : m_version(0) 47 : m_version(0)
46 { 48 {
47 } 49 }
48 50
49 void FontFaceCache::add(CSSFontSelector* cssFontSelector, const StyleRuleFontFac e* fontFaceRule, PassRefPtrWillBeRawPtr<FontFace> prpFontFace) 51 void FontFaceCache::add(CSSFontSelector* cssFontSelector, const StyleRuleFontFac e* fontFaceRule, PassRefPtrWillBeRawPtr<FontFace> prpFontFace)
50 { 52 {
51 RefPtrWillBeRawPtr<FontFace> fontFace = prpFontFace; 53 RefPtrWillBeRawPtr<FontFace> fontFace = prpFontFace;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 if (m_fontFaces.isEmpty()) 122 if (m_fontFaces.isEmpty())
121 return; 123 return;
122 124
123 m_fontFaces.clear(); 125 m_fontFaces.clear();
124 m_fonts.clear(); 126 m_fonts.clear();
125 m_styleRuleToFontFace.clear(); 127 m_styleRuleToFontFace.clear();
126 m_cssConnectedFontFaces.clear(); 128 m_cssConnectedFontFaces.clear();
127 ++m_version; 129 ++m_version;
128 } 130 }
129 131
130 static inline bool compareFontFaces(CSSSegmentedFontFace* first, CSSSegmentedFon tFace* second, FontTraits desiredTraits)
131 {
132 const FontTraits& firstTraits = first->traits();
133 const FontTraits& secondTraits = second->traits();
134
135 bool firstHasDesiredVariant = firstTraits.variant() == desiredTraits.variant ();
136 bool secondHasDesiredVariant = secondTraits.variant() == desiredTraits.varia nt();
137
138 if (firstHasDesiredVariant != secondHasDesiredVariant)
139 return firstHasDesiredVariant;
140
141 // We need to check font-variant css property for CSS2.1 compatibility.
142 if (desiredTraits.variant() == FontVariantSmallCaps) {
143 // Prefer a font that has indicated that it can only support small-caps to a font that claims to support
144 // all variants. The specialized font is more likely to be true small-ca ps and not require synthesis.
145 bool firstRequiresSmallCaps = firstTraits.variant() == FontVariantSmallC aps;
146 bool secondRequiresSmallCaps = secondTraits.variant() == FontVariantSmal lCaps;
147 if (firstRequiresSmallCaps != secondRequiresSmallCaps)
148 return firstRequiresSmallCaps;
149 }
150
151 bool firstHasDesiredStyle = firstTraits.style() == desiredTraits.style();
152 bool secondHasDesiredStyle = secondTraits.style() == desiredTraits.style();
153
154 if (firstHasDesiredStyle != secondHasDesiredStyle)
155 return firstHasDesiredStyle;
156
157 if (desiredTraits.style() == FontStyleItalic) {
158 // Prefer a font that has indicated that it can only support italics to a font that claims to support
159 // all styles. The specialized font is more likely to be the one the aut hor wants used.
160 bool firstRequiresItalics = firstTraits.style() == FontStyleItalic;
161 bool secondRequiresItalics = secondTraits.style() == FontStyleItalic;
162 if (firstRequiresItalics != secondRequiresItalics)
163 return firstRequiresItalics;
164 }
165 if (secondTraits.weight() == desiredTraits.weight())
166 return false;
167
168 if (firstTraits.weight() == desiredTraits.weight())
169 return true;
170
171 // http://www.w3.org/TR/2011/WD-css3-fonts-20111004/#font-matching-algorithm says :
172 // - If the desired weight is less than 400, weights below the desired wei ght are checked in descending order followed by weights above the desired weight in ascending order until a match is found.
173 // - If the desired weight is greater than 500, weights above the desired weight are checked in ascending order followed by weights below the desired weig ht in descending order until a match is found.
174 // - If the desired weight is 400, 500 is checked first and then the rule for desired weights less than 400 is used.
175 // - If the desired weight is 500, 400 is checked first and then the rule for desired weights less than 400 is used.
176 static const unsigned fallbackRuleSets = 9;
177 static const unsigned rulesPerSet = 8;
178 static const FontWeight weightFallbackRuleSets[fallbackRuleSets][rulesPerSet ] = {
179 { FontWeight200, FontWeight300, FontWeight400, FontWeight500, FontWeight 600, FontWeight700, FontWeight800, FontWeight900 },
180 { FontWeight100, FontWeight300, FontWeight400, FontWeight500, FontWeight 600, FontWeight700, FontWeight800, FontWeight900 },
181 { FontWeight200, FontWeight100, FontWeight400, FontWeight500, FontWeight 600, FontWeight700, FontWeight800, FontWeight900 },
182 { FontWeight500, FontWeight300, FontWeight200, FontWeight100, FontWeight 600, FontWeight700, FontWeight800, FontWeight900 },
183 { FontWeight400, FontWeight300, FontWeight200, FontWeight100, FontWeight 600, FontWeight700, FontWeight800, FontWeight900 },
184 { FontWeight700, FontWeight800, FontWeight900, FontWeight500, FontWeight 400, FontWeight300, FontWeight200, FontWeight100 },
185 { FontWeight800, FontWeight900, FontWeight600, FontWeight500, FontWeight 400, FontWeight300, FontWeight200, FontWeight100 },
186 { FontWeight900, FontWeight700, FontWeight600, FontWeight500, FontWeight 400, FontWeight300, FontWeight200, FontWeight100 },
187 { FontWeight800, FontWeight700, FontWeight600, FontWeight500, FontWeight 400, FontWeight300, FontWeight200, FontWeight100 }
188 };
189
190 unsigned ruleSetIndex = static_cast<unsigned>(desiredTraits.weight());
191 ASSERT(ruleSetIndex < fallbackRuleSets);
192 const FontWeight* weightFallbackRule = weightFallbackRuleSets[ruleSetIndex];
193 for (unsigned i = 0; i < rulesPerSet; ++i) {
194 if (secondTraits.weight() == weightFallbackRule[i])
195 return false;
196 if (firstTraits.weight() == weightFallbackRule[i])
197 return true;
198 }
199
200 return false;
201 }
202
203 CSSSegmentedFontFace* FontFaceCache::get(const FontDescription& fontDescription, const AtomicString& family) 132 CSSSegmentedFontFace* FontFaceCache::get(const FontDescription& fontDescription, const AtomicString& family)
204 { 133 {
205 TraitsMap* familyFontFaces = m_fontFaces.get(family); 134 TraitsMap* familyFontFaces = m_fontFaces.get(family);
206 if (!familyFontFaces || familyFontFaces->isEmpty()) 135 if (!familyFontFaces || familyFontFaces->isEmpty())
207 return 0; 136 return 0;
208 137
209 FamilyToTraitsMap::AddResult traitsResult = m_fonts.add(family, nullptr); 138 FamilyToTraitsMap::AddResult traitsResult = m_fonts.add(family, nullptr);
210 if (!traitsResult.storedValue->value) 139 if (!traitsResult.storedValue->value)
211 traitsResult.storedValue->value = adoptPtrWillBeNoop(new TraitsMap); 140 traitsResult.storedValue->value = adoptPtrWillBeNoop(new TraitsMap);
212 141
213 FontTraits traits = fontDescription.traits(); 142 FontTraits traits = fontDescription.traits();
214 TraitsMap::AddResult faceResult = traitsResult.storedValue->value->add(trait s.bitfield(), nullptr); 143 TraitsMap::AddResult faceResult = traitsResult.storedValue->value->add(trait s.bitfield(), nullptr);
215 if (!faceResult.storedValue->value) { 144 if (!faceResult.storedValue->value) {
216 for (const auto& item : *familyFontFaces) { 145 for (const auto& item : *familyFontFaces) {
217 CSSSegmentedFontFace* candidate = item.value.get(); 146 CSSSegmentedFontFace* candidate = item.value.get();
218 FontTraits candidateTraits = candidate->traits(); 147 FontStyleMatcher styleMatcher(traits);
219 if (traits.style() == FontStyleNormal && candidateTraits.style() != FontStyleNormal) 148 if (!faceResult.storedValue->value || styleMatcher.isCandidateBetter (candidate, faceResult.storedValue->value.get()))
220 continue;
221 if (traits.variant() == FontVariantNormal && candidateTraits.variant () != FontVariantNormal)
222 continue;
223 if (!faceResult.storedValue->value || compareFontFaces(candidate, fa ceResult.storedValue->value.get(), traits))
224 faceResult.storedValue->value = candidate; 149 faceResult.storedValue->value = candidate;
225 } 150 }
226 } 151 }
227 return faceResult.storedValue->value.get(); 152 return faceResult.storedValue->value.get();
228 } 153 }
229 154
230 DEFINE_TRACE(FontFaceCache) 155 DEFINE_TRACE(FontFaceCache)
231 { 156 {
232 #if ENABLE(OILPAN) 157 #if ENABLE(OILPAN)
233 visitor->trace(m_fontFaces); 158 visitor->trace(m_fontFaces);
234 visitor->trace(m_fonts); 159 visitor->trace(m_fonts);
235 visitor->trace(m_styleRuleToFontFace); 160 visitor->trace(m_styleRuleToFontFace);
236 visitor->trace(m_cssConnectedFontFaces); 161 visitor->trace(m_cssConnectedFontFaces);
237 #endif 162 #endif
238 } 163 }
239 164
240 } 165 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698