diff options
-rw-r--r-- | include/gpu/GrGlyph.h | 6 | ||||
-rw-r--r-- | src/gpu/GrAtlas.cpp | 196 | ||||
-rw-r--r-- | src/gpu/GrAtlas.h | 81 | ||||
-rw-r--r-- | src/gpu/GrRectanizer.cpp | 6 | ||||
-rw-r--r-- | src/gpu/GrRectanizer.h | 2 | ||||
-rw-r--r-- | src/gpu/GrTextContext.cpp | 12 | ||||
-rw-r--r-- | src/gpu/GrTextStrike.cpp | 36 | ||||
-rw-r--r-- | src/gpu/GrTextStrike.h | 16 |
8 files changed, 205 insertions, 150 deletions
diff --git a/include/gpu/GrGlyph.h b/include/gpu/GrGlyph.h index c730f24cce..fe4c835773 100644 --- a/include/gpu/GrGlyph.h +++ b/include/gpu/GrGlyph.h @@ -11,7 +11,7 @@ #include "GrRect.h" #include "SkPath.h" -class GrAtlas; +class GrPlot; /* Need this to be quad-state: - complete w/ image @@ -22,14 +22,14 @@ class GrAtlas; struct GrGlyph { typedef uint32_t PackedID; - GrAtlas* fAtlas; + GrPlot* fPlot; SkPath* fPath; PackedID fPackedID; GrIRect16 fBounds; GrIPoint16 fAtlasLocation; void init(GrGlyph::PackedID packed, const SkIRect& bounds) { - fAtlas = NULL; + fPlot = NULL; fPath = NULL; fPackedID = packed; fBounds.set(bounds); diff --git a/src/gpu/GrAtlas.cpp b/src/gpu/GrAtlas.cpp index b3340a02d9..e33ec6519e 100644 --- a/src/gpu/GrAtlas.cpp +++ b/src/gpu/GrAtlas.cpp @@ -6,13 +6,10 @@ * found in the LICENSE file. */ - - #include "GrAtlas.h" #include "GrContext.h" #include "GrGpu.h" #include "GrRectanizer.h" -#include "GrPlotMgr.h" #if 0 #define GR_PLOT_WIDTH 8 @@ -50,70 +47,34 @@ static int g_UploadCount = 0; #endif -GrAtlas::GrAtlas(GrAtlasMgr* mgr, int plotX, int plotY, int bpp) : - fDrawToken(NULL, 0) { - fAtlasMgr = mgr; // just a pointer, not an owner - fNext = NULL; - - fTexture = mgr->getTexture(); // we're not an owner, just a pointer - fPlot.set(plotX, plotY); - +GrPlot::GrPlot() : fDrawToken(NULL, 0) + , fNext(NULL) + , fTexture(NULL) + , fAtlasMgr(NULL) + , fBytesPerPixel(1) +{ fRects = GrRectanizer::Factory(GR_ATLAS_WIDTH - BORDER, GR_ATLAS_HEIGHT - BORDER); - - fBytesPerPixel = bpp; - -#ifdef SK_DEBUG -// GrPrintf(" GrAtlas %p [%d %d] %d\n", this, plotX, plotY, gCounter); - gCounter += 1; -#endif + fOffset.set(0, 0); } -GrAtlas::~GrAtlas() { - fAtlasMgr->freePlot(fPlot.fX, fPlot.fY); - +GrPlot::~GrPlot() { delete fRects; - -#ifdef SK_DEBUG - --gCounter; -// GrPrintf("~GrAtlas %p [%d %d] %d\n", this, fPlot.fX, fPlot.fY, gCounter); -#endif } -bool GrAtlas::RemoveUnusedAtlases(GrAtlasMgr* atlasMgr, GrAtlas** startAtlas) { - // GrAtlas** is used so that a pointer to the head element can be passed in and - // modified when the first element is deleted - GrAtlas** atlasRef = startAtlas; - GrAtlas* atlas = *startAtlas; - bool removed = false; - while (NULL != atlas) { - if (atlas->drawToken().isIssued()) { - *atlasRef = atlas->fNext; - atlasMgr->deleteAtlas(atlas); - atlas = *atlasRef; - removed = true; - } else { - atlasRef = &atlas->fNext; - atlas = atlas->fNext; - } - } - - return removed; -} - -static void adjustForPlot(GrIPoint16* loc, const GrIPoint16& plot) { - loc->fX += plot.fX * GR_ATLAS_WIDTH; - loc->fY += plot.fY * GR_ATLAS_HEIGHT; +static void adjust_for_offset(GrIPoint16* loc, const GrIPoint16& offset) { + loc->fX += offset.fX * GR_ATLAS_WIDTH; + loc->fY += offset.fY * GR_ATLAS_HEIGHT; } -static uint8_t* zerofill(uint8_t* ptr, int count) { +static uint8_t* zero_fill(uint8_t* ptr, int count) { while (--count >= 0) { *ptr++ = 0; } return ptr; } -bool GrAtlas::addSubImage(int width, int height, const void* image, +bool GrPlot::addSubImage(int width, int height, const void* image, GrIPoint16* loc) { if (!fRects->addRect(width + BORDER, height + BORDER, loc)) { return false; @@ -128,16 +89,16 @@ bool GrAtlas::addSubImage(int width, int height, const void* image, sk_bzero(dst, dstRB); // zero top row dst += dstRB; for (int y = 0; y < height; y++) { - dst = zerofill(dst, fBytesPerPixel); // zero left edge + dst = zero_fill(dst, fBytesPerPixel); // zero left edge memcpy(dst, image, width * fBytesPerPixel); dst += width * fBytesPerPixel; - dst = zerofill(dst, fBytesPerPixel); // zero right edge + dst = zero_fill(dst, fBytesPerPixel); // zero right edge image = (const void*)((const char*)image + width * fBytesPerPixel); } sk_bzero(dst, dstRB); // zero bottom row image = storage.get(); } - adjustForPlot(loc, fPlot); + adjust_for_offset(loc, fOffset); GrContext* context = fTexture->getContext(); // We pass the flag that does not force a flush. We assume our caller is // smart and hasn't referenced the part of the texture we're about to update @@ -165,12 +126,30 @@ GrAtlasMgr::GrAtlasMgr(GrGpu* gpu, GrPixelConfig config) { fPixelConfig = config; gpu->ref(); fTexture = NULL; - fPlotMgr = SkNEW_ARGS(GrPlotMgr, (GR_PLOT_WIDTH, GR_PLOT_HEIGHT)); + + // set up allocated plots + int bpp = GrBytesPerPixel(fPixelConfig); + fPlots = SkNEW_ARRAY(GrPlot, (GR_PLOT_WIDTH*GR_PLOT_HEIGHT)); + fFreePlots = NULL; + GrPlot* currPlot = fPlots; + for (int y = GR_PLOT_HEIGHT-1; y >= 0; --y) { + for (int x = GR_PLOT_WIDTH-1; x >= 0; --x) { + currPlot->fAtlasMgr = this; + currPlot->fOffset.set(x, y); + currPlot->fBytesPerPixel = bpp; + + // add to free list + currPlot->fNext = fFreePlots; + fFreePlots = currPlot; + + ++currPlot; + } + } } GrAtlasMgr::~GrAtlasMgr() { SkSafeUnref(fTexture); - delete fPlotMgr; + SkDELETE_ARRAY(fPlots); fGpu->unref(); #if FONT_CACHE_STATS @@ -178,23 +157,22 @@ GrAtlasMgr::~GrAtlasMgr() { #endif } -GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas, - int width, int height, const void* image, - GrIPoint16* loc) { - // iterate through entire atlas list, see if we can find a hole - GrAtlas* atlasIter = *atlas; - while (atlasIter) { - if (atlasIter->addSubImage(width, height, image, loc)) { - return atlasIter; +GrPlot* GrAtlasMgr::addToAtlas(GrAtlas* atlas, + int width, int height, const void* image, + GrIPoint16* loc) { + // iterate through entire plot list, see if we can find a hole + GrPlot* plotIter = atlas->fPlots; + while (plotIter) { + if (plotIter->addSubImage(width, height, image, loc)) { + return plotIter; } - atlasIter = atlasIter->fNext; + plotIter = plotIter->fNext; } - // If the above fails, then either we have no starting atlas, or the current - // atlas list is full. Either way we need to allocate a new atlas - - GrIPoint16 plot; - if (!fPlotMgr->newPlot(&plot)) { + // If the above fails, then either we have no starting plot, or the current + // plot list is full. Either way we need to allocate a new plot + GrPlot* newPlot = this->allocPlot(); + if (NULL == newPlot) { return NULL; } @@ -211,22 +189,74 @@ GrAtlas* GrAtlasMgr::addToAtlas(GrAtlas** atlas, return NULL; } } - - int bpp = GrBytesPerPixel(fPixelConfig); - GrAtlas* newAtlas = SkNEW_ARGS(GrAtlas, (this, plot.fX, plot.fY, bpp)); - if (!newAtlas->addSubImage(width, height, image, loc)) { - delete newAtlas; + // be sure to set texture for fast lookup + newPlot->fTexture = fTexture; + + if (!newPlot->addSubImage(width, height, image, loc)) { + this->freePlot(newPlot); return NULL; } - // new atlas, put at head - newAtlas->fNext = *atlas; - *atlas = newAtlas; + // new plot, put at head + newPlot->fNext = atlas->fPlots; + atlas->fPlots = newPlot; - return newAtlas; + return newPlot; +} + +bool GrAtlasMgr::removeUnusedPlots(GrAtlas* atlas) { + // GrPlot** is used so that the head element can be easily + // modified when the first element is deleted + GrPlot** plotRef = &atlas->fPlots; + GrPlot* plot = atlas->fPlots; + bool removed = false; + while (NULL != plot) { + if (plot->drawToken().isIssued()) { + *plotRef = plot->fNext; + this->freePlot(plot); + plot = *plotRef; + removed = true; + } else { + plotRef = &plot->fNext; + plot = plot->fNext; + } + } + + return removed; } -void GrAtlasMgr::freePlot(int x, int y) { - SkASSERT(fPlotMgr->isBusy(x, y)); - fPlotMgr->freePlot(x, y); +void GrAtlasMgr::deletePlotList(GrPlot* plot) { + while (NULL != plot) { + GrPlot* next = plot->fNext; + this->freePlot(plot); + plot = next; + } +} + +GrPlot* GrAtlasMgr::allocPlot() { + if (NULL == fFreePlots) { + return NULL; + } else { + GrPlot* alloc = fFreePlots; + fFreePlots = alloc->fNext; +#ifdef SK_DEBUG +// GrPrintf(" GrPlot %p [%d %d] %d\n", this, alloc->fOffset.fX, alloc->fOffset.fY, gCounter); + gCounter += 1; +#endif + return alloc; + } + +} + +void GrAtlasMgr::freePlot(GrPlot* plot) { + SkASSERT(this == plot->fAtlasMgr); + + plot->fRects->reset(); + plot->fNext = fFreePlots; + fFreePlots = plot; + +#ifdef SK_DEBUG + --gCounter; +// GrPrintf("~GrPlot %p [%d %d] %d\n", this, plot->fOffset.fX, plot->fOffset.fY, gCounter); +#endif } diff --git a/src/gpu/GrAtlas.h b/src/gpu/GrAtlas.h index b2acaee8e2..d06bba1435 100644 --- a/src/gpu/GrAtlas.h +++ b/src/gpu/GrAtlas.h @@ -6,11 +6,10 @@ * found in the LICENSE file. */ - - #ifndef GrAtlas_DEFINED #define GrAtlas_DEFINED + #include "GrPoint.h" #include "GrTexture.h" #include "GrDrawTarget.h" @@ -18,69 +17,93 @@ class GrGpu; class GrRectanizer; class GrAtlasMgr; - -class GrAtlas { +class GrAtlas; + +// The backing GrTexture for a set of GrAtlases is broken into a spatial grid of GrPlots. When +// a GrAtlas needs space on the texture, it requests a GrPlot. Each GrAtlas can claim one +// or more GrPlots. The GrPlots keep track of subimage placement via their GrRectanizer. Once a +// GrPlot is "full" (i.e. there is no room for the new subimage according to the GrRectanizer), the +// GrAtlas can request a new GrPlot via GrAtlasMgr::addToAtlas(). +// +// If all GrPlots are allocated, the replacement strategy is up to the client. The drawToken is +// available to ensure that all draw calls are finished for that particular GrPlot. +// GrAtlasMgr::removeUnusedPlots() will free up any finished plots for a given GrAtlas. + +class GrPlot { public: - int getPlotX() const { return fPlot.fX; } - int getPlotY() const { return fPlot.fY; } + int getOffsetX() const { return fOffset.fX; } + int getOffsetY() const { return fOffset.fY; } GrTexture* texture() const { return fTexture; } bool addSubImage(int width, int height, const void*, GrIPoint16*); - static void FreeLList(GrAtlas* atlas) { - while (NULL != atlas) { - GrAtlas* next = atlas->fNext; - delete atlas; - atlas = next; - } - } - - static bool RemoveUnusedAtlases(GrAtlasMgr* atlasMgr, GrAtlas** startAtlas); - GrDrawTarget::DrawToken drawToken() const { return fDrawToken; } void setDrawToken(GrDrawTarget::DrawToken draw) { fDrawToken = draw; } private: - GrAtlas(GrAtlasMgr*, int plotX, int plotY, int bpp); - ~GrAtlas(); // does not try to delete the fNext field + GrPlot(); + ~GrPlot(); // does not try to delete the fNext field // for recycling GrDrawTarget::DrawToken fDrawToken; - GrAtlas* fNext; + GrPlot* fNext; GrTexture* fTexture; GrRectanizer* fRects; GrAtlasMgr* fAtlasMgr; - GrIPoint16 fPlot; + GrIPoint16 fOffset; int fBytesPerPixel; friend class GrAtlasMgr; }; -class GrPlotMgr; - class GrAtlasMgr { public: GrAtlasMgr(GrGpu*, GrPixelConfig); ~GrAtlasMgr(); - GrAtlas* addToAtlas(GrAtlas**, int width, int height, const void*, GrIPoint16*); - void deleteAtlas(GrAtlas* atlas) { delete atlas; } - + // add subimage of width, height dimensions to atlas + // returns the containing GrPlot and location relative to the backing texture + GrPlot* addToAtlas(GrAtlas*, int width, int height, const void*, GrIPoint16*); + + // free up any plots that are not waiting on a draw call + bool removeUnusedPlots(GrAtlas* atlas); + + // to be called by ~GrAtlas() + void deletePlotList(GrPlot* plot); + GrTexture* getTexture() const { return fTexture; } - // to be called by ~GrAtlas() - void freePlot(int x, int y); - private: + GrPlot* allocPlot(); + void freePlot(GrPlot* plot); + GrGpu* fGpu; GrPixelConfig fPixelConfig; GrTexture* fTexture; - GrPlotMgr* fPlotMgr; + + // allocated array of GrPlots + GrPlot* fPlots; + // linked list of free GrPlots + GrPlot* fFreePlots; +}; + +class GrAtlas { +public: + GrAtlas(GrAtlasMgr* mgr) : fPlots(NULL), fAtlasMgr(mgr) { } + ~GrAtlas() { fAtlasMgr->deletePlotList(fPlots); } + + bool isEmpty() { return NULL == fPlots; } + +private: + GrPlot* fPlots; + GrAtlasMgr* fAtlasMgr; + + friend class GrAtlasMgr; }; #endif diff --git a/src/gpu/GrRectanizer.cpp b/src/gpu/GrRectanizer.cpp index 7b49530366..418bf196bc 100644 --- a/src/gpu/GrRectanizer.cpp +++ b/src/gpu/GrRectanizer.cpp @@ -24,6 +24,12 @@ public: virtual ~GrRectanizerPow2() { } + virtual void reset() { + fNextStripY = 0; + fAreaSoFar = 0; + sk_bzero(fRows, sizeof(fRows)); + } + virtual bool addRect(int w, int h, GrIPoint16* loc); virtual float percentFull() const { diff --git a/src/gpu/GrRectanizer.h b/src/gpu/GrRectanizer.h index dc479f1c8d..c1ac2c129e 100644 --- a/src/gpu/GrRectanizer.h +++ b/src/gpu/GrRectanizer.h @@ -26,6 +26,8 @@ public: virtual ~GrRectanizer() {} + virtual void reset() = 0; + int width() const { return fWidth; } int height() const { return fHeight; } diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index e4303c1d7c..b050305908 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -139,7 +139,7 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, GrFixed height = glyph->fBounds.height(); // check if we clipped out - if (true || NULL == glyph->fAtlas) { + if (true || NULL == glyph->fPlot) { int x = vx >> 16; int y = vy >> 16; if (fClipRect.quickReject(x, y, x + width, y + height)) { @@ -149,13 +149,13 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, } GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); - if (NULL == glyph->fAtlas) { + if (NULL == glyph->fPlot) { if (fStrike->getGlyphAtlas(glyph, scaler, drawToken)) { goto HAS_ATLAS; } - // try to clear out an unused atlas before we flush - fContext->getFontCache()->freeAtlasExceptFor(fStrike); + // try to clear out an unused plot before we flush + fContext->getFontCache()->freePlotExceptFor(fStrike); if (fStrike->getGlyphAtlas(glyph, scaler, drawToken)) { goto HAS_ATLAS; } @@ -193,13 +193,13 @@ void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, } HAS_ATLAS: - SkASSERT(glyph->fAtlas); + SkASSERT(glyph->fPlot); // now promote them to fixed (TODO: Rethink using fixed pt). width = SkIntToFixed(width); height = SkIntToFixed(height); - GrTexture* texture = glyph->fAtlas->texture(); + GrTexture* texture = glyph->fPlot->texture(); SkASSERT(texture); if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { diff --git a/src/gpu/GrTextStrike.cpp b/src/gpu/GrTextStrike.cpp index d1f1861abd..e399c91f6c 100644 --- a/src/gpu/GrTextStrike.cpp +++ b/src/gpu/GrTextStrike.cpp @@ -103,7 +103,7 @@ void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { strike = strikeToPurge->fPrev; if (purge) { // keep purging if we won't free up any atlases with this strike. - purge = (NULL == strikeToPurge->fAtlas); + purge = strikeToPurge->fAtlas.isEmpty(); int index = fCache.slowFindIndex(strikeToPurge); SkASSERT(index >= 0); fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()); @@ -116,7 +116,7 @@ void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { #endif } -void GrFontCache::freeAtlasExceptFor(GrTextStrike* preserveStrike) { +void GrFontCache::freePlotExceptFor(GrTextStrike* preserveStrike) { SkASSERT(NULL != preserveStrike); GrTextStrike* strike = fTail; GrMaskFormat maskFormat = preserveStrike->fMaskFormat; @@ -127,8 +127,8 @@ void GrFontCache::freeAtlasExceptFor(GrTextStrike* preserveStrike) { } GrTextStrike* strikeToPurge = strike; strike = strikeToPurge->fPrev; - if (strikeToPurge->removeUnusedAtlases()) { - if (NULL == strikeToPurge->fAtlas) { + if (strikeToPurge->removeUnusedPlots()) { + if (strikeToPurge->fAtlas.isEmpty()) { int index = fCache.slowFindIndex(strikeToPurge); SkASSERT(index >= 0); fCache.removeAt(index, strikeToPurge->fFontScalerKey->getHash()); @@ -186,13 +186,12 @@ void GrFontCache::validate() const { GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, GrMaskFormat format, - GrAtlasMgr* atlasMgr) : fPool(64) { + GrAtlasMgr* atlasMgr) : fPool(64), fAtlas(atlasMgr) { fFontScalerKey = key; fFontScalerKey->ref(); fFontCache = cache; // no need to ref, it won't go away before we do fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do - fAtlas = NULL; fMaskFormat = format; @@ -207,13 +206,12 @@ GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, static void free_glyph(GrGlyph*& glyph) { glyph->free(); } static void invalidate_glyph(GrGlyph*& glyph) { - if (glyph->fAtlas && glyph->fAtlas->drawToken().isIssued()) { - glyph->fAtlas = NULL; + if (glyph->fPlot && glyph->fPlot->drawToken().isIssued()) { + glyph->fPlot = NULL; } } GrTextStrike::~GrTextStrike() { - GrAtlas::FreeLList(fAtlas); fFontScalerKey->unref(); fCache.getArray().visitAll(free_glyph); @@ -236,9 +234,9 @@ GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, return glyph; } -bool GrTextStrike::removeUnusedAtlases() { +bool GrTextStrike::removeUnusedPlots() { fCache.getArray().visitAll(invalidate_glyph); - return GrAtlas::RemoveUnusedAtlases(fAtlasMgr, &fAtlas); + return fAtlasMgr->removeUnusedPlots(&fAtlas); } bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler, @@ -251,8 +249,8 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler, SkASSERT(glyph); SkASSERT(scaler); SkASSERT(fCache.contains(glyph)); - if (glyph->fAtlas) { - glyph->fAtlas->setDrawToken(currentDrawToken); + if (glyph->fPlot) { + glyph->fPlot->setDrawToken(currentDrawToken); return true; } @@ -268,14 +266,14 @@ bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler, return false; } - GrAtlas* atlas = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(), - glyph->height(), storage.get(), - &glyph->fAtlasLocation); - if (NULL == atlas) { + GrPlot* plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(), + glyph->height(), storage.get(), + &glyph->fAtlasLocation); + if (NULL == plot) { return false; } - glyph->fAtlas = atlas; - atlas->setDrawToken(currentDrawToken); + glyph->fPlot = plot; + plot->setDrawToken(currentDrawToken); return true; } diff --git a/src/gpu/GrTextStrike.h b/src/gpu/GrTextStrike.h index 66bbb0d93c..2f52d98704 100644 --- a/src/gpu/GrTextStrike.h +++ b/src/gpu/GrTextStrike.h @@ -17,8 +17,8 @@ #include "GrPoint.h" #include "GrGlyph.h" #include "GrDrawTarget.h" +#include "GrAtlas.h" -class GrAtlasMgr; class GrFontCache; class GrGpu; class GrFontPurgeListener; @@ -45,10 +45,9 @@ public: const GrGlyph* glyphAt(int index) const { return fCache.getArray()[index]; } - GrAtlas* getAtlas() const { return fAtlas; } - // returns true if an atlas was removed - bool removeUnusedAtlases(); + // returns true if a plot was removed + bool removeUnusedPlots(); public: // for LRU @@ -63,13 +62,11 @@ private: GrFontCache* fFontCache; GrAtlasMgr* fAtlasMgr; - GrAtlas* fAtlas; // linklist + GrAtlas fAtlas; GrMaskFormat fMaskFormat; GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler); - // returns true if after the purge, the strike is empty - bool purgeAtlasAtY(GrAtlas* atlas, int yCoord); friend class GrFontCache; }; @@ -85,8 +82,8 @@ public: void purgeExceptFor(GrTextStrike*); - // remove an unused atlas and its strike (if necessary) - void freeAtlasExceptFor(GrTextStrike*); + // remove an unused plot and its strike (if necessary) + void freePlotExceptFor(GrTextStrike*); // testing int countStrikes() const { return fCache.getArray().count(); } @@ -113,7 +110,6 @@ private: GrGpu* fGpu; GrAtlasMgr* fAtlasMgr[kMaskFormatCount]; - GrTextStrike* generateStrike(GrFontScaler*, const Key&); inline void detachStrikeFromList(GrTextStrike*); }; |