void GrBatchFontCache::HandleEviction(GrBatchAtlas::AtlasID id, void* ptr) { GrBatchFontCache* fontCache = reinterpret_cast<GrBatchFontCache*>(ptr); SkTDynamicHash<GrBatchTextStrike, GrFontDescKey>::Iter iter(&fontCache->fCache); for (; !iter.done(); ++iter) { GrBatchTextStrike* strike = &*iter; strike->removeID(id); // clear out any empty strikes. We will preserve the strike whose call to addToAtlas // triggered the eviction if (strike != fontCache->fPreserveStrike && 0 == strike->fAtlasedGlyphs) { fontCache->fCache.remove(*(strike->fFontScalerKey)); SkDELETE(strike); } } }
void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target, GrBatchFontCache* fontCache, GrBlobRegenHelper *helper, Run* run, Run::SubRunInfo* info, SkGlyphCache** cache, SkTypeface** typeface, GrFontScaler** scaler, const SkDescriptor** desc, int glyphCount, size_t vertexStride, GrColor color, SkScalar transX, SkScalar transY) const { static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along regenGlyphs"); GrBatchTextStrike* strike = nullptr; if (regenTexCoords) { info->resetBulkUseToken(); // We can reuse if we have a valid strike and our descriptors / typeface are the // same. The override descriptor is only for the non distance field text within // a run const SkDescriptor* newDesc = (run->fOverrideDescriptor && !info->drawAsDistanceFields()) ? run->fOverrideDescriptor->getDesc() : run->fDescriptor.getDesc(); if (!*cache || !SkTypeface::Equal(*typeface, run->fTypeface) || !((*desc)->equals(*newDesc))) { if (*cache) { SkGlyphCache::AttachCache(*cache); } *desc = newDesc; *cache = SkGlyphCache::DetachCache(run->fTypeface, run->fEffects, *desc); *scaler = GrTextUtils::GetGrFontScaler(*cache); *typeface = run->fTypeface; } if (regenGlyphs) { strike = fontCache->getStrike(*scaler); } else { strike = info->strike(); } } bool brokenRun = false; for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) { GrGlyph* glyph = nullptr; int log2Width = 0, log2Height = 0; if (regenTexCoords) { size_t glyphOffset = glyphIdx + info->glyphStartIndex(); if (regenGlyphs) { // Get the id from the old glyph, and use the new strike to lookup // the glyph. GrGlyph::PackedID id = fGlyphs[glyphOffset]->fPackedID; fGlyphs[glyphOffset] = strike->getGlyph(id, info->maskFormat(), *scaler); SkASSERT(id == fGlyphs[glyphOffset]->fPackedID); } glyph = fGlyphs[glyphOffset]; SkASSERT(glyph && glyph->fMaskFormat == info->maskFormat()); if (!fontCache->hasGlyph(glyph) && !strike->addGlyphToAtlas(target, glyph, *scaler, info->maskFormat())) { helper->flush(); brokenRun = glyphIdx > 0; SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target, glyph, *scaler, info->maskFormat()); SkASSERT(success); } fontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph, target->nextDrawToken()); log2Width = fontCache->log2Width(info->maskFormat()); log2Height = fontCache->log2Height(info->maskFormat()); } intptr_t vertex = reinterpret_cast<intptr_t>(fVertices); vertex += info->vertexStartIndex(); vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph; regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertexStride, info->drawAsDistanceFields(), transX, transY, log2Width, log2Height, color); helper->incGlyphCount(); }
inline void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Blob* blob, Run* run, TextInfo* info, SkGlyphCache** cache, SkTypeface** typeface, GrFontScaler** scaler, const SkDescriptor** desc, const GrGeometryProcessor* gp, int glyphCount, size_t vertexStride, GrColor color, SkScalar transX, SkScalar transY) const { static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along regenGlyphs"); GrBatchTextStrike* strike = nullptr; if (regenTexCoords) { info->fBulkUseToken.reset(); // We can reuse if we have a valid strike and our descriptors / typeface are the // same. The override descriptor is only for the non distance field text within // a run const SkDescriptor* newDesc = (run->fOverrideDescriptor && !this->usesDistanceFields()) ? run->fOverrideDescriptor->getDesc() : run->fDescriptor.getDesc(); if (!*cache || !SkTypeface::Equal(*typeface, run->fTypeface) || !((*desc)->equals(*newDesc))) { if (*cache) { SkGlyphCache::AttachCache(*cache); } *desc = newDesc; *cache = SkGlyphCache::DetachCache(run->fTypeface, *desc); *scaler = GrTextContext::GetGrFontScaler(*cache); strike = info->fStrike; *typeface = run->fTypeface; } if (regenGlyphs) { strike = fFontCache->getStrike(*scaler); } else { strike = info->fStrike; } } bool brokenRun = false; for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) { GrGlyph* glyph = nullptr; if (regenTexCoords) { size_t glyphOffset = glyphIdx + info->fGlyphStartIndex; if (regenGlyphs) { // Get the id from the old glyph, and use the new strike to lookup // the glyph. GrGlyph::PackedID id = blob->fGlyphs[glyphOffset]->fPackedID; blob->fGlyphs[glyphOffset] = strike->getGlyph(id, this->maskFormat(), *scaler); SkASSERT(id == blob->fGlyphs[glyphOffset]->fPackedID); } glyph = blob->fGlyphs[glyphOffset]; SkASSERT(glyph && glyph->fMaskFormat == this->maskFormat()); if (!fFontCache->hasGlyph(glyph) && !strike->addGlyphToAtlas(target, glyph, *scaler, this->maskFormat())) { this->flush(target, flushInfo); target->initDraw(gp, this->pipeline()); brokenRun = glyphIdx > 0; SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target, glyph, *scaler, this->maskFormat()); SkASSERT(success); } fFontCache->addGlyphToBulkAndSetUseToken(&info->fBulkUseToken, glyph, target->currentToken()); } intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices); vertex += info->fVertexStartIndex; vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph; regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertexStride, this->usesDistanceFields(), transX, transY, color); flushInfo->fGlyphsToFlush++; }
void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target, GrBatchFontCache* fontCache, GrBlobRegenHelper *helper, Run* run, Run::SubRunInfo* info, SkAutoGlyphCache* lazyCache, int glyphCount, size_t vertexStride, GrColor color, SkScalar transX, SkScalar transY) const { SkASSERT(lazyCache); static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along regenGlyphs"); GrBatchTextStrike* strike = nullptr; if (regenTexCoords) { info->resetBulkUseToken(); const SkDescriptor* desc = (run->fOverrideDescriptor && !info->drawAsDistanceFields()) ? run->fOverrideDescriptor->getDesc() : run->fDescriptor.getDesc(); if (!*lazyCache || (*lazyCache)->getDescriptor() != *desc) { SkScalerContextEffects effects; effects.fPathEffect = run->fPathEffect.get(); effects.fRasterizer = run->fRasterizer.get(); effects.fMaskFilter = run->fMaskFilter.get(); lazyCache->reset(SkGlyphCache::DetachCache(run->fTypeface, effects, desc)); } if (regenGlyphs) { strike = fontCache->getStrike(lazyCache->get()); } else { strike = info->strike(); } } bool brokenRun = false; for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) { GrGlyph* glyph = nullptr; int log2Width = 0, log2Height = 0; if (regenTexCoords) { size_t glyphOffset = glyphIdx + info->glyphStartIndex(); if (regenGlyphs) { // Get the id from the old glyph, and use the new strike to lookup // the glyph. GrGlyph::PackedID id = fGlyphs[glyphOffset]->fPackedID; fGlyphs[glyphOffset] = strike->getGlyph(id, info->maskFormat(), lazyCache->get()); SkASSERT(id == fGlyphs[glyphOffset]->fPackedID); } glyph = fGlyphs[glyphOffset]; SkASSERT(glyph && glyph->fMaskFormat == info->maskFormat()); if (!fontCache->hasGlyph(glyph) && !strike->addGlyphToAtlas(target, glyph, lazyCache->get(), info->maskFormat())) { helper->flush(); brokenRun = glyphIdx > 0; SkDEBUGCODE(bool success =) strike->addGlyphToAtlas(target, glyph, lazyCache->get(), info->maskFormat()); SkASSERT(success); } fontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph, target->nextDrawToken()); log2Width = fontCache->log2Width(info->maskFormat()); log2Height = fontCache->log2Height(info->maskFormat()); } intptr_t vertex = reinterpret_cast<intptr_t>(fVertices); vertex += info->vertexStartIndex(); vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph; regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertexStride, info->drawAsDistanceFields(), transX, transY, log2Width, log2Height, color); helper->incGlyphCount(); }