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