OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2010 Google Inc. | 2 * Copyright 2010 Google Inc. |
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 "GrAtlas.h" | 8 #include "GrAtlas.h" |
9 #include "GrGpu.h" | 9 #include "GrGpu.h" |
10 #include "GrRectanizer.h" | 10 #include "GrRectanizer.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 fTail = NULL; | 103 fTail = NULL; |
104 } | 104 } |
105 | 105 |
106 void GrFontCache::purgeStrike(GrTextStrike* strike) { | 106 void GrFontCache::purgeStrike(GrTextStrike* strike) { |
107 const GrFontCache::Key key(strike->fFontScalerKey); | 107 const GrFontCache::Key key(strike->fFontScalerKey); |
108 fCache.remove(key, strike); | 108 fCache.remove(key, strike); |
109 this->detachStrikeFromList(strike); | 109 this->detachStrikeFromList(strike); |
110 delete strike; | 110 delete strike; |
111 } | 111 } |
112 | 112 |
113 void GrFontCache::purgeExceptFor(GrTextStrike* preserveStrike) { | 113 bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike) { |
114 SkASSERT(NULL != preserveStrike); | 114 SkASSERT(NULL != preserveStrike); |
115 GrTextStrike* strike = fTail; | 115 |
116 bool purge = true; | 116 GrAtlasMgr* atlasMgr = preserveStrike->fAtlasMgr; |
| 117 GrPlot* plot = atlasMgr->getUnusedPlot(); |
| 118 if (NULL == plot) { |
| 119 return false; |
| 120 } |
| 121 plot->resetRects(); |
| 122 |
| 123 GrTextStrike* strike = fHead; |
117 GrMaskFormat maskFormat = preserveStrike->fMaskFormat; | 124 GrMaskFormat maskFormat = preserveStrike->fMaskFormat; |
118 while (strike) { | 125 while (strike) { |
119 if (strike == preserveStrike || maskFormat != strike->fMaskFormat) { | 126 if (maskFormat != strike->fMaskFormat) { |
120 strike = strike->fPrev; | 127 strike = strike->fNext; |
121 continue; | 128 continue; |
122 } | 129 } |
| 130 |
123 GrTextStrike* strikeToPurge = strike; | 131 GrTextStrike* strikeToPurge = strike; |
124 strike = strikeToPurge->fPrev; | 132 strike = strikeToPurge->fNext; |
125 if (purge) { | 133 strikeToPurge->removePlot(plot); |
126 // keep purging if we won't free up any atlases with this strike. | 134 |
127 purge = strikeToPurge->fAtlas.isEmpty(); | 135 // clear out any empty strikes (except this one) |
| 136 if (strikeToPurge != preserveStrike && strikeToPurge->fAtlas.isEmpty())
{ |
128 this->purgeStrike(strikeToPurge); | 137 this->purgeStrike(strikeToPurge); |
129 } | 138 } |
130 } | 139 } |
| 140 |
131 #if FONT_CACHE_STATS | 141 #if FONT_CACHE_STATS |
132 ++g_PurgeCount; | 142 ++g_PurgeCount; |
133 #endif | 143 #endif |
134 } | |
135 | 144 |
136 void GrFontCache::freePlotExceptFor(GrTextStrike* preserveStrike) { | 145 return true; |
137 SkASSERT(NULL != preserveStrike); | |
138 GrTextStrike* strike = fTail; | |
139 GrMaskFormat maskFormat = preserveStrike->fMaskFormat; | |
140 while (strike) { | |
141 if (strike == preserveStrike || maskFormat != strike->fMaskFormat) { | |
142 strike = strike->fPrev; | |
143 continue; | |
144 } | |
145 GrTextStrike* strikeToPurge = strike; | |
146 strike = strikeToPurge->fPrev; | |
147 if (strikeToPurge->removeUnusedPlots()) { | |
148 if (strikeToPurge->fAtlas.isEmpty()) { | |
149 this->purgeStrike(strikeToPurge); | |
150 } | |
151 break; | |
152 } | |
153 } | |
154 } | 146 } |
155 | 147 |
156 #ifdef SK_DEBUG | 148 #ifdef SK_DEBUG |
157 void GrFontCache::validate() const { | 149 void GrFontCache::validate() const { |
158 int count = fCache.count(); | 150 int count = fCache.count(); |
159 if (0 == count) { | 151 if (0 == count) { |
160 SkASSERT(!fHead); | 152 SkASSERT(!fHead); |
161 SkASSERT(!fTail); | 153 SkASSERT(!fTail); |
162 } else if (1 == count) { | 154 } else if (1 == count) { |
163 SkASSERT(fHead == fTail); | 155 SkASSERT(fHead == fTail); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 /* | 206 /* |
215 The text strike is specific to a given font/style/matrix setup, which is | 207 The text strike is specific to a given font/style/matrix setup, which is |
216 represented by the GrHostFontScaler object we are given in getGlyph(). | 208 represented by the GrHostFontScaler object we are given in getGlyph(). |
217 | 209 |
218 We map a 32bit glyphID to a GrGlyph record, which in turn points to a | 210 We map a 32bit glyphID to a GrGlyph record, which in turn points to a |
219 atlas and a position within that texture. | 211 atlas and a position within that texture. |
220 */ | 212 */ |
221 | 213 |
222 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, | 214 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, |
223 GrMaskFormat format, | 215 GrMaskFormat format, |
224 GrAtlasMgr* atlasMgr) : fPool(64), fAtlas(atlasMgr) { | 216 GrAtlasMgr* atlasMgr) : fPool(64) { |
225 fFontScalerKey = key; | 217 fFontScalerKey = key; |
226 fFontScalerKey->ref(); | 218 fFontScalerKey->ref(); |
227 | 219 |
228 fFontCache = cache; // no need to ref, it won't go away before we do | 220 fFontCache = cache; // no need to ref, it won't go away before we do |
229 fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do | 221 fAtlasMgr = atlasMgr; // no need to ref, it won't go away before we do |
230 | 222 |
231 fMaskFormat = format; | 223 fMaskFormat = format; |
232 | 224 |
233 #ifdef SK_DEBUG | 225 #ifdef SK_DEBUG |
234 // GrPrintf(" GrTextStrike %p %d\n", this, gCounter); | 226 // GrPrintf(" GrTextStrike %p %d\n", this, gCounter); |
235 gCounter += 1; | 227 gCounter += 1; |
236 #endif | 228 #endif |
237 } | 229 } |
238 | 230 |
239 // these signatures are needed because they're used with | 231 // this signature is needed because it's used with |
240 // SkTDArray::visitAll() (see destructor & removeUnusedAtlases()) | 232 // SkTDArray::visitAll() (see destructor) |
241 static void free_glyph(GrGlyph*& glyph) { glyph->free(); } | 233 static void free_glyph(GrGlyph*& glyph) { glyph->free(); } |
242 | 234 |
243 static void invalidate_glyph(GrGlyph*& glyph) { | |
244 if (glyph->fPlot && glyph->fPlot->drawToken().isIssued()) { | |
245 glyph->fPlot = NULL; | |
246 } | |
247 } | |
248 | |
249 GrTextStrike::~GrTextStrike() { | 235 GrTextStrike::~GrTextStrike() { |
250 fFontScalerKey->unref(); | 236 fFontScalerKey->unref(); |
251 fCache.getArray().visitAll(free_glyph); | 237 fCache.getArray().visitAll(free_glyph); |
252 | 238 |
253 #ifdef SK_DEBUG | 239 #ifdef SK_DEBUG |
254 gCounter -= 1; | 240 gCounter -= 1; |
255 // GrPrintf("~GrTextStrike %p %d\n", this, gCounter); | 241 // GrPrintf("~GrTextStrike %p %d\n", this, gCounter); |
256 #endif | 242 #endif |
257 } | 243 } |
258 | 244 |
(...skipping 12 matching lines...) Expand all Loading... |
271 bounds.fRight += DISTANCE_FIELD_PAD; | 257 bounds.fRight += DISTANCE_FIELD_PAD; |
272 bounds.fTop -= DISTANCE_FIELD_PAD; | 258 bounds.fTop -= DISTANCE_FIELD_PAD; |
273 bounds.fBottom += DISTANCE_FIELD_PAD; | 259 bounds.fBottom += DISTANCE_FIELD_PAD; |
274 } | 260 } |
275 #endif | 261 #endif |
276 glyph->init(packed, bounds); | 262 glyph->init(packed, bounds); |
277 fCache.insert(packed, glyph); | 263 fCache.insert(packed, glyph); |
278 return glyph; | 264 return glyph; |
279 } | 265 } |
280 | 266 |
281 bool GrTextStrike::removeUnusedPlots() { | 267 void GrTextStrike::removePlot(const GrPlot* plot) { |
282 fCache.getArray().visitAll(invalidate_glyph); | 268 SkTDArray<GrGlyph*>& glyphArray = fCache.getArray(); |
283 return fAtlasMgr->removeUnusedPlots(&fAtlas); | 269 for (int i = 0; i < glyphArray.count(); ++i) { |
| 270 if (plot == glyphArray[i]->fPlot) { |
| 271 glyphArray[i]->fPlot = NULL; |
| 272 } |
| 273 } |
| 274 |
| 275 fAtlasMgr->removePlot(&fAtlas, plot); |
284 } | 276 } |
285 | 277 |
286 | 278 |
287 bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { | 279 bool GrTextStrike::addGlyphToAtlas(GrGlyph* glyph, GrFontScaler* scaler) { |
288 #if 0 // testing hack to force us to flush our cache often | 280 #if 0 // testing hack to force us to flush our cache often |
289 static int gCounter; | 281 static int gCounter; |
290 if ((++gCounter % 10) == 0) return false; | 282 if ((++gCounter % 10) == 0) return false; |
291 #endif | 283 #endif |
292 | 284 |
293 SkASSERT(glyph); | 285 SkASSERT(glyph); |
294 SkASSERT(scaler); | 286 SkASSERT(scaler); |
295 SkASSERT(fCache.contains(glyph)); | 287 SkASSERT(fCache.contains(glyph)); |
296 SkASSERT(NULL == glyph->fPlot); | 288 SkASSERT(NULL == glyph->fPlot); |
297 | 289 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 } | 402 } |
411 #endif | 403 #endif |
412 | 404 |
413 if (NULL == plot) { | 405 if (NULL == plot) { |
414 return false; | 406 return false; |
415 } | 407 } |
416 | 408 |
417 glyph->fPlot = plot; | 409 glyph->fPlot = plot; |
418 return true; | 410 return true; |
419 } | 411 } |
OLD | NEW |