| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 "SkDistanceFieldGen.h" | 8 #include "SkDistanceFieldGen.h" |
| 9 #include "SkPoint.h" | 9 #include "SkPoint.h" |
| 10 | 10 |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 if (dist <= -distanceMagnitude) { | 320 if (dist <= -distanceMagnitude) { |
| 321 return 255; | 321 return 255; |
| 322 } else if (dist > distanceMagnitude) { | 322 } else if (dist > distanceMagnitude) { |
| 323 return 0; | 323 return 0; |
| 324 } else { | 324 } else { |
| 325 return (unsigned char)((distanceMagnitude-dist)*128.0f/distanceMagnitude
); | 325 return (unsigned char)((distanceMagnitude-dist)*128.0f/distanceMagnitude
); |
| 326 } | 326 } |
| 327 } | 327 } |
| 328 #endif | 328 #endif |
| 329 | 329 |
| 330 // assumes an 8-bit image and distance field | 330 // assumes a padded 8-bit image and distance field |
| 331 bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField, | 331 // width and height are the original width and height of the image |
| 332 const unsigned char* image, | 332 bool generate_distance_field_from_image(unsigned char* distanceField, |
| 333 int width, int height, | 333 const unsigned char* copyPtr, |
| 334 int distanceMagnitude) { | 334 int width, int height) { |
| 335 SkASSERT(NULL != distanceField); | 335 SkASSERT(NULL != distanceField); |
| 336 SkASSERT(NULL != image); | 336 SkASSERT(NULL != copyPtr); |
| 337 | 337 |
| 338 // the final distance field will have additional texels on each side to hand
le | |
| 339 // the maximum distance + 1 for bilerp | |
| 340 // we expand our temp data by one more on each side to simplify | 338 // we expand our temp data by one more on each side to simplify |
| 341 // the scanning code -- will always be treated as infinitely far away | 339 // the scanning code -- will always be treated as infinitely far away |
| 342 int pad = distanceMagnitude+2; | 340 int pad = SK_DistanceFieldPad + 1; |
| 343 | 341 |
| 344 // set params for distance field data | 342 // set params for distance field data |
| 345 int dataWidth = width + 2*pad; | 343 int dataWidth = width + 2*pad; |
| 346 int dataHeight = height + 2*pad; | 344 int dataHeight = height + 2*pad; |
| 347 | 345 |
| 348 // create temp data | 346 // create temp data |
| 349 size_t dataSize = dataWidth*dataHeight*sizeof(DFData); | 347 size_t dataSize = dataWidth*dataHeight*sizeof(DFData); |
| 350 SkAutoSMalloc<1024> dfStorage(dataSize); | 348 SkAutoSMalloc<1024> dfStorage(dataSize); |
| 351 DFData* dataPtr = (DFData*) dfStorage.get(); | 349 DFData* dataPtr = (DFData*) dfStorage.get(); |
| 352 sk_bzero(dataPtr, dataSize); | 350 sk_bzero(dataPtr, dataSize); |
| 353 | 351 |
| 354 SkAutoSMalloc<1024> edgeStorage(dataWidth*dataHeight*sizeof(char)); | 352 SkAutoSMalloc<1024> edgeStorage(dataWidth*dataHeight*sizeof(char)); |
| 355 unsigned char* edgePtr = (unsigned char*) edgeStorage.get(); | 353 unsigned char* edgePtr = (unsigned char*) edgeStorage.get(); |
| 356 sk_bzero(edgePtr, dataWidth*dataHeight*sizeof(char)); | 354 sk_bzero(edgePtr, dataWidth*dataHeight*sizeof(char)); |
| 357 | 355 |
| 358 SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char)); | |
| 359 unsigned char* copyPtr = (unsigned char*) copyStorage.get(); | |
| 360 | |
| 361 // we copy our source image into a padded copy to ensure we catch edge trans
itions | |
| 362 // around the outside | |
| 363 const unsigned char* currImage = image; | |
| 364 sk_bzero(copyPtr, (width+2)*sizeof(char)); | |
| 365 unsigned char* currCopy = copyPtr + width + 2; | |
| 366 for (int i = 0; i < height; ++i) { | |
| 367 *currCopy++ = 0; | |
| 368 memcpy(currCopy, currImage, width*sizeof(char)); | |
| 369 currImage += width; | |
| 370 currCopy += width; | |
| 371 *currCopy++ = 0; | |
| 372 } | |
| 373 sk_bzero(currCopy, (width+2)*sizeof(char)); | |
| 374 | |
| 375 // copy glyph into distance field storage | 356 // copy glyph into distance field storage |
| 376 init_glyph_data(dataPtr, edgePtr, copyPtr, | 357 init_glyph_data(dataPtr, edgePtr, copyPtr, |
| 377 dataWidth, dataHeight, | 358 dataWidth, dataHeight, |
| 378 width+2, height+2, pad-1); | 359 width+2, height+2, SK_DistanceFieldPad); |
| 379 | 360 |
| 380 // create initial distance data, particularly at edges | 361 // create initial distance data, particularly at edges |
| 381 init_distances(dataPtr, edgePtr, dataWidth, dataHeight); | 362 init_distances(dataPtr, edgePtr, dataWidth, dataHeight); |
| 382 | 363 |
| 383 // now perform Euclidean distance transform to propagate distances | 364 // now perform Euclidean distance transform to propagate distances |
| 384 | 365 |
| 385 // forwards in y | 366 // forwards in y |
| 386 DFData* currData = dataPtr+dataWidth+1; // skip outer buffer | 367 DFData* currData = dataPtr+dataWidth+1; // skip outer buffer |
| 387 unsigned char* currEdge = edgePtr+dataWidth+1; | 368 unsigned char* currEdge = edgePtr+dataWidth+1; |
| 388 for (int j = 1; j < dataHeight-1; ++j) { | 369 for (int j = 1; j < dataHeight-1; ++j) { |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 float result = alpha + (1.0f-alpha)*edge; | 439 float result = alpha + (1.0f-alpha)*edge; |
| 459 unsigned char val = sk_float_round2int(255*result); | 440 unsigned char val = sk_float_round2int(255*result); |
| 460 *dfPtr++ = val; | 441 *dfPtr++ = val; |
| 461 #else | 442 #else |
| 462 float dist; | 443 float dist; |
| 463 if (currData->fAlpha > 0.5f) { | 444 if (currData->fAlpha > 0.5f) { |
| 464 dist = -SkScalarSqrt(currData->fDistSq); | 445 dist = -SkScalarSqrt(currData->fDistSq); |
| 465 } else { | 446 } else { |
| 466 dist = SkScalarSqrt(currData->fDistSq); | 447 dist = SkScalarSqrt(currData->fDistSq); |
| 467 } | 448 } |
| 468 *dfPtr++ = pack_distance_field_val(dist, (float)distanceMagnitude); | 449 *dfPtr++ = pack_distance_field_val(dist, (float)SK_DistanceFieldMagn
itude); |
| 469 #endif | 450 #endif |
| 470 ++currData; | 451 ++currData; |
| 471 ++currEdge; | 452 ++currEdge; |
| 472 } | 453 } |
| 473 currData += 2; | 454 currData += 2; |
| 474 currEdge += 2; | 455 currEdge += 2; |
| 475 } | 456 } |
| 476 | 457 |
| 477 return true; | 458 return true; |
| 478 } | 459 } |
| 460 |
| 461 // assumes an 8-bit image and distance field |
| 462 bool SkGenerateDistanceFieldFromA8Image(unsigned char* distanceField, |
| 463 const unsigned char* image, |
| 464 int width, int height, int rowBytes) { |
| 465 SkASSERT(NULL != distanceField); |
| 466 SkASSERT(NULL != image); |
| 467 |
| 468 // create temp data |
| 469 SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char)); |
| 470 unsigned char* copyPtr = (unsigned char*) copyStorage.get(); |
| 471 |
| 472 // we copy our source image into a padded copy to ensure we catch edge trans
itions |
| 473 // around the outside |
| 474 const unsigned char* currSrcScanLine = image; |
| 475 sk_bzero(copyPtr, (width+2)*sizeof(char)); |
| 476 unsigned char* currDestPtr = copyPtr + width + 2; |
| 477 for (int i = 0; i < height; ++i) { |
| 478 *currDestPtr++ = 0; |
| 479 memcpy(currDestPtr, currSrcScanLine, rowBytes); |
| 480 currSrcScanLine += rowBytes; |
| 481 currDestPtr += width; |
| 482 *currDestPtr++ = 0; |
| 483 } |
| 484 sk_bzero(currDestPtr, (width+2)*sizeof(char)); |
| 485 |
| 486 return generate_distance_field_from_image(distanceField, copyPtr, width, hei
ght); |
| 487 } |
| 488 |
| 489 // assumes a 1-bit image and 8-bit distance field |
| 490 bool SkGenerateDistanceFieldFromBWImage(unsigned char* distanceField, |
| 491 const unsigned char* image, |
| 492 int width, int height, int rowBytes) { |
| 493 SkASSERT(NULL != distanceField); |
| 494 SkASSERT(NULL != image); |
| 495 |
| 496 // create temp data |
| 497 SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char)); |
| 498 unsigned char* copyPtr = (unsigned char*) copyStorage.get(); |
| 499 |
| 500 // we copy our source image into a padded copy to ensure we catch edge trans
itions |
| 501 // around the outside |
| 502 const unsigned char* currSrcScanLine = image; |
| 503 sk_bzero(copyPtr, (width+2)*sizeof(char)); |
| 504 unsigned char* currDestPtr = copyPtr + width + 2; |
| 505 for (int i = 0; i < height; ++i) { |
| 506 *currDestPtr++ = 0; |
| 507 int rowWritesLeft = width; |
| 508 const unsigned char *maskPtr = currSrcScanLine; |
| 509 while (rowWritesLeft > 0) { |
| 510 unsigned mask = *maskPtr++; |
| 511 for (int i = 7; i >= 0 && rowWritesLeft; --i, --rowWritesLeft) { |
| 512 *currDestPtr++ = (mask & (1 << i)) ? 0xff : 0; |
| 513 } |
| 514 } |
| 515 currSrcScanLine += rowBytes; |
| 516 *currDestPtr++ = 0; |
| 517 } |
| 518 sk_bzero(currDestPtr, (width+2)*sizeof(char)); |
| 519 |
| 520 return generate_distance_field_from_image(distanceField, copyPtr, width, hei
ght); |
| 521 } |
| OLD | NEW |