Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |