Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: src/core/SkDistanceFieldGen.cpp

Issue 197423003: Fix distance field edge detection. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
11 struct DFData { 11 struct DFData {
12 float fAlpha; // alpha value of source texel 12 float fAlpha; // alpha value of source texel
13 float fDistSq; // distance squared to nearest (so far) edge texel 13 float fDistSq; // distance squared to nearest (so far) edge texel
14 SkPoint fDistVector; // distance vector to nearest (so far) edge texel 14 SkPoint fDistVector; // distance vector to nearest (so far) edge texel
15 }; 15 };
16 16
robertphillips 2014/03/12 16:40:07 Name this guy EdgeFlags? NeighborFlags might be cl
17 enum {
18 kEdgeFlag_Left = 0x01,
19 kEdgeFlag_Right = 0x02,
20 kEdgeFlag_TopLeft = 0x04,
21 kEdgeFlag_Top = 0x08,
22 kEdgeFlag_TopRight = 0x10,
23 kEdgeFlag_BottomLeft = 0x20,
24 kEdgeFlag_Bottom = 0x40,
25 kEdgeFlag_BottomRight = 0x80,
26 kEdgeFlag_All = 0xff
27 };
28
17 // We treat an "edge" as a place where we cross from a texel >= 128 to a texel < 128, 29 // We treat an "edge" as a place where we cross from a texel >= 128 to a texel < 128,
18 // or vice versa. This means we just need to check if the MSBs are different. 30 // or vice versa. This means we just need to check if the MSBs are different.
robertphillips 2014/03/12 16:40:07 // 'edgeFlags' is used to limit the directions in
19 static bool found_edge(const unsigned char* imagePtr, int width) { 31 static bool found_edge(const unsigned char* imagePtr, int width, int edgeFlags) {
32 // the order of these should match the edge flags above
robertphillips 2014/03/12 16:40:07 swap 8 out for kEdgeFlagCount? Add kNum8ConnectedN
20 const int offsets[8] = {-1, 1, -width-1, -width, -width+1, width-1, width, w idth+1 }; 33 const int offsets[8] = {-1, 1, -width-1, -width, -width+1, width-1, width, w idth+1 };
21 34
22 // search for an edge 35 // search for an edge
23 int checkVal = *imagePtr >> 7; 36 unsigned char currVal = *imagePtr >> 7;
24 for (int i = 0; i < 8; ++i) { 37 for (int i = 0; i < 8; ++i) {
25 const unsigned char* checkPtr = imagePtr + offsets[i]; 38 unsigned char checkVal;
26 if (checkVal ^ (*checkPtr >> 7)) { 39 if ((1 << i) & edgeFlags) {
40 const unsigned char* checkPtr = imagePtr + offsets[i];
41 checkVal = *checkPtr >> 7;
42 } else {
43 checkVal = 0;
44 }
45 SkASSERT(checkVal == 0 || checkVal == 1);
46 SkASSERT(currVal == 0 || currVal == 1);
47 if (checkVal != currVal) {
27 return true; 48 return true;
28 } 49 }
29 } 50 }
30 51
31 return false; 52 return false;
32 } 53 }
33 54
34 static void init_glyph_data(DFData* data, unsigned char* edges, const unsigned c har* image, 55 static void init_glyph_data(DFData* data, unsigned char* edges, const unsigned c har* image,
35 int dataWidth, int dataHeight, 56 int dataWidth, int dataHeight,
36 int imageWidth, int imageHeight, 57 int imageWidth, int imageHeight,
37 int pad) { 58 int pad) {
38 data += pad*dataWidth; 59 data += pad*dataWidth;
39 data += pad; 60 data += pad;
40 edges += (pad*dataWidth + pad); 61 edges += (pad*dataWidth + pad);
41 62
42 for (int j = 0; j < imageHeight; ++j) { 63 for (int j = 0; j < imageHeight; ++j) {
43 for (int i = 0; i < imageWidth; ++i) { 64 for (int i = 0; i < imageWidth; ++i) {
44 if (255 == *image) { 65 if (255 == *image) {
45 data->fAlpha = 1.0f; 66 data->fAlpha = 1.0f;
46 } else { 67 } else {
47 data->fAlpha = (*image)*0.00392156862f; // 1/255 68 data->fAlpha = (*image)*0.00392156862f; // 1/255
48 } 69 }
49 if (i > 0 && i < imageWidth-1 && j > 0 && j < imageHeight-1 && 70 int checkMask = kEdgeFlag_All;
robertphillips 2014/03/12 16:40:07 Would it be helpful to add helper values like "kAl
50 found_edge(image, imageWidth)) { 71 if (i == 0) {
72 checkMask &= ~(kEdgeFlag_Left|kEdgeFlag_TopLeft|kEdgeFlag_Bottom Left);
73 }
74 if (i == imageWidth-1) {
75 checkMask &= ~(kEdgeFlag_Right|kEdgeFlag_TopRight|kEdgeFlag_Bott omRight);
76 }
77 if (j == 0) {
78 checkMask &= ~(kEdgeFlag_TopLeft|kEdgeFlag_Top|kEdgeFlag_TopRigh t);
79 }
80 if (j == imageHeight-1) {
81 checkMask &= ~(kEdgeFlag_BottomLeft|kEdgeFlag_Bottom|kEdgeFlag_B ottomRight);
82 }
83 if (found_edge(image, imageWidth, checkMask)) {
51 *edges = 255; // using 255 makes for convenient debug rendering 84 *edges = 255; // using 255 makes for convenient debug rendering
52 } 85 }
53 ++data; 86 ++data;
54 ++image; 87 ++image;
55 ++edges; 88 ++edges;
56 } 89 }
57 data += 2*pad; 90 data += 2*pad;
58 edges += 2*pad; 91 edges += 2*pad;
59 } 92 }
60 } 93 }
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 check = curr + width+1; 293 check = curr + width+1;
261 distVec = check->fDistVector; 294 distVec = check->fDistVector;
262 distSq = check->fDistSq + 2.0f*(distVec.fX + distVec.fY + 1.0f); 295 distSq = check->fDistSq + 2.0f*(distVec.fX + distVec.fY + 1.0f);
263 if (distSq < curr->fDistSq) { 296 if (distSq < curr->fDistSq) {
264 distVec.fX += 1.0f; 297 distVec.fX += 1.0f;
265 distVec.fY += 1.0f; 298 distVec.fY += 1.0f;
266 curr->fDistSq = distSq; 299 curr->fDistSq = distSq;
267 curr->fDistVector = distVec; 300 curr->fDistVector = distVec;
268 } 301 }
269 } 302 }
270 303
robertphillips 2014/03/12 16:40:07 // Enable this to ...?
304 #define DUMP_EDGE 0
305
306 #if !DUMP_EDGE
271 static unsigned char pack_distance_field_val(float dist, float distanceMagnitude ) { 307 static unsigned char pack_distance_field_val(float dist, float distanceMagnitude ) {
272 if (dist <= -distanceMagnitude) { 308 if (dist <= -distanceMagnitude) {
273 return 255; 309 return 255;
274 } else if (dist > distanceMagnitude) { 310 } else if (dist > distanceMagnitude) {
275 return 0; 311 return 0;
276 } else { 312 } else {
277 return (unsigned char)((distanceMagnitude-dist)*128.0f/distanceMagnitude ); 313 return (unsigned char)((distanceMagnitude-dist)*128.0f/distanceMagnitude );
278 } 314 }
279 } 315 }
316 #endif
280 317
281 // assumes an 8-bit image and distance field 318 // assumes an 8-bit image and distance field
282 bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField, 319 bool SkGenerateDistanceFieldFromImage(unsigned char* distanceField,
283 const unsigned char* image, 320 const unsigned char* image,
284 int width, int height, 321 int width, int height,
285 int distanceMagnitude) { 322 int distanceMagnitude) {
286 SkASSERT(NULL != distanceField); 323 SkASSERT(NULL != distanceField);
287 SkASSERT(NULL != image); 324 SkASSERT(NULL != image);
288 325
289 // the final distance field will have additional texels on each side to hand le 326 // the final distance field will have additional texels on each side to hand le
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 currData -= dataWidth-1; 412 currData -= dataWidth-1;
376 currEdge -= dataWidth-1; 413 currEdge -= dataWidth-1;
377 } 414 }
378 415
379 // copy results to final distance field data 416 // copy results to final distance field data
380 currData = dataPtr + dataWidth+1; 417 currData = dataPtr + dataWidth+1;
381 currEdge = edgePtr + dataWidth+1; 418 currEdge = edgePtr + dataWidth+1;
382 unsigned char *dfPtr = distanceField; 419 unsigned char *dfPtr = distanceField;
383 for (int j = 1; j < dataHeight-1; ++j) { 420 for (int j = 1; j < dataHeight-1; ++j) {
384 for (int i = 1; i < dataWidth-1; ++i) { 421 for (int i = 1; i < dataWidth-1; ++i) {
422 #if DUMP_EDGE
423 unsigned char val = (currData->fAlpha >= 0.5f) ? 255 : 0;
robertphillips 2014/03/12 16:40:07 newline after { and before } ?
424 if (*currEdge) { val = 128; }
425 *dfPtr++ = val;
426 #else
385 float dist; 427 float dist;
386 if (currData->fAlpha > 0.5f) { 428 if (currData->fAlpha > 0.5f) {
387 dist = -SkScalarSqrt(currData->fDistSq); 429 dist = -SkScalarSqrt(currData->fDistSq);
388 } else { 430 } else {
389 dist = SkScalarSqrt(currData->fDistSq); 431 dist = SkScalarSqrt(currData->fDistSq);
390 } 432 }
391
392 *dfPtr++ = pack_distance_field_val(dist, (float)distanceMagnitude); 433 *dfPtr++ = pack_distance_field_val(dist, (float)distanceMagnitude);
434 #endif
393 ++currData; 435 ++currData;
394 ++currEdge; 436 ++currEdge;
395 } 437 }
396 currData += 2; 438 currData += 2;
397 currEdge += 2; 439 currEdge += 2;
398 } 440 }
399 441
400 return true; 442 return true;
401 } 443 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698