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" |
11 #include "GrTextStrike.h" | 11 #include "GrTextStrike.h" |
12 #include "GrTextStrike_impl.h" | 12 #include "GrTextStrike_impl.h" |
13 #include "SkString.h" | 13 #include "SkString.h" |
14 | 14 |
| 15 #include "edtaa3.h" |
| 16 |
15 SK_DEFINE_INST_COUNT(GrFontScaler) | 17 SK_DEFINE_INST_COUNT(GrFontScaler) |
16 SK_DEFINE_INST_COUNT(GrKey) | 18 SK_DEFINE_INST_COUNT(GrKey) |
17 | 19 |
18 /////////////////////////////////////////////////////////////////////////////// | 20 /////////////////////////////////////////////////////////////////////////////// |
19 | 21 |
20 #define FONT_CACHE_STATS 0 | 22 #define FONT_CACHE_STATS 0 |
21 #if FONT_CACHE_STATS | 23 #if FONT_CACHE_STATS |
22 static int g_PurgeCount = 0; | 24 static int g_PurgeCount = 0; |
23 #endif | 25 #endif |
24 | 26 |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
186 ++gDumpCount; | 188 ++gDumpCount; |
187 } | 189 } |
188 #endif | 190 #endif |
189 | 191 |
190 /////////////////////////////////////////////////////////////////////////////// | 192 /////////////////////////////////////////////////////////////////////////////// |
191 | 193 |
192 #ifdef SK_DEBUG | 194 #ifdef SK_DEBUG |
193 static int gCounter; | 195 static int gCounter; |
194 #endif | 196 #endif |
195 | 197 |
| 198 #define DISTANCE_FIELD_PAD 4 |
| 199 #define DISTANCE_FIELD_RANGE (4.0) |
| 200 |
196 /* | 201 /* |
197 The text strike is specific to a given font/style/matrix setup, which is | 202 The text strike is specific to a given font/style/matrix setup, which is |
198 represented by the GrHostFontScaler object we are given in getGlyph(). | 203 represented by the GrHostFontScaler object we are given in getGlyph(). |
199 | 204 |
200 We map a 32bit glyphID to a GrGlyph record, which in turn points to a | 205 We map a 32bit glyphID to a GrGlyph record, which in turn points to a |
201 atlas and a position within that texture. | 206 atlas and a position within that texture. |
202 */ | 207 */ |
203 | 208 |
204 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, | 209 GrTextStrike::GrTextStrike(GrFontCache* cache, const GrKey* key, |
205 GrMaskFormat format, | 210 GrMaskFormat format, |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
239 } | 244 } |
240 | 245 |
241 GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, | 246 GrGlyph* GrTextStrike::generateGlyph(GrGlyph::PackedID packed, |
242 GrFontScaler* scaler) { | 247 GrFontScaler* scaler) { |
243 SkIRect bounds; | 248 SkIRect bounds; |
244 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { | 249 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { |
245 return NULL; | 250 return NULL; |
246 } | 251 } |
247 | 252 |
248 GrGlyph* glyph = fPool.alloc(); | 253 GrGlyph* glyph = fPool.alloc(); |
| 254 // expand bounds to hold full distance field data |
| 255 if (fUseDistanceField) { |
| 256 bounds.fLeft -= DISTANCE_FIELD_PAD; |
| 257 bounds.fRight += DISTANCE_FIELD_PAD; |
| 258 bounds.fTop -= DISTANCE_FIELD_PAD; |
| 259 bounds.fBottom += DISTANCE_FIELD_PAD; |
| 260 } |
249 glyph->init(packed, bounds); | 261 glyph->init(packed, bounds); |
250 fCache.insert(packed, glyph); | 262 fCache.insert(packed, glyph); |
251 return glyph; | 263 return glyph; |
252 } | 264 } |
253 | 265 |
254 bool GrTextStrike::removeUnusedPlots() { | 266 bool GrTextStrike::removeUnusedPlots() { |
255 fCache.getArray().visitAll(invalidate_glyph); | 267 fCache.getArray().visitAll(invalidate_glyph); |
256 return fAtlasMgr->removeUnusedPlots(&fAtlas); | 268 return fAtlasMgr->removeUnusedPlots(&fAtlas); |
257 } | 269 } |
258 | 270 |
| 271 |
259 bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { | 272 bool GrTextStrike::getGlyphAtlas(GrGlyph* glyph, GrFontScaler* scaler) { |
260 #if 0 // testing hack to force us to flush our cache often | 273 #if 0 // testing hack to force us to flush our cache often |
261 static int gCounter; | 274 static int gCounter; |
262 if ((++gCounter % 10) == 0) return false; | 275 if ((++gCounter % 10) == 0) return false; |
263 #endif | 276 #endif |
264 | 277 |
265 SkASSERT(glyph); | 278 SkASSERT(glyph); |
266 SkASSERT(scaler); | 279 SkASSERT(scaler); |
267 SkASSERT(fCache.contains(glyph)); | 280 SkASSERT(fCache.contains(glyph)); |
268 SkASSERT(NULL == glyph->fPlot); | 281 SkASSERT(NULL == glyph->fPlot); |
269 | 282 |
270 SkAutoRef ar(scaler); | 283 SkAutoRef ar(scaler); |
271 | 284 |
272 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); | 285 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); |
273 size_t size = glyph->fBounds.area() * bytesPerPixel; | 286 |
274 SkAutoSMalloc<1024> storage(size); | 287 GrPlot* plot; |
275 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), | 288 if (fUseDistanceField) { |
276 glyph->height(), | 289 SkASSERT(1 == bytesPerPixel); |
277 glyph->width() * bytesPerPixel, | 290 |
278 storage.get())) { | 291 // we've already expanded the glyph dimensions to match the final size |
279 return false; | 292 // but must shrink back down to get the packed glyph data |
| 293 int dfwidth = glyph->width(); |
| 294 int dfheight = glyph->height(); |
| 295 int width = dfwidth - 2*DISTANCE_FIELD_PAD; |
| 296 int height = dfheight - 2*DISTANCE_FIELD_PAD; |
| 297 size_t stride = width*bytesPerPixel; |
| 298 |
| 299 size_t size = width * height * bytesPerPixel; |
| 300 SkAutoSMalloc<1024> storage(size); |
| 301 if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride
, storage.get())) { |
| 302 return false; |
| 303 } |
| 304 |
| 305 // alloc storage for distance field glyph |
| 306 size_t dfsize = dfwidth * dfheight * bytesPerPixel; |
| 307 SkAutoSMalloc<1024> dfstorage(dfsize); |
| 308 |
| 309 // copy glyph into distance field storage |
| 310 memset(dfstorage.get(), 0, dfsize); |
| 311 |
| 312 unsigned char* ptr = (unsigned char*) storage.get(); |
| 313 unsigned char* dfptr = (unsigned char*) dfstorage.get(); |
| 314 size_t dfstride = dfwidth*bytesPerPixel; |
| 315 dfptr += DISTANCE_FIELD_PAD*dfstride; |
| 316 dfptr += DISTANCE_FIELD_PAD*bytesPerPixel; |
| 317 |
| 318 for (int i = 0; i < height; ++i) { |
| 319 memcpy(dfptr, ptr, stride); |
| 320 |
| 321 dfptr += dfstride; |
| 322 ptr += stride; |
| 323 } |
| 324 |
| 325 // generate distance field data |
| 326 short* distx = new short[dfwidth*dfheight]; |
| 327 short* disty = new short[dfwidth*dfheight]; |
| 328 double* outerdist = new double[dfwidth*dfheight]; |
| 329 double* gx = new double[dfwidth*dfheight]; |
| 330 double* gy = new double[dfwidth*dfheight]; |
| 331 dfptr = (unsigned char*) dfstorage.get(); |
| 332 computegradient(dfptr, dfwidth, dfheight, gx, gy); |
| 333 edtaa3(dfptr, gx, gy, dfwidth, dfheight, distx, disty, outerdist); |
| 334 |
| 335 for (int i = 0; i < dfwidth*dfheight; ++i) { |
| 336 *dfptr++ = 255 - *dfptr; |
| 337 } |
| 338 double* innerdist = new double[dfwidth*dfheight]; |
| 339 dfptr = (unsigned char*) dfstorage.get(); |
| 340 memset(gx, 0, sizeof(double)*dfwidth*dfheight); |
| 341 memset(gy, 0, sizeof(double)*dfwidth*dfheight); |
| 342 computegradient(dfptr, dfwidth, dfheight, gx, gy); |
| 343 edtaa3(dfptr, gx, gy, dfwidth, dfheight, distx, disty, innerdist); |
| 344 |
| 345 for (int i = 0; i < dfwidth*dfheight; ++i) { |
| 346 unsigned char val; |
| 347 double outerval = outerdist[i]; |
| 348 if (outerval < 0.0) { outerval = 0.0; } |
| 349 double innerval = innerdist[i]; |
| 350 if (innerval < 0.0) { innerval = 0.0; } |
| 351 double dist = outerval - innerval; |
| 352 if (dist <= -DISTANCE_FIELD_RANGE) { |
| 353 val = 255; |
| 354 } else if (dist > DISTANCE_FIELD_RANGE) { |
| 355 val = 0; |
| 356 } else { |
| 357 val = (unsigned char)((DISTANCE_FIELD_RANGE-dist)*128.0/DISTANCE
_FIELD_RANGE); |
| 358 } |
| 359 *dfptr++ = val; |
| 360 } |
| 361 |
| 362 delete [] distx; |
| 363 delete [] disty; |
| 364 delete [] innerdist; |
| 365 delete [] outerdist; |
| 366 |
| 367 // copy to atlas |
| 368 plot = fAtlasMgr->addToAtlas(&fAtlas, dfwidth, dfheight, dfstorage.get()
, |
| 369 &glyph->fAtlasLocation); |
| 370 |
| 371 } else { |
| 372 size_t size = glyph->fBounds.area() * bytesPerPixel; |
| 373 SkAutoSMalloc<1024> storage(size); |
| 374 if (!scaler->getPackedGlyphImage(glyph->fPackedID, glyph->width(), |
| 375 glyph->height(), |
| 376 glyph->width() * bytesPerPixel, |
| 377 storage.get())) { |
| 378 return false; |
| 379 } |
| 380 |
| 381 plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(), glyph->height(), s
torage.get(), |
| 382 &glyph->fAtlasLocation); |
280 } | 383 } |
281 | 384 |
282 GrPlot* plot = fAtlasMgr->addToAtlas(&fAtlas, glyph->width(), | |
283 glyph->height(), storage.get(), | |
284 &glyph->fAtlasLocation); | |
285 if (NULL == plot) { | 385 if (NULL == plot) { |
286 return false; | 386 return false; |
287 } | 387 } |
288 | 388 |
289 glyph->fPlot = plot; | 389 glyph->fPlot = plot; |
290 return true; | 390 return true; |
291 } | 391 } |
| 392 |
OLD | NEW |