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

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 asserts for checking code in range 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
« src/core/SkGlyphCache.h ('K') | « 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(kSentinelGlyphID);
72 sentinel->init(0);
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(int16_t insertion_index) {
140 for (int i = 0; i < kHashCount; ++i) {
141 if (fGlyphHash[i] >= 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 >= 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->lookupByChar(id, kJustAdvance_MetricsType);
183 SkGlyph* glyph = fGlyphHash[index];
184 193
185 if (NULL == glyph || glyph->fID != id) {
186 glyph = this->lookupMetrics(glyphID, kJustAdvance_MetricsType);
187 fGlyphHash[index] = glyph;
188 }
189 return *glyph;
190 } 194 }
191 195
192 /////////////////////////////////////////////////////////////////////////////// 196 ///////////////////////////////////////////////////////////////////////////////
193 197
194 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { 198 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) {
195 VALIDATE(); 199 VALIDATE();
196 uint32_t id = SkGlyph::MakeID(charCode); 200 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 } 201 }
215 202
216 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, 203 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode,
217 SkFixed x, SkFixed y) { 204 SkFixed x, SkFixed y) {
218 VALIDATE(); 205 VALIDATE();
219 uint32_t id = SkGlyph::MakeID(charCode, x, y); 206 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 } 207 }
238 208
239 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) { 209 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID) {
240 VALIDATE(); 210 VALIDATE();
241 uint32_t id = SkGlyph::MakeID(glyphID); 211 uint32_t id = SkGlyph::MakeID(glyphID);
242 unsigned index = ID2HashIndex(id); 212 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 } 213 }
258 214
259 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) { 215 const SkGlyph& SkGlyphCache::getGlyphIDMetrics(uint16_t glyphID, SkFixed x, SkFi xed y) {
260 VALIDATE(); 216 VALIDATE();
261 uint32_t id = SkGlyph::MakeID(glyphID, x, y); 217 uint32_t id = SkGlyph::MakeID(glyphID, x, y);
262 unsigned index = ID2HashIndex(id); 218 return *this->lookupByCombinedID(id, kFull_MetricsType);
263 SkGlyph* glyph = fGlyphHash[index]; 219 }
264 220
265 if (NULL == glyph || glyph->fID != id) { 221 SkGlyph* SkGlyphCache::lookupByChar(SkUnichar charCode, MetricsType type, SkFixe d x, SkFixed y) {
266 RecordHashCollisionIf(glyph != NULL); 222 uint32_t id = SkGlyph::MakeID(charCode, x, y);
267 glyph = this->lookupMetrics(id, kFull_MetricsType); 223 CharGlyphRec* rec = this->getCharGlyphRec(id);
268 fGlyphHash[index] = glyph; 224 SkGlyph* glyph;
225 if (rec->fID != id) {
226 RecordHashCollisionIf(glyph_index != kSentinelGlyphIndex);
227 // this ID is based on the UniChar
228 rec->fID = id;
229 // this ID is based on the glyph index
230 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y);
231 rec->fGlyphIndex = this->lookupMetrics(id, type);
232 glyph = &fGlyphArray[rec->fGlyphIndex];
269 } else { 233 } else {
270 RecordHashSuccess(); 234 RecordHashSuccess();
271 if (glyph->isJustAdvance()) { 235 glyph = &fGlyphArray[rec->fGlyphIndex];
236 if (type == kFull_MetricsType && glyph->isJustAdvance()) {
272 fScalerContext->getMetrics(glyph); 237 fScalerContext->getMetrics(glyph);
273 } 238 }
274 } 239 }
275 SkASSERT(glyph->isFullMetrics()); 240 return glyph;
276 return *glyph;
277 } 241 }
278 242
279 SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) { 243 SkGlyph* SkGlyphCache::lookupByCombinedID(uint32_t id, MetricsType type) {
280 SkGlyph* glyph; 244 uint32_t hash_index = ID2HashIndex(id);
245 uint16_t glyph_index = fGlyphHash[hash_index];
246 SkGlyph* glyph = &fGlyphArray[glyph_index];
247
248 if (glyph->fID != id) {
249 RecordHashCollisionIf(glyph_index != kSentinelGlyphIndex);
250 glyph_index = this->lookupMetrics(id, type);
251 fGlyphHash[hash_index] = glyph_index;
252 glyph = &fGlyphArray[glyph_index];
253 } else {
254 RecordHashSuccess();
255 if (type == kFull_MetricsType && glyph->isJustAdvance()) {
256 fScalerContext->getMetrics(glyph);
257 }
258 }
259 return glyph;
260 }
281 261
282 int hi = 0; 262 uint16_t SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) {
283 int count = fGlyphArray.count(); 263 // Count is always greater than 0 because of the sentinel.
284 264 SkGlyph* gptr = fGlyphArray.begin();
285 if (count) { 265 int lo = 0;
286 SkGlyph** gptr = fGlyphArray.begin(); 266 int hi = fGlyphArray.count() - 1;
287 int lo = 0; 267 while (lo < hi) {
288 268 int mid = (hi + lo) >> 1;
289 hi = count - 1; 269 if (gptr[mid].fID < id) {
290 while (lo < hi) { 270 lo = mid + 1;
291 int mid = (hi + lo) >> 1; 271 } else {
292 if (gptr[mid]->fID < id) { 272 hi = mid;
293 lo = mid + 1;
294 } else {
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 } 273 }
310 } 274 }
311 275
276 uint16_t glyph_index = hi;
277 SkGlyph* glyph = &gptr[glyph_index];
278 if (glyph->fID == id) {
279 if (kFull_MetricsType == mtype && glyph->isJustAdvance()) {
280 fScalerContext->getMetrics(glyph);
281 }
282 SkASSERT(glyph_index != kSentinelGlyphIndex);
283 return glyph_index;
284 }
285
286 // check if we need to bump hi before falling though to the allocator
287 if (glyph->fID < id) {
288 glyph_index += 1;
289 }
290
312 // not found, but hi tells us where to inser the new glyph 291 // not found, but hi tells us where to inser the new glyph
313 fMemoryUsed += sizeof(SkGlyph); 292 fMemoryUsed += sizeof(SkGlyph);
293
294 this->adjustCaches(glyph_index);
314 295
315 glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph), 296 glyph = fGlyphArray.insert(glyph_index);
316 SkChunkAlloc::kThrow_AllocFailType);
317 glyph->init(id); 297 glyph->init(id);
318 *fGlyphArray.insert(hi) = glyph;
319 298
320 if (kJustAdvance_MetricsType == mtype) { 299 if (kJustAdvance_MetricsType == mtype) {
321 fScalerContext->getAdvance(glyph); 300 fScalerContext->getAdvance(glyph);
322 } else { 301 } else {
323 SkASSERT(kFull_MetricsType == mtype); 302 SkASSERT(kFull_MetricsType == mtype);
324 fScalerContext->getMetrics(glyph); 303 fScalerContext->getMetrics(glyph);
325 } 304 }
326 305
327 return glyph; 306 SkASSERT(glyph_index != kSentinelGlyphIndex);
307 return glyph_index;
328 } 308 }
329 309
330 const void* SkGlyphCache::findImage(const SkGlyph& glyph) { 310 const void* SkGlyphCache::findImage(const SkGlyph& glyph) {
331 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) { 311 if (glyph.fWidth > 0 && glyph.fWidth < kMaxGlyphWidth) {
332 if (NULL == glyph.fImage) { 312 if (NULL == glyph.fImage) {
333 size_t size = glyph.computeImageSize(); 313 size_t size = glyph.computeImageSize();
334 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size, 314 const_cast<SkGlyph&>(glyph).fImage = fGlyphAlloc.alloc(size,
335 SkChunkAlloc::kReturnNil_AllocFailType); 315 SkChunkAlloc::kReturnNil_AllocFailType);
336 // check that alloc() actually succeeded 316 // check that alloc() actually succeeded
337 if (glyph.fImage) { 317 if (glyph.fImage) {
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 return tls ? tls->getCacheSizeLimit() : 0; 726 return tls ? tls->getCacheSizeLimit() : 0;
747 } 727 }
748 728
749 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { 729 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
750 if (0 == bytes) { 730 if (0 == bytes) {
751 SkGlyphCache_Globals::DeleteTLS(); 731 SkGlyphCache_Globals::DeleteTLS();
752 } else { 732 } else {
753 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); 733 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes);
754 } 734 }
755 } 735 }
OLDNEW
« src/core/SkGlyphCache.h ('K') | « src/core/SkGlyphCache.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698