Chromium Code Reviews| Index: src/core/SkGlyphCache.cpp |
| diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp |
| index 57c54bfc1ec3f7f35d3c499ba14c26abe99bcdcf..219337af4258872b38fda96e043b236a8b6d9be9 100755 |
| --- a/src/core/SkGlyphCache.cpp |
| +++ b/src/core/SkGlyphCache.cpp |
| @@ -68,8 +68,8 @@ SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkSca |
| fScalerContext->getFontMetrics(&fFontMetrics); |
| // init to 0 so that all of the pointers will be null |
|
reed1
2015/01/30 13:57:38
comment (0) disagrees with the code (0xFF)
I'm gu
herb_g
2015/02/01 05:09:27
Done.
|
| - memset(fGlyphHash, 0, sizeof(fGlyphHash)); |
| - |
| + memset(fGlyphHash, 0xFF, sizeof(fGlyphHash)); |
| + |
| fMemoryUsed = sizeof(*this); |
| fGlyphArray.setReserve(kMinGlyphCount); |
| @@ -106,10 +106,10 @@ SkGlyphCache::~SkGlyphCache() { |
| } |
| #endif |
| - SkGlyph** gptr = fGlyphArray.begin(); |
| - SkGlyph** stop = fGlyphArray.end(); |
| + SkGlyph* gptr = fGlyphArray.begin(); |
| + SkGlyph* stop = fGlyphArray.end(); |
| while (gptr < stop) { |
| - SkPath* path = (*gptr)->fPath; |
| + SkPath* path = gptr->fPath; |
| if (path) { |
| SkDELETE(path); |
| } |
| @@ -120,6 +120,7 @@ SkGlyphCache::~SkGlyphCache() { |
| this->invokeAndRemoveAuxProcs(); |
| } |
| + |
| SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) { |
| if (NULL == fCharToGlyphHash.get()) { |
| fCharToGlyphHash.reset(kHashCount); |
| @@ -131,6 +132,26 @@ SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) { |
| return &fCharToGlyphHash[ID2HashIndex(id)]; |
| } |
| +void SkGlyphCache::adjustCaches(int16_t insertion_index) { |
| + for (int i = 0; i < kHashCount; ++i) { |
| + // Beware: the following code uses the wrap around behavior of the |
| + // unsigned unint16_t to change the kInvalidGlyph value to zero allowing |
| + // a single comparison for if the index needs to be incremented. |
| + // This trick is also used below. |
| + if (fGlyphHash[i] + 1 >= insertion_index + 1) { |
| + fGlyphHash[i] += 1; |
| + } |
| + } |
| + if (fCharToGlyphHash.get() != NULL) { |
| + for (int i = 0; i < kHashCount; ++i) { |
| + // See the warning about about the following code. |
| + if (fCharToGlyphHash[i].fGlyphIndex + 1 >= insertion_index + 1) { |
| + fCharToGlyphHash[i].fGlyphIndex += 1; |
| + } |
| + } |
| + } |
| +} |
| + |
| /////////////////////////////////////////////////////////////////////////////// |
| #ifdef SK_DEBUG |
| @@ -145,7 +166,7 @@ uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { |
| const CharGlyphRec& rec = *this->getCharGlyphRec(id); |
| if (rec.fID == id) { |
| - return rec.fGlyph->getGlyphID(); |
| + return fGlyphArray[rec.fGlyphIndex].getGlyphID(); |
| } else { |
| return fScalerContext->charToGlyphID(charCode); |
| } |
| @@ -163,159 +184,125 @@ unsigned SkGlyphCache::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 *maintainCharCache(charCode, kJustAdvance_MetricsType); |
| } |
| const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { |
| VALIDATE(); |
| uint32_t id = SkGlyph::MakeID(glyphID); |
| - unsigned index = ID2HashIndex(id); |
| - SkGlyph* glyph = fGlyphHash[index]; |
| + return *maintainGlyphCache(id, kJustAdvance_MetricsType); |
| - 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 *maintainCharCache(charCode, kFull_MetricsType); |
| } |
| const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, |
| SkFixed x, SkFixed y) { |
| VALIDATE(); |
| + return *maintainCharCache(charCode, kFull_MetricsType, x, y); |
| +} |
| + |
| +const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { |
| + VALIDATE(); |
| + uint32_t id = SkGlyph::MakeID(glyphID); |
| + return *this->maintainGlyphCache(id, kFull_MetricsType); |
| +} |
| + |
| +const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFixed y) { |
| + VALIDATE(); |
| + uint32_t id = SkGlyph::MakeID(glyphID, x, y); |
| + return *this->maintainGlyphCache(id, kFull_MetricsType); |
| +} |
| + |
| +SkGlyph* SkGlyphCache::maintainCharCache(SkUnichar charCode, MetricsType type, SkFixed x, SkFixed y) { |
| uint32_t id = SkGlyph::MakeID(charCode, x, y); |
| CharGlyphRec* rec = this->getCharGlyphRec(id); |
| - |
| + SkGlyph* glyph; |
| if (rec->fID != id) { |
| - RecordHashCollisionIf(rec->fGlyph != NULL); |
| + RecordHashCollisionIf(rec->fGlyph != kInvalidGlyph); |
| // 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); |
| + rec->fGlyphIndex = this->lookupMetrics(id, kFull_MetricsType); |
| + glyph = &fGlyphArray[rec->fGlyphIndex]; |
| } else { |
| RecordHashSuccess(); |
| - if (rec->fGlyph->isJustAdvance()) { |
| - fScalerContext->getMetrics(rec->fGlyph); |
| - } |
| - } |
| - SkASSERT(rec->fGlyph->isFullMetrics()); |
| - return *rec->fGlyph; |
| -} |
| - |
| -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()) { |
| + glyph = &fGlyphArray[rec->fGlyphIndex]; |
| + if (type == kFull_MetricsType && glyph->isJustAdvance()) { |
| fScalerContext->getMetrics(glyph); |
| } |
| } |
| SkASSERT(glyph->isFullMetrics()); |
| - return *glyph; |
| + 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) { |
| +SkGlyph* SkGlyphCache::maintainGlyphCache(uint32_t id, MetricsType type) { |
| + uint32_t hash_index = ID2HashIndex(id); |
| + uint16_t glyph_index = fGlyphHash[hash_index]; |
| + SkGlyph* glyph; |
| + |
| + if (kInvalidGlyph == glyph_index |
| + || (glyph = &fGlyphArray[glyph_index])->fID != id) { |
| RecordHashCollisionIf(glyph != NULL); |
| - glyph = this->lookupMetrics(id, kFull_MetricsType); |
| - fGlyphHash[index] = glyph; |
| + glyph_index = this->lookupMetrics(id, type); |
| + fGlyphHash[hash_index] = glyph_index; |
| + glyph = &fGlyphArray[glyph_index]; |
| } else { |
| RecordHashSuccess(); |
| - if (glyph->isJustAdvance()) { |
| - fScalerContext->getMetrics(glyph); |
| + if (type == kFull_MetricsType && glyph->isJustAdvance()) { |
| + fScalerContext->getMetrics(glyph); |
| } |
| + SkASSERT(glyph->isFullMetrics()); |
| } |
| - SkASSERT(glyph->isFullMetrics()); |
| - return *glyph; |
| + 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; |
| - |
| +uint16_t SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { |
| + uint16_t glyph_index = 0; |
| + int count = fGlyphArray.count(); |
| + int hi = 0; |
| + |
| + if (count > 0) { |
| + SkGlyph* gptr = fGlyphArray.begin(); |
| + int lo = 0; |
| + |
| hi = count - 1; |
| while (lo < hi) { |
| int mid = (hi + lo) >> 1; |
| - if (gptr[mid]->fID < id) { |
| + if (gptr[mid].fID < id) { |
| lo = mid + 1; |
| } else { |
| hi = mid; |
| } |
| } |
| - glyph = gptr[hi]; |
| + glyph_index = hi; |
| + SkGlyph* glyph = &gptr[hi]; |
| if (glyph->fID == id) { |
| if (kFull_MetricsType == mtype && glyph->isJustAdvance()) { |
| fScalerContext->getMetrics(glyph); |
| } |
| - return glyph; |
| + return glyph_index; |
| } |
| - |
| + |
| // check if we need to bump hi before falling though to the allocator |
| if (glyph->fID < id) { |
| - hi += 1; |
| + glyph_index += 1; |
| } |
| } |
| - |
| + |
| // not found, but hi tells us where to inser the new glyph |
| fMemoryUsed += sizeof(SkGlyph); |
| + |
| + this->adjustCaches(glyph_index); |
| - glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph), |
| - SkChunkAlloc::kThrow_AllocFailType); |
| + SkGlyph* glyph = fGlyphArray.insert(glyph_index); |
| glyph->init(id); |
| - *fGlyphArray.insert(hi) = glyph; |
| if (kJustAdvance_MetricsType == mtype) { |
| fScalerContext->getAdvance(glyph); |
| @@ -324,7 +311,7 @@ SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { |
| fScalerContext->getMetrics(glyph); |
| } |
| - return glyph; |
| + return glyph_index; |
| } |
| const void* SkGlyphCache::findImage(const SkGlyph& glyph) { |