const GrStencilAndCoverTextContext::TextBlob& GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob, const SkPaint& skPaint) { // The font-related parameters are baked into the text blob and will override this skPaint, so // the only remaining properties that can affect a TextBlob are the ones related to stroke. if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path. if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) { fLRUList.remove(*found); fLRUList.addToTail(*found); return **found; } TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint, fContext, &fSurfaceProps); this->purgeToFit(*blob); fBlobIdCache.set(skBlob->uniqueID(), blob); fLRUList.addToTail(blob); fCacheSize += blob->cpuMemorySize(); return *blob; } else { GrStrokeInfo stroke(skPaint); SkSTArray<4, uint32_t, true> key; key.reset(1 + stroke.computeUniqueKeyFragmentData32Cnt()); key[0] = skBlob->uniqueID(); stroke.asUniqueKeyFragment(&key[1]); if (TextBlob** found = fBlobKeyCache.find(key)) { fLRUList.remove(*found); fLRUList.addToTail(*found); return **found; } TextBlob* blob = new TextBlob(key, skBlob, skPaint, fContext, &fSurfaceProps); this->purgeToFit(*blob); fBlobKeyCache.set(blob); fLRUList.addToTail(blob); fCacheSize += blob->cpuMemorySize(); return *blob; } }
void GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) { static const size_t maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for caching text blobs. size_t maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize(); while (fCacheSize && fCacheSize > maxSizeForNewBlob) { TextBlob* lru = fLRUList.head(); if (1 == lru->key().count()) { // 1-length keys are unterstood to be the blob id. fBlobIdCache.remove(lru->key()[0]); } else { fBlobKeyCache.remove(lru->key()); } fLRUList.remove(lru); fCacheSize -= lru->cpuMemorySize(); delete lru; } }