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 |