SkTypeface* SkFontMgr_Indirect::createTypefaceFromFontId(const SkFontIdentity& id) const { if (id.fDataId == SkFontIdentity::kInvalidDataId) { return nullptr; } SkAutoMutexAcquire ama(fDataCacheMutex); SkAutoTUnref<SkTypeface> dataTypeface; int dataTypefaceIndex = 0; for (int i = 0; i < fDataCache.count(); ++i) { const DataEntry& entry = fDataCache[i]; if (entry.fDataId == id.fDataId) { if (entry.fTtcIndex == id.fTtcIndex && !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref()) { return entry.fTypeface; } if (dataTypeface.get() == nullptr && !entry.fTypeface->weak_expired() && entry.fTypeface->try_ref()) { dataTypeface.reset(entry.fTypeface); dataTypefaceIndex = entry.fTtcIndex; } } if (entry.fTypeface->weak_expired()) { fDataCache.removeShuffle(i); --i; } } // No exact match, but did find a data match. if (dataTypeface.get() != nullptr) { SkAutoTDelete<SkStreamAsset> stream(dataTypeface->openStream(nullptr)); if (stream.get() != nullptr) { return fImpl->createFromStream(stream.release(), dataTypefaceIndex); } } // No data match, request data and add entry. SkAutoTDelete<SkStreamAsset> stream(fProxy->getData(id.fDataId)); if (stream.get() == nullptr) { return nullptr; } SkAutoTUnref<SkTypeface> typeface(fImpl->createFromStream(stream.release(), id.fTtcIndex)); if (typeface.get() == nullptr) { return nullptr; } DataEntry& newEntry = fDataCache.push_back(); typeface->weak_ref(); newEntry.fDataId = id.fDataId; newEntry.fTtcIndex = id.fTtcIndex; newEntry.fTypeface = typeface.get(); // weak reference passed to new entry. return typeface.release(); }