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 "GrGpu.h" | 8 #include "GrGpu.h" |
9 #include "GrRectanizer.h" | 9 #include "GrRectanizer.h" |
10 #include "GrSurfacePriv.h" | 10 #include "GrSurfacePriv.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 GrFontCache::k8888_AtlasType, | 73 GrFontCache::k8888_AtlasType, |
74 GrFontCache::k8888_AtlasType | 74 GrFontCache::k8888_AtlasType |
75 }; | 75 }; |
76 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_s
ize_mismatch); | 76 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_s
ize_mismatch); |
77 | 77 |
78 SkASSERT(sAtlasIndices[format] < GrFontCache::kAtlasCount); | 78 SkASSERT(sAtlasIndices[format] < GrFontCache::kAtlasCount); |
79 return sAtlasIndices[format]; | 79 return sAtlasIndices[format]; |
80 } | 80 } |
81 | 81 |
82 GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler) { | 82 GrTextStrike* GrFontCache::generateStrike(GrFontScaler* scaler) { |
83 GrTextStrike* strike = SkNEW_ARGS(GrTextStrike, (this, scaler->getKey())); | 83 GrMaskFormat format = scaler->getMaskFormat(); |
84 fCache.add(strike); | |
85 | |
86 if (fHead) { | |
87 fHead->fPrev = strike; | |
88 } else { | |
89 SkASSERT(NULL == fTail); | |
90 fTail = strike; | |
91 } | |
92 strike->fPrev = NULL; | |
93 strike->fNext = fHead; | |
94 fHead = strike; | |
95 | |
96 return strike; | |
97 } | |
98 | |
99 void GrFontCache::freeAll() { | |
100 SkTDynamicHash<GrTextStrike, GrFontDescKey>::Iter iter(&fCache); | |
101 while (!iter.done()) { | |
102 SkDELETE(&(*iter)); | |
103 ++iter; | |
104 } | |
105 fCache.rewind(); | |
106 for (int i = 0; i < kAtlasCount; ++i) { | |
107 delete fAtlases[i]; | |
108 fAtlases[i] = NULL; | |
109 } | |
110 fHead = NULL; | |
111 fTail = NULL; | |
112 } | |
113 | |
114 void GrFontCache::purgeStrike(GrTextStrike* strike) { | |
115 fCache.remove(*(strike->fFontScalerKey)); | |
116 this->detachStrikeFromList(strike); | |
117 delete strike; | |
118 } | |
119 | |
120 | |
121 GrPlot* GrFontCache::addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* u
sage, | |
122 int width, int height, const void* image, | |
123 SkIPoint16* loc) { | |
124 GrPixelConfig config = mask_format_to_pixel_config(format); | 84 GrPixelConfig config = mask_format_to_pixel_config(format); |
125 int atlasIndex = mask_format_to_atlas_index(format); | 85 int atlasIndex = mask_format_to_atlas_index(format); |
126 if (NULL == fAtlases[atlasIndex]) { | 86 if (NULL == fAtlases[atlasIndex]) { |
127 SkISize textureSize = SkISize::Make(GR_ATLAS_TEXTURE_WIDTH, | 87 SkISize textureSize = SkISize::Make(GR_ATLAS_TEXTURE_WIDTH, |
128 GR_ATLAS_TEXTURE_HEIGHT); | 88 GR_ATLAS_TEXTURE_HEIGHT); |
129 fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrTextur
eFlags, | 89 fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrTextur
eFlags, |
130 textureSize, | 90 textureSize, |
131 GR_NUM_PLOTS_X, | 91 GR_NUM_PLOTS_X, |
132 GR_NUM_PLOTS_Y, | 92 GR_NUM_PLOTS_Y, |
133 true)); | 93 true)); |
134 } | 94 } |
135 return fAtlases[atlasIndex]->addToAtlas(usage, width, height, image, loc); | 95 GrTextStrike* strike = SkNEW_ARGS(GrTextStrike, |
| 96 (this, scaler->getKey(), format, fAtlases[
atlasIndex])); |
| 97 fCache.add(strike); |
| 98 |
| 99 if (fHead) { |
| 100 fHead->fPrev = strike; |
| 101 } else { |
| 102 SkASSERT(NULL == fTail); |
| 103 fTail = strike; |
| 104 } |
| 105 strike->fPrev = NULL; |
| 106 strike->fNext = fHead; |
| 107 fHead = strike; |
| 108 |
| 109 return strike; |
136 } | 110 } |
137 | 111 |
| 112 void GrFontCache::freeAll() { |
| 113 SkTDynamicHash<GrTextStrike, GrFontDescKey>::Iter iter(&fCache); |
| 114 while (!iter.done()) { |
| 115 SkDELETE(&(*iter)); |
| 116 ++iter; |
| 117 } |
| 118 fCache.rewind(); |
| 119 for (int i = 0; i < kAtlasCount; ++i) { |
| 120 delete fAtlases[i]; |
| 121 fAtlases[i] = NULL; |
| 122 } |
| 123 fHead = NULL; |
| 124 fTail = NULL; |
| 125 } |
138 | 126 |
139 bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike, const GrGlyph* gl
yph) { | 127 void GrFontCache::purgeStrike(GrTextStrike* strike) { |
| 128 fCache.remove(*(strike->fFontScalerKey)); |
| 129 this->detachStrikeFromList(strike); |
| 130 delete strike; |
| 131 } |
| 132 |
| 133 bool GrFontCache::freeUnusedPlot(GrTextStrike* preserveStrike) { |
140 SkASSERT(preserveStrike); | 134 SkASSERT(preserveStrike); |
141 | 135 |
142 int index = mask_format_to_atlas_index(glyph->fMaskFormat); | 136 GrAtlas* atlas = preserveStrike->fAtlas; |
143 GrAtlas* atlas = fAtlases[index]; | |
144 GrPlot* plot = atlas->getUnusedPlot(); | 137 GrPlot* plot = atlas->getUnusedPlot(); |
145 if (NULL == plot) { | 138 if (NULL == plot) { |
146 return false; | 139 return false; |
147 } | 140 } |
148 plot->resetRects(); | 141 plot->resetRects(); |
149 | 142 |
150 GrTextStrike* strike = fHead; | 143 GrTextStrike* strike = fHead; |
| 144 GrMaskFormat maskFormat = preserveStrike->fMaskFormat; |
151 while (strike) { | 145 while (strike) { |
| 146 if (maskFormat != strike->fMaskFormat) { |
| 147 strike = strike->fNext; |
| 148 continue; |
| 149 } |
| 150 |
152 GrTextStrike* strikeToPurge = strike; | 151 GrTextStrike* strikeToPurge = strike; |
153 strike = strikeToPurge->fNext; | 152 strike = strikeToPurge->fNext; |
154 strikeToPurge->removePlot(plot); | 153 strikeToPurge->removePlot(plot); |
155 | 154 |
156 // clear out any empty strikes (except this one) | 155 // clear out any empty strikes (except this one) |
157 if (strikeToPurge != preserveStrike && strikeToPurge->fPlotUsage.isEmpty
()) { | 156 if (strikeToPurge != preserveStrike && strikeToPurge->fPlotUsage.isEmpty
()) { |
158 this->purgeStrike(strikeToPurge); | 157 this->purgeStrike(strikeToPurge); |
159 } | 158 } |
160 } | 159 } |
161 | 160 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
222 #endif | 221 #endif |
223 | 222 |
224 /* | 223 /* |
225 The text strike is specific to a given font/style/matrix setup, which is | 224 The text strike is specific to a given font/style/matrix setup, which is |
226 represented by the GrHostFontScaler object we are given in getGlyph(). | 225 represented by the GrHostFontScaler object we are given in getGlyph(). |
227 | 226 |
228 We map a 32bit glyphID to a GrGlyph record, which in turn points to a | 227 We map a 32bit glyphID to a GrGlyph record, which in turn points to a |
229 atlas and a position within that texture. | 228 atlas and a position within that texture. |
230 */ | 229 */ |
231 | 230 |
232 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrFontDescKey* key) : fPool
(64) { | 231 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrFontDescKey* key, |
| 232 GrMaskFormat format, |
| 233 GrAtlas* atlas) : fPool(64) { |
233 fFontScalerKey = key; | 234 fFontScalerKey = key; |
234 fFontScalerKey->ref(); | 235 fFontScalerKey->ref(); |
235 | 236 |
236 fFontCache = cache; // no need to ref, it won't go away before we do | 237 fFontCache = cache; // no need to ref, it won't go away before we do |
| 238 fAtlas = atlas; // no need to ref, it won't go away before we do |
| 239 |
| 240 fMaskFormat = format; |
237 | 241 |
238 #ifdef SK_DEBUG | 242 #ifdef SK_DEBUG |
239 // GrPrintf(" GrTextStrike %p %d\n", this, gCounter); | 243 // GrPrintf(" GrTextStrike %p %d\n", this, gCounter); |
240 gCounter += 1; | 244 gCounter += 1; |
241 #endif | 245 #endif |
242 } | 246 } |
243 | 247 |
244 GrTextStrike::~GrTextStrike() { | 248 GrTextStrike::~GrTextStrike() { |
245 fFontScalerKey->unref(); | 249 fFontScalerKey->unref(); |
246 SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache); | 250 SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache); |
(...skipping 13 matching lines...) Expand all Loading... |
260 SkIRect bounds; | 264 SkIRect bounds; |
261 if (fUseDistanceField) { | 265 if (fUseDistanceField) { |
262 if (!scaler->getPackedGlyphDFBounds(packed, &bounds)) { | 266 if (!scaler->getPackedGlyphDFBounds(packed, &bounds)) { |
263 return NULL; | 267 return NULL; |
264 } | 268 } |
265 } else { | 269 } else { |
266 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { | 270 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { |
267 return NULL; | 271 return NULL; |
268 } | 272 } |
269 } | 273 } |
270 GrMaskFormat format = scaler->getPackedGlyphMaskFormat(packed); | 274 |
271 | |
272 GrGlyph* glyph = fPool.alloc(); | 275 GrGlyph* glyph = fPool.alloc(); |
273 glyph->init(packed, bounds, format); | 276 glyph->init(packed, bounds); |
274 fCache.add(glyph); | 277 fCache.add(glyph); |
275 return glyph; | 278 return glyph; |
276 } | 279 } |
277 | 280 |
278 void GrTextStrike::removePlot(const GrPlot* plot) { | 281 void GrTextStrike::removePlot(const GrPlot* plot) { |
279 SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache); | 282 SkTDynamicHash<GrGlyph, GrGlyph::PackedID>::Iter iter(&fCache); |
280 while (!iter.done()) { | 283 while (!iter.done()) { |
281 if (plot == (*iter).fPlot) { | 284 if (plot == (*iter).fPlot) { |
282 (*iter).fPlot = NULL; | 285 (*iter).fPlot = NULL; |
283 } | 286 } |
(...skipping 23 matching lines...) Expand all Loading... |
307 if ((++gCounter % 10) == 0) return false; | 310 if ((++gCounter % 10) == 0) return false; |
308 #endif | 311 #endif |
309 | 312 |
310 SkASSERT(glyph); | 313 SkASSERT(glyph); |
311 SkASSERT(scaler); | 314 SkASSERT(scaler); |
312 SkASSERT(fCache.find(glyph->fPackedID)); | 315 SkASSERT(fCache.find(glyph->fPackedID)); |
313 SkASSERT(NULL == glyph->fPlot); | 316 SkASSERT(NULL == glyph->fPlot); |
314 | 317 |
315 SkAutoUnref ar(SkSafeRef(scaler)); | 318 SkAutoUnref ar(SkSafeRef(scaler)); |
316 | 319 |
317 int bytesPerPixel = GrMaskFormatBytesPerPixel(glyph->fMaskFormat); | 320 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); |
318 | 321 |
319 size_t size = glyph->fBounds.area() * bytesPerPixel; | 322 size_t size = glyph->fBounds.area() * bytesPerPixel; |
320 GrAutoMalloc<1024> storage(size); | 323 GrAutoMalloc<1024> storage(size); |
321 | 324 |
322 if (fUseDistanceField) { | 325 if (fUseDistanceField) { |
323 if (!scaler->getPackedGlyphDFImage(glyph->fPackedID, glyph->width(), | 326 if (!scaler->getPackedGlyphDFImage(glyph->fPackedID, glyph->width(), |
324 glyph->height(), | 327 glyph->height(), |
325 storage.get())) { | 328 storage.get())) { |
326 return false; | 329 return false; |
327 } | 330 } |
328 } else { | 331 } else { |
329 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), | 332 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), |
330 glyph->height(), | 333 glyph->height(), |
331 glyph->width() * bytesPerPixel, | 334 glyph->width() * bytesPerPixel, |
332 storage.get())) { | 335 storage.get())) { |
333 return false; | 336 return false; |
334 } | 337 } |
335 } | 338 } |
336 | 339 |
337 GrPlot* plot = fFontCache->addToAtlas(glyph->fMaskFormat, &fPlotUsage, | 340 GrPlot* plot = fAtlas->addToAtlas(&fPlotUsage, glyph->width(), |
338 glyph->width(), glyph->height(), | 341 glyph->height(), storage.get(), |
339 storage.get(), &glyph->fAtlasLocation)
; | 342 &glyph->fAtlasLocation); |
340 | 343 |
341 if (NULL == plot) { | 344 if (NULL == plot) { |
342 return false; | 345 return false; |
343 } | 346 } |
344 | 347 |
345 glyph->fPlot = plot; | 348 glyph->fPlot = plot; |
346 return true; | 349 return true; |
347 } | 350 } |
OLD | NEW |