| 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 SK_DISTANCEFIELD_FONTS | 15 #if SK_DISTANCEFIELD_FONTS |
| 16 #include "SkDistanceFieldGen.h" | 16 #include "edtaa3.h" |
| 17 #endif | 17 #endif |
| 18 | 18 |
| 19 /////////////////////////////////////////////////////////////////////////////// | 19 /////////////////////////////////////////////////////////////////////////////// |
| 20 | 20 |
| 21 #define FONT_CACHE_STATS 0 | 21 #define FONT_CACHE_STATS 0 |
| 22 #if FONT_CACHE_STATS | 22 #if FONT_CACHE_STATS |
| 23 static int g_PurgeCount = 0; | 23 static int g_PurgeCount = 0; |
| 24 #endif | 24 #endif |
| 25 | 25 |
| 26 GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) { | 26 GrFontCache::GrFontCache(GrGpu* gpu) : fGpu(gpu) { |
| (...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 192 } | 192 } |
| 193 #endif | 193 #endif |
| 194 | 194 |
| 195 /////////////////////////////////////////////////////////////////////////////// | 195 /////////////////////////////////////////////////////////////////////////////// |
| 196 | 196 |
| 197 #ifdef SK_DEBUG | 197 #ifdef SK_DEBUG |
| 198 static int gCounter; | 198 static int gCounter; |
| 199 #endif | 199 #endif |
| 200 | 200 |
| 201 #if SK_DISTANCEFIELD_FONTS | 201 #if SK_DISTANCEFIELD_FONTS |
| 202 // this acts as the max magnitude for the distance field, | 202 #define DISTANCE_FIELD_PAD 4 |
| 203 // as well as the pad we need around the glyph | 203 #define DISTANCE_FIELD_RANGE (4.0) |
| 204 #define DISTANCE_FIELD_RANGE 4 | |
| 205 #endif | 204 #endif |
| 206 | 205 |
| 207 /* | 206 /* |
| 208 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 |
| 209 represented by the GrHostFontScaler object we are given in getGlyph(). | 208 represented by the GrHostFontScaler object we are given in getGlyph(). |
| 210 | 209 |
| 211 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 |
| 212 atlas and a position within that texture. | 211 atlas and a position within that texture. |
| 213 */ | 212 */ |
| 214 | 213 |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 247 GrFontScaler* scaler) { | 246 GrFontScaler* scaler) { |
| 248 SkIRect bounds; | 247 SkIRect bounds; |
| 249 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { | 248 if (!scaler->getPackedGlyphBounds(packed, &bounds)) { |
| 250 return NULL; | 249 return NULL; |
| 251 } | 250 } |
| 252 | 251 |
| 253 GrGlyph* glyph = fPool.alloc(); | 252 GrGlyph* glyph = fPool.alloc(); |
| 254 #if SK_DISTANCEFIELD_FONTS | 253 #if SK_DISTANCEFIELD_FONTS |
| 255 // expand bounds to hold full distance field data | 254 // expand bounds to hold full distance field data |
| 256 if (fUseDistanceField) { | 255 if (fUseDistanceField) { |
| 257 bounds.fLeft -= DISTANCE_FIELD_RANGE; | 256 bounds.fLeft -= DISTANCE_FIELD_PAD; |
| 258 bounds.fRight += DISTANCE_FIELD_RANGE; | 257 bounds.fRight += DISTANCE_FIELD_PAD; |
| 259 bounds.fTop -= DISTANCE_FIELD_RANGE; | 258 bounds.fTop -= DISTANCE_FIELD_PAD; |
| 260 bounds.fBottom += DISTANCE_FIELD_RANGE; | 259 bounds.fBottom += DISTANCE_FIELD_PAD; |
| 261 } | 260 } |
| 262 #endif | 261 #endif |
| 263 glyph->init(packed, bounds); | 262 glyph->init(packed, bounds); |
| 264 fCache.insert(packed, glyph); | 263 fCache.insert(packed, glyph); |
| 265 return glyph; | 264 return glyph; |
| 266 } | 265 } |
| 267 | 266 |
| 268 void GrTextStrike::removePlot(const GrPlot* plot) { | 267 void GrTextStrike::removePlot(const GrPlot* plot) { |
| 269 SkTDArray<GrGlyph*>& glyphArray = fCache.getArray(); | 268 SkTDArray<GrGlyph*>& glyphArray = fCache.getArray(); |
| 270 for (int i = 0; i < glyphArray.count(); ++i) { | 269 for (int i = 0; i < glyphArray.count(); ++i) { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 288 SkASSERT(fCache.contains(glyph)); | 287 SkASSERT(fCache.contains(glyph)); |
| 289 SkASSERT(NULL == glyph->fPlot); | 288 SkASSERT(NULL == glyph->fPlot); |
| 290 | 289 |
| 291 SkAutoRef ar(scaler); | 290 SkAutoRef ar(scaler); |
| 292 | 291 |
| 293 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); | 292 int bytesPerPixel = GrMaskFormatBytesPerPixel(fMaskFormat); |
| 294 | 293 |
| 295 GrPlot* plot; | 294 GrPlot* plot; |
| 296 #if SK_DISTANCEFIELD_FONTS | 295 #if SK_DISTANCEFIELD_FONTS |
| 297 if (fUseDistanceField) { | 296 if (fUseDistanceField) { |
| 297 SkASSERT(1 == bytesPerPixel); |
| 298 |
| 298 // we've already expanded the glyph dimensions to match the final size | 299 // we've already expanded the glyph dimensions to match the final size |
| 299 // but must shrink back down to get the packed glyph data | 300 // but must shrink back down to get the packed glyph data |
| 300 int dfWidth = glyph->width(); | 301 int dfWidth = glyph->width(); |
| 301 int dfHeight = glyph->height(); | 302 int dfHeight = glyph->height(); |
| 302 int width = dfWidth - 2*DISTANCE_FIELD_RANGE; | 303 int width = dfWidth - 2*DISTANCE_FIELD_PAD; |
| 303 int height = dfHeight - 2*DISTANCE_FIELD_RANGE; | 304 int height = dfHeight - 2*DISTANCE_FIELD_PAD; |
| 304 int stride = width*bytesPerPixel; | 305 size_t stride = width*bytesPerPixel; |
| 305 | 306 |
| 306 size_t size = width * height * bytesPerPixel; | 307 size_t size = width * height * bytesPerPixel; |
| 307 SkAutoSMalloc<1024> storage(size); | 308 SkAutoSMalloc<1024> storage(size); |
| 308 if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride
, storage.get())) { | 309 if (!scaler->getPackedGlyphImage(glyph->fPackedID, width, height, stride
, storage.get())) { |
| 309 return false; | 310 return false; |
| 310 } | 311 } |
| 311 | 312 |
| 312 // alloc storage for distance field glyph | 313 // alloc storage for distance field glyph |
| 313 size_t dfSize = dfWidth * dfHeight * bytesPerPixel; | 314 size_t dfSize = dfWidth * dfHeight * bytesPerPixel; |
| 314 SkAutoSMalloc<1024> dfStorage(dfSize); | 315 SkAutoSMalloc<1024> dfStorage(dfSize); |
| 315 | |
| 316 if (1 == bytesPerPixel) { | |
| 317 (void) SkGenerateDistanceFieldFromImage((unsigned char*)dfStorage.ge
t(), | |
| 318 (unsigned char*)storage.get(
), | |
| 319 width, height, DISTANCE_FIEL
D_RANGE); | |
| 320 } else { | |
| 321 // TODO: Fix color emoji | |
| 322 // for now, copy glyph into distance field storage | |
| 323 // this is not correct, but it won't crash | |
| 324 sk_bzero(dfStorage.get(), dfSize); | |
| 325 unsigned char* ptr = (unsigned char*) storage.get(); | |
| 326 unsigned char* dfPtr = (unsigned char*) dfStorage.get(); | |
| 327 size_t dfStride = dfWidth*bytesPerPixel; | |
| 328 dfPtr += DISTANCE_FIELD_RANGE*dfStride; | |
| 329 dfPtr += DISTANCE_FIELD_RANGE*bytesPerPixel; | |
| 330 | 316 |
| 331 for (int i = 0; i < height; ++i) { | 317 // copy glyph into distance field storage |
| 332 memcpy(dfPtr, ptr, stride); | 318 sk_bzero(dfStorage.get(), dfSize); |
| 333 | 319 |
| 334 dfPtr += dfStride; | 320 unsigned char* ptr = (unsigned char*) storage.get(); |
| 335 ptr += stride; | 321 unsigned char* dfPtr = (unsigned char*) dfStorage.get(); |
| 322 size_t dfStride = dfWidth*bytesPerPixel; |
| 323 dfPtr += DISTANCE_FIELD_PAD*dfStride; |
| 324 dfPtr += DISTANCE_FIELD_PAD*bytesPerPixel; |
| 325 |
| 326 for (int i = 0; i < height; ++i) { |
| 327 memcpy(dfPtr, ptr, stride); |
| 328 |
| 329 dfPtr += dfStride; |
| 330 ptr += stride; |
| 331 } |
| 332 |
| 333 // generate distance field data |
| 334 SkAutoSMalloc<1024> distXStorage(dfWidth*dfHeight*sizeof(short)); |
| 335 SkAutoSMalloc<1024> distYStorage(dfWidth*dfHeight*sizeof(short)); |
| 336 SkAutoSMalloc<1024> outerDistStorage(dfWidth*dfHeight*sizeof(double)); |
| 337 SkAutoSMalloc<1024> innerDistStorage(dfWidth*dfHeight*sizeof(double)); |
| 338 SkAutoSMalloc<1024> gxStorage(dfWidth*dfHeight*sizeof(double)); |
| 339 SkAutoSMalloc<1024> gyStorage(dfWidth*dfHeight*sizeof(double)); |
| 340 |
| 341 short* distX = (short*) distXStorage.get(); |
| 342 short* distY = (short*) distYStorage.get(); |
| 343 double* outerDist = (double*) outerDistStorage.get(); |
| 344 double* innerDist = (double*) innerDistStorage.get(); |
| 345 double* gx = (double*) gxStorage.get(); |
| 346 double* gy = (double*) gyStorage.get(); |
| 347 |
| 348 dfPtr = (unsigned char*) dfStorage.get(); |
| 349 EDTAA::computegradient(dfPtr, dfWidth, dfHeight, gx, gy); |
| 350 EDTAA::edtaa3(dfPtr, gx, gy, dfWidth, dfHeight, distX, distY, outerDist)
; |
| 351 |
| 352 for (int i = 0; i < dfWidth*dfHeight; ++i) { |
| 353 *dfPtr = 255 - *dfPtr; |
| 354 dfPtr++; |
| 355 } |
| 356 dfPtr = (unsigned char*) dfStorage.get(); |
| 357 sk_bzero(gx, sizeof(double)*dfWidth*dfHeight); |
| 358 sk_bzero(gy, sizeof(double)*dfWidth*dfHeight); |
| 359 EDTAA::computegradient(dfPtr, dfWidth, dfHeight, gx, gy); |
| 360 EDTAA::edtaa3(dfPtr, gx, gy, dfWidth, dfHeight, distX, distY, innerDist)
; |
| 361 |
| 362 for (int i = 0; i < dfWidth*dfHeight; ++i) { |
| 363 unsigned char val; |
| 364 double outerval = outerDist[i]; |
| 365 if (outerval < 0.0) { |
| 366 outerval = 0.0; |
| 336 } | 367 } |
| 368 double innerval = innerDist[i]; |
| 369 if (innerval < 0.0) { |
| 370 innerval = 0.0; |
| 371 } |
| 372 double dist = outerval - innerval; |
| 373 if (dist <= -DISTANCE_FIELD_RANGE) { |
| 374 val = 255; |
| 375 } else if (dist > DISTANCE_FIELD_RANGE) { |
| 376 val = 0; |
| 377 } else { |
| 378 val = (unsigned char)((DISTANCE_FIELD_RANGE-dist)*128.0/DISTANCE
_FIELD_RANGE); |
| 379 } |
| 380 *dfPtr++ = val; |
| 337 } | 381 } |
| 338 | 382 |
| 339 // copy to atlas | 383 // copy to atlas |
| 340 plot = fAtlasMgr->addToAtlas(&fAtlas, dfWidth, dfHeight, dfStorage.get()
, | 384 plot = fAtlasMgr->addToAtlas(&fAtlas, dfWidth, dfHeight, dfStorage.get()
, |
| 341 &glyph->fAtlasLocation); | 385 &glyph->fAtlasLocation); |
| 342 | 386 |
| 343 } else { | 387 } else { |
| 344 #endif | 388 #endif |
| 345 size_t size = glyph->fBounds.area() * bytesPerPixel; | 389 size_t size = glyph->fBounds.area() * bytesPerPixel; |
| 346 SkAutoSMalloc<1024> storage(size); | 390 SkAutoSMalloc<1024> storage(size); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 358 } | 402 } |
| 359 #endif | 403 #endif |
| 360 | 404 |
| 361 if (NULL == plot) { | 405 if (NULL == plot) { |
| 362 return false; | 406 return false; |
| 363 } | 407 } |
| 364 | 408 |
| 365 glyph->fPlot = plot; | 409 glyph->fPlot = plot; |
| 366 return true; | 410 return true; |
| 367 } | 411 } |
| OLD | NEW |