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

Side by Side Diff: third_party/WebKit/Source/platform/fonts/FontFallbackIterator.cpp

Issue 2230233002: Skip redundant fonts returned by FontFallbackIterator (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Logging removed Created 4 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 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "platform/fonts/FontFallbackIterator.h" 5 #include "platform/fonts/FontFallbackIterator.h"
6 6
7 #include "platform/Logging.h" 7 #include "platform/Logging.h"
8 #include "platform/fonts/FontCache.h" 8 #include "platform/fonts/FontCache.h"
9 #include "platform/fonts/FontDescription.h" 9 #include "platform/fonts/FontDescription.h"
10 #include "platform/fonts/FontFallbackList.h" 10 #include "platform/fonts/FontFallbackList.h"
(...skipping 16 matching lines...) Expand all
27 FontFallbackPriority fontFallbackPriority) 27 FontFallbackPriority fontFallbackPriority)
28 : m_fontDescription(description) 28 : m_fontDescription(description)
29 , m_fontFallbackList(fallbackList) 29 , m_fontFallbackList(fallbackList)
30 , m_currentFontDataIndex(0) 30 , m_currentFontDataIndex(0)
31 , m_segmentedFaceIndex(0) 31 , m_segmentedFaceIndex(0)
32 , m_fallbackStage(FontGroupFonts) 32 , m_fallbackStage(FontGroupFonts)
33 , m_fontFallbackPriority(fontFallbackPriority) 33 , m_fontFallbackPriority(fontFallbackPriority)
34 { 34 {
35 } 35 }
36 36
37 bool FontFallbackIterator::needsHintList() const
38 {
39 if (m_fallbackStage != FontGroupFonts && m_fallbackStage != SegmentedFace) {
40 return false;
41 }
42
43 const FontData* fontData = m_fontFallbackList->fontDataAt(m_fontDescription, m_currentFontDataIndex);
44 return fontData && fontData->isSegmented();
45 }
46
47 bool FontFallbackIterator::alreadyLoadingRangeForHintChar(UChar32 hintChar) 37 bool FontFallbackIterator::alreadyLoadingRangeForHintChar(UChar32 hintChar)
48 { 38 {
49 for (auto it = m_trackedLoadingRangeSets.begin(); it != m_trackedLoadingRang eSets.end(); ++it) { 39 for (auto it = m_trackedLoadingRangeSets.begin(); it != m_trackedLoadingRang eSets.end(); ++it) {
50 if ((*it)->contains(hintChar)) 40 if ((*it)->contains(hintChar))
51 return true; 41 return true;
52 } 42 }
53 return false; 43 return false;
54 } 44 }
55 45
56 bool FontFallbackIterator::rangeSetContributesForHint(const Vector<UChar32> hint List, const FontDataForRangeSet* segmentedFace) 46 bool FontFallbackIterator::rangeSetContributesForHint(const Vector<UChar32> hint List, const FontDataForRangeSet* segmentedFace)
57 { 47 {
58 for (auto it = hintList.begin(); it != hintList.end(); ++it) { 48 for (auto it = hintList.begin(); it != hintList.end(); ++it) {
59 if (segmentedFace->contains(*it)) { 49 if (segmentedFace->contains(*it)) {
60 if (!alreadyLoadingRangeForHintChar(*it)) 50 if (!alreadyLoadingRangeForHintChar(*it))
61 return true; 51 return true;
62 } 52 }
63 } 53 }
64 return false; 54 return false;
65 } 55 }
66 56
67 void FontFallbackIterator::willUseRange(const AtomicString& family, const FontDa taForRangeSet& rangeSet) 57 void FontFallbackIterator::willUseRange(const AtomicString& family, const FontDa taForRangeSet& rangeSet)
68 { 58 {
69 FontSelector* selector = m_fontFallbackList->getFontSelector(); 59 FontSelector* selector = m_fontFallbackList->getFontSelector();
70 if (!selector) 60 if (!selector)
71 return; 61 return;
72 62
73 selector->willUseRange(m_fontDescription, family, rangeSet); 63 selector->willUseRange(m_fontDescription, family, rangeSet);
74 } 64 }
75 65
66 const PassRefPtr<FontDataForRangeSet> FontFallbackIterator::uniqueOrNext(
67 PassRefPtr<FontDataForRangeSet> candidate,
68 const Vector<UChar32>& hintList) {
69 SkTypeface* candidateTypeface = candidate->fontData()->platformData().typefa ce();
70 if (!candidateTypeface)
71 return next(hintList);
72
73 uint32_t candidateId = candidateTypeface->uniqueID();
74 if (m_uniqueFontDataForRangeSetsReturned.contains(candidateId)) {
behdad 2016/08/15 21:09:19 Shouldn't this be a while loop, skipping until som
drott 2016/08/23 18:20:31 Can you explain a bit more what you were expecting
75 return next(hintList);
76 }
77
78 // We don't want to skip subsetted ranges because HarfBuzzShaper's behavior
79 // depends on the subsetting.
80 if (candidate->isEntireRange())
81 m_uniqueFontDataForRangeSetsReturned.add(candidateId);
82 return candidate;
83 }
84
85
76 const PassRefPtr<FontDataForRangeSet> FontFallbackIterator::next(const Vector<UC har32>& hintList) 86 const PassRefPtr<FontDataForRangeSet> FontFallbackIterator::next(const Vector<UC har32>& hintList)
77 { 87 {
78 if (m_fallbackStage == OutOfLuck) 88 if (m_fallbackStage == OutOfLuck)
79 return adoptRef(new FontDataForRangeSet()); 89 return adoptRef(new FontDataForRangeSet());
80 90
81 if (m_fallbackStage == FallbackPriorityFonts) { 91 if (m_fallbackStage == FallbackPriorityFonts) {
82 // Only try one fallback priority font, 92 // Only try one fallback priority font,
83 // then proceed to regular system fallback. 93 // then proceed to regular system fallback.
84 m_fallbackStage = SystemFonts; 94 m_fallbackStage = SystemFonts;
85 RefPtr<FontDataForRangeSet> fallbackPriorityFontRange = adoptRef(new Fon tDataForRangeSet(fallbackPriorityFont(hintList[0]))); 95 RefPtr<FontDataForRangeSet> fallbackPriorityFontRange = adoptRef(new Fon tDataForRangeSet(fallbackPriorityFont(hintList[0])));
86 if (fallbackPriorityFontRange->hasFontData()) 96 if (fallbackPriorityFontRange->hasFontData())
87 return fallbackPriorityFontRange.release(); 97 return uniqueOrNext(fallbackPriorityFontRange.release(), hintList);
88 return next(hintList); 98 return next(hintList);
89 } 99 }
90 100
91 if (m_fallbackStage == SystemFonts) { 101 if (m_fallbackStage == SystemFonts) {
92 // We've reached pref + system fallback. 102 // We've reached pref + system fallback.
93 ASSERT(hintList.size()); 103 ASSERT(hintList.size());
94 RefPtr<SimpleFontData> systemFont = uniqueSystemFontForHint(hintList[0]) ; 104 RefPtr<SimpleFontData> systemFont = uniqueSystemFontForHint(hintList[0]) ;
95 if (systemFont) { 105 if (systemFont) {
96 // Fallback fonts are not retained in the FontDataCache. 106 // Fallback fonts are not retained in the FontDataCache.
97 return adoptRef(new FontDataForRangeSet(systemFont)); 107 return uniqueOrNext(adoptRef(new FontDataForRangeSet(systemFont)), h intList);
98 } 108 }
99 109
100 // If we don't have options from the system fallback anymore or had 110 // If we don't have options from the system fallback anymore or had
101 // previously returned them, we only have the last resort font left. 111 // previously returned them, we only have the last resort font left.
102 // TODO: crbug.com/42217 Improve this by doing the last run with a last 112 // TODO: crbug.com/42217 Improve this by doing the last run with a last
103 // resort font that has glyphs for everything, for example the Unicode 113 // resort font that has glyphs for everything, for example the Unicode
104 // LastResort font, not just Times or Arial. 114 // LastResort font, not just Times or Arial.
105 FontCache* fontCache = FontCache::fontCache(); 115 FontCache* fontCache = FontCache::fontCache();
106 m_fallbackStage = OutOfLuck; 116 m_fallbackStage = OutOfLuck;
107 RefPtr<SimpleFontData> lastResort = fontCache->getLastResortFallbackFont (m_fontDescription).get(); 117 RefPtr<SimpleFontData> lastResort = fontCache->getLastResortFallbackFont (m_fontDescription).get();
108 RELEASE_ASSERT(lastResort); 118 RELEASE_ASSERT(lastResort);
119 // Don't skip the LastResort font in uniqueOrNext() since HarfBuzzShaper
120 // needs to use this one to place missing glyph boxes.
109 return adoptRef(new FontDataForRangeSetFromCache(lastResort)); 121 return adoptRef(new FontDataForRangeSetFromCache(lastResort));
110 } 122 }
111 123
112 ASSERT(m_fallbackStage == FontGroupFonts 124 ASSERT(m_fallbackStage == FontGroupFonts
113 || m_fallbackStage == SegmentedFace); 125 || m_fallbackStage == SegmentedFace);
114 const FontData* fontData = m_fontFallbackList->fontDataAt( 126 const FontData* fontData = m_fontFallbackList->fontDataAt(
115 m_fontDescription, m_currentFontDataIndex); 127 m_fontDescription, m_currentFontDataIndex);
116 128
117 if (!fontData) { 129 if (!fontData) {
118 // If there is no fontData coming from the fallback list, it means 130 // If there is no fontData coming from the fallback list, it means
119 // we are now looking at system fonts, either for prioritized symbol 131 // we are now looking at system fonts, either for prioritized symbol
120 // or emoji fonts or by calling system fallback API. 132 // or emoji fonts or by calling system fallback API.
121 m_fallbackStage = isNonTextFallbackPriority(m_fontFallbackPriority) 133 m_fallbackStage = isNonTextFallbackPriority(m_fontFallbackPriority)
122 ? FallbackPriorityFonts 134 ? FallbackPriorityFonts
123 : SystemFonts; 135 : SystemFonts;
124 return next(hintList); 136 return next(hintList);
125 } 137 }
126 138
127 // Otherwise we've received a fontData from the font-family: set of fonts, 139 // Otherwise we've received a fontData from the font-family: set of fonts,
128 // and a non-segmented one in this case. 140 // and a non-segmented one in this case.
129 if (!fontData->isSegmented()) { 141 if (!fontData->isSegmented()) {
130 // Skip forward to the next font family for the next call to next(). 142 // Skip forward to the next font family for the next call to next().
131 m_currentFontDataIndex++; 143 m_currentFontDataIndex++;
132 if (!fontData->isLoading()) { 144 if (!fontData->isLoading()) {
133 RefPtr<SimpleFontData> nonSegmented = const_cast<SimpleFontData*>(to SimpleFontData(fontData)); 145 RefPtr<SimpleFontData> nonSegmented = const_cast<SimpleFontData*>(to SimpleFontData(fontData));
134 // The fontData object that we have here is tracked in m_fontList of 146 // The fontData object that we have here is tracked in m_fontList of
135 // FontFallbackList and gets released in the font cache when the 147 // FontFallbackList and gets released in the font cache when the
136 // FontFallbackList is destroyed. 148 // FontFallbackList is destroyed.
137 return adoptRef(new FontDataForRangeSet(nonSegmented)); 149 return uniqueOrNext(adoptRef(new FontDataForRangeSet(nonSegmented)), hintList);
138 } 150 }
139 return next(hintList); 151 return next(hintList);
140 } 152 }
141 153
142 // Iterate over ranges of a segmented font below. 154 // Iterate over ranges of a segmented font below.
143 155
144 const SegmentedFontData* segmented = toSegmentedFontData(fontData); 156 const SegmentedFontData* segmented = toSegmentedFontData(fontData);
145 if (m_fallbackStage != SegmentedFace) { 157 if (m_fallbackStage != SegmentedFace) {
146 m_segmentedFaceIndex = 0; 158 m_segmentedFaceIndex = 0;
147 m_fallbackStage = SegmentedFace; 159 m_fallbackStage = SegmentedFace;
148 } 160 }
149 161
150 ASSERT(m_segmentedFaceIndex < segmented->numFaces()); 162 ASSERT(m_segmentedFaceIndex < segmented->numFaces());
151 RefPtr<FontDataForRangeSet> currentSegmentedFace = segmented->faceAt(m_segme ntedFaceIndex); 163 RefPtr<FontDataForRangeSet> currentSegmentedFace = segmented->faceAt(m_segme ntedFaceIndex);
152 m_segmentedFaceIndex++; 164 m_segmentedFaceIndex++;
153 165
154 if (m_segmentedFaceIndex == segmented->numFaces()) { 166 if (m_segmentedFaceIndex == segmented->numFaces()) {
155 // Switch from iterating over a segmented face to the next family from 167 // Switch from iterating over a segmented face to the next family from
156 // the font-family: group of fonts. 168 // the font-family: group of fonts.
157 m_fallbackStage = FontGroupFonts; 169 m_fallbackStage = FontGroupFonts;
158 m_currentFontDataIndex++; 170 m_currentFontDataIndex++;
159 } 171 }
160 172
161 if (rangeSetContributesForHint(hintList, currentSegmentedFace.get())) { 173 if (rangeSetContributesForHint(hintList, currentSegmentedFace.get())) {
162 const SimpleFontData* fontData = currentSegmentedFace->fontData(); 174 const SimpleFontData* fontData = currentSegmentedFace->fontData();
163 if (const CustomFontData* customFontData = fontData->customFontData()) 175 if (const CustomFontData* customFontData = fontData->customFontData())
164 customFontData->beginLoadIfNeeded(); 176 customFontData->beginLoadIfNeeded();
165 if (!fontData->isLoading()) 177 if (!fontData->isLoading())
166 return currentSegmentedFace; 178 return uniqueOrNext(currentSegmentedFace, hintList);
167 m_trackedLoadingRangeSets.append(currentSegmentedFace); 179 m_trackedLoadingRangeSets.append(currentSegmentedFace);
168 } 180 }
169 181
170 return next(hintList); 182 return next(hintList);
171 } 183 }
172 184
173 const PassRefPtr<SimpleFontData> FontFallbackIterator::fallbackPriorityFont( 185 const PassRefPtr<SimpleFontData> FontFallbackIterator::fallbackPriorityFont(
174 UChar32 hint) 186 UChar32 hint)
175 { 187 {
176 return FontCache::fontCache()->fallbackFontForCharacter( 188 return FontCache::fontCache()->fallbackFontForCharacter(
(...skipping 10 matching lines...) Expand all
187 // already. 199 // already.
188 if (!hint || m_previouslyAskedForHint.contains(hint)) 200 if (!hint || m_previouslyAskedForHint.contains(hint))
189 return nullptr; 201 return nullptr;
190 202
191 FontCache* fontCache = FontCache::fontCache(); 203 FontCache* fontCache = FontCache::fontCache();
192 m_previouslyAskedForHint.add(hint); 204 m_previouslyAskedForHint.add(hint);
193 return fontCache->fallbackFontForCharacter(m_fontDescription, hint, m_fontFa llbackList->primarySimpleFontData(m_fontDescription)); 205 return fontCache->fallbackFontForCharacter(m_fontDescription, hint, m_fontFa llbackList->primarySimpleFontData(m_fontDescription));
194 } 206 }
195 207
196 } // namespace blink 208 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698