Chromium Code Reviews| 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 if (g->fPath != NULL) { |
|
mtklein
2015/07/21 19:35:52
Just FYI, SkDELETE does a null check, so this shou
herb_g
2015/07/21 22:27:34
Done.
| |
| 87 size_t glyphAlloc = fGlyphAlloc.totalCapacity(); | 61 SkDELETE(g->fPath); |
| 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 } | |
| 94 size_t glyphUsed = fGlyphArray.count() * sizeof(SkGlyph); | |
| 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 } | 62 } |
| 101 } | 63 } |
| 102 | 64 ); |
| 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); | 65 SkDescriptor::Free(fDesc); |
| 118 SkDELETE(fScalerContext); | 66 SkDELETE(fScalerContext); |
| 119 this->invokeAndRemoveAuxProcs(); | 67 this->invokeAndRemoveAuxProcs(); |
| 120 } | 68 } |
| 121 | 69 |
| 122 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) { | 70 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(PackedUnicharID packed UnicharID) { |
| 123 if (NULL == fCharToGlyphHash.get()) { | 71 if (NULL == fPackedUnicharIDToPackedGlyphID.get()) { |
| 124 // Allocate the array. | 72 // Allocate the array. |
| 125 fCharToGlyphHash.reset(kHashCount); | 73 fPackedUnicharIDToPackedGlyphID.reset(kHashCount); |
| 126 // Initialize entries of fCharToGlyphHash to index the sentinel glyph an d | 74 // Initialize array to map character and position with the impossible gl yph ID. This |
| 127 // an fID value that will not match any id. | 75 // represents no mapping. |
| 128 for (int i = 0; i <kHashCount; ++i) { | 76 for (int i = 0; i <kHashCount; ++i) { |
| 129 fCharToGlyphHash[i].fID = SkGlyph::kImpossibleID; | 77 fPackedUnicharIDToPackedGlyphID[i].fPackedUnicharID = SkGlyph::kImpo ssibleID; |
| 130 fCharToGlyphHash[i].fGlyphIndex = 0; | 78 fPackedUnicharIDToPackedGlyphID[i].fPackedGlyphID = 0; |
| 131 } | 79 } |
| 132 } | 80 } |
| 133 | 81 |
| 134 return &fCharToGlyphHash[ID2HashIndex(id)]; | 82 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 } | 83 } |
| 151 | 84 |
| 152 /////////////////////////////////////////////////////////////////////////////// | 85 /////////////////////////////////////////////////////////////////////////////// |
| 153 | 86 |
| 154 #ifdef SK_DEBUG | 87 #ifdef SK_DEBUG |
| 155 #define VALIDATE() AutoValidate av(this) | 88 #define VALIDATE() AutoValidate av(this) |
| 156 #else | 89 #else |
| 157 #define VALIDATE() | 90 #define VALIDATE() |
| 158 #endif | 91 #endif |
| 159 | 92 |
| 160 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { | 93 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { |
| 161 VALIDATE(); | 94 VALIDATE(); |
| 162 uint32_t id = SkGlyph::MakeID(charCode); | 95 PackedUnicharID packedUnicharID = SkGlyph::MakeID(charCode); |
| 163 const CharGlyphRec& rec = *this->getCharGlyphRec(id); | 96 const CharGlyphRec& rec = *this->getCharGlyphRec(packedUnicharID); |
| 164 | 97 |
| 165 if (rec.fID == id) { | 98 if (rec.fPackedUnicharID == packedUnicharID) { |
| 166 return fGlyphArray[rec.fGlyphIndex].getGlyphID(); | 99 return SkGlyph::ID2Code(rec.fPackedGlyphID); |
| 167 } else { | 100 } else { |
| 168 return fScalerContext->charToGlyphID(charCode); | 101 return fScalerContext->charToGlyphID(charCode); |
| 169 } | 102 } |
| 170 } | 103 } |
| 171 | 104 |
| 172 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { | 105 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { |
| 173 return fScalerContext->glyphIDToChar(glyphID); | 106 return fScalerContext->glyphIDToChar(glyphID); |
| 174 } | 107 } |
| 175 | 108 |
| 176 unsigned SkGlyphCache::getGlyphCount() { | 109 unsigned SkGlyphCache::getGlyphCount() { |
| 177 return fScalerContext->getGlyphCount(); | 110 return fScalerContext->getGlyphCount(); |
| 178 } | 111 } |
| 179 | 112 |
| 180 /////////////////////////////////////////////////////////////////////////////// | 113 /////////////////////////////////////////////////////////////////////////////// |
| 181 | 114 |
| 182 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { | 115 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { |
| 183 VALIDATE(); | 116 VALIDATE(); |
| 184 return *this->lookupByChar(charCode, kJustAdvance_MetricsType); | 117 return *this->lookupByChar(charCode, kJustAdvance_MetricsType); |
| 185 } | 118 } |
| 186 | 119 |
| 187 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { | 120 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { |
| 188 VALIDATE(); | 121 VALIDATE(); |
| 189 uint32_t id = SkGlyph::MakeID(glyphID); | 122 PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID); |
| 190 return *this->lookupByCombinedID(id, kJustAdvance_MetricsType); | 123 return *this->lookupByPackedGlyphID(packedGlyphID, kJustAdvance_MetricsType) ; |
| 191 } | 124 } |
| 192 | 125 |
| 193 /////////////////////////////////////////////////////////////////////////////// | 126 /////////////////////////////////////////////////////////////////////////////// |
| 194 | 127 |
| 195 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { | 128 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { |
| 196 VALIDATE(); | 129 VALIDATE(); |
| 197 return *this->lookupByChar(charCode, kFull_MetricsType); | 130 return *this->lookupByChar(charCode, kFull_MetricsType); |
| 198 } | 131 } |
| 199 | 132 |
| 200 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, | 133 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, SkFixed x, Sk Fixed y) { |
| 201 SkFixed x, SkFixed y) { | |
| 202 VALIDATE(); | 134 VALIDATE(); |
| 203 return *this->lookupByChar(charCode, kFull_MetricsType, x, y); | 135 return *this->lookupByChar(charCode, kFull_MetricsType, x, y); |
| 204 } | 136 } |
| 205 | 137 |
| 206 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { | 138 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { |
| 207 VALIDATE(); | 139 VALIDATE(); |
| 208 uint32_t id = SkGlyph::MakeID(glyphID); | 140 PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID); |
| 209 return *this->lookupByCombinedID(id, kFull_MetricsType); | 141 return *this->lookupByPackedGlyphID(packedGlyphID, kFull_MetricsType); |
| 210 } | 142 } |
| 211 | 143 |
| 212 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) { | 144 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) { |
| 213 VALIDATE(); | 145 VALIDATE(); |
| 214 uint32_t id = SkGlyph::MakeID(glyphID, x, y); | 146 PackedGlyphID packedGlyphID = SkGlyph::MakeID(glyphID, x, y); |
| 215 return *this->lookupByCombinedID(id, kFull_MetricsType); | 147 return *this->lookupByPackedGlyphID(packedGlyphID, kFull_MetricsType); |
| 216 } | 148 } |
| 217 | 149 |
| 218 SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixe d x, SkFixed y) { | 150 SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixe d x, SkFixed y) { |
| 219 uint32_t id = SkGlyph::MakeID(charCode, x, y); | 151 PackedUnicharID id = SkGlyph::MakeID(charCode, x, y); |
| 220 CharGlyphRec* rec = this->getCharGlyphRec(id); | 152 CharGlyphRec* rec = this->getCharGlyphRec(id); |
| 221 SkGlyph* glyph; | 153 if (rec->fPackedUnicharID != id) { |
| 222 if (rec->fID != id) { | |
| 223 RecordHashCollisionIf(glyph_index != SkGlyph::kImpossibleID); | |
| 224 // this ID is based on the UniChar | 154 // this ID is based on the UniChar |
| 225 rec->fID = id; | 155 rec->fPackedUnicharID = id; |
| 226 // this ID is based on the glyph index | 156 // this ID is based on the glyph index |
| 227 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y); | 157 PackedGlyphID combinedID = SkGlyph::MakeID(fScalerContext->charToGlyphID (charCode), x, y); |
| 228 rec->fGlyphIndex = this->lookupMetrics(id, type); | 158 rec->fPackedGlyphID = combinedID; |
| 229 glyph = &fGlyphArray[rec->fGlyphIndex]; | 159 return this->lookupByPackedGlyphID(combinedID, type); |
| 230 } else { | 160 } else { |
| 231 RecordHashSuccess(); | 161 return this->lookupByPackedGlyphID(rec->fPackedGlyphID, type); |
| 232 glyph = &fGlyphArray[rec->fGlyphIndex]; | |
| 233 if (type == kFull_MetricsType && glyph->isJustAdvance()) { | |
| 234 fScalerContext->getMetrics(glyph); | |
| 235 } | |
| 236 } | 162 } |
| 237 return glyph; | |
| 238 } | 163 } |
| 239 | 164 |
| 240 SkGlyph* SkGlyphCache::lookupByCombinedID(uint32_t id, MetricsType type) { | 165 SkGlyph* SkGlyphCache::lookupByPackedGlyphID(PackedGlyphID packedGlyphID, Metric sType type) { |
| 241 uint32_t hash_index = ID2HashIndex(id); | 166 SkGlyph* glyph = fGlyphMap.find(packedGlyphID); |
| 242 uint16_t glyph_index = fGlyphHash[hash_index]; | |
| 243 SkGlyph* glyph = &fGlyphArray[glyph_index]; | |
| 244 | 167 |
| 245 if (glyph->fID != id) { | 168 if (NULL == glyph) { |
| 246 RecordHashCollisionIf(glyph_index != SkGlyph::kImpossibleID); | 169 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 { | 170 } else { |
| 251 RecordHashSuccess(); | |
| 252 if (type == kFull_MetricsType && glyph->isJustAdvance()) { | 171 if (type == kFull_MetricsType && glyph->isJustAdvance()) { |
| 253 fScalerContext->getMetrics(glyph); | 172 fScalerContext->getMetrics(glyph); |
| 254 } | 173 } |
| 255 } | 174 } |
| 256 return glyph; | 175 return glyph; |
| 257 } | 176 } |
| 258 | 177 |
| 259 uint16_t SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { | 178 SkGlyph* SkGlyphCache::allocateNewGlyph(PackedGlyphID packedGlyphID, MetricsType mtype) { |
| 260 SkASSERT(id != SkGlyph::kImpossibleID); | 179 fMemoryUsed += sizeof(SkGlyph); |
| 261 // Count is always greater than 0 because of the sentinel. | 180 |
| 262 // The fGlyphArray cache is in descending order, so that the sentinel with a value of ~0 is | 181 SkGlyph* glyphPtr; |
| 263 // always at index 0. | 182 { |
| 264 SkGlyph* gptr = fGlyphArray.begin(); | 183 SkGlyph glyph; |
| 265 int lo = 0; | 184 glyph.initGlyphFromCombinedID(packedGlyphID); |
| 266 int hi = fGlyphArray.count() - 1; | 185 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 } | 186 } |
| 275 | 187 |
| 276 uint16_t glyph_index = hi; | 188 if (kJustAdvance_MetricsType == mtype) { |
| 277 SkGlyph* glyph = &gptr[glyph_index]; | 189 fScalerContext->getAdvance(glyphPtr); |
| 278 if (glyph->fID == id) { | 190 } else { |
| 279 if (kFull_MetricsType == mtype && glyph->isJustAdvance()) { | 191 SkASSERT(kFull_MetricsType == mtype); |
| 280 fScalerContext->getMetrics(glyph); | 192 fScalerContext->getMetrics(glyphPtr); |
| 281 } | |
| 282 SkASSERT(glyph->fID != SkGlyph::kImpossibleID); | |
| 283 return glyph_index; | |
| 284 } | 193 } |
| 285 | 194 |
| 286 // check if we need to bump hi before falling though to the allocator | 195 SkASSERT(glyphPtr->fID != SkGlyph::kImpossibleID); |
| 287 if (glyph->fID > id) { | 196 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 } | 197 } |
| 309 | 198 |
| 310 const void* SkGlyphCache::findImage(const SkGlyph& glyph) { | 199 const void* SkGlyphCache::findImage(const SkGlyph& glyph) { |
| 311 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { | 200 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { |
| 312 if (NULL == glyph.fImage) { | 201 if (NULL == glyph.fImage) { |
| 313 size_t size = glyph.computeImageSize(); | 202 size_t size = glyph.computeImageSize(); |
| 314 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size, | 203 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size, |
| 315 SkChunkAlloc::kReturnNil_AllocFailType); | 204 SkChunkAlloc::kReturnNil_AllocFailType); |
| 316 // check that alloc() actually succeeded | 205 // check that alloc() actually succeeded |
| 317 if (glyph.fImage) { | 206 if (glyph.fImage) { |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 347 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize) ); | 236 matrix.preScale(SkScalarInvert(rec.fTextSize), SkScalarInvert(rec.fTextSize) ); |
| 348 SkString name; | 237 SkString name; |
| 349 face->getFamilyName(&name); | 238 face->getFamilyName(&name); |
| 350 | 239 |
| 351 SkString msg; | 240 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", | 241 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, | 242 face->uniqueID(), name.c_str(), face->style(), rec.fTextSize, |
| 354 matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewX], | 243 matrix[SkMatrix::kMScaleX], matrix[SkMatrix::kMSkewX], |
| 355 matrix[SkMatrix::kMSkewY], matrix[SkMatrix::kMScaleY], | 244 matrix[SkMatrix::kMSkewY], matrix[SkMatrix::kMScaleY], |
| 356 rec.fLumBits & 0xFF, rec.fDeviceGamma, rec.fPaintGamma, rec.fCont rast, | 245 rec.fLumBits & 0xFF, rec.fDeviceGamma, rec.fPaintGamma, rec.fCont rast, |
| 357 fGlyphArray.count()); | 246 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()); | 247 SkDebugf("%s\n", msg.c_str()); |
| 363 } | 248 } |
| 364 | 249 |
| 365 /////////////////////////////////////////////////////////////////////////////// | 250 /////////////////////////////////////////////////////////////////////////////// |
| 366 | 251 |
| 367 bool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const { | 252 bool SkGlyphCache::getAuxProcData(void (*proc)(void*), void** dataPtr) const { |
| 368 const AuxProcRec* rec = fAuxProcList; | 253 const AuxProcRec* rec = fAuxProcList; |
| 369 while (rec) { | 254 while (rec) { |
| 370 if (rec->fProc == proc) { | 255 if (rec->fProc == proc) { |
| 371 if (dataPtr) { | 256 if (dataPtr) { |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 522 void SkGlyphCache::Dump() { | 407 void SkGlyphCache::Dump() { |
| 523 SkGlyphCache_Globals& globals = get_globals(); | 408 SkGlyphCache_Globals& globals = get_globals(); |
| 524 AutoAcquire ac(globals.fLock); | 409 AutoAcquire ac(globals.fLock); |
| 525 SkGlyphCache* cache; | 410 SkGlyphCache* cache; |
| 526 | 411 |
| 527 globals.validate(); | 412 globals.validate(); |
| 528 | 413 |
| 529 SkDebugf("SkGlyphCache strikes:%d memory:%d\n", | 414 SkDebugf("SkGlyphCache strikes:%d memory:%d\n", |
| 530 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed()); | 415 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed()); |
| 531 | 416 |
| 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) { | 417 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(); | 418 cache->dump(); |
| 543 } | 419 } |
| 544 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS | |
| 545 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount)); | |
| 546 #endif | |
| 547 } | 420 } |
| 548 | 421 |
| 549 /////////////////////////////////////////////////////////////////////////////// | 422 /////////////////////////////////////////////////////////////////////////////// |
| 550 | 423 |
| 551 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { | 424 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { |
| 552 AutoAcquire ac(fLock); | 425 AutoAcquire ac(fLock); |
| 553 | 426 |
| 554 this->validate(); | 427 this->validate(); |
| 555 cache->validate(); | 428 cache->validate(); |
| 556 | 429 |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 716 } | 589 } |
| 717 | 590 |
| 718 void SkGraphics::PurgeFontCache() { | 591 void SkGraphics::PurgeFontCache() { |
| 719 get_globals().purgeAll(); | 592 get_globals().purgeAll(); |
| 720 SkTypefaceCache::PurgeAll(); | 593 SkTypefaceCache::PurgeAll(); |
| 721 } | 594 } |
| 722 | 595 |
| 723 // TODO(herb): clean up TLS apis. | 596 // TODO(herb): clean up TLS apis. |
| 724 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } | 597 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } |
| 725 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } | 598 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } |
| OLD | NEW |