| Index: src/core/SkGlyphCache.cpp
|
| diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
|
| index 57c54bfc1ec3f7f35d3c499ba14c26abe99bcdcf..31f2485da2052e186a8346130952de6f569b7b21 100755
|
| --- a/src/core/SkGlyphCache.cpp
|
| +++ b/src/core/SkGlyphCache.cpp
|
| @@ -40,24 +40,13 @@ static SkGlyphCache_Globals& getGlobals() {
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| -#ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
|
| - #define RecordHashSuccess() fHashHitCount += 1
|
| - #define RecordHashCollisionIf(pred) do { if (pred) fHashMissCount += 1; } while (0)
|
| -#else
|
| - #define RecordHashSuccess() (void)0
|
| - #define RecordHashCollisionIf(pred) (void)0
|
| -#endif
|
| -#define RecordHashCollision() RecordHashCollisionIf(true)
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| // so we don't grow our arrays a lot
|
| #define kMinGlyphCount 16
|
| #define kMinGlyphImageSize (16*2)
|
| #define kMinAllocAmount ((sizeof(SkGlyph) + kMinGlyphImageSize) * kMinGlyphCount)
|
|
|
| SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkScalerContext* ctx)
|
| - : fScalerContext(ctx), fGlyphAlloc(kMinAllocAmount) {
|
| + : fScalerContext(ctx), fAlloc(kMinAllocAmount) {
|
| SkASSERT(typeface);
|
| SkASSERT(desc);
|
| SkASSERT(ctx);
|
| @@ -67,70 +56,20 @@ SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkSca
|
| fDesc = desc->copy();
|
| fScalerContext->getFontMetrics(&fFontMetrics);
|
|
|
| - // init to 0 so that all of the pointers will be null
|
| - memset(fGlyphHash, 0, sizeof(fGlyphHash));
|
| -
|
| fMemoryUsed = sizeof(*this);
|
|
|
| - fGlyphArray.setReserve(kMinGlyphCount);
|
| -
|
| fAuxProcList = NULL;
|
| -
|
| -#ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
|
| - fHashHitCount = fHashMissCount = 0;
|
| -#endif
|
| }
|
|
|
| -SkGlyphCache::~SkGlyphCache() {
|
| -#if 0
|
| - {
|
| - size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*);
|
| - size_t glyphAlloc = fGlyphAlloc.totalCapacity();
|
| - size_t glyphHashUsed = 0;
|
| - size_t uniHashUsed = 0;
|
| - for (int i = 0; i < kHashCount; ++i) {
|
| - glyphHashUsed += fGlyphHash[i] ? sizeof(fGlyphHash[0]) : 0;
|
| - uniHashUsed += fCharToGlyphHash[i].fID != 0xFFFFFFFF ? sizeof(fCharToGlyphHash[0]) : 0;
|
| - }
|
| - size_t glyphUsed = fGlyphArray.count() * sizeof(SkGlyph);
|
| - size_t imageUsed = 0;
|
| - for (int i = 0; i < fGlyphArray.count(); ++i) {
|
| - const SkGlyph& g = *fGlyphArray[i];
|
| - if (g.fImage) {
|
| - imageUsed += g.fHeight * g.rowBytes();
|
| - }
|
| - }
|
| +static void delete_path(uint32_t, SkGlyph* glyph) { SkDELETE(glyph->fPath); }
|
|
|
| - SkDebugf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, glyphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n",
|
| - ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), glyphHashUsed, sizeof(CharGlyphRec) * kHashCount, uniHashUsed);
|
| -
|
| - }
|
| -#endif
|
| - SkGlyph** gptr = fGlyphArray.begin();
|
| - SkGlyph** stop = fGlyphArray.end();
|
| - while (gptr < stop) {
|
| - SkPath* path = (*gptr)->fPath;
|
| - if (path) {
|
| - SkDELETE(path);
|
| - }
|
| - gptr += 1;
|
| - }
|
| +SkGlyphCache::~SkGlyphCache() {
|
| + fGlyphs.foreach(delete_path);
|
| SkDescriptor::Free(fDesc);
|
| SkDELETE(fScalerContext);
|
| this->invokeAndRemoveAuxProcs();
|
| }
|
|
|
| -SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) {
|
| - if (NULL == fCharToGlyphHash.get()) {
|
| - fCharToGlyphHash.reset(kHashCount);
|
| - // init with 0xFF so that the charCode field will be -1, which is invalid
|
| - memset(fCharToGlyphHash.get(), 0xFF,
|
| - sizeof(CharGlyphRec) * kHashCount);
|
| - }
|
| -
|
| - return &fCharToGlyphHash[ID2HashIndex(id)];
|
| -}
|
| -
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| #ifdef SK_DEBUG
|
| @@ -141,14 +80,12 @@ SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) {
|
|
|
| uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) {
|
| VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(charCode);
|
| - const CharGlyphRec& rec = *this->getCharGlyphRec(id);
|
| -
|
| - if (rec.fID == id) {
|
| - return rec.fGlyph->getGlyphID();
|
| - } else {
|
| - return fScalerContext->charToGlyphID(charCode);
|
| + if (const uint16_t* glyphID = fCharToGlyphID.find(charCode)) {
|
| + return *glyphID;
|
| }
|
| + uint16_t glyphID = fScalerContext->charToGlyphID(charCode);
|
| + fCharToGlyphID.set(charCode, glyphID);
|
| + return glyphID;
|
| }
|
|
|
| SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) {
|
| @@ -159,179 +96,66 @@ unsigned SkGlyphCache::getGlyphCount() {
|
| return fScalerContext->getGlyphCount();
|
| }
|
|
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) {
|
| - VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(charCode);
|
| - CharGlyphRec* rec = this->getCharGlyphRec(id);
|
| -
|
| - if (rec->fID != id) {
|
| - // this ID is based on the UniChar
|
| - rec->fID = id;
|
| - // this ID is based on the glyph index
|
| - id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode));
|
| - rec->fGlyph = this->lookupMetrics(id, kJustAdvance_MetricsType);
|
| - }
|
| - return *rec->fGlyph;
|
| + return this->getGlyphIDAdvance(this->unicharToGlyph(charCode));
|
| }
|
| -
|
| -const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) {
|
| - VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(glyphID);
|
| - unsigned index = ID2HashIndex(id);
|
| - SkGlyph* glyph = fGlyphHash[index];
|
| -
|
| - if (NULL == glyph || glyph->fID != id) {
|
| - glyph = this->lookupMetrics(glyphID, kJustAdvance_MetricsType);
|
| - fGlyphHash[index] = glyph;
|
| - }
|
| - return *glyph;
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////
|
| -
|
| const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) {
|
| - VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(charCode);
|
| - CharGlyphRec* rec = this->getCharGlyphRec(id);
|
| -
|
| - if (rec->fID != id) {
|
| - RecordHashCollisionIf(rec->fGlyph != NULL);
|
| - // this ID is based on the UniChar
|
| - rec->fID = id;
|
| - // this ID is based on the glyph index
|
| - id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode));
|
| - rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType);
|
| - } else {
|
| - RecordHashSuccess();
|
| - if (rec->fGlyph->isJustAdvance()) {
|
| - fScalerContext->getMetrics(rec->fGlyph);
|
| - }
|
| - }
|
| - SkASSERT(rec->fGlyph->isFullMetrics());
|
| - return *rec->fGlyph;
|
| + return this->getGlyphIDMetrics(this->unicharToGlyph(charCode));
|
| +}
|
| +const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, SkFixed x, SkFixed y) {
|
| + return this->getGlyphIDMetrics(this->unicharToGlyph(charCode), x, y);
|
| }
|
|
|
| -const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode,
|
| - SkFixed x, SkFixed y) {
|
| +const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) {
|
| VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(charCode, x, y);
|
| - CharGlyphRec* rec = this->getCharGlyphRec(id);
|
| -
|
| - if (rec->fID != id) {
|
| - RecordHashCollisionIf(rec->fGlyph != NULL);
|
| - // this ID is based on the UniChar
|
| - rec->fID = id;
|
| - // this ID is based on the glyph index
|
| - id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y);
|
| - rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType);
|
| - } else {
|
| - RecordHashSuccess();
|
| - if (rec->fGlyph->isJustAdvance()) {
|
| - fScalerContext->getMetrics(rec->fGlyph);
|
| - }
|
| - }
|
| - SkASSERT(rec->fGlyph->isFullMetrics());
|
| - return *rec->fGlyph;
|
| + const SkGlyph* glyph =
|
| + this->lookupMetrics(SkGlyph::MakeID(glyphID), kJustAdvance_MetricsType);
|
| + SkASSERT(glyph);
|
| + return *glyph;
|
| }
|
|
|
| const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) {
|
| VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(glyphID);
|
| - unsigned index = ID2HashIndex(id);
|
| - SkGlyph* glyph = fGlyphHash[index];
|
| -
|
| - if (NULL == glyph || glyph->fID != id) {
|
| - RecordHashCollisionIf(glyph != NULL);
|
| - glyph = this->lookupMetrics(glyphID, kFull_MetricsType);
|
| - fGlyphHash[index] = glyph;
|
| - } else {
|
| - RecordHashSuccess();
|
| - if (glyph->isJustAdvance()) {
|
| - fScalerContext->getMetrics(glyph);
|
| - }
|
| - }
|
| + const SkGlyph* glyph =
|
| + this->lookupMetrics(SkGlyph::MakeID(glyphID), kFull_MetricsType);
|
| + SkASSERT(glyph);
|
| SkASSERT(glyph->isFullMetrics());
|
| return *glyph;
|
| }
|
|
|
| const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFixed y) {
|
| VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(glyphID, x, y);
|
| - unsigned index = ID2HashIndex(id);
|
| - SkGlyph* glyph = fGlyphHash[index];
|
| -
|
| - if (NULL == glyph || glyph->fID != id) {
|
| - RecordHashCollisionIf(glyph != NULL);
|
| - glyph = this->lookupMetrics(id, kFull_MetricsType);
|
| - fGlyphHash[index] = glyph;
|
| - } else {
|
| - RecordHashSuccess();
|
| - if (glyph->isJustAdvance()) {
|
| - fScalerContext->getMetrics(glyph);
|
| - }
|
| - }
|
| + const SkGlyph* glyph =
|
| + this->lookupMetrics(SkGlyph::MakeID(glyphID, x, y), kFull_MetricsType);
|
| + SkASSERT(glyph);
|
| SkASSERT(glyph->isFullMetrics());
|
| return *glyph;
|
| }
|
|
|
| SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) {
|
| - SkGlyph* glyph;
|
| -
|
| - int hi = 0;
|
| - int count = fGlyphArray.count();
|
| -
|
| - if (count) {
|
| - SkGlyph** gptr = fGlyphArray.begin();
|
| - int lo = 0;
|
| -
|
| - hi = count - 1;
|
| - while (lo < hi) {
|
| - int mid = (hi + lo) >> 1;
|
| - if (gptr[mid]->fID < id) {
|
| - lo = mid + 1;
|
| - } else {
|
| - hi = mid;
|
| - }
|
| - }
|
| - glyph = gptr[hi];
|
| - if (glyph->fID == id) {
|
| - if (kFull_MetricsType == mtype && glyph->isJustAdvance()) {
|
| - fScalerContext->getMetrics(glyph);
|
| - }
|
| - return glyph;
|
| - }
|
| -
|
| - // check if we need to bump hi before falling though to the allocator
|
| - if (glyph->fID < id) {
|
| - hi += 1;
|
| + if (SkGlyph* glyph = fGlyphs.find(id)) {
|
| + if (kFull_MetricsType == mtype && glyph->isJustAdvance()) {
|
| + fScalerContext->getMetrics(glyph);
|
| }
|
| + return glyph;
|
| }
|
|
|
| - // not found, but hi tells us where to inser the new glyph
|
| - fMemoryUsed += sizeof(SkGlyph);
|
| -
|
| - glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph),
|
| - SkChunkAlloc::kThrow_AllocFailType);
|
| - glyph->init(id);
|
| - *fGlyphArray.insert(hi) = glyph;
|
| -
|
| + SkGlyph glyph;
|
| + glyph.init(id);
|
| if (kJustAdvance_MetricsType == mtype) {
|
| - fScalerContext->getAdvance(glyph);
|
| + fScalerContext->getAdvance(&glyph);
|
| } else {
|
| SkASSERT(kFull_MetricsType == mtype);
|
| - fScalerContext->getMetrics(glyph);
|
| + fScalerContext->getMetrics(&glyph);
|
| }
|
| -
|
| - return glyph;
|
| + return fGlyphs.set(id, glyph);
|
| }
|
|
|
| const void* SkGlyphCache::findImage(const SkGlyph& glyph) {
|
| if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) {
|
| if (NULL == glyph.fImage) {
|
| size_t size = glyph.computeImageSize();
|
| - const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size,
|
| + const_cast<SkGlyph&>(glyph).fImage = fAlloc.alloc(size,
|
| SkChunkAlloc::kReturnNil_AllocFailType);
|
| // check that alloc() actually succeeded
|
| if (glyph.fImage) {
|
| @@ -374,11 +198,7 @@ void SkGlyphCache::dump() const {
|
| matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewX],
|
| matrix[SkMatrix::kMSkewY], matrix[SkMatrix::kMScaleY],
|
| rec.fLumBits & 0xFF, rec.fDeviceGamma, rec.fPaintGamma, rec.fContrast,
|
| - fGlyphArray.count());
|
| -#ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
|
| - const int sum = SkTMax(fHashHitCount + fHashMissCount, 1); // avoid divide-by-zero
|
| - msg.appendf(" hash:%2d\n", 100 * fHashHitCount / sum);
|
| -#endif
|
| + fGlyphs.count());
|
| SkDebugf("%s\n", msg.c_str());
|
| }
|
|
|
| @@ -548,21 +368,9 @@ void SkGlyphCache::Dump() {
|
| SkDebugf("SkGlyphCache strikes:%d memory:%d\n",
|
| globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed());
|
|
|
| -#ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
|
| - int hitCount = 0;
|
| - int missCount = 0;
|
| -#endif
|
| -
|
| for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) {
|
| -#ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
|
| - hitCount += cache->fHashHitCount;
|
| - missCount += cache->fHashMissCount;
|
| -#endif
|
| cache->dump();
|
| }
|
| -#ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
|
| - SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount));
|
| -#endif
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -674,20 +482,6 @@ void SkGlyphCache_Globals::internalDetachCache(SkGlyphCache* cache) {
|
| #ifdef SK_DEBUG
|
|
|
| void SkGlyphCache::validate() const {
|
| -#ifdef SK_DEBUG_GLYPH_CACHE
|
| - int count = fGlyphArray.count();
|
| - for (int i = 0; i < count; i++) {
|
| - const SkGlyph* glyph = fGlyphArray[i];
|
| - SkASSERT(glyph);
|
| - SkASSERT(fGlyphAlloc.contains(glyph));
|
| - if (glyph->fImage) {
|
| - SkASSERT(fGlyphAlloc.contains(glyph->fImage));
|
| - }
|
| - if (glyph->fDistanceField) {
|
| - SkASSERT(fGlyphAlloc.contains(glyph->fDistanceField));
|
| - }
|
| - }
|
| -#endif
|
| }
|
|
|
| void SkGlyphCache_Globals::validate() const {
|
|
|