| 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 "SkPath.h" | 12 #include "SkPath.h" |
| 13 #include "SkTemplates.h" | 13 #include "SkTemplates.h" |
| 14 #include "SkTypeface.h" | 14 #include "SkTypeface.h" |
| 15 | 15 |
| 16 //#define SPEW_PURGE_STATUS | 16 //#define SPEW_PURGE_STATUS |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 SkGlyphCache_Globals* create_globals() { | 20 SkGlyphCache_Globals* create_globals() { return new SkGlyphCache_Globals; } |
| 21 return SkNEW(SkGlyphCache_Globals); | |
| 22 } | |
| 23 | 21 |
| 24 } // namespace | 22 } // namespace |
| 25 | 23 |
| 26 SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals); | 24 SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals); |
| 27 | 25 |
| 28 // Returns the shared globals | 26 // Returns the shared globals |
| 29 static SkGlyphCache_Globals& get_globals() { | 27 static SkGlyphCache_Globals& get_globals() { |
| 30 return *globals.get(); | 28 return *globals.get(); |
| 31 } | 29 } |
| 32 | 30 |
| (...skipping 15 matching lines...) Expand all Loading... |
| 48 fPrev = fNext = NULL; | 46 fPrev = fNext = NULL; |
| 49 | 47 |
| 50 fScalerContext->getFontMetrics(&fFontMetrics); | 48 fScalerContext->getFontMetrics(&fFontMetrics); |
| 51 | 49 |
| 52 fMemoryUsed = sizeof(*this); | 50 fMemoryUsed = sizeof(*this); |
| 53 | 51 |
| 54 fAuxProcList = NULL; | 52 fAuxProcList = NULL; |
| 55 } | 53 } |
| 56 | 54 |
| 57 SkGlyphCache::~SkGlyphCache() { | 55 SkGlyphCache::~SkGlyphCache() { |
| 58 fGlyphMap.foreach( | 56 fGlyphMap.foreach ([](SkGlyph* g) { delete g->fPath; }); |
| 59 [](SkGlyph* g) { | |
| 60 SkDELETE(g->fPath); | |
| 61 } | |
| 62 ); | |
| 63 SkDescriptor::Free(fDesc); | 57 SkDescriptor::Free(fDesc); |
| 64 SkDELETE(fScalerContext); | 58 delete fScalerContext; |
| 65 this->invokeAndRemoveAuxProcs(); | 59 this->invokeAndRemoveAuxProcs(); |
| 66 } | 60 } |
| 67 | 61 |
| 68 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(PackedUnicharID packed
UnicharID) { | 62 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(PackedUnicharID packed
UnicharID) { |
| 69 if (NULL == fPackedUnicharIDToPackedGlyphID.get()) { | 63 if (NULL == fPackedUnicharIDToPackedGlyphID.get()) { |
| 70 // Allocate the array. | 64 // Allocate the array. |
| 71 fPackedUnicharIDToPackedGlyphID.reset(kHashCount); | 65 fPackedUnicharIDToPackedGlyphID.reset(kHashCount); |
| 72 // Initialize array to map character and position with the impossible gl
yph ID. This | 66 // Initialize array to map character and position with the impossible gl
yph ID. This |
| 73 // represents no mapping. | 67 // represents no mapping. |
| 74 for (int i = 0; i <kHashCount; ++i) { | 68 for (int i = 0; i <kHashCount; ++i) { |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 214 fMemoryUsed += size; | 208 fMemoryUsed += size; |
| 215 } | 209 } |
| 216 } | 210 } |
| 217 } | 211 } |
| 218 return glyph.fImage; | 212 return glyph.fImage; |
| 219 } | 213 } |
| 220 | 214 |
| 221 const SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) { | 215 const SkPath* SkGlyphCache::findPath(const SkGlyph& glyph) { |
| 222 if (glyph.fWidth) { | 216 if (glyph.fWidth) { |
| 223 if (glyph.fPath == NULL) { | 217 if (glyph.fPath == NULL) { |
| 224 const_cast<SkGlyph&>(glyph).fPath = SkNEW(SkPath); | 218 const_cast<SkGlyph&>(glyph).fPath = new SkPath; |
| 225 fScalerContext->getPath(glyph, glyph.fPath); | 219 fScalerContext->getPath(glyph, glyph.fPath); |
| 226 fMemoryUsed += sizeof(SkPath) + | 220 fMemoryUsed += sizeof(SkPath) + |
| 227 glyph.fPath->countPoints() * sizeof(SkPoint); | 221 glyph.fPath->countPoints() * sizeof(SkPoint); |
| 228 } | 222 } |
| 229 } | 223 } |
| 230 return glyph.fPath; | 224 return glyph.fPath; |
| 231 } | 225 } |
| 232 | 226 |
| 233 void SkGlyphCache::dump() const { | 227 void SkGlyphCache::dump() const { |
| 234 const SkTypeface* face = fScalerContext->getTypeface(); | 228 const SkTypeface* face = fScalerContext->getTypeface(); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 | 266 |
| 273 AuxProcRec* rec = fAuxProcList; | 267 AuxProcRec* rec = fAuxProcList; |
| 274 while (rec) { | 268 while (rec) { |
| 275 if (rec->fProc == proc) { | 269 if (rec->fProc == proc) { |
| 276 rec->fData = data; | 270 rec->fData = data; |
| 277 return; | 271 return; |
| 278 } | 272 } |
| 279 rec = rec->fNext; | 273 rec = rec->fNext; |
| 280 } | 274 } |
| 281 // not found, create a new rec | 275 // not found, create a new rec |
| 282 rec = SkNEW(AuxProcRec); | 276 rec = new AuxProcRec; |
| 283 rec->fProc = proc; | 277 rec->fProc = proc; |
| 284 rec->fData = data; | 278 rec->fData = data; |
| 285 rec->fNext = fAuxProcList; | 279 rec->fNext = fAuxProcList; |
| 286 fAuxProcList = rec; | 280 fAuxProcList = rec; |
| 287 } | 281 } |
| 288 | 282 |
| 289 void SkGlyphCache::invokeAndRemoveAuxProcs() { | 283 void SkGlyphCache::invokeAndRemoveAuxProcs() { |
| 290 AuxProcRec* rec = fAuxProcList; | 284 AuxProcRec* rec = fAuxProcList; |
| 291 while (rec) { | 285 while (rec) { |
| 292 rec->fProc(rec->fData); | 286 rec->fProc(rec->fData); |
| 293 AuxProcRec* next = rec->fNext; | 287 AuxProcRec* next = rec->fNext; |
| 294 SkDELETE(rec); | 288 delete rec; |
| 295 rec = next; | 289 rec = next; |
| 296 } | 290 } |
| 297 } | 291 } |
| 298 | 292 |
| 299 /////////////////////////////////////////////////////////////////////////////// | 293 /////////////////////////////////////////////////////////////////////////////// |
| 300 /////////////////////////////////////////////////////////////////////////////// | 294 /////////////////////////////////////////////////////////////////////////////// |
| 301 | 295 |
| 302 | 296 |
| 303 class AutoAcquire { | 297 class AutoAcquire { |
| 304 public: | 298 public: |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 380 // cache once and try again. | 374 // cache once and try again. |
| 381 { | 375 { |
| 382 // pass true the first time, to notice if the scalercontext failed, | 376 // pass true the first time, to notice if the scalercontext failed, |
| 383 // so we can try the purge. | 377 // so we can try the purge. |
| 384 SkScalerContext* ctx = typeface->createScalerContext(desc, true); | 378 SkScalerContext* ctx = typeface->createScalerContext(desc, true); |
| 385 if (!ctx) { | 379 if (!ctx) { |
| 386 get_globals().purgeAll(); | 380 get_globals().purgeAll(); |
| 387 ctx = typeface->createScalerContext(desc, false); | 381 ctx = typeface->createScalerContext(desc, false); |
| 388 SkASSERT(ctx); | 382 SkASSERT(ctx); |
| 389 } | 383 } |
| 390 cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx)); | 384 cache = new SkGlyphCache(typeface, desc, ctx); |
| 391 } | 385 } |
| 392 | 386 |
| 393 AutoValidate av(cache); | 387 AutoValidate av(cache); |
| 394 | 388 |
| 395 if (!proc(cache, context)) { // need to reattach | 389 if (!proc(cache, context)) { // need to reattach |
| 396 globals.attachCacheToHead(cache); | 390 globals.attachCacheToHead(cache); |
| 397 cache = NULL; | 391 cache = NULL; |
| 398 } | 392 } |
| 399 return cache; | 393 return cache; |
| 400 } | 394 } |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 495 // we start at the tail and proceed backwards, as the linklist is in LRU | 489 // we start at the tail and proceed backwards, as the linklist is in LRU |
| 496 // order, with unimportant entries at the tail. | 490 // order, with unimportant entries at the tail. |
| 497 SkGlyphCache* cache = this->internalGetTail(); | 491 SkGlyphCache* cache = this->internalGetTail(); |
| 498 while (cache != NULL && | 492 while (cache != NULL && |
| 499 (bytesFreed < bytesNeeded || countFreed < countNeeded)) { | 493 (bytesFreed < bytesNeeded || countFreed < countNeeded)) { |
| 500 SkGlyphCache* prev = cache->fPrev; | 494 SkGlyphCache* prev = cache->fPrev; |
| 501 bytesFreed += cache->fMemoryUsed; | 495 bytesFreed += cache->fMemoryUsed; |
| 502 countFreed += 1; | 496 countFreed += 1; |
| 503 | 497 |
| 504 this->internalDetachCache(cache); | 498 this->internalDetachCache(cache); |
| 505 SkDELETE(cache); | 499 delete cache; |
| 506 cache = prev; | 500 cache = prev; |
| 507 } | 501 } |
| 508 | 502 |
| 509 this->validate(); | 503 this->validate(); |
| 510 | 504 |
| 511 #ifdef SPEW_PURGE_STATUS | 505 #ifdef SPEW_PURGE_STATUS |
| 512 if (countFreed) { | 506 if (countFreed) { |
| 513 SkDebugf("purging %dK from font cache [%d entries]\n", | 507 SkDebugf("purging %dK from font cache [%d entries]\n", |
| 514 (int)(bytesFreed >> 10), countFreed); | 508 (int)(bytesFreed >> 10), countFreed); |
| 515 } | 509 } |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 } | 606 } |
| 613 | 607 |
| 614 void SkGraphics::PurgeFontCache() { | 608 void SkGraphics::PurgeFontCache() { |
| 615 get_globals().purgeAll(); | 609 get_globals().purgeAll(); |
| 616 SkTypefaceCache::PurgeAll(); | 610 SkTypefaceCache::PurgeAll(); |
| 617 } | 611 } |
| 618 | 612 |
| 619 // TODO(herb): clean up TLS apis. | 613 // TODO(herb): clean up TLS apis. |
| 620 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } | 614 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; } |
| 621 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } | 615 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { } |
| OLD | NEW |