void FontFallbackList::determinePitch(const FontDescription& fontDescription) const { for (unsigned fontIndex = 0; ; ++fontIndex) { const FontData* fontData = fontDataAt(fontDescription, fontIndex); if (!fontData) { // All fonts are custom fonts and are loading. Fallback should be variable pitch. m_pitch = VariablePitch; break; } const SimpleFontData* simpleFontData; if (fontData->isSegmented()) { const SegmentedFontData* segmentedFontData = toSegmentedFontData(fontData); if (segmentedFontData->numRanges() != 1 || !segmentedFontData->rangeAt(0).isEntireRange()) { m_pitch = VariablePitch; break; } simpleFontData = segmentedFontData->rangeAt(0).fontData().get(); } else { simpleFontData = toSimpleFontData(fontData); } if (!fontData->isLoadingFallback()) { m_pitch = simpleFontData->pitch(); break; } } }
void FontGlyphs::releaseFontData() { unsigned numFonts = m_realizedFontData.size(); for (unsigned i = 0; i < numFonts; ++i) { if (m_realizedFontData[i]->isCustomFont()) continue; ASSERT(!m_realizedFontData[i]->isSegmented()); fontCache().releaseFontData(toSimpleFontData(m_realizedFontData[i])); } }
void FontFallbackList::releaseFontData() { unsigned numFonts = m_fontList.size(); for (unsigned i = 0; i < numFonts; ++i) { if (!m_fontList[i]->isCustomFont()) { ASSERT(!m_fontList[i]->isSegmented()); FontCache::fontCache()->releaseFontData(toSimpleFontData(m_fontList[i])); } } }
void FontGlyphs::determinePitch(const FontDescription& description) const { const FontData* fontData = primaryFontData(description); if (!fontData->isSegmented()) m_pitch = toSimpleFontData(*fontData).pitch(); else { const SegmentedFontData& segmentedFontData = toSegmentedFontData(*fontData); unsigned numRanges = segmentedFontData.numRanges(); if (numRanges == 1) m_pitch = segmentedFontData.rangeAt(0).fontData()->pitch(); else m_pitch = VariablePitch; } }
const FontDataForRangeSet FontFallbackIterator::next(const Vector<UChar32>& hintList) { if (m_fallbackStage == OutOfLuck) return FontDataForRangeSet(); if (m_fallbackStage == FallbackPriorityFonts) { // Only try one fallback priority font, // then proceed to regular system fallback. m_fallbackStage = SystemFonts; FontDataForRangeSet fallbackPriorityFontRange(fallbackPriorityFont(hintList[0])); if (fallbackPriorityFontRange.hasFontData()) return fallbackPriorityFontRange; return next(hintList); } if (m_fallbackStage == SystemFonts) { // We've reached pref + system fallback. ASSERT(hintList.size()); RefPtr<SimpleFontData> systemFont = uniqueSystemFontForHint(hintList[0]); if (systemFont) return FontDataForRangeSet(systemFont); // If we don't have options from the system fallback anymore or had // previously returned them, we only have the last resort font left. // TODO: crbug.com/42217 Improve this by doing the last run with a last // resort font that has glyphs for everything, for example the Unicode // LastResort font, not just Times or Arial. FontCache* fontCache = FontCache::fontCache(); m_fallbackStage = OutOfLuck; RefPtr<SimpleFontData> lastResort = fontCache->getLastResortFallbackFont(m_fontDescription).get(); RELEASE_ASSERT(lastResort); return FontDataForRangeSet(lastResort); } ASSERT(m_fallbackStage == FontGroupFonts || m_fallbackStage == SegmentedFace); const FontData* fontData = m_fontFallbackList->fontDataAt( m_fontDescription, m_currentFontDataIndex); if (!fontData) { // If there is no fontData coming from the fallback list, it means // we are now looking at system fonts, either for prioritized symbol // or emoji fonts or by calling system fallback API. m_fallbackStage = isNonTextFallbackPriority(m_fontFallbackPriority) ? FallbackPriorityFonts : SystemFonts; return next(hintList); } // Otherwise we've received a fontData from the font-family: set of fonts, // and a non-segmented one in this case. if (!fontData->isSegmented()) { // Skip forward to the next font family for the next call to next(). m_currentFontDataIndex++; if (!fontData->isLoading()) { RefPtr<SimpleFontData> nonSegmented = const_cast<SimpleFontData*>(toSimpleFontData(fontData)); return FontDataForRangeSet(nonSegmented); } return next(hintList); } // Iterate over ranges of a segmented font below. const SegmentedFontData* segmented = toSegmentedFontData(fontData); if (m_fallbackStage != SegmentedFace) { m_segmentedFaceIndex = 0; m_fallbackStage = SegmentedFace; } ASSERT(m_segmentedFaceIndex < segmented->numFaces()); FontDataForRangeSet currentSegmentedFace = segmented->faceAt(m_segmentedFaceIndex); m_segmentedFaceIndex++; if (m_segmentedFaceIndex == segmented->numFaces()) { // Switch from iterating over a segmented face to the next family from // the font-family: group of fonts. m_fallbackStage = FontGroupFonts; m_currentFontDataIndex++; } if (rangeSetContributesForHint(hintList, currentSegmentedFace)) { if (currentSegmentedFace.fontData()->customFontData()) currentSegmentedFace.fontData()->customFontData()->beginLoadIfNeeded(); if (!currentSegmentedFace.fontData()->isLoading()) return currentSegmentedFace; m_trackedLoadingRangeSets.append(currentSegmentedFace); } return next(hintList); }