Flutter Engine
The Flutter Engine
Classes | Macros | Enumerations | Functions
SkDistanceFieldGen.cpp File Reference
#include "src/core/SkDistanceFieldGen.h"
#include "include/core/SkPoint.h"
#include "include/core/SkScalar.h"
#include "include/private/base/SkMalloc.h"
#include "include/private/base/SkTPin.h"
#include "include/private/base/SkTemplates.h"
#include "src/base/SkAutoMalloc.h"
#include "src/core/SkMask.h"
#include "src/core/SkPointPriv.h"
#include <cstdint>
#include <cstring>
#include <utility>

Go to the source code of this file.

Classes

struct  DFData
 

Macros

#define DUMP_EDGE   0
 

Enumerations

enum  NeighborFlags {
  kLeft_NeighborFlag = 0x01 , kRight_NeighborFlag = 0x02 , kTopLeft_NeighborFlag = 0x04 , kTop_NeighborFlag = 0x08 ,
  kTopRight_NeighborFlag = 0x10 , kBottomLeft_NeighborFlag = 0x20 , kBottom_NeighborFlag = 0x40 , kBottomRight_NeighborFlag = 0x80 ,
  kAll_NeighborFlags = 0xff , kNeighborFlagCount = 8
}
 

Functions

static bool found_edge (const unsigned char *imagePtr, int width, int neighborFlags)
 
static void init_glyph_data (DFData *data, unsigned char *edges, const unsigned char *image, int dataWidth, int dataHeight, int imageWidth, int imageHeight, int pad)
 
static float edge_distance (const SkPoint &direction, float alpha)
 
static void init_distances (DFData *data, unsigned char *edges, int width, int height)
 
static void F1 (DFData *curr, int width)
 
static void F2 (DFData *curr, int width)
 
static void B1 (DFData *curr, int width)
 
static void B2 (DFData *curr, int width)
 
template<int distanceMagnitude>
static unsigned char pack_distance_field_val (float dist)
 
static bool generate_distance_field_from_image (unsigned char *distanceField, const unsigned char *copyPtr, int width, int height)
 
bool SkGenerateDistanceFieldFromA8Image (unsigned char *distanceField, const unsigned char *image, int width, int height, size_t rowBytes)
 
bool SkGenerateDistanceFieldFromLCD16Mask (unsigned char *distanceField, const unsigned char *image, int w, int h, size_t rowBytes)
 
bool SkGenerateDistanceFieldFromBWImage (unsigned char *distanceField, const unsigned char *image, int width, int height, size_t rowBytes)
 

Macro Definition Documentation

◆ DUMP_EDGE

#define DUMP_EDGE   0

Definition at line 332 of file SkDistanceFieldGen.cpp.

Enumeration Type Documentation

◆ NeighborFlags

Enumerator
kLeft_NeighborFlag 
kRight_NeighborFlag 
kTopLeft_NeighborFlag 
kTop_NeighborFlag 
kTopRight_NeighborFlag 
kBottomLeft_NeighborFlag 
kBottom_NeighborFlag 
kBottomRight_NeighborFlag 
kAll_NeighborFlags 
kNeighborFlagCount 

Definition at line 33 of file SkDistanceFieldGen.cpp.

33 {
34 kLeft_NeighborFlag = 0x01,
37 kTop_NeighborFlag = 0x08,
42 kAll_NeighborFlags = 0xff,
43
45};
@ kLeft_NeighborFlag
@ kAll_NeighborFlags
@ kBottom_NeighborFlag
@ kBottomLeft_NeighborFlag
@ kRight_NeighborFlag
@ kTop_NeighborFlag
@ kTopLeft_NeighborFlag
@ kNeighborFlagCount
@ kBottomRight_NeighborFlag
@ kTopRight_NeighborFlag

Function Documentation

◆ B1()

static void B1 ( DFData curr,
int  width 
)
static

Definition at line 273 of file SkDistanceFieldGen.cpp.

273 {
274 // left
275 DFData* check = curr - 1;
276 SkPoint distVec = check->fDistVector;
277 float distSq = check->fDistSq - 2.0f*distVec.fX + 1.0f;
278 if (distSq < curr->fDistSq) {
279 distVec.fX -= 1.0f;
280 curr->fDistSq = distSq;
281 curr->fDistVector = distVec;
282 }
283}
#define check(reporter, ref, unref, make, kill)
Definition: RefCntTest.cpp:85
SkPoint fDistVector
float fX
x-axis value
Definition: SkPoint_impl.h:164

◆ B2()

static void B2 ( DFData curr,
int  width 
)
static

Definition at line 287 of file SkDistanceFieldGen.cpp.

287 {
288 // right
289 DFData* check = curr + 1;
290 SkPoint distVec = check->fDistVector;
291 float distSq = check->fDistSq + 2.0f*distVec.fX + 1.0f;
292 if (distSq < curr->fDistSq) {
293 distVec.fX += 1.0f;
294 curr->fDistSq = distSq;
295 curr->fDistVector = distVec;
296 }
297
298 // bottom left
299 check = curr + width-1;
300 distVec = check->fDistVector;
301 distSq = check->fDistSq - 2.0f*(distVec.fX - distVec.fY - 1.0f);
302 if (distSq < curr->fDistSq) {
303 distVec.fX -= 1.0f;
304 distVec.fY += 1.0f;
305 curr->fDistSq = distSq;
306 curr->fDistVector = distVec;
307 }
308
309 // bottom
310 check = curr + width;
311 distVec = check->fDistVector;
312 distSq = check->fDistSq + 2.0f*distVec.fY + 1.0f;
313 if (distSq < curr->fDistSq) {
314 distVec.fY += 1.0f;
315 curr->fDistSq = distSq;
316 curr->fDistVector = distVec;
317 }
318
319 // bottom right
320 check = curr + width+1;
321 distVec = check->fDistVector;
322 distSq = check->fDistSq + 2.0f*(distVec.fX + distVec.fY + 1.0f);
323 if (distSq < curr->fDistSq) {
324 distVec.fX += 1.0f;
325 distVec.fY += 1.0f;
326 curr->fDistSq = distSq;
327 curr->fDistVector = distVec;
328 }
329}
int32_t width
float fY
y-axis value
Definition: SkPoint_impl.h:165

◆ edge_distance()

static float edge_distance ( const SkPoint direction,
float  alpha 
)
static

Definition at line 125 of file SkDistanceFieldGen.cpp.

125 {
126 float dx = direction.fX;
127 float dy = direction.fY;
128 float distance;
130 distance = 0.5f - alpha;
131 } else {
132 // this is easier if we treat the direction as being in the first octant
133 // (other octants are symmetrical)
134 dx = SkScalarAbs(dx);
135 dy = SkScalarAbs(dy);
136 if (dx < dy) {
137 using std::swap;
138 swap(dx, dy);
139 }
140
141 // a1 = 0.5*dy/dx is the smaller fractional area chopped off by the edge
142 // to avoid the divide, we just consider the numerator
143 float a1num = 0.5f*dy;
144
145 // we now compute the approximate distance, depending where the alpha falls
146 // relative to the edge fractional area
147
148 // if 0 <= alpha < a1
149 if (alpha*dx < a1num) {
150 // TODO: find a way to do this without square roots?
151 distance = 0.5f*(dx + dy) - SkScalarSqrt(2.0f*dx*dy*alpha);
152 // if a1 <= alpha <= 1 - a1
153 } else if (alpha*dx < (dx - a1num)) {
154 distance = (0.5f - alpha)*dx;
155 // if 1 - a1 < alpha <= 1
156 } else {
157 // TODO: find a way to do this without square roots?
158 distance = -0.5f*(dx + dy) + SkScalarSqrt(2.0f*dx*dy*(1.0f - alpha));
159 }
160 }
161
162 return distance;
163}
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
#define SkScalarSqrt(x)
Definition: SkScalar.h:42
#define SkScalarAbs(x)
Definition: SkScalar.h:39
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208

◆ F1()

static void F1 ( DFData curr,
int  width 
)
static

Definition at line 213 of file SkDistanceFieldGen.cpp.

213 {
214 // upper left
215 DFData* check = curr - width-1;
216 SkPoint distVec = check->fDistVector;
217 float distSq = check->fDistSq - 2.0f*(distVec.fX + distVec.fY - 1.0f);
218 if (distSq < curr->fDistSq) {
219 distVec.fX -= 1.0f;
220 distVec.fY -= 1.0f;
221 curr->fDistSq = distSq;
222 curr->fDistVector = distVec;
223 }
224
225 // up
226 check = curr - width;
227 distVec = check->fDistVector;
228 distSq = check->fDistSq - 2.0f*distVec.fY + 1.0f;
229 if (distSq < curr->fDistSq) {
230 distVec.fY -= 1.0f;
231 curr->fDistSq = distSq;
232 curr->fDistVector = distVec;
233 }
234
235 // upper right
236 check = curr - width+1;
237 distVec = check->fDistVector;
238 distSq = check->fDistSq + 2.0f*(distVec.fX - distVec.fY + 1.0f);
239 if (distSq < curr->fDistSq) {
240 distVec.fX += 1.0f;
241 distVec.fY -= 1.0f;
242 curr->fDistSq = distSq;
243 curr->fDistVector = distVec;
244 }
245
246 // left
247 check = curr - 1;
248 distVec = check->fDistVector;
249 distSq = check->fDistSq - 2.0f*distVec.fX + 1.0f;
250 if (distSq < curr->fDistSq) {
251 distVec.fX -= 1.0f;
252 curr->fDistSq = distSq;
253 curr->fDistVector = distVec;
254 }
255}

◆ F2()

static void F2 ( DFData curr,
int  width 
)
static

Definition at line 259 of file SkDistanceFieldGen.cpp.

259 {
260 // right
261 DFData* check = curr + 1;
262 SkPoint distVec = check->fDistVector;
263 float distSq = check->fDistSq + 2.0f*distVec.fX + 1.0f;
264 if (distSq < curr->fDistSq) {
265 distVec.fX += 1.0f;
266 curr->fDistSq = distSq;
267 curr->fDistVector = distVec;
268 }
269}

◆ found_edge()

static bool found_edge ( const unsigned char *  imagePtr,
int  width,
int  neighborFlags 
)
static

Definition at line 51 of file SkDistanceFieldGen.cpp.

51 {
52 // the order of these should match the neighbor flags above
53 const int kNum8ConnectedNeighbors = 8;
54 const int offsets[8] = {-1, 1, -width-1, -width, -width+1, width-1, width, width+1 };
55 SkASSERT(kNum8ConnectedNeighbors == kNeighborFlagCount);
56
57 // search for an edge
58 unsigned char currVal = *imagePtr;
59 unsigned char currCheck = (currVal >> 7);
60 for (int i = 0; i < kNum8ConnectedNeighbors; ++i) {
61 unsigned char neighborVal;
62 if ((1 << i) & neighborFlags) {
63 const unsigned char* checkPtr = imagePtr + offsets[i];
64 neighborVal = *checkPtr;
65 } else {
66 neighborVal = 0;
67 }
68 unsigned char neighborCheck = (neighborVal >> 7);
69 SkASSERT(currCheck == 0 || currCheck == 1);
70 SkASSERT(neighborCheck == 0 || neighborCheck == 1);
71 // if sharp transition
72 if (currCheck != neighborCheck ||
73 // or both <128 and >0
74 (!currCheck && !neighborCheck && currVal && neighborVal)) {
75 return true;
76 }
77 }
78
79 return false;
80}
#define SkASSERT(cond)
Definition: SkAssert.h:116
list offsets
Definition: mskp_parser.py:37

◆ generate_distance_field_from_image()

static bool generate_distance_field_from_image ( unsigned char *  distanceField,
const unsigned char *  copyPtr,
int  width,
int  height 
)
static

Definition at line 354 of file SkDistanceFieldGen.cpp.

356 {
357 SkASSERT(distanceField);
358 SkASSERT(copyPtr);
359
360 // we expand our temp data by one more on each side to simplify
361 // the scanning code -- will always be treated as infinitely far away
362 int pad = SK_DistanceFieldPad + 1;
363
364 // set params for distance field data
365 int dataWidth = width + 2*pad;
366 int dataHeight = height + 2*pad;
367
368 // create zeroed temp DFData+edge storage
369 UniqueVoidPtr storage(sk_calloc_throw(dataWidth*dataHeight*(sizeof(DFData) + 1)));
370 DFData* dataPtr = (DFData*)storage.get();
371 unsigned char* edgePtr = (unsigned char*)storage.get() + dataWidth*dataHeight*sizeof(DFData);
372
373 // copy glyph into distance field storage
374 init_glyph_data(dataPtr, edgePtr, copyPtr,
375 dataWidth, dataHeight,
377
378 // create initial distance data, particularly at edges
379 init_distances(dataPtr, edgePtr, dataWidth, dataHeight);
380
381 // now perform Euclidean distance transform to propagate distances
382
383 // forwards in y
384 DFData* currData = dataPtr+dataWidth+1; // skip outer buffer
385 unsigned char* currEdge = edgePtr+dataWidth+1;
386 for (int j = 1; j < dataHeight-1; ++j) {
387 // forwards in x
388 for (int i = 1; i < dataWidth-1; ++i) {
389 // don't need to calculate distance for edge pixels
390 if (!*currEdge) {
391 F1(currData, dataWidth);
392 }
393 ++currData;
394 ++currEdge;
395 }
396
397 // backwards in x
398 --currData; // reset to end
399 --currEdge;
400 for (int i = 1; i < dataWidth-1; ++i) {
401 // don't need to calculate distance for edge pixels
402 if (!*currEdge) {
403 F2(currData, dataWidth);
404 }
405 --currData;
406 --currEdge;
407 }
408
409 currData += dataWidth+1;
410 currEdge += dataWidth+1;
411 }
412
413 // backwards in y
414 currData = dataPtr+dataWidth*(dataHeight-2) - 1; // skip outer buffer
415 currEdge = edgePtr+dataWidth*(dataHeight-2) - 1;
416 for (int j = 1; j < dataHeight-1; ++j) {
417 // forwards in x
418 for (int i = 1; i < dataWidth-1; ++i) {
419 // don't need to calculate distance for edge pixels
420 if (!*currEdge) {
421 B1(currData, dataWidth);
422 }
423 ++currData;
424 ++currEdge;
425 }
426
427 // backwards in x
428 --currData; // reset to end
429 --currEdge;
430 for (int i = 1; i < dataWidth-1; ++i) {
431 // don't need to calculate distance for edge pixels
432 if (!*currEdge) {
433 B2(currData, dataWidth);
434 }
435 --currData;
436 --currEdge;
437 }
438
439 currData -= dataWidth-1;
440 currEdge -= dataWidth-1;
441 }
442
443 // copy results to final distance field data
444 currData = dataPtr + dataWidth+1;
445 currEdge = edgePtr + dataWidth+1;
446 unsigned char *dfPtr = distanceField;
447 for (int j = 1; j < dataHeight-1; ++j) {
448 for (int i = 1; i < dataWidth-1; ++i) {
449#if DUMP_EDGE
450 float alpha = currData->fAlpha;
451 float edge = 0.0f;
452 if (*currEdge) {
453 edge = 0.25f;
454 }
455 // blend with original image
456 float result = alpha + (1.0f-alpha)*edge;
457 unsigned char val = sk_float_round2int(255*result);
458 *dfPtr++ = val;
459#else
460 float dist;
461 if (currData->fAlpha > 0.5f) {
462 dist = -SkScalarSqrt(currData->fDistSq);
463 } else {
464 dist = SkScalarSqrt(currData->fDistSq);
465 }
466 *dfPtr++ = pack_distance_field_val<SK_DistanceFieldMagnitude>(dist);
467#endif
468 ++currData;
469 ++currEdge;
470 }
471 currData += 2;
472 currEdge += 2;
473 }
474
475 return true;
476}
static void init_glyph_data(DFData *data, unsigned char *edges, const unsigned char *image, int dataWidth, int dataHeight, int imageWidth, int imageHeight, int pad)
static void B2(DFData *curr, int width)
static void init_distances(DFData *data, unsigned char *edges, int width, int height)
static void B1(DFData *curr, int width)
static void F1(DFData *curr, int width)
static void F2(DFData *curr, int width)
#define SK_DistanceFieldPad
#define sk_float_round2int(x)
static void * sk_calloc_throw(size_t size)
Definition: SkMalloc.h:71
GAsyncResult * result
std::unique_ptr< void, SkOverloadedFunctionObject< void(void *), sk_free > > UniqueVoidPtr
Definition: SkTemplates.h:431
int32_t height

◆ init_distances()

static void init_distances ( DFData data,
unsigned char *  edges,
int  width,
int  height 
)
static

Definition at line 165 of file SkDistanceFieldGen.cpp.

165 {
166 // skip one pixel border
167 DFData* currData = data;
168 DFData* prevData = data - width;
169 DFData* nextData = data + width;
170
171 for (int j = 0; j < height; ++j) {
172 for (int i = 0; i < width; ++i) {
173 if (*edges) {
174 // we should not be in the one-pixel outside band
175 SkASSERT(i > 0 && i < width-1 && j > 0 && j < height-1);
176 // gradient will point from low to high
177 // +y is down in this case
178 // i.e., if you're outside, gradient points towards edge
179 // if you're inside, gradient points away from edge
180 SkPoint currGrad;
181 currGrad.fX = (prevData+1)->fAlpha - (prevData-1)->fAlpha
182 + SK_ScalarSqrt2*(currData+1)->fAlpha
183 - SK_ScalarSqrt2*(currData-1)->fAlpha
184 + (nextData+1)->fAlpha - (nextData-1)->fAlpha;
185 currGrad.fY = (nextData-1)->fAlpha - (prevData-1)->fAlpha
186 + SK_ScalarSqrt2*nextData->fAlpha
187 - SK_ScalarSqrt2*prevData->fAlpha
188 + (nextData+1)->fAlpha - (prevData+1)->fAlpha;
189 SkPointPriv::SetLengthFast(&currGrad, 1.0f);
190
191 // init squared distance to edge and distance vector
192 float dist = edge_distance(currGrad, currData->fAlpha);
193 currGrad.scale(dist, &currData->fDistVector);
194 currData->fDistSq = dist*dist;
195 } else {
196 // init distance to "far away"
197 currData->fDistSq = 2000000.f;
198 currData->fDistVector.fX = 1000.f;
199 currData->fDistVector.fY = 1000.f;
200 }
201 ++currData;
202 ++prevData;
203 ++nextData;
204 ++edges;
205 }
206 }
207}
static float edge_distance(const SkPoint &direction, float alpha)
#define SK_ScalarSqrt2
Definition: SkScalar.h:20
static bool SetLengthFast(SkPoint *pt, float length)
Definition: SkPoint.cpp:94
void scale(float scale, SkPoint *dst) const
Definition: SkPoint.cpp:17
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ init_glyph_data()

static void init_glyph_data ( DFData data,
unsigned char *  edges,
const unsigned char *  image,
int  dataWidth,
int  dataHeight,
int  imageWidth,
int  imageHeight,
int  pad 
)
static

Definition at line 82 of file SkDistanceFieldGen.cpp.

85 {
86 data += pad*dataWidth;
87 data += pad;
88 edges += (pad*dataWidth + pad);
89
90 for (int j = 0; j < imageHeight; ++j) {
91 for (int i = 0; i < imageWidth; ++i) {
92 if (255 == *image) {
93 data->fAlpha = 1.0f;
94 } else {
95 data->fAlpha = (*image)*0.00392156862f; // 1/255
96 }
97 int checkMask = kAll_NeighborFlags;
98 if (i == 0) {
100 }
101 if (i == imageWidth-1) {
103 }
104 if (j == 0) {
106 }
107 if (j == imageHeight-1) {
109 }
110 if (found_edge(image, imageWidth, checkMask)) {
111 *edges = 255; // using 255 makes for convenient debug rendering
112 }
113 ++data;
114 ++image;
115 ++edges;
116 }
117 data += 2*pad;
118 edges += 2*pad;
119 }
120}
static bool found_edge(const unsigned char *imagePtr, int width, int neighborFlags)
sk_sp< const SkImage > image
Definition: SkRecords.h:269
static const int imageHeight
static const int imageWidth

◆ pack_distance_field_val()

template<int distanceMagnitude>
static unsigned char pack_distance_field_val ( float  dist)
static

Definition at line 336 of file SkDistanceFieldGen.cpp.

336 {
337 // The distance field is constructed as unsigned char values, so that the zero value is at 128,
338 // Beside 128, we have 128 values in range [0, 128), but only 127 values in range (128, 255].
339 // So we multiply distanceMagnitude by 127/128 at the latter range to avoid overflow.
340 dist = SkTPin<float>(-dist, -distanceMagnitude, distanceMagnitude * 127.0f / 128.0f);
341
342 // Scale into the positive range for unsigned distance.
343 dist += distanceMagnitude;
344
345 // Scale into unsigned char range.
346 // Round to place negative and positive values as equally as possible around 128
347 // (which represents zero).
348 return (unsigned char)SkScalarRoundToInt(dist / (2 * distanceMagnitude) * 256.0f);
349}
#define SkScalarRoundToInt(x)
Definition: SkScalar.h:37

◆ SkGenerateDistanceFieldFromA8Image()

bool SkGenerateDistanceFieldFromA8Image ( unsigned char *  distanceField,
const unsigned char *  image,
int  w,
int  h,
size_t  rowBytes 
)

Given 8-bit mask data, generate the associated distance field

Parameters
distanceFieldThe distance field to be generated. Should already be allocated by the client with the padding above.
image8-bit mask we're using to generate the distance field.
wWidth of the original image.
hHeight of the original image.
rowBytesSize of each row in the image, in bytes

Definition at line 479 of file SkDistanceFieldGen.cpp.

481 {
482 SkASSERT(distanceField);
484
485 // create temp data
486 SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char));
487 unsigned char* copyPtr = (unsigned char*) copyStorage.get();
488
489 // we copy our source image into a padded copy to ensure we catch edge transitions
490 // around the outside
491 const unsigned char* currSrcScanLine = image;
492 sk_bzero(copyPtr, (width+2)*sizeof(char));
493 unsigned char* currDestPtr = copyPtr + width + 2;
494 for (int i = 0; i < height; ++i) {
495 *currDestPtr++ = 0;
496 memcpy(currDestPtr, currSrcScanLine, width);
497 currSrcScanLine += rowBytes;
498 currDestPtr += width;
499 *currDestPtr++ = 0;
500 }
501 sk_bzero(currDestPtr, (width+2)*sizeof(char));
502
503 return generate_distance_field_from_image(distanceField, copyPtr, width, height);
504}
sk_bzero(glyphs, sizeof(glyphs))
static bool generate_distance_field_from_image(unsigned char *distanceField, const unsigned char *copyPtr, int width, int height)

◆ SkGenerateDistanceFieldFromBWImage()

bool SkGenerateDistanceFieldFromBWImage ( unsigned char *  distanceField,
const unsigned char *  image,
int  w,
int  h,
size_t  rowBytes 
)

Given 1-bit mask data, generate the associated distance field

Parameters
distanceFieldThe distance field to be generated. Should already be allocated by the client with the padding above.
image1-bit mask we're using to generate the distance field.
wWidth of the original image.
hHeight of the original image.
rowBytesSize of each row in the image, in bytes

Definition at line 537 of file SkDistanceFieldGen.cpp.

539 {
540 SkASSERT(distanceField);
542
543 // create temp data
544 SkAutoSMalloc<1024> copyStorage((width+2)*(height+2)*sizeof(char));
545 unsigned char* copyPtr = (unsigned char*) copyStorage.get();
546
547 // we copy our source image into a padded copy to ensure we catch edge transitions
548 // around the outside
549 const unsigned char* currSrcScanLine = image;
550 sk_bzero(copyPtr, (width+2)*sizeof(char));
551 unsigned char* currDestPtr = copyPtr + width + 2;
552 for (int i = 0; i < height; ++i) {
553 *currDestPtr++ = 0;
554
555 int rowWritesLeft = width;
556 const unsigned char *maskPtr = currSrcScanLine;
557 while (rowWritesLeft > 0) {
558 unsigned mask = *maskPtr++;
559 for (int j = 7; j >= 0 && rowWritesLeft; --j, --rowWritesLeft) {
560 *currDestPtr++ = (mask & (1 << j)) ? 0xff : 0;
561 }
562 }
563 currSrcScanLine += rowBytes;
564
565 *currDestPtr++ = 0;
566 }
567 sk_bzero(currDestPtr, (width+2)*sizeof(char));
568
569 return generate_distance_field_from_image(distanceField, copyPtr, width, height);
570}

◆ SkGenerateDistanceFieldFromLCD16Mask()

bool SkGenerateDistanceFieldFromLCD16Mask ( unsigned char *  distanceField,
const unsigned char *  image,
int  w,
int  h,
size_t  rowBytes 
)

Given LCD16 mask data (not a 16-bit image), generate the associated distance field

Parameters
distanceFieldThe distance field to be generated. Should already be allocated by the client with the padding above.
image16-bit LCD data we're using to generate the distance field.
wWidth of the original image.
hHeight of the original image.
rowBytesSize of each row in the image, in bytes

Definition at line 507 of file SkDistanceFieldGen.cpp.

509 {
510 SkASSERT(distanceField);
512
513 // create temp data
514 SkAutoSMalloc<1024> copyStorage((w+2)*(h+2)*sizeof(char));
515 unsigned char* copyPtr = (unsigned char*) copyStorage.get();
516
517 // we copy our source image into a padded copy to ensure we catch edge transitions
518 // around the outside
519 const uint16_t* start = reinterpret_cast<const uint16_t*>(image);
520 auto currSrcScanline = SkMask::AlphaIter<SkMask::kLCD16_Format>(start);
521 auto endSrcScanline = SkMask::AlphaIter<SkMask::kLCD16_Format>(start + w);
522 sk_bzero(copyPtr, (w+2)*sizeof(char));
523 unsigned char* currDestPtr = copyPtr + w + 2;
524 for (int i = 0; i < h; ++i, currSrcScanline >>= rowBytes, endSrcScanline >>= rowBytes) {
525 *currDestPtr++ = 0;
526 for (auto src = currSrcScanline; src < endSrcScanline; ++src) {
527 *currDestPtr++ = *src;
528 }
529 *currDestPtr++ = 0;
530 }
531 sk_bzero(currDestPtr, (w+2)*sizeof(char));
532
533 return generate_distance_field_from_image(distanceField, copyPtr, w, h);
534}
SkScalar w
SkScalar h