OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #include "SkGlyphCache.h" | 10 #include "SkGlyphCache.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 SkASSERT(desc); | 79 SkASSERT(desc); |
80 SkASSERT(ctx); | 80 SkASSERT(ctx); |
81 | 81 |
82 fPrev = fNext = NULL; | 82 fPrev = fNext = NULL; |
83 | 83 |
84 fDesc = desc->copy(); | 84 fDesc = desc->copy(); |
85 fScalerContext->getFontMetrics(&fFontMetrics); | 85 fScalerContext->getFontMetrics(&fFontMetrics); |
86 | 86 |
87 // init to 0 so that all of the pointers will be null | 87 // init to 0 so that all of the pointers will be null |
88 memset(fGlyphHash, 0, sizeof(fGlyphHash)); | 88 memset(fGlyphHash, 0, sizeof(fGlyphHash)); |
89 | 89 // init with 0xFF so that the charCode field will be -1, which is invalid |
| 90 memset(fCharToGlyphHash, 0xFF, sizeof(fCharToGlyphHash)); |
| 91 |
90 fMemoryUsed = sizeof(*this); | 92 fMemoryUsed = sizeof(*this); |
91 | 93 |
92 fGlyphArray.setReserve(kMinGlyphCount); | 94 fGlyphArray.setReserve(kMinGlyphCount); |
93 | 95 |
94 fAuxProcList = NULL; | 96 fAuxProcList = NULL; |
95 } | 97 } |
96 | 98 |
97 SkGlyphCache::~SkGlyphCache() { | 99 SkGlyphCache::~SkGlyphCache() { |
98 #if 0 | 100 #if 0 |
99 { | 101 { |
100 size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*); | 102 size_t ptrMem = fGlyphArray.count() * sizeof(SkGlyph*); |
101 size_t glyphAlloc = fGlyphAlloc.totalCapacity(); | 103 size_t glyphAlloc = fGlyphAlloc.totalCapacity(); |
102 size_t glyphHashUsed = 0; | 104 size_t glyphHashUsed = 0; |
103 size_t uniHashUsed = 0; | 105 size_t uniHashUsed = 0; |
104 for (int i = 0; i < kHashCount; ++i) { | 106 for (int i = 0; i < kHashCount; ++i) { |
105 glyphHashUsed += fGlyphHash[i] ? sizeof(fGlyphHash[0]) : 0; | 107 glyphHashUsed += fGlyphHash[i] ? sizeof(fGlyphHash[0]) : 0; |
106 uniHashUsed += fCharToGlyphHash[i].fID != 0xFFFFFFFF ? sizeof(fCharT
oGlyphHash[0]) : 0; | 108 uniHashUsed += fCharToGlyphHash[i].fID != 0xFFFFFFFF ? sizeof(fCharT
oGlyphHash[0]) : 0; |
107 } | 109 } |
108 size_t glyphUsed = fGlyphArray.count() * sizeof(SkGlyph); | 110 size_t glyphUsed = fGlyphArray.count() * sizeof(SkGlyph); |
109 size_t imageUsed = 0; | 111 size_t imageUsed = 0; |
110 for (int i = 0; i < fGlyphArray.count(); ++i) { | 112 for (int i = 0; i < fGlyphArray.count(); ++i) { |
111 const SkGlyph& g = *fGlyphArray[i]; | 113 const SkGlyph& g = *fGlyphArray[i]; |
112 if (g.fImage) { | 114 if (g.fImage) { |
113 imageUsed += g.fHeight * g.rowBytes(); | 115 imageUsed += g.fHeight * g.rowBytes(); |
114 } | 116 } |
115 } | 117 } |
116 | 118 |
117 SkDebugf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, gl
yphHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n
", | 119 printf("glyphPtrArray,%zu, Alloc,%zu, imageUsed,%zu, glyphUsed,%zu, glyp
hHashAlloc,%zu, glyphHashUsed,%zu, unicharHashAlloc,%zu, unicharHashUsed,%zu\n", |
118 ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), g
lyphHashUsed, sizeof(CharGlyphRec) * kHashCount, uniHashUsed); | 120 ptrMem, glyphAlloc, imageUsed, glyphUsed, sizeof(fGlyphHash), g
lyphHashUsed, sizeof(fCharToGlyphHash), uniHashUsed); |
119 | 121 |
120 } | 122 } |
121 #endif | 123 #endif |
122 SkGlyph** gptr = fGlyphArray.begin(); | 124 SkGlyph** gptr = fGlyphArray.begin(); |
123 SkGlyph** stop = fGlyphArray.end(); | 125 SkGlyph** stop = fGlyphArray.end(); |
124 while (gptr < stop) { | 126 while (gptr < stop) { |
125 SkPath* path = (*gptr)->fPath; | 127 SkPath* path = (*gptr)->fPath; |
126 if (path) { | 128 if (path) { |
127 SkDELETE(path); | 129 SkDELETE(path); |
128 } | 130 } |
129 gptr += 1; | 131 gptr += 1; |
130 } | 132 } |
131 SkDescriptor::Free(fDesc); | 133 SkDescriptor::Free(fDesc); |
132 SkDELETE(fScalerContext); | 134 SkDELETE(fScalerContext); |
133 this->invokeAndRemoveAuxProcs(); | 135 this->invokeAndRemoveAuxProcs(); |
134 } | 136 } |
135 | 137 |
136 SkGlyphCache::CharGlyphRec* SkGlyphCache::getCharGlyphRec(uint32_t id) { | |
137 if (NULL == fCharToGlyphHash) { | |
138 fCharToGlyphHash.reset(new CharGlyphRec[kHashCount]); | |
139 // init with 0xFF so that the charCode field will be -1, which is invali
d | |
140 memset(fCharToGlyphHash, 0xFF, sizeof(CharGlyphRec) * kHashCount); | |
141 } | |
142 | |
143 return &fCharToGlyphHash[ID2HashIndex(id)]; | |
144 } | |
145 | |
146 /////////////////////////////////////////////////////////////////////////////// | 138 /////////////////////////////////////////////////////////////////////////////// |
147 | 139 |
148 #ifdef SK_DEBUG | 140 #ifdef SK_DEBUG |
149 #define VALIDATE() AutoValidate av(this) | 141 #define VALIDATE() AutoValidate av(this) |
150 #else | 142 #else |
151 #define VALIDATE() | 143 #define VALIDATE() |
152 #endif | 144 #endif |
153 | 145 |
154 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { | 146 uint16_t SkGlyphCache::unicharToGlyph(SkUnichar charCode) { |
155 VALIDATE(); | 147 VALIDATE(); |
156 uint32_t id = SkGlyph::MakeID(charCode); | 148 uint32_t id = SkGlyph::MakeID(charCode); |
157 const CharGlyphRec& rec = *this->getCharGlyphRec(id); | 149 const CharGlyphRec& rec = fCharToGlyphHash[ID2HashIndex(id)]; |
158 | 150 |
159 if (rec.fID == id) { | 151 if (rec.fID == id) { |
160 return rec.fGlyph->getGlyphID(); | 152 return rec.fGlyph->getGlyphID(); |
161 } else { | 153 } else { |
162 return fScalerContext->charToGlyphID(charCode); | 154 return fScalerContext->charToGlyphID(charCode); |
163 } | 155 } |
164 } | 156 } |
165 | 157 |
166 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { | 158 SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { |
167 return fScalerContext->glyphIDToChar(glyphID); | 159 return fScalerContext->glyphIDToChar(glyphID); |
168 } | 160 } |
169 | 161 |
170 unsigned SkGlyphCache::getGlyphCount() { | 162 unsigned SkGlyphCache::getGlyphCount() { |
171 return fScalerContext->getGlyphCount(); | 163 return fScalerContext->getGlyphCount(); |
172 } | 164 } |
173 | 165 |
174 /////////////////////////////////////////////////////////////////////////////// | 166 /////////////////////////////////////////////////////////////////////////////// |
175 | 167 |
176 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { | 168 const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { |
177 VALIDATE(); | 169 VALIDATE(); |
178 uint32_t id = SkGlyph::MakeID(charCode); | 170 uint32_t id = SkGlyph::MakeID(charCode); |
179 CharGlyphRec* rec = this->getCharGlyphRec(id); | 171 CharGlyphRec* rec = &fCharToGlyphHash[ID2HashIndex(id)]; |
180 | 172 |
181 if (rec->fID != id) { | 173 if (rec->fID != id) { |
182 // this ID is based on the UniChar | 174 // this ID is based on the UniChar |
183 rec->fID = id; | 175 rec->fID = id; |
184 // this ID is based on the glyph index | 176 // this ID is based on the glyph index |
185 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode)); | 177 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode)); |
186 rec->fGlyph = this->lookupMetrics(id, kJustAdvance_MetricsType); | 178 rec->fGlyph = this->lookupMetrics(id, kJustAdvance_MetricsType); |
187 } | 179 } |
188 return *rec->fGlyph; | 180 return *rec->fGlyph; |
189 } | 181 } |
190 | 182 |
191 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { | 183 const SkGlyph& SkGlyphCache::getGlyphIDAdvance(uint16_t glyphID) { |
192 VALIDATE(); | 184 VALIDATE(); |
193 uint32_t id = SkGlyph::MakeID(glyphID); | 185 uint32_t id = SkGlyph::MakeID(glyphID); |
194 unsigned index = ID2HashIndex(id); | 186 unsigned index = ID2HashIndex(id); |
195 SkGlyph* glyph = fGlyphHash[index]; | 187 SkGlyph* glyph = fGlyphHash[index]; |
196 | 188 |
197 if (NULL == glyph || glyph->fID != id) { | 189 if (NULL == glyph || glyph->fID != id) { |
198 glyph = this->lookupMetrics(glyphID, kJustAdvance_MetricsType); | 190 glyph = this->lookupMetrics(glyphID, kJustAdvance_MetricsType); |
199 fGlyphHash[index] = glyph; | 191 fGlyphHash[index] = glyph; |
200 } | 192 } |
201 return *glyph; | 193 return *glyph; |
202 } | 194 } |
203 | 195 |
204 /////////////////////////////////////////////////////////////////////////////// | 196 /////////////////////////////////////////////////////////////////////////////// |
205 | 197 |
206 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { | 198 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode) { |
207 VALIDATE(); | 199 VALIDATE(); |
208 uint32_t id = SkGlyph::MakeID(charCode); | 200 uint32_t id = SkGlyph::MakeID(charCode); |
209 CharGlyphRec* rec = this->getCharGlyphRec(id); | 201 CharGlyphRec* rec = &fCharToGlyphHash[ID2HashIndex(id)]; |
210 | 202 |
211 if (rec->fID != id) { | 203 if (rec->fID != id) { |
212 RecordHashCollisionIf(rec->fGlyph != NULL); | 204 RecordHashCollisionIf(rec->fGlyph != NULL); |
213 // this ID is based on the UniChar | 205 // this ID is based on the UniChar |
214 rec->fID = id; | 206 rec->fID = id; |
215 // this ID is based on the glyph index | 207 // this ID is based on the glyph index |
216 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode)); | 208 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode)); |
217 rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType); | 209 rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType); |
218 } else { | 210 } else { |
219 RecordHashSuccess(); | 211 RecordHashSuccess(); |
220 if (rec->fGlyph->isJustAdvance()) { | 212 if (rec->fGlyph->isJustAdvance()) { |
221 fScalerContext->getMetrics(rec->fGlyph); | 213 fScalerContext->getMetrics(rec->fGlyph); |
222 } | 214 } |
223 } | 215 } |
224 SkASSERT(rec->fGlyph->isFullMetrics()); | 216 SkASSERT(rec->fGlyph->isFullMetrics()); |
225 return *rec->fGlyph; | 217 return *rec->fGlyph; |
226 } | 218 } |
227 | 219 |
228 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, | 220 const SkGlyph& SkGlyphCache::getUnicharMetrics(SkUnichar charCode, |
229 SkFixed x, SkFixed y) { | 221 SkFixed x, SkFixed y) { |
230 VALIDATE(); | 222 VALIDATE(); |
231 uint32_t id = SkGlyph::MakeID(charCode, x, y); | 223 uint32_t id = SkGlyph::MakeID(charCode, x, y); |
232 CharGlyphRec* rec = this->getCharGlyphRec(id); | 224 CharGlyphRec* rec = &fCharToGlyphHash[ID2HashIndex(id)]; |
233 | 225 |
234 if (rec->fID != id) { | 226 if (rec->fID != id) { |
235 RecordHashCollisionIf(rec->fGlyph != NULL); | 227 RecordHashCollisionIf(rec->fGlyph != NULL); |
236 // this ID is based on the UniChar | 228 // this ID is based on the UniChar |
237 rec->fID = id; | 229 rec->fID = id; |
238 // this ID is based on the glyph index | 230 // this ID is based on the glyph index |
239 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y); | 231 id = SkGlyph::MakeID(fScalerContext->charToGlyphID(charCode), x, y); |
240 rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType); | 232 rec->fGlyph = this->lookupMetrics(id, kFull_MetricsType); |
241 } else { | 233 } else { |
242 RecordHashSuccess(); | 234 RecordHashSuccess(); |
(...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 return tls ? tls->getCacheSizeLimit() : 0; | 701 return tls ? tls->getCacheSizeLimit() : 0; |
710 } | 702 } |
711 | 703 |
712 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { | 704 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { |
713 if (0 == bytes) { | 705 if (0 == bytes) { |
714 SkGlyphCache_Globals::DeleteTLS(); | 706 SkGlyphCache_Globals::DeleteTLS(); |
715 } else { | 707 } else { |
716 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); | 708 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes); |
717 } | 709 } |
718 } | 710 } |
OLD | NEW |