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 "config.h" | 5 #include "config.h" |
6 #include "platform/fonts/FontFallbackIterator.h" | 6 #include "platform/fonts/FontFallbackIterator.h" |
7 | 7 |
8 #include "platform/Logging.h" | 8 #include "platform/Logging.h" |
9 #include "platform/fonts/FontCache.h" | 9 #include "platform/fonts/FontCache.h" |
10 #include "platform/fonts/FontDescription.h" | 10 #include "platform/fonts/FontDescription.h" |
(...skipping 21 matching lines...) Expand all Loading... |
32 bool FontFallbackIterator::needsHintList() const | 32 bool FontFallbackIterator::needsHintList() const |
33 { | 33 { |
34 if (m_fallbackStage != FontGroupFonts && m_fallbackStage != SegmentedFace) { | 34 if (m_fallbackStage != FontGroupFonts && m_fallbackStage != SegmentedFace) { |
35 return false; | 35 return false; |
36 } | 36 } |
37 | 37 |
38 const FontData* fontData = m_fontFallbackList->fontDataAt(m_fontDescription,
m_currentFontDataIndex); | 38 const FontData* fontData = m_fontFallbackList->fontDataAt(m_fontDescription,
m_currentFontDataIndex); |
39 return fontData && fontData->isSegmented(); | 39 return fontData && fontData->isSegmented(); |
40 } | 40 } |
41 | 41 |
42 static bool rangeContributesForHint(const Vector<UChar32> hintList, const FontDa
taRange& fontDataRange) | 42 bool FontFallbackIterator::alreadyLoadingRangeForHintChar(UChar32 hintChar) |
| 43 { |
| 44 for (auto it = m_loadingCustomFontForRanges.begin(); it != m_loadingCustomFo
ntForRanges.end(); ++it) { |
| 45 if (it->contains(hintChar)) |
| 46 return true; |
| 47 } |
| 48 return false; |
| 49 } |
| 50 |
| 51 bool FontFallbackIterator::rangeContributesForHint(const Vector<UChar32> hintLis
t, const FontDataRange& fontDataRange) |
43 { | 52 { |
44 for (auto it = hintList.begin(); it != hintList.end(); ++it) { | 53 for (auto it = hintList.begin(); it != hintList.end(); ++it) { |
45 if (*it >= fontDataRange.from() && *it <= fontDataRange.to()) { | 54 if (*it >= fontDataRange.from() && *it <= fontDataRange.to()) { |
46 return true; | 55 if (!alreadyLoadingRangeForHintChar(*it)) |
| 56 return true; |
47 } | 57 } |
48 } | 58 } |
49 return false; | 59 return false; |
50 } | 60 } |
51 | 61 |
52 void FontFallbackIterator::willUseRange(const AtomicString& family, const FontDa
taRange& range) | 62 void FontFallbackIterator::willUseRange(const AtomicString& family, const FontDa
taRange& range) |
53 { | 63 { |
54 FontSelector* selector = m_fontFallbackList->fontSelector(); | 64 FontSelector* selector = m_fontFallbackList->fontSelector(); |
55 if (!selector) | 65 if (!selector) |
56 return; | 66 return; |
57 | 67 |
58 selector->willUseRange(m_fontDescription, family, range); | 68 selector->willUseRange(m_fontDescription, family, range); |
59 } | 69 } |
60 | 70 |
61 const SimpleFontData* FontFallbackIterator::next(const Vector<UChar32>& hintList
) | 71 const FontDataRange FontFallbackIterator::next(const Vector<UChar32>& hintList) |
62 { | 72 { |
63 if (m_fallbackStage == OutOfLuck) | 73 if (m_fallbackStage == OutOfLuck) |
64 return nullptr; | 74 return FontDataRange(); |
65 | 75 |
66 const FontData* fontData = m_fontFallbackList->fontDataAt(m_fontDescription,
m_currentFontDataIndex); | 76 const FontData* fontData = m_fontFallbackList->fontDataAt(m_fontDescription,
m_currentFontDataIndex); |
67 | 77 |
| 78 // If there is no fontData coming from the fallback list, it means |
| 79 // we have reached the system fallback stage. |
68 if (!fontData) { | 80 if (!fontData) { |
69 m_fallbackStage = SystemFonts; | 81 m_fallbackStage = SystemFonts; |
70 // We've reached pref + system fallback. | 82 // We've reached pref + system fallback. |
71 ASSERT(hintList.size()); | 83 ASSERT(hintList.size()); |
72 const SimpleFontData* systemFont = uniqueSystemFontForHint(hintList[0]); | 84 RefPtr<SimpleFontData> systemFont = uniqueSystemFontForHint(hintList[0])
; |
73 if (systemFont) | 85 if (systemFont) |
74 return systemFont; | 86 return FontDataRange(systemFont); |
75 | 87 |
76 // If we don't have options from the system fallback anymore or had | 88 // If we don't have options from the system fallback anymore or had |
77 // previously returned them, we only have the last resort font left. | 89 // previously returned them, we only have the last resort font left. |
78 // TODO: crbug.com/42217 Improve this by doing the last run with a last | 90 // TODO: crbug.com/42217 Improve this by doing the last run with a last |
79 // resort font that has glyphs for everything, for example the Unicode | 91 // resort font that has glyphs for everything, for example the Unicode |
80 // LastResort font, not just Times or Arial. | 92 // LastResort font, not just Times or Arial. |
81 FontCache* fontCache = FontCache::fontCache(); | 93 FontCache* fontCache = FontCache::fontCache(); |
82 m_fallbackStage = OutOfLuck; | 94 m_fallbackStage = OutOfLuck; |
83 SimpleFontData* lastResort = fontCache->getLastResortFallbackFont(m_font
Description).get(); | 95 RefPtr<SimpleFontData> lastResort = fontCache->getLastResortFallbackFont
(m_fontDescription).get(); |
84 RELEASE_ASSERT(lastResort); | 96 RELEASE_ASSERT(lastResort); |
85 return lastResort; | 97 return FontDataRange(lastResort); |
86 } | 98 } |
87 | 99 |
| 100 // Otherwise we've received a fontData from the font-family: set of fonts, |
| 101 // and a non-segmented one in this case. |
88 if (!fontData->isSegmented()) { | 102 if (!fontData->isSegmented()) { |
89 // Skip forward to the next font family for the next call to next(). | 103 // Skip forward to the next font family for the next call to next(). |
90 m_currentFontDataIndex++; | 104 m_currentFontDataIndex++; |
91 m_currentFamily = m_currentFamily->next(); | 105 m_currentFamily = m_currentFamily->next(); |
92 return toSimpleFontData(fontData); | 106 if (!fontData->isLoading()) { |
| 107 RefPtr<SimpleFontData> nonSegmented = const_cast<SimpleFontData*>(to
SimpleFontData(fontData)); |
| 108 // TODO crbug.com/546465: Investigate if we might need to do |
| 109 // something like |
| 110 // toSimpleFontData(fontData)->customFontData()->beginLoadIfNeeded() |
| 111 // here to trigger loading. |
| 112 return FontDataRange(nonSegmented); |
| 113 } |
| 114 return next(hintList); |
93 } | 115 } |
94 | 116 |
95 // Iterate over ranges of a segmented font below. | 117 // Iterate over ranges of a segmented font below. |
96 | 118 |
97 const SegmentedFontData* segmented = toSegmentedFontData(fontData); | 119 const SegmentedFontData* segmented = toSegmentedFontData(fontData); |
98 if (m_fallbackStage != SegmentedFace) { | 120 if (m_fallbackStage != SegmentedFace) { |
99 m_segmentedIndex = 0; | 121 m_segmentedIndex = 0; |
100 m_fallbackStage = SegmentedFace; | 122 m_fallbackStage = SegmentedFace; |
101 } | 123 } |
102 | 124 |
103 ASSERT(m_segmentedIndex < segmented->numRanges()); | 125 ASSERT(m_segmentedIndex < segmented->numRanges()); |
104 FontDataRange currentRange = segmented->rangeAt(m_segmentedIndex); | 126 FontDataRange currentRange = segmented->rangeAt(m_segmentedIndex); |
105 m_segmentedIndex++; | 127 m_segmentedIndex++; |
106 AtomicString segmentedFamily = m_currentFamily->family(); | 128 AtomicString segmentedFamily = m_currentFamily->family(); |
107 | 129 |
108 if (m_segmentedIndex == segmented->numRanges()) { | 130 if (m_segmentedIndex == segmented->numRanges()) { |
109 // Switch from iterating over a segmented face to the next family from | 131 // Switch from iterating over a segmented face to the next family from |
110 // the font-family: group of fonts. | 132 // the font-family: group of fonts. |
111 m_fallbackStage = FontGroupFonts; | 133 m_fallbackStage = FontGroupFonts; |
112 m_currentFontDataIndex++; | 134 m_currentFontDataIndex++; |
113 m_currentFamily = m_currentFamily->next(); | 135 m_currentFamily = m_currentFamily->next(); |
114 } | 136 } |
115 | 137 |
116 if (rangeContributesForHint(hintList, currentRange)) { | 138 if (rangeContributesForHint(hintList, currentRange)) { |
117 willUseRange(segmentedFamily, currentRange); | 139 willUseRange(segmentedFamily, currentRange); |
118 return currentRange.fontData().get(); | 140 if (!currentRange.fontData()->isLoading()) |
| 141 return currentRange; |
| 142 m_loadingCustomFontForRanges.append(currentRange); |
119 } | 143 } |
120 | 144 |
121 return next(hintList); | 145 return next(hintList); |
122 } | 146 } |
123 | 147 |
124 const SimpleFontData* FontFallbackIterator::uniqueSystemFontForHint(UChar32 hint
) | 148 const PassRefPtr<SimpleFontData> FontFallbackIterator::uniqueSystemFontForHint(U
Char32 hint) |
125 { | 149 { |
126 FontCache* fontCache = FontCache::fontCache(); | 150 FontCache* fontCache = FontCache::fontCache(); |
127 | 151 |
128 // When we're asked for a fallback for the same characters again, we give up | 152 // When we're asked for a fallback for the same characters again, we give up |
129 // because the shaper must have previously tried shaping with the font | 153 // because the shaper must have previously tried shaping with the font |
130 // already. | 154 // already. |
131 if (m_visitedSystemFonts.find(hint) != m_visitedSystemFonts.end()) { | 155 if (m_visitedSystemFonts.find(hint) != m_visitedSystemFonts.end()) { |
132 return nullptr; | 156 return nullptr; |
133 } | 157 } |
134 | 158 |
135 RefPtr<SimpleFontData> fallbackFont = fontCache->fallbackFontForCharacter(m_
fontDescription, hint, m_fontFallbackList->primarySimpleFontData(m_fontDescripti
on)); | 159 RefPtr<SimpleFontData> fallbackFont = fontCache->fallbackFontForCharacter(m_
fontDescription, hint, m_fontFallbackList->primarySimpleFontData(m_fontDescripti
on)); |
136 | 160 |
137 return m_visitedSystemFonts.add(hint, fallbackFont).storedValue->value.get()
; | 161 return m_visitedSystemFonts.add(hint, fallbackFont).storedValue->value; |
138 } | 162 } |
139 | 163 |
140 } // namespace blink | 164 } // namespace blink |
OLD | NEW |