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) { |