Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(70)

Side by Side Diff: src/core/SkGlyphCache.cpp

Issue 885903002: Make the glyph array entries inline. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix comments remove old code Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkGlyphCache.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkSca lerContext* ctx) 59 SkGlyphCache::SkGlyphCache(SkTypeface* typeface, const SkDescriptor* desc, SkSca lerContext* ctx)
60 : fScalerContext(ctx), fGlyphAlloc(kMinAllocAmount) { 60 : fScalerContext(ctx), fGlyphAlloc(kMinAllocAmount) {
61 SkASSERT(typeface); 61 SkASSERT(typeface);
62 SkASSERT(desc); 62 SkASSERT(desc);
63 SkASSERT(ctx); 63 SkASSERT(ctx);
64 64
65 fPrev = fNext = NULL; 65 fPrev = fNext = NULL;
66 66
67 fDesc = desc->copy(); 67 fDesc = desc->copy();
68 fScalerContext->getFontMetrics(&fFontMetrics); 68 fScalerContext->getFontMetrics(&fFontMetrics);
69
70 // Create the sentinel SkGlyph.
71 SkGlyph* sentinel = fGlyphArray.insert(kSentinelGlyphIndex);
72 sentinel->initGlyphFromCombinedID(kSentinelGlyphID);
73
74 // Initialize all index to zero which points to the sentinel SkGlyph.
75 memset(fGlyphHash, 0x00, sizeof(fGlyphHash));
69 76
70 // init to 0 so that all of the pointers will be null
71 memset(fGlyphHash, 0, sizeof(fGlyphHash));
72
73 fMemoryUsed = sizeof(*this); 77 fMemoryUsed = sizeof(*this);
74 78
75 fGlyphArray.setReserve(kMinGlyphCount); 79 fGlyphArray.setReserve(kMinGlyphCount);
76 80
77 fAuxProcList = NULL; 81 fAuxProcList = NULL;
78 82
79 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 83 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
80 fHashHitCount = fHashMissCount = 0; 84 fHashHitCount = fHashMissCount = 0;
81 #endif 85 #endif
82 } 86 }
(...skipping 16 matching lines...) Expand all
99 if (g.fImage) { 103 if (g.fImage) {
100 imageUsed += g.fHeight * g.rowBytes(); 104 imageUsed += g.fHeight * g.rowBytes();
101 } 105 }
102 } 106 }
103 107
104 SkDebugf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, gl yphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n ", 108 SkDebugf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, gl yphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n ",
105 ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), g lyphHashUsed, sizeof(CharGlyphRec) * kHashCount, uniHashUsed); 109 ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), g lyphHashUsed, sizeof(CharGlyphRec) * kHashCount, uniHashUsed);
106 110
107 } 111 }
108 #endif 112 #endif
109 SkGlyph** gptr = fGlyphArray.begin(); 113 SkGlyph* gptr = fGlyphArray.begin();
110 SkGlyph** stop = fGlyphArray.end(); 114 SkGlyph* stop = fGlyphArray.end();
111 while (gptr < stop) { 115 while (gptr < stop) {
112 SkPath* path = (*gptr)->fPath; 116 SkPath* path = gptr->fPath;
113 if (path) { 117 if (path) {
114 SkDELETE(path); 118 SkDELETE(path);
115 } 119 }
116 gptr += 1; 120 gptr += 1;
117 } 121 }
118 SkDescriptor::Free(fDesc); 122 SkDescriptor::Free(fDesc);
119 SkDELETE(fScalerContext); 123 SkDELETE(fScalerContext);
120 this->invokeAndRemoveAuxProcs(); 124 this->invokeAndRemoveAuxProcs();
121 } 125 }
122 126
123 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) { 127 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) {
124 if (NULL == fCharToGlyphHash.get()) { 128 if (NULL == fCharToGlyphHash.get()) {
129 // Allocate the array.
125 fCharToGlyphHash.reset(kHashCount); 130 fCharToGlyphHash.reset(kHashCount);
126 // init with 0xFF so that the charCode field will be -1, which is invali d 131 // Initialize entries of fCharToGlyphHash to index the sentinel glyph.
127 memset(fCharToGlyphHash.get(), 0xFF, 132 memset(fCharToGlyphHash.get(), 0x00,
128 sizeof(CharGlyphRec) * kHashCount); 133 sizeof(CharGlyphRec) * kHashCount);
129 } 134 }
130 135
131 return &fCharToGlyphHash[ID2HashIndex(id)]; 136 return &fCharToGlyphHash[ID2HashIndex(id)];
132 } 137 }
133 138
139 void SkGlyphCache::adjustCaches(int insertion_index) {
140 for (int i = 0; i < kHashCount; ++i) {
141 if (fGlyphHash[i] >= SkToU16(insertion_index)) {
142 fGlyphHash[i] += 1;
143 }
144 }
145 if (fCharToGlyphHash.get() != NULL) {
146 for (int i = 0; i < kHashCount; ++i) {
147 if (fCharToGlyphHash[i].fGlyphIndex >= SkToU16(insertion_index)) {
148 fCharToGlyphHash[i].fGlyphIndex += 1;
149 }
150 }
151 }
152 }
153
134 /////////////////////////////////////////////////////////////////////////////// 154 ///////////////////////////////////////////////////////////////////////////////
135 155
136 #ifdef SK_DEBUG 156 #ifdef SK_DEBUG
137 #define VALIDATE() AutoValidate av(this) 157 #define VALIDATE() AutoValidate av(this)
138 #else 158 #else
139 #define VALIDATE() 159 #define VALIDATE()
140 #endif 160 #endif
141 161
142 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { 162 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) {
143 VALIDATE(); 163 VALIDATE();
144 uint32_t id = SkGlyph::MakeID(charCode); 164 uint32_t id = SkGlyph::MakeID(charCode);
145 const CharGlyphRec& rec = *this->getCharGlyphRec(id); 165 const CharGlyphRec& rec = *this->getCharGlyphRec(id);
146 166
147 if (rec.fID == id) { 167 if (rec.fID == id) {
148 return rec.fGlyph->getGlyphID(); 168 return fGlyphArray[rec.fGlyphIndex].getGlyphID();
149 } else { 169 } else {
150 return fScalerContext->charToGlyphID(charCode); 170 return fScalerContext->charToGlyphID(charCode);
151 } 171 }
152 } 172 }
153 173
154 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { 174 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) {
155 return fScalerContext->glyphIDToChar(glyphID); 175 return fScalerContext->glyphIDToChar(glyphID);
156 } 176 }
157 177
158 unsigned SkGlyphCache::getGlyphCount() { 178 unsigned SkGlyphCache::getGlyphCount() {
159 return fScalerContext->getGlyphCount(); 179 return fScalerContext->getGlyphCount();
160 } 180 }
161 181
162 /////////////////////////////////////////////////////////////////////////////// 182 ///////////////////////////////////////////////////////////////////////////////
163 183
164 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { 184 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) {
165 VALIDATE(); 185 VALIDATE();
166 uint32_t id = SkGlyph::MakeID(charCode); 186 return *this->lookupByChar(charCode, kJustAdvance_MetricsType);
167 CharGlyphRec* rec = this->getCharGlyphRec(id);
168
169 if (rec->fID != id) {
170 // this ID is based on the UniChar
171 rec->fID = id;
172 // this ID is based on the glyph index
173 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode));
174 rec->fGlyph = this->lookupMetrics(id, kJustAdvance_MetricsType);
175 }
176 return *rec->fGlyph;
177 } 187 }
178 188
179 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { 189 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) {
180 VALIDATE(); 190 VALIDATE();
181 uint32_t id = SkGlyph::MakeID(glyphID); 191 uint32_t id = SkGlyph::MakeID(glyphID);
182 unsigned index = ID2HashIndex(id); 192 return *this->lookupByCombinedID(id, kJustAdvance_MetricsType);
183 SkGlyph* glyph = fGlyphHash[index];
184
185 if (NULL == glyph || glyph->fID != id) {
186 glyph = this->lookupMetrics(glyphID, kJustAdvance_MetricsType);
187 fGlyphHash[index] = glyph;
188 }
189 return *glyph;
190 } 193 }
191 194
192 /////////////////////////////////////////////////////////////////////////////// 195 ///////////////////////////////////////////////////////////////////////////////
193 196
194 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { 197 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) {
195 VALIDATE(); 198 VALIDATE();
196 uint32_t id = SkGlyph::MakeID(charCode); 199 return *this->lookupByChar(charCode, kFull_MetricsType);
197 CharGlyphRec* rec = this->getCharGlyphRec(id);
198
199 if (rec->fID != id) {
200 RecordHashCollisionIf(rec->fGlyph != NULL);
201 // this ID is based on the UniChar
202 rec->fID = id;
203 // this ID is based on the glyph index
204 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode));
205 rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType);
206 } else {
207 RecordHashSuccess();
208 if (rec->fGlyph->isJustAdvance()) {
209 fScalerContext->getMetrics(rec->fGlyph);
210 }
211 }
212 SkASSERT(rec->fGlyph->isFullMetrics());
213 return *rec->fGlyph;
214 } 200 }
215 201
216 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, 202 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode,
217 SkFixed x, SkFixed y) { 203 SkFixed x, SkFixed y) {
218 VALIDATE(); 204 VALIDATE();
219 uint32_t id = SkGlyph::MakeID(charCode, x, y); 205 return *this->lookupByChar(charCode, kFull_MetricsType, x, y);
220 CharGlyphRec* rec = this->getCharGlyphRec(id);
221
222 if (rec->fID != id) {
223 RecordHashCollisionIf(rec->fGlyph != NULL);
224 // this ID is based on the UniChar
225 rec->fID = id;
226 // this ID is based on the glyph index
227 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y);
228 rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType);
229 } else {
230 RecordHashSuccess();
231 if (rec->fGlyph->isJustAdvance()) {
232 fScalerContext->getMetrics(rec->fGlyph);
233 }
234 }
235 SkASSERT(rec->fGlyph->isFullMetrics());
236 return *rec->fGlyph;
237 } 206 }
238 207
239 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { 208 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) {
240 VALIDATE(); 209 VALIDATE();
241 uint32_t id = SkGlyph::MakeID(glyphID); 210 uint32_t id = SkGlyph::MakeID(glyphID);
242 unsigned index = ID2HashIndex(id); 211 return *this->lookupByCombinedID(id, kFull_MetricsType);
243 SkGlyph* glyph = fGlyphHash[index];
244
245 if (NULL == glyph || glyph->fID != id) {
246 RecordHashCollisionIf(glyph != NULL);
247 glyph = this->lookupMetrics(glyphID, kFull_MetricsType);
248 fGlyphHash[index] = glyph;
249 } else {
250 RecordHashSuccess();
251 if (glyph->isJustAdvance()) {
252 fScalerContext->getMetrics(glyph);
253 }
254 }
255 SkASSERT(glyph->isFullMetrics());
256 return *glyph;
257 } 212 }
258 213
259 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) { 214 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) {
260 VALIDATE(); 215 VALIDATE();
261 uint32_t id = SkGlyph::MakeID(glyphID, x, y); 216 uint32_t id = SkGlyph::MakeID(glyphID, x, y);
262 unsigned index = ID2HashIndex(id); 217 return *this->lookupByCombinedID(id, kFull_MetricsType);
263 SkGlyph* glyph = fGlyphHash[index]; 218 }
264 219
265 if (NULL == glyph || glyph->fID != id) { 220 SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixe d x, SkFixed y) {
266 RecordHashCollisionIf(glyph != NULL); 221 uint32_t id = SkGlyph::MakeID(charCode, x, y);
267 glyph = this->lookupMetrics(id, kFull_MetricsType); 222 CharGlyphRec* rec = this->getCharGlyphRec(id);
268 fGlyphHash[index] = glyph; 223 SkGlyph* glyph;
224 if (rec->fID != id) {
225 RecordHashCollisionIf(glyph_index != kSentinelGlyphIndex);
226 // this ID is based on the UniChar
227 rec->fID = id;
228 // this ID is based on the glyph index
229 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y);
230 rec->fGlyphIndex = this->lookupMetrics(id, type);
231 glyph = &fGlyphArray[rec->fGlyphIndex];
269 } else { 232 } else {
270 RecordHashSuccess(); 233 RecordHashSuccess();
271 if (glyph->isJustAdvance()) { 234 glyph = &fGlyphArray[rec->fGlyphIndex];
235 if (type == kFull_MetricsType && glyph->isJustAdvance()) {
272 fScalerContext->getMetrics(glyph); 236 fScalerContext->getMetrics(glyph);
273 } 237 }
274 } 238 }
275 SkASSERT(glyph->isFullMetrics()); 239 return glyph;
276 return *glyph;
277 } 240 }
278 241
279 SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { 242 SkGlyph* SkGlyphCache::lookupByCombinedID(uint32_t id, MetricsType type) {
280 SkGlyph* glyph; 243 uint32_t hash_index = ID2HashIndex(id);
244 uint16_t glyph_index = fGlyphHash[hash_index];
245 SkGlyph* glyph = &fGlyphArray[glyph_index];
246
247 if (glyph->fID != id) {
248 RecordHashCollisionIf(glyph_index != kSentinelGlyphIndex);
249 glyph_index = this->lookupMetrics(id, type);
250 fGlyphHash[hash_index] = glyph_index;
251 glyph = &fGlyphArray[glyph_index];
252 } else {
253 RecordHashSuccess();
254 if (type == kFull_MetricsType && glyph->isJustAdvance()) {
255 fScalerContext->getMetrics(glyph);
256 }
257 }
258 return glyph;
259 }
281 260
282 int hi = 0; 261 uint16_t SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) {
283 int count = fGlyphArray.count(); 262 // Count is always greater than 0 because of the sentinel.
284 263 // The fGlyphArray cache is in descending order, so that the sentinel with a value of ~0 is
285 if (count) { 264 // always at index 0.
286 SkGlyph** gptr = fGlyphArray.begin(); 265 SkGlyph* gptr = fGlyphArray.begin();
287 int lo = 0; 266 int lo = 0;
288 267 int hi = fGlyphArray.count() - 1;
289 hi = count - 1; 268 while (lo < hi) {
290 while (lo < hi) { 269 int mid = (hi + lo) >> 1;
291 int mid = (hi + lo) >> 1; 270 if (gptr[mid].fID > id) {
292 if (gptr[mid]->fID < id) { 271 lo = mid + 1;
293 lo = mid + 1; 272 } else {
294 } else { 273 hi = mid;
295 hi = mid;
296 }
297 }
298 glyph = gptr[hi];
299 if (glyph->fID == id) {
300 if (kFull_MetricsType == mtype && glyph->isJustAdvance()) {
301 fScalerContext->getMetrics(glyph);
302 }
303 return glyph;
304 }
305
306 // check if we need to bump hi before falling though to the allocator
307 if (glyph->fID < id) {
308 hi += 1;
309 } 274 }
310 } 275 }
311 276
312 // not found, but hi tells us where to inser the new glyph 277 uint16_t glyph_index = hi;
278 SkGlyph* glyph = &gptr[glyph_index];
279 if (glyph->fID == id) {
280 if (kFull_MetricsType == mtype && glyph->isJustAdvance()) {
281 fScalerContext->getMetrics(glyph);
282 }
283 SkASSERT(glyph_index != kSentinelGlyphIndex);
284 return glyph_index;
285 }
286
287 // check if we need to bump hi before falling though to the allocator
288 if (glyph->fID > id) {
289 glyph_index += 1;
290 }
291
292 // Not found, but hi contains the index of the insertion point of the new gl yph.
313 fMemoryUsed += sizeof(SkGlyph); 293 fMemoryUsed += sizeof(SkGlyph);
294
295 this->adjustCaches(glyph_index);
314 296
315 glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph), 297 glyph = fGlyphArray.insert(glyph_index);
316 SkChunkAlloc::kThrow_AllocFailType); 298 glyph->initGlyphFromCombinedID(id);
317 glyph->initCommon(id);
318 *fGlyphArray.insert(hi) = glyph;
319 299
320 if (kJustAdvance_MetricsType == mtype) { 300 if (kJustAdvance_MetricsType == mtype) {
321 fScalerContext->getAdvance(glyph); 301 fScalerContext->getAdvance(glyph);
322 } else { 302 } else {
323 SkASSERT(kFull_MetricsType == mtype); 303 SkASSERT(kFull_MetricsType == mtype);
324 fScalerContext->getMetrics(glyph); 304 fScalerContext->getMetrics(glyph);
325 } 305 }
326 306
327 return glyph; 307 SkASSERT(glyph_index != kSentinelGlyphIndex);
308 return glyph_index;
328 } 309 }
329 310
330 const void* SkGlyphCache::findImage(const SkGlyph& glyph) { 311 const void* SkGlyphCache::findImage(const SkGlyph& glyph) {
331 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { 312 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) {
332 if (NULL == glyph.fImage) { 313 if (NULL == glyph.fImage) {
333 size_t size = glyph.computeImageSize(); 314 size_t size = glyph.computeImageSize();
334 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size, 315 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size,
335 SkChunkAlloc::kReturnNil_AllocFailType); 316 SkChunkAlloc::kReturnNil_AllocFailType);
336 // check that alloc() actually succeeded 317 // check that alloc() actually succeeded
337 if (glyph.fImage) { 318 if (glyph.fImage) {
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 return tls ? tls->getCacheSizeLimit() : 0; 727 return tls ? tls->getCacheSizeLimit() : 0;
747 } 728 }
748 729
749 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { 730 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
750 if (0 == bytes) { 731 if (0 == bytes) {
751 SkGlyphCache_Globals::DeleteTLS(); 732 SkGlyphCache_Globals::DeleteTLS();
752 } else { 733 } else {
753 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); 734 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes);
754 } 735 }
755 } 736 }
OLDNEW
« no previous file with comments | « src/core/SkGlyphCache.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698