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

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: Add hash index adjustment 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 69
70 // init to 0 so that all of the pointers will be null 70 // init to 0 so that all of the pointers will be null
reed1 2015/01/30 13:57:38 comment (0) disagrees with the code (0xFF) I'm gu
herb_g 2015/02/01 05:09:27 Done.
71 memset(fGlyphHash, 0, sizeof(fGlyphHash)); 71 memset(fGlyphHash, 0xFF, sizeof(fGlyphHash));
72 72
73 fMemoryUsed = sizeof(*this); 73 fMemoryUsed = sizeof(*this);
74 74
75 fGlyphArray.setReserve(kMinGlyphCount); 75 fGlyphArray.setReserve(kMinGlyphCount);
76 76
77 fAuxProcList = NULL; 77 fAuxProcList = NULL;
78 78
79 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 79 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
80 fHashHitCount = fHashMissCount = 0; 80 fHashHitCount = fHashMissCount = 0;
81 #endif 81 #endif
82 } 82 }
(...skipping 16 matching lines...) Expand all
99 if (g.fImage) { 99 if (g.fImage) {
100 imageUsed += g.fHeight * g.rowBytes(); 100 imageUsed += g.fHeight * g.rowBytes();
101 } 101 }
102 } 102 }
103 103
104 SkDebugf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, gl yphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n ", 104 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); 105 ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), g lyphHashUsed, sizeof(CharGlyphRec) * kHashCount, uniHashUsed);
106 106
107 } 107 }
108 #endif 108 #endif
109 SkGlyph** gptr = fGlyphArray.begin(); 109 SkGlyph* gptr = fGlyphArray.begin();
110 SkGlyph** stop = fGlyphArray.end(); 110 SkGlyph* stop = fGlyphArray.end();
111 while (gptr < stop) { 111 while (gptr < stop) {
112 SkPath* path = (*gptr)->fPath; 112 SkPath* path = gptr->fPath;
113 if (path) { 113 if (path) {
114 SkDELETE(path); 114 SkDELETE(path);
115 } 115 }
116 gptr += 1; 116 gptr += 1;
117 } 117 }
118 SkDescriptor::Free(fDesc); 118 SkDescriptor::Free(fDesc);
119 SkDELETE(fScalerContext); 119 SkDELETE(fScalerContext);
120 this->invokeAndRemoveAuxProcs(); 120 this->invokeAndRemoveAuxProcs();
121 } 121 }
122 122
123
123 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) { 124 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) {
124 if (NULL == fCharToGlyphHash.get()) { 125 if (NULL == fCharToGlyphHash.get()) {
125 fCharToGlyphHash.reset(kHashCount); 126 fCharToGlyphHash.reset(kHashCount);
126 // init with 0xFF so that the charCode field will be -1, which is invali d 127 // init with 0xFF so that the charCode field will be -1, which is invali d
127 memset(fCharToGlyphHash.get(), 0xFF, 128 memset(fCharToGlyphHash.get(), 0xFF,
128 sizeof(CharGlyphRec) * kHashCount); 129 sizeof(CharGlyphRec) * kHashCount);
129 } 130 }
130 131
131 return &fCharToGlyphHash[ID2HashIndex(id)]; 132 return &fCharToGlyphHash[ID2HashIndex(id)];
132 } 133 }
133 134
135 void SkGlyphCache::adjustCaches(int16_t insertion_index) {
136 for (int i = 0; i < kHashCount; ++i) {
137 // Beware: the following code uses the wrap around behavior of the
138 // unsigned unint16_t to change the kInvalidGlyph value to zero allowing
139 // a single comparison for if the index needs to be incremented.
140 // This trick is also used below.
141 if (fGlyphHash[i] + 1 >= insertion_index + 1) {
142 fGlyphHash[i] += 1;
143 }
144 }
145 if (fCharToGlyphHash.get() != NULL) {
146 for (int i = 0; i < kHashCount; ++i) {
147 // See the warning about about the following code.
148 if (fCharToGlyphHash[i].fGlyphIndex + 1 >= insertion_index + 1) {
149 fCharToGlyphHash[i].fGlyphIndex += 1;
150 }
151 }
152 }
153 }
154
134 /////////////////////////////////////////////////////////////////////////////// 155 ///////////////////////////////////////////////////////////////////////////////
135 156
136 #ifdef SK_DEBUG 157 #ifdef SK_DEBUG
137 #define VALIDATE() AutoValidate av(this) 158 #define VALIDATE() AutoValidate av(this)
138 #else 159 #else
139 #define VALIDATE() 160 #define VALIDATE()
140 #endif 161 #endif
141 162
142 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { 163 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) {
143 VALIDATE(); 164 VALIDATE();
144 uint32_t id = SkGlyph::MakeID(charCode); 165 uint32_t id = SkGlyph::MakeID(charCode);
145 const CharGlyphRec& rec = *this->getCharGlyphRec(id); 166 const CharGlyphRec& rec = *this->getCharGlyphRec(id);
146 167
147 if (rec.fID == id) { 168 if (rec.fID == id) {
148 return rec.fGlyph->getGlyphID(); 169 return fGlyphArray[rec.fGlyphIndex].getGlyphID();
149 } else { 170 } else {
150 return fScalerContext->charToGlyphID(charCode); 171 return fScalerContext->charToGlyphID(charCode);
151 } 172 }
152 } 173 }
153 174
154 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { 175 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) {
155 return fScalerContext->glyphIDToChar(glyphID); 176 return fScalerContext->glyphIDToChar(glyphID);
156 } 177 }
157 178
158 unsigned SkGlyphCache::getGlyphCount() { 179 unsigned SkGlyphCache::getGlyphCount() {
159 return fScalerContext->getGlyphCount(); 180 return fScalerContext->getGlyphCount();
160 } 181 }
161 182
162 /////////////////////////////////////////////////////////////////////////////// 183 ///////////////////////////////////////////////////////////////////////////////
163 184
164 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { 185 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) {
165 VALIDATE(); 186 VALIDATE();
166 uint32_t id = SkGlyph::MakeID(charCode); 187 return *maintainCharCache(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 } 188 }
178 189
179 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { 190 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) {
180 VALIDATE(); 191 VALIDATE();
181 uint32_t id = SkGlyph::MakeID(glyphID); 192 uint32_t id = SkGlyph::MakeID(glyphID);
182 unsigned index = ID2HashIndex(id); 193 return *maintainGlyphCache(id, kJustAdvance_MetricsType);
183 SkGlyph* glyph = fGlyphHash[index];
184 194
185 if (NULL == glyph || glyph->fID != id) {
186 glyph = this->lookupMetrics(glyphID, kJustAdvance_MetricsType);
187 fGlyphHash[index] = glyph;
188 }
189 return *glyph;
190 } 195 }
191 196
192 /////////////////////////////////////////////////////////////////////////////// 197 ///////////////////////////////////////////////////////////////////////////////
193 198
194 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { 199 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) {
195 VALIDATE(); 200 VALIDATE();
196 uint32_t id = SkGlyph::MakeID(charCode); 201 return *maintainCharCache(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 } 202 }
215 203
216 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, 204 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode,
217 SkFixed x, SkFixed y) { 205 SkFixed x, SkFixed y) {
218 VALIDATE(); 206 VALIDATE();
219 uint32_t id = SkGlyph::MakeID(charCode, x, y); 207 return *maintainCharCache(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 } 208 }
238 209
239 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { 210 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) {
240 VALIDATE(); 211 VALIDATE();
241 uint32_t id = SkGlyph::MakeID(glyphID); 212 uint32_t id = SkGlyph::MakeID(glyphID);
242 unsigned index = ID2HashIndex(id); 213 return *this->maintainGlyphCache(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 } 214 }
258 215
259 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) { 216 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) {
260 VALIDATE(); 217 VALIDATE();
261 uint32_t id = SkGlyph::MakeID(glyphID, x, y); 218 uint32_t id = SkGlyph::MakeID(glyphID, x, y);
262 unsigned index = ID2HashIndex(id); 219 return *this->maintainGlyphCache(id, kFull_MetricsType);
263 SkGlyph* glyph = fGlyphHash[index]; 220 }
264 221
265 if (NULL == glyph || glyph->fID != id) { 222 SkGlyph* SkGlyphCache::maintainCharCache(SkUnichar charCode, MetricsType type, S kFixed x, SkFixed y) {
266 RecordHashCollisionIf(glyph != NULL); 223 uint32_t id = SkGlyph::MakeID(charCode, x, y);
267 glyph = this->lookupMetrics(id, kFull_MetricsType); 224 CharGlyphRec* rec = this->getCharGlyphRec(id);
268 fGlyphHash[index] = glyph; 225 SkGlyph* glyph;
226 if (rec->fID != id) {
227 RecordHashCollisionIf(rec->fGlyph != kInvalidGlyph);
228 // this ID is based on the UniChar
229 rec->fID = id;
230 // this ID is based on the glyph index
231 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y);
232 rec->fGlyphIndex = this->lookupMetrics(id, kFull_MetricsType);
233 glyph = &fGlyphArray[rec->fGlyphIndex];
269 } else { 234 } else {
270 RecordHashSuccess(); 235 RecordHashSuccess();
271 if (glyph->isJustAdvance()) { 236 glyph = &fGlyphArray[rec->fGlyphIndex];
237 if (type == kFull_MetricsType && glyph->isJustAdvance()) {
272 fScalerContext->getMetrics(glyph); 238 fScalerContext->getMetrics(glyph);
273 } 239 }
274 } 240 }
275 SkASSERT(glyph->isFullMetrics()); 241 SkASSERT(glyph->isFullMetrics());
276 return *glyph; 242 return glyph;
277 } 243 }
278 244
279 SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { 245 SkGlyph* SkGlyphCache::maintainGlyphCache(uint32_t id, MetricsType type) {
246 uint32_t hash_index = ID2HashIndex(id);
247 uint16_t glyph_index = fGlyphHash[hash_index];
280 SkGlyph* glyph; 248 SkGlyph* glyph;
249
250 if (kInvalidGlyph == glyph_index
251 || (glyph = &fGlyphArray[glyph_index])->fID != id) {
252 RecordHashCollisionIf(glyph != NULL);
253 glyph_index = this->lookupMetrics(id, type);
254 fGlyphHash[hash_index] = glyph_index;
255 glyph = &fGlyphArray[glyph_index];
256 } else {
257 RecordHashSuccess();
258 if (type == kFull_MetricsType && glyph->isJustAdvance()) {
259 fScalerContext->getMetrics(glyph);
260 }
261 SkASSERT(glyph->isFullMetrics());
262 }
263 return glyph;
264 }
281 265
282 int hi = 0; 266 uint16_t SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) {
283 int count = fGlyphArray.count(); 267 uint16_t glyph_index = 0;
284 268 int count = fGlyphArray.count();
285 if (count) { 269 int hi = 0;
286 SkGlyph** gptr = fGlyphArray.begin(); 270
287 int lo = 0; 271 if (count > 0) {
288 272 SkGlyph* gptr = fGlyphArray.begin();
273 int lo = 0;
274
289 hi = count - 1; 275 hi = count - 1;
290 while (lo < hi) { 276 while (lo < hi) {
291 int mid = (hi + lo) >> 1; 277 int mid = (hi + lo) >> 1;
292 if (gptr[mid]->fID < id) { 278 if (gptr[mid].fID < id) {
293 lo = mid + 1; 279 lo = mid + 1;
294 } else { 280 } else {
295 hi = mid; 281 hi = mid;
296 } 282 }
297 } 283 }
298 glyph = gptr[hi]; 284 glyph_index = hi;
285 SkGlyph* glyph = &gptr[hi];
299 if (glyph->fID == id) { 286 if (glyph->fID == id) {
300 if (kFull_MetricsType == mtype && glyph->isJustAdvance()) { 287 if (kFull_MetricsType == mtype && glyph->isJustAdvance()) {
301 fScalerContext->getMetrics(glyph); 288 fScalerContext->getMetrics(glyph);
302 } 289 }
303 return glyph; 290 return glyph_index;
304 } 291 }
305 292
306 // check if we need to bump hi before falling though to the allocator 293 // check if we need to bump hi before falling though to the allocator
307 if (glyph->fID < id) { 294 if (glyph->fID < id) {
308 hi += 1; 295 glyph_index += 1;
309 } 296 }
310 } 297 }
311 298
312 // not found, but hi tells us where to inser the new glyph 299 // not found, but hi tells us where to inser the new glyph
313 fMemoryUsed += sizeof(SkGlyph); 300 fMemoryUsed += sizeof(SkGlyph);
301
302 this->adjustCaches(glyph_index);
314 303
315 glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph), 304 SkGlyph* glyph = fGlyphArray.insert(glyph_index);
316 SkChunkAlloc::kThrow_AllocFailType);
317 glyph->init(id); 305 glyph->init(id);
318 *fGlyphArray.insert(hi) = glyph;
319 306
320 if (kJustAdvance_MetricsType == mtype) { 307 if (kJustAdvance_MetricsType == mtype) {
321 fScalerContext->getAdvance(glyph); 308 fScalerContext->getAdvance(glyph);
322 } else { 309 } else {
323 SkASSERT(kFull_MetricsType == mtype); 310 SkASSERT(kFull_MetricsType == mtype);
324 fScalerContext->getMetrics(glyph); 311 fScalerContext->getMetrics(glyph);
325 } 312 }
326 313
327 return glyph; 314 return glyph_index;
328 } 315 }
329 316
330 const void* SkGlyphCache::findImage(const SkGlyph& glyph) { 317 const void* SkGlyphCache::findImage(const SkGlyph& glyph) {
331 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { 318 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) {
332 if (NULL == glyph.fImage) { 319 if (NULL == glyph.fImage) {
333 size_t size = glyph.computeImageSize(); 320 size_t size = glyph.computeImageSize();
334 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size, 321 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size,
335 SkChunkAlloc::kReturnNil_AllocFailType); 322 SkChunkAlloc::kReturnNil_AllocFailType);
336 // check that alloc() actually succeeded 323 // check that alloc() actually succeeded
337 if (glyph.fImage) { 324 if (glyph.fImage) {
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 return tls ? tls->getCacheSizeLimit() : 0; 733 return tls ? tls->getCacheSizeLimit() : 0;
747 } 734 }
748 735
749 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { 736 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
750 if (0 == bytes) { 737 if (0 == bytes) {
751 SkGlyphCache_Globals::DeleteTLS(); 738 SkGlyphCache_Globals::DeleteTLS();
752 } else { 739 } else {
753 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); 740 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes);
754 } 741 }
755 } 742 }
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