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 |