| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkGlyphCache.h" | 8 #include "SkGlyphCache.h" |
| 9 #include "SkGlyphCache_Globals.h" | 9 #include "SkGlyphCache_Globals.h" |
| 10 #include "SkGraphics.h" | 10 #include "SkGraphics.h" |
| 11 #include "SkLazyPtr.h" | 11 #include "SkLazyPtr.h" |
| 12 #include "SkMutex.h" | |
| 13 #include "SkPaint.h" | |
| 14 #include "SkPath.h" | 12 #include "SkPath.h" |
| 15 #include "SkTLS.h" | |
| 16 #include "SkTemplates.h" | 13 #include "SkTemplates.h" |
| 17 #include "SkTypeface.h" | 14 #include "SkTypeface.h" |
| 18 | 15 |
| 19 //#define SPEW_PURGE_STATUS | 16 //#define SPEW_PURGE_STATUS |
| 20 | 17 |
| 21 namespace { | 18 namespace { |
| 22 | 19 |
| 23 SkGlyphCache_Globals* create_globals() { | 20 SkGlyphCache_Globals* create_globals() { |
| 24 return SkNEW(SkGlyphCache_Globals); | 21 return SkNEW(SkGlyphCache_Globals); |
| 25 } | 22 } |
| 26 | 23 |
| 27 } // namespace | 24 } // namespace |
| 28 | 25 |
| 29 SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals); | 26 SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals); |
| 30 | 27 |
| 31 // Returns the shared globals | 28 // Returns the shared globals |
| 32 static SkGlyphCache_Globals& get_globals() { | 29 static SkGlyphCache_Globals& get_globals() { |
| 33 return *globals.get(); | 30 return *globals.get(); |
| 34 } | 31 } |
| 35 | 32 |
| 36 /////////////////////////////////////////////////////////////////////////////// | 33 /////////////////////////////////////////////////////////////////////////////// |
| 37 | 34 |
| 38 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | |
| 39 #define RecordHashSuccess() fHashHitCount += 1 | |
| 40 #define RecordHashCollisionIf(pred) do { if (pred) fHashMissCount += 1;
} while (0) | |
| 41 #else | |
| 42 #define RecordHashSuccess() (void)0 | |
| 43 #define RecordHashCollisionIf(pred) (void)0 | |
| 44 #endif | |
| 45 #define RecordHashCollision() RecordHashCollisionIf(true) | |
| 46 | |
| 47 /////////////////////////////////////////////////////////////////////////////// | |
| 48 | |
| 49 // so we don't grow our arrays a lot | 35 // so we don't grow our arrays a lot |
| 50 #define kMinGlyphCount 16 | 36 #define kMinGlyphCount 16 |
| 51 #define kMinGlyphImageSize (16*2) | 37 #define kMinGlyphImageSize (16*2) |
| 52 #define kMinAllocAmount ((sizeof(SkGlyph) + kMinGlyphImageSize) * kMinGlyphC
ount) | 38 #define kMinAllocAmount ((sizeof(SkGlyph) + kMinGlyphImageSize) * kMinGlyphC
ount) |
| 53 | 39 |
| 54 SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkSca
lerContext* ctx) | 40 SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkSca
lerContext* ctx) |
| 55 : fScalerContext(ctx), fGlyphAlloc(kMinAllocAmount) { | 41 : fDesc(desc->copy()) |
| 42 , fScalerContext(ctx) |
| 43 , fGlyphAlloc(kMinAllocAmount) { |
| 56 SkASSERT(typeface); | 44 SkASSERT(typeface); |
| 57 SkASSERT(desc); | 45 SkASSERT(desc); |
| 58 SkASSERT(ctx); | 46 SkASSERT(ctx); |
| 59 | 47 |
| 60 fPrev = fNext = NULL; | 48 fPrev = fNext = NULL; |
| 61 | 49 |
| 62 fDesc = desc->copy(); | |
| 63 fScalerContext->getFontMetrics(&fFontMetrics); | 50 fScalerContext->getFontMetrics(&fFontMetrics); |
| 64 | 51 |
| 65 // Create the sentinel SkGlyph. | |
| 66 SkGlyph* sentinel = fGlyphArray.insert(0); | |
| 67 sentinel->initGlyphFromCombinedID(SkGlyph::kImpossibleID); | |
| 68 | |
| 69 // Initialize all index to zero which points to the sentinel SkGlyph. | |
| 70 memset(fGlyphHash, 0x00, sizeof(fGlyphHash)); | |
| 71 | |
| 72 fMemoryUsed = sizeof(*this); | 52 fMemoryUsed = sizeof(*this); |
| 73 | 53 |
| 74 fGlyphArray.setReserve(kMinGlyphCount); | |
| 75 | |
| 76 fAuxProcList = NULL; | 54 fAuxProcList = NULL; |
| 77 | |
| 78 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | |
| 79 fHashHitCount = fHashMissCount = 0; | |
| 80 #endif | |
| 81 } | 55 } |
| 82 | 56 |
| 83 SkGlyphCache::~SkGlyphCache() { | 57 SkGlyphCache::~SkGlyphCache() { |
| 84 #if 0 | 58 fGlyphMap.foreach( |
| 85 { | 59 [](SkGlyph* g) { |
| 86 size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*); | 60 SkDELETE(g->fPath); |
| 87 size_t glyphAlloc = fGlyphAlloc.totalCapacity(); | |
| 88 size_t glyphHashUsed = 0; | |
| 89 size_t uniHashUsed = 0; | |
| 90 for (int i = 0; i < kHashCount; ++i) { | |
| 91 glyphHashUsed += fGlyphHash[i] ? sizeof(fGlyphHash[0]) : 0; | |
| 92 uniHashUsed += fCharToGlyphHash[i].fID != 0xFFFFFFFF ? sizeof(fCharT
oGlyphHash[0]) : 0; | |
| 93 } | 61 } |
| 94 size_t glyphUsed = fGlyphArray.count() * sizeof(SkGlyph); | 62 ); |
| 95 size_t imageUsed = 0; | |
| 96 for (int i = 0; i < fGlyphArray.count(); ++i) { | |
| 97 const SkGlyph& g = *fGlyphArray[i]; | |
| 98 if (g.fImage) { | |
| 99 imageUsed += g.fHeight * g.rowBytes(); | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 SkDebugf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, gl
yphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n
", | |
| 104 ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), g
lyphHashUsed, sizeof(CharGlyphRec) * kHashCount, uniHashUsed); | |
| 105 | |
| 106 } | |
| 107 #endif | |
| 108 SkGlyph* gptr = fGlyphArray.begin(); | |
| 109 SkGlyph* stop = fGlyphArray.end(); | |
| 110 while (gptr < stop) { | |
| 111 SkPath* path = gptr->fPath; | |
| 112 if (path) { | |
| 113 SkDELETE(path); | |
| 114 } | |
| 115 gptr += 1; | |
| 116 } | |
| 117 SkDescriptor::Free(fDesc); | 63 SkDescriptor::Free(fDesc); |
| 118 SkDELETE(fScalerContext); | 64 SkDELETE(fScalerContext); |
| 119 this->invokeAndRemoveAuxProcs(); | 65 this->invokeAndRemoveAuxProcs(); |
| 120 } | 66 } |
| 121 | 67 |
| 122 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) { | 68 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(PackedUnicharID packed
UnicharID) { |
| 123 if (NULL == fCharToGlyphHash.get()) { | 69 if (NULL == fPackedUnicharIDToPackedGlyphID.get()) { |
| 124 // Allocate the array. | 70 // Allocate the array. |
| 125 fCharToGlyphHash.reset(kHashCount); | 71 fPackedUnicharIDToPackedGlyphID.reset(kHashCount); |
| 126 // Initialize entries of fCharToGlyphHash to index the sentinel glyph an
d | 72 // Initialize array to map character and position with the impossible gl
yph ID. This |
| 127 // an fID value that will not match any id. | 73 // represents no mapping. |
| 128 for (int i = 0; i <kHashCount; ++i) { | 74 for (int i = 0; i <kHashCount; ++i) { |
| 129 fCharToGlyphHash[i].fID = SkGlyph::kImpossibleID; | 75 fPackedUnicharIDToPackedGlyphID[i].fPackedUnicharID = SkGlyph::kImpo
ssibleID; |
| 130 fCharToGlyphHash[i].fGlyphIndex = 0; | 76 fPackedUnicharIDToPackedGlyphID[i].fPackedGlyphID = 0; |
| 131 } | 77 } |
| 132 } | 78 } |
| 133 | 79 |
| 134 return &fCharToGlyphHash[ID2HashIndex(id)]; | 80 return &fPackedUnicharIDToPackedGlyphID[SkChecksum::CheapMix(packedUnicharID
) & kHashMask]; |
| 135 } | |
| 136 | |
| 137 void SkGlyphCache::adjustCaches(int insertion_index) { | |
| 138 for (int i = 0; i < kHashCount; ++i) { | |
| 139 if (fGlyphHash[i] >= SkToU16(insertion_index)) { | |
| 140 fGlyphHash[i] += 1; | |
| 141 } | |
| 142 } | |
| 143 if (fCharToGlyphHash.get() != NULL) { | |
| 144 for (int i = 0; i < kHashCount; ++i) { | |
| 145 if (fCharToGlyphHash[i].fGlyphIndex >= SkToU16(insertion_index)) { | |
| 146 fCharToGlyphHash[i].fGlyphIndex += 1; | |
| 147 } | |
| 148 } | |
| 149 } | |
| 150 } | 81 } |
| 151 | 82 |
| 152 /////////////////////////////////////////////////////////////////////////////// | 83 /////////////////////////////////////////////////////////////////////////////// |
| 153 | 84 |
| 154 #ifdef SK_DEBUG | 85 #ifdef SK_DEBUG |
| 155 #define VALIDATE() AutoValidate av(this) | 86 #define VALIDATE() AutoValidate av(this) |
| 156 #else | 87 #else |
| 157 #define VALIDATE() | 88 #define VALIDATE() |
| 158 #endif | 89 #endif |
| 159 | 90 |
| 160 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { | 91 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { |
| 161 VALIDATE(); | 92 VALIDATE(); |
| 162 uint32_t id = SkGlyph::MakeID(charCode); | 93 PackedUnicharID packedUnicharID = SkGlyph::MakeID(charCode); |
| 163 const CharGlyphRec& rec = *this->getCharGlyphRec(id); | 94 const CharGlyphRec& rec = *this->getCharGlyphRec(packedUnicharID); |
| 164 | 95 |
| 165 if (rec.fID == id) { | 96 if (rec.fPackedUnicharID == packedUnicharID) { |
| 166 return fGlyphArray[rec.fGlyphIndex].getGlyphID(); | 97 return SkGlyph::ID2Code(rec.fPackedGlyphID); |
| 167 } else { | 98 } else { |
| 168 return fScalerContext->charToGlyphID(charCode); | 99 return fScalerContext->charToGlyphID(charCode); |
| 169 } | 100 } |
| 170 } | 101 } |
| 171 | 102 |
| 172 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { | 103 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { |
| 173 return fScalerContext->glyphIDToChar(glyphID); | 104 return fScalerContext->glyphIDToChar(glyphID); |
| 174 } | 105 } |
| 175 | 106 |
| 176 unsigned SkGlyphCache::getGlyphCount() { | 107 unsigned SkGlyphCache::getGlyphCount() { |
| 177 return fScalerContext->getGlyphCount(); | 108 return fScalerContext->getGlyphCount(); |
| 178 } | 109 } |
| 179 | 110 |
| 180 /////////////////////////////////////////////////////////////////////////////// | 111 /////////////////////////////////////////////////////////////////////////////// |
| 181 | 112 |
| 182 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { | 113 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { |
| 183 VALIDATE(); | 114 VALIDATE(); |
| 184 return *this->lookupByChar(charCode, kJustAdvance_MetricsType); | 115 return *this->lookupByChar(charCode, kJustAdvance_MetricsType); |
| 185 } | 116 } |
| 186 | 117 |
| 187 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { | 118 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { |
| 188 VALIDATE(); | 119 VALIDATE(); |
| 189 uint32_t id = SkGlyph::MakeID(glyphID); | 120 PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID); |
| 190 return *this->lookupByCombinedID(id, kJustAdvance_MetricsType); | 121 return *this->lookupByPackedGlyphID(packedGlyphID, kJustAdvance_MetricsType)
; |
| 191 } | 122 } |
| 192 | 123 |
| 193 /////////////////////////////////////////////////////////////////////////////// | 124 /////////////////////////////////////////////////////////////////////////////// |
| 194 | 125 |
| 195 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { | 126 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { |
| 196 VALIDATE(); | 127 VALIDATE(); |
| 197 return *this->lookupByChar(charCode, kFull_MetricsType); | 128 return *this->lookupByChar(charCode, kFull_MetricsType); |
| 198 } | 129 } |
| 199 | 130 |
| 200 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, | 131 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, SkFixed x, Sk
Fixed y) { |
| 201 SkFixed x, SkFixed y) { | |
| 202 VALIDATE(); | 132 VALIDATE(); |
| 203 return *this->lookupByChar(charCode, kFull_MetricsType, x, y); | 133 return *this->lookupByChar(charCode, kFull_MetricsType, x, y); |
| 204 } | 134 } |
| 205 | 135 |
| 206 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { | 136 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { |
| 207 VALIDATE(); | 137 VALIDATE(); |
| 208 uint32_t id = SkGlyph::MakeID(glyphID); | 138 PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID); |
| 209 return *this->lookupByCombinedID(id, kFull_MetricsType); | 139 return *this->lookupByPackedGlyphID(packedGlyphID, kFull_MetricsType); |
| 210 } | 140 } |
| 211 | 141 |
| 212 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi
xed y) { | 142 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi
xed y) { |
| 213 VALIDATE(); | 143 VALIDATE(); |
| 214 uint32_t id = SkGlyph::MakeID(glyphID, x, y); | 144 PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID, x, y); |
| 215 return *this->lookupByCombinedID(id, kFull_MetricsType); | 145 return *this->lookupByPackedGlyphID(packedGlyphID, kFull_MetricsType); |
| 216 } | 146 } |
| 217 | 147 |
| 218 SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixe
d x, SkFixed y) { | 148 SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixe
d x, SkFixed y) { |
| 219 uint32_t id = SkGlyph::MakeID(charCode, x, y); | 149 PackedUnicharID id = SkGlyph::MakeID(charCode, x, y); |
| 220 CharGlyphRec* rec = this->getCharGlyphRec(id); | 150 CharGlyphRec* rec = this->getCharGlyphRec(id); |
| 221 SkGlyph* glyph; | 151 if (rec->fPackedUnicharID != id) { |
| 222 if (rec->fID != id) { | |
| 223 RecordHashCollisionIf(glyph_index != SkGlyph::kImpossibleID); | |
| 224 // this ID is based on the UniChar | 152 // this ID is based on the UniChar |
| 225 rec->fID = id; | 153 rec->fPackedUnicharID = id; |
| 226 // this ID is based on the glyph index | 154 // this ID is based on the glyph index |
| 227 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y); | 155 PackedGlyphID combinedID = SkGlyph::MakeID(fScalerContext->charToGlyphID
(charCode), x, y); |
| 228 rec->fGlyphIndex = this->lookupMetrics(id, type); | 156 rec->fPackedGlyphID = combinedID; |
| 229 glyph = &fGlyphArray[rec->fGlyphIndex]; | 157 return this->lookupByPackedGlyphID(combinedID, type); |
| 230 } else { | 158 } else { |
| 231 RecordHashSuccess(); | 159 return this->lookupByPackedGlyphID(rec->fPackedGlyphID, type); |
| 232 glyph = &fGlyphArray[rec->fGlyphIndex]; | |
| 233 if (type == kFull_MetricsType && glyph->isJustAdvance()) { | |
| 234 fScalerContext->getMetrics(glyph); | |
| 235 } | |
| 236 } | 160 } |
| 237 return glyph; | |
| 238 } | 161 } |
| 239 | 162 |
| 240 SkGlyph* SkGlyphCache::lookupByCombinedID(uint32_t id, MetricsType type) { | 163 SkGlyph* SkGlyphCache::lookupByPackedGlyphID(PackedGlyphID packedGlyphID, Metric
sType type) { |
| 241 uint32_t hash_index = ID2HashIndex(id); | 164 SkGlyph* glyph = fGlyphMap.find(packedGlyphID); |
| 242 uint16_t glyph_index = fGlyphHash[hash_index]; | |
| 243 SkGlyph* glyph = &fGlyphArray[glyph_index]; | |
| 244 | 165 |
| 245 if (glyph->fID != id) { | 166 if (NULL == glyph) { |
| 246 RecordHashCollisionIf(glyph_index != SkGlyph::kImpossibleID); | 167 glyph = this->allocateNewGlyph(packedGlyphID, type); |
| 247 glyph_index = this->lookupMetrics(id, type); | |
| 248 fGlyphHash[hash_index] = glyph_index; | |
| 249 glyph = &fGlyphArray[glyph_index]; | |
| 250 } else { | 168 } else { |
| 251 RecordHashSuccess(); | |
| 252 if (type == kFull_MetricsType && glyph->isJustAdvance()) { | 169 if (type == kFull_MetricsType && glyph->isJustAdvance()) { |
| 253 fScalerContext->getMetrics(glyph); | 170 fScalerContext->getMetrics(glyph); |
| 254 } | 171 } |
| 255 } | 172 } |
| 256 return glyph; | 173 return glyph; |
| 257 } | 174 } |
| 258 | 175 |
| 259 uint16_t SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { | 176 SkGlyph* SkGlyphCache::allocateNewGlyph(PackedGlyphID packedGlyphID, MetricsType
mtype) { |
| 260 SkASSERT(id != SkGlyph::kImpossibleID); | 177 fMemoryUsed += sizeof(SkGlyph); |
| 261 // Count is always greater than 0 because of the sentinel. | 178 |
| 262 // The fGlyphArray cache is in descending order, so that the sentinel with a
value of ~0 is | 179 SkGlyph* glyphPtr; |
| 263 // always at index 0. | 180 { |
| 264 SkGlyph* gptr = fGlyphArray.begin(); | 181 SkGlyph glyph; |
| 265 int lo = 0; | 182 glyph.initGlyphFromCombinedID(packedGlyphID); |
| 266 int hi = fGlyphArray.count() - 1; | 183 glyphPtr = fGlyphMap.set(glyph); |
| 267 while (lo < hi) { | |
| 268 int mid = (hi + lo) >> 1; | |
| 269 if (gptr[mid].fID > id) { | |
| 270 lo = mid + 1; | |
| 271 } else { | |
| 272 hi = mid; | |
| 273 } | |
| 274 } | 184 } |
| 275 | 185 |
| 276 uint16_t glyph_index = hi; | 186 if (kJustAdvance_MetricsType == mtype) { |
| 277 SkGlyph* glyph = &gptr[glyph_index]; | 187 fScalerContext->getAdvance(glyphPtr); |
| 278 if (glyph->fID == id) { | 188 } else { |
| 279 if (kFull_MetricsType == mtype && glyph->isJustAdvance()) { | 189 SkASSERT(kFull_MetricsType == mtype); |
| 280 fScalerContext->getMetrics(glyph); | 190 fScalerContext->getMetrics(glyphPtr); |
| 281 } | |
| 282 SkASSERT(glyph->fID != SkGlyph::kImpossibleID); | |
| 283 return glyph_index; | |
| 284 } | 191 } |
| 285 | 192 |
| 286 // check if we need to bump hi before falling though to the allocator | 193 SkASSERT(glyphPtr->fID != SkGlyph::kImpossibleID); |
| 287 if (glyph->fID > id) { | 194 return glyphPtr; |
| 288 glyph_index += 1; | |
| 289 } | |
| 290 | |
| 291 // Not found, but hi contains the index of the insertion point of the new gl
yph. | |
| 292 fMemoryUsed += sizeof(SkGlyph); | |
| 293 | |
| 294 this->adjustCaches(glyph_index); | |
| 295 | |
| 296 glyph = fGlyphArray.insert(glyph_index); | |
| 297 glyph->initGlyphFromCombinedID(id); | |
| 298 | |
| 299 if (kJustAdvance_MetricsType == mtype) { | |
| 300 fScalerContext->getAdvance(glyph); | |
| 301 } else { | |
| 302 SkASSERT(kFull_MetricsType == mtype); | |
| 303 fScalerContext->getMetrics(glyph); | |
| 304 } | |
| 305 | |
| 306 SkASSERT(glyph->fID != SkGlyph::kImpossibleID); | |
| 307 return glyph_index; | |
| 308 } | 195 } |
| 309 | 196 |
| 310 const void* SkGlyphCache::findImage(const SkGlyph& glyph) { | 197 const void* SkGlyphCache::findImage(const SkGlyph& glyph) { |
| 311 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { | 198 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { |
| 312 if (NULL == glyph.fImage) { | 199 if (NULL == glyph.fImage) { |
| 313 size_t size = glyph.computeImageSize(); | 200 size_t size = glyph.computeImageSize(); |
| 314 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size, | 201 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size, |
| 315 SkChunkAlloc::kReturnNil_AllocFailType); | 202 SkChunkAlloc::kReturnNil_AllocFailType); |
| 316 // check that alloc() actually succeeded | 203 // check that alloc() actually succeeded |
| 317 if (glyph.fImage) { | 204 if (glyph.fImage) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 347 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize)
); | 234 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize)
); |
| 348 SkString name; | 235 SkString name; |
| 349 face->getFamilyName(&name); | 236 face->getFamilyName(&name); |
| 350 | 237 |
| 351 SkString msg; | 238 SkString msg; |
| 352 msg.printf("cache typeface:%x %25s:%d size:%2g [%g %g %g %g] lum:%02X devG:%
d pntG:%d cntr:%d glyphs:%3d", | 239 msg.printf("cache typeface:%x %25s:%d size:%2g [%g %g %g %g] lum:%02X devG:%
d pntG:%d cntr:%d glyphs:%3d", |
| 353 face->uniqueID(), name.c_str(), face->style(), rec.fTextSize, | 240 face->uniqueID(), name.c_str(), face->style(), rec.fTextSize, |
| 354 matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewX], | 241 matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewX], |
| 355 matrix[SkMatrix::kMSkewY], matrix[SkMatrix::kMScaleY], | 242 matrix[SkMatrix::kMSkewY], matrix[SkMatrix::kMScaleY], |
| 356 rec.fLumBits & 0xFF, rec.fDeviceGamma, rec.fPaintGamma, rec.fCont
rast, | 243 rec.fLumBits & 0xFF, rec.fDeviceGamma, rec.fPaintGamma, rec.fCont
rast, |
| 357 fGlyphArray.count()); | 244 fGlyphMap.count()); |
| 358 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | |
| 359 const int sum = SkTMax(fHashHitCount + fHashMissCount, 1); // avoid divide
-by-zero | |
| 360 msg.appendf(" hash:%2d\n", 100 * fHashHitCount / sum); | |
| 361 #endif | |
| 362 SkDebugf("%s\n", msg.c_str()); | 245 SkDebugf("%s\n", msg.c_str()); |
| 363 } | 246 } |
| 364 | 247 |
| 365 /////////////////////////////////////////////////////////////////////////////// | 248 /////////////////////////////////////////////////////////////////////////////// |
| 366 | 249 |
| 367 bool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const { | 250 bool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const { |
| 368 const AuxProcRec* rec = fAuxProcList; | 251 const AuxProcRec* rec = fAuxProcList; |
| 369 while (rec) { | 252 while (rec) { |
| 370 if (rec->fProc == proc) { | 253 if (rec->fProc == proc) { |
| 371 if (dataPtr) { | 254 if (dataPtr) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 522 void SkGlyphCache::Dump() { | 405 void SkGlyphCache::Dump() { |
| 523 SkGlyphCache_Globals& globals = get_globals(); | 406 SkGlyphCache_Globals& globals = get_globals(); |
| 524 AutoAcquire ac(globals.fLock); | 407 AutoAcquire ac(globals.fLock); |
| 525 SkGlyphCache* cache; | 408 SkGlyphCache* cache; |
| 526 | 409 |
| 527 globals.validate(); | 410 globals.validate(); |
| 528 | 411 |
| 529 SkDebugf("SkGlyphCache strikes:%d memory:%d\n", | 412 SkDebugf("SkGlyphCache strikes:%d memory:%d\n", |
| 530 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed()); | 413 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed()); |
| 531 | 414 |
| 532 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | |
| 533 int hitCount = 0; | |
| 534 int missCount = 0; | |
| 535 #endif | |
| 536 | |
| 537 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext)
{ | 415 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext)
{ |
| 538 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | |
| 539 hitCount += cache->fHashHitCount; | |
| 540 missCount += cache->fHashMissCount; | |
| 541 #endif | |
| 542 cache->dump(); | 416 cache->dump(); |
| 543 } | 417 } |
| 544 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | |
| 545 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount)); | |
| 546 #endif | |
| 547 } | 418 } |
| 548 | 419 |
| 549 /////////////////////////////////////////////////////////////////////////////// | 420 /////////////////////////////////////////////////////////////////////////////// |
| 550 | 421 |
| 551 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { | 422 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { |
| 552 AutoAcquire ac(fLock); | 423 AutoAcquire ac(fLock); |
| 553 | 424 |
| 554 this->validate(); | 425 this->validate(); |
| 555 cache->validate(); | 426 cache->validate(); |
| 556 | 427 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 716 } | 587 } |
| 717 | 588 |
| 718 void SkGraphics::PurgeFontCache() { | 589 void SkGraphics::PurgeFontCache() { |
| 719 get_globals().purgeAll(); | 590 get_globals().purgeAll(); |
| 720 SkTypefaceCache::PurgeAll(); | 591 SkTypefaceCache::PurgeAll(); |
| 721 } | 592 } |
| 722 | 593 |
| 723 // TODO(herb): clean up TLS apis. | 594 // TODO(herb): clean up TLS apis. |
| 724 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } | 595 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } |
| 725 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } | 596 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } |
| OLD | NEW |