| Index: src/core/SkGlyphCache.cpp
|
| diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp
|
| index ae268d517c93491702d2763b3ebd6d0ed18006cc..9b0199f6cf9f3f23b253aa77ab56276376d13055 100755
|
| --- a/src/core/SkGlyphCache.cpp
|
| +++ b/src/core/SkGlyphCache.cpp
|
| @@ -9,10 +9,7 @@
|
| #include "SkGlyphCache_Globals.h"
|
| #include "SkGraphics.h"
|
| #include "SkLazyPtr.h"
|
| -#include "SkMutex.h"
|
| -#include "SkPaint.h"
|
| #include "SkPath.h"
|
| -#include "SkTLS.h"
|
| #include "SkTemplates.h"
|
| #include "SkTypeface.h"
|
|
|
| @@ -35,118 +32,52 @@ static SkGlyphCache_Globals& get_globals() {
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| -#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) {
|
| + : fDesc(desc->copy())
|
| + , fScalerContext(ctx)
|
| + , fGlyphAlloc(kMinAllocAmount) {
|
| SkASSERT(typeface);
|
| SkASSERT(desc);
|
| SkASSERT(ctx);
|
|
|
| fPrev = fNext = NULL;
|
|
|
| - fDesc = desc->copy();
|
| fScalerContext->getFontMetrics(&fFontMetrics);
|
|
|
| - // Create the sentinel SkGlyph.
|
| - SkGlyph* sentinel = fGlyphArray.insert(0);
|
| - sentinel->initGlyphFromCombinedID(SkGlyph::kImpossibleID);
|
| -
|
| - // Initialize all index to zero which points to the sentinel SkGlyph.
|
| - memset(fGlyphHash, 0x00, 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;
|
| + fGlyphMap.foreach(
|
| + [](SkGlyph* g) {
|
| + SkDELETE(g->fPath);
|
| }
|
| - 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();
|
| - }
|
| - }
|
| -
|
| - 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;
|
| - }
|
| + );
|
| SkDescriptor::Free(fDesc);
|
| SkDELETE(fScalerContext);
|
| this->invokeAndRemoveAuxProcs();
|
| }
|
|
|
| -SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) {
|
| - if (NULL == fCharToGlyphHash.get()) {
|
| +SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(PackedUnicharID packedUnicharID) {
|
| + if (NULL == fPackedUnicharIDToPackedGlyphID.get()) {
|
| // Allocate the array.
|
| - fCharToGlyphHash.reset(kHashCount);
|
| - // Initialize entries of fCharToGlyphHash to index the sentinel glyph and
|
| - // an fID value that will not match any id.
|
| + fPackedUnicharIDToPackedGlyphID.reset(kHashCount);
|
| + // Initialize array to map character and position with the impossible glyph ID. This
|
| + // represents no mapping.
|
| for (int i = 0; i <kHashCount; ++i) {
|
| - fCharToGlyphHash[i].fID = SkGlyph::kImpossibleID;
|
| - fCharToGlyphHash[i].fGlyphIndex = 0;
|
| + fPackedUnicharIDToPackedGlyphID[i].fPackedUnicharID = SkGlyph::kImpossibleID;
|
| + fPackedUnicharIDToPackedGlyphID[i].fPackedGlyphID = 0;
|
| }
|
| }
|
|
|
| - return &fCharToGlyphHash[ID2HashIndex(id)];
|
| -}
|
| -
|
| -void SkGlyphCache::adjustCaches(int insertion_index) {
|
| - for (int i = 0; i < kHashCount; ++i) {
|
| - if (fGlyphHash[i] >= SkToU16(insertion_index)) {
|
| - fGlyphHash[i] += 1;
|
| - }
|
| - }
|
| - if (fCharToGlyphHash.get() != NULL) {
|
| - for (int i = 0; i < kHashCount; ++i) {
|
| - if (fCharToGlyphHash[i].fGlyphIndex >= SkToU16(insertion_index)) {
|
| - fCharToGlyphHash[i].fGlyphIndex += 1;
|
| - }
|
| - }
|
| - }
|
| + return &fPackedUnicharIDToPackedGlyphID[SkChecksum::CheapMix(packedUnicharID) & kHashMask];
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -159,11 +90,11 @@ void SkGlyphCache::adjustCaches(int insertion_index) {
|
|
|
| uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) {
|
| VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(charCode);
|
| - const CharGlyphRec& rec = *this->getCharGlyphRec(id);
|
| + PackedUnicharID packedUnicharID = SkGlyph::MakeID(charCode);
|
| + const CharGlyphRec& rec = *this->getCharGlyphRec(packedUnicharID);
|
|
|
| - if (rec.fID == id) {
|
| - return fGlyphArray[rec.fGlyphIndex].getGlyphID();
|
| + if (rec.fPackedUnicharID == packedUnicharID) {
|
| + return SkGlyph::ID2Code(rec.fPackedGlyphID);
|
| } else {
|
| return fScalerContext->charToGlyphID(charCode);
|
| }
|
| @@ -186,8 +117,8 @@ const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) {
|
|
|
| const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) {
|
| VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(glyphID);
|
| - return *this->lookupByCombinedID(id, kJustAdvance_MetricsType);
|
| + PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID);
|
| + return *this->lookupByPackedGlyphID(packedGlyphID, kJustAdvance_MetricsType);
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -197,58 +128,44 @@ const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) {
|
| return *this->lookupByChar(charCode, kFull_MetricsType);
|
| }
|
|
|
| -const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode,
|
| - SkFixed x, SkFixed y) {
|
| +const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, SkFixed x, SkFixed y) {
|
| VALIDATE();
|
| return *this->lookupByChar(charCode, kFull_MetricsType, x, y);
|
| }
|
|
|
| const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) {
|
| VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(glyphID);
|
| - return *this->lookupByCombinedID(id, kFull_MetricsType);
|
| + PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID);
|
| + return *this->lookupByPackedGlyphID(packedGlyphID, kFull_MetricsType);
|
| }
|
|
|
| const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFixed y) {
|
| VALIDATE();
|
| - uint32_t id = SkGlyph::MakeID(glyphID, x, y);
|
| - return *this->lookupByCombinedID(id, kFull_MetricsType);
|
| + PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID, x, y);
|
| + return *this->lookupByPackedGlyphID(packedGlyphID, kFull_MetricsType);
|
| }
|
|
|
| SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixed x, SkFixed y) {
|
| - uint32_t id = SkGlyph::MakeID(charCode, x, y);
|
| + PackedUnicharID id = SkGlyph::MakeID(charCode, x, y);
|
| CharGlyphRec* rec = this->getCharGlyphRec(id);
|
| - SkGlyph* glyph;
|
| - if (rec->fID != id) {
|
| - RecordHashCollisionIf(glyph_index != SkGlyph::kImpossibleID);
|
| + if (rec->fPackedUnicharID != id) {
|
| // this ID is based on the UniChar
|
| - rec->fID = id;
|
| + rec->fPackedUnicharID = id;
|
| // this ID is based on the glyph index
|
| - id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y);
|
| - rec->fGlyphIndex = this->lookupMetrics(id, type);
|
| - glyph = &fGlyphArray[rec->fGlyphIndex];
|
| + PackedGlyphID combinedID = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y);
|
| + rec->fPackedGlyphID = combinedID;
|
| + return this->lookupByPackedGlyphID(combinedID, type);
|
| } else {
|
| - RecordHashSuccess();
|
| - glyph = &fGlyphArray[rec->fGlyphIndex];
|
| - if (type == kFull_MetricsType && glyph->isJustAdvance()) {
|
| - fScalerContext->getMetrics(glyph);
|
| - }
|
| + return this->lookupByPackedGlyphID(rec->fPackedGlyphID, type);
|
| }
|
| - return glyph;
|
| }
|
|
|
| -SkGlyph* SkGlyphCache::lookupByCombinedID(uint32_t id, MetricsType type) {
|
| - uint32_t hash_index = ID2HashIndex(id);
|
| - uint16_t glyph_index = fGlyphHash[hash_index];
|
| - SkGlyph* glyph = &fGlyphArray[glyph_index];
|
| +SkGlyph* SkGlyphCache::lookupByPackedGlyphID(PackedGlyphID packedGlyphID, MetricsType type) {
|
| + SkGlyph* glyph = fGlyphMap.find(packedGlyphID);
|
|
|
| - if (glyph->fID != id) {
|
| - RecordHashCollisionIf(glyph_index != SkGlyph::kImpossibleID);
|
| - glyph_index = this->lookupMetrics(id, type);
|
| - fGlyphHash[hash_index] = glyph_index;
|
| - glyph = &fGlyphArray[glyph_index];
|
| + if (NULL == glyph) {
|
| + glyph = this->allocateNewGlyph(packedGlyphID, type);
|
| } else {
|
| - RecordHashSuccess();
|
| if (type == kFull_MetricsType && glyph->isJustAdvance()) {
|
| fScalerContext->getMetrics(glyph);
|
| }
|
| @@ -256,55 +173,25 @@ SkGlyph* SkGlyphCache::lookupByCombinedID(uint32_t id, MetricsType type) {
|
| return glyph;
|
| }
|
|
|
| -uint16_t SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) {
|
| - SkASSERT(id != SkGlyph::kImpossibleID);
|
| - // Count is always greater than 0 because of the sentinel.
|
| - // The fGlyphArray cache is in descending order, so that the sentinel with a value of ~0 is
|
| - // always at index 0.
|
| - SkGlyph* gptr = fGlyphArray.begin();
|
| - int lo = 0;
|
| - int hi = fGlyphArray.count() - 1;
|
| - while (lo < hi) {
|
| - int mid = (hi + lo) >> 1;
|
| - if (gptr[mid].fID > id) {
|
| - lo = mid + 1;
|
| - } else {
|
| - hi = mid;
|
| - }
|
| - }
|
| -
|
| - uint16_t glyph_index = hi;
|
| - SkGlyph* glyph = &gptr[glyph_index];
|
| - if (glyph->fID == id) {
|
| - if (kFull_MetricsType == mtype && glyph->isJustAdvance()) {
|
| - fScalerContext->getMetrics(glyph);
|
| - }
|
| - SkASSERT(glyph->fID != SkGlyph::kImpossibleID);
|
| - return glyph_index;
|
| - }
|
| -
|
| - // check if we need to bump hi before falling though to the allocator
|
| - if (glyph->fID > id) {
|
| - glyph_index += 1;
|
| - }
|
| -
|
| - // Not found, but hi contains the index of the insertion point of the new glyph.
|
| +SkGlyph* SkGlyphCache::allocateNewGlyph(PackedGlyphID packedGlyphID, MetricsType mtype) {
|
| fMemoryUsed += sizeof(SkGlyph);
|
|
|
| - this->adjustCaches(glyph_index);
|
| -
|
| - glyph = fGlyphArray.insert(glyph_index);
|
| - glyph->initGlyphFromCombinedID(id);
|
| + SkGlyph* glyphPtr;
|
| + {
|
| + SkGlyph glyph;
|
| + glyph.initGlyphFromCombinedID(packedGlyphID);
|
| + glyphPtr = fGlyphMap.set(glyph);
|
| + }
|
|
|
| if (kJustAdvance_MetricsType == mtype) {
|
| - fScalerContext->getAdvance(glyph);
|
| + fScalerContext->getAdvance(glyphPtr);
|
| } else {
|
| SkASSERT(kFull_MetricsType == mtype);
|
| - fScalerContext->getMetrics(glyph);
|
| + fScalerContext->getMetrics(glyphPtr);
|
| }
|
|
|
| - SkASSERT(glyph->fID != SkGlyph::kImpossibleID);
|
| - return glyph_index;
|
| + SkASSERT(glyphPtr->fID != SkGlyph::kImpossibleID);
|
| + return glyphPtr;
|
| }
|
|
|
| const void* SkGlyphCache::findImage(const SkGlyph& glyph) {
|
| @@ -354,11 +241,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
|
| + fGlyphMap.count());
|
| SkDebugf("%s\n", msg.c_str());
|
| }
|
|
|
| @@ -529,21 +412,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
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|