blob: f0bea40d208d82cf2c4e39274c9a51c3110e0856 [file] [log] [blame]
commit-bot@chromium.org064779a2013-07-01 17:50:29 +00001/*
2 * CAUTION: EXPERIMENTAL CODE
3 *
4 * This code is not to be used and will not be supported
5 * if it fails on you. DO NOT USE!
6 *
7 */
8
9#include "SkPathUtils.h"
10
11#include "SkPath.h"
12#include "SkPathOps.h" // this can't be found, how do I link it?
13#include "SkRegion.h"
14
15typedef void (*line2path)(SkPath*, const char*, int, int);
16#define SQRT_2 1.41421356237f
17#define ON 0xFF000000 // black pixel
18#define OFF 0x00000000 // transparent pixel
19
20// assumes stride is in bytes
21/*
22static void FillRandomBits( int chars, char* bits ){
23 SkTime time;
24 SkMWCRandom rand = SkMWCRandom( time.GetMSecs() );
25
26 for (int i = 0; i < chars; ++i){
27 bits[i] = rand.nextU();
28 }
29}OA
30*/
31
32static int GetBit( const char* buffer, int x ) {
33 int byte = x >> 3;
34 int bit = x & 7;
35
36 return buffer[byte] & (128 >> bit);
37}
38
39/*
40static void Line2path_pixel(SkPath* path, const char* line,
41 int lineIdx, int width) {
42 for (int i = 0; i < width; ++i) {
43 // simply makes every ON pixel into a rect path
44 if (GetBit(line,i)) {
45 path->addRect(SkRect::MakeXYWH(i, lineIdx, 1, 1),
46 SkPath::kCW_Direction);
47 }
48 }
49}
50
51static void Line2path_pixelCircle(SkPath* path, const char* line,
52 int lineIdx, int width) {
53 for (int i = 0; i < width; ++i) {
54 // simply makes every ON pixel into a circle path
55 if (GetBit(line,i)) {
56 path->addCircle(i + SK_ScalarHalf,
57 lineIdx + SK_ScalarHalf,
58 SkFloatToScalar(SQRT_2 / 2.0f));
59 }
60 }
61}
62*/
63
64static void Line2path_span(SkPath* path, const char* line,
65 int lineIdx, int width) {
66 bool inRun = 0;
67 int start = 1;
68
69 for (int i = 0; i < width; ++i) {
70 int curPixel = GetBit(line,i);
71
72 if ( (curPixel!=0) != inRun ) { // if transition
73 if (curPixel) { // if transition on
74 inRun = 1;
75 start = i; // mark beginning of span
76 }else { // if transition off add the span as a path
77 inRun = 0;
dierk@google.com74887b62013-07-01 19:30:14 +000078 path->addRect(SkRect::MakeXYWH(start, lineIdx, i-start, SK_Scalar1),
commit-bot@chromium.org064779a2013-07-01 17:50:29 +000079 SkPath::kCW_Direction);
80 }
81 }
82 }
83
84 if (inRun==1) { // close any open spans
85 int end = 0;
86 if ( GetBit(line,width-1) ) ++end;
87 path->addRect(SkRect::MakeXYWH(start, lineIdx,
dierk@google.com74887b62013-07-01 19:30:14 +000088 width - SK_Scalar1 + end - start, SK_Scalar1),
commit-bot@chromium.org064779a2013-07-01 17:50:29 +000089 SkPath::kCW_Direction);
dierk@google.com6bee4ec2013-07-01 19:52:36 +000090 } else if ( GetBit(line, width - 1) ) { // if last pixel on add
dierk@google.com74887b62013-07-01 19:30:14 +000091 path->addRect(SkRect::MakeXYWH(width - SK_Scalar1, lineIdx,
92 SK_Scalar1, SK_Scalar1),
commit-bot@chromium.org064779a2013-07-01 17:50:29 +000093 SkPath::kCW_Direction);
94 }
95}
96
97void SkPathUtils::BitsToPath_Path(SkPath* path,
98 const char* bitmap,
99 int h, int w, int stride) {
100 // loop for every line in bitmap
101 for (int i = 0; i < h; ++i) {
102 // fn ptr handles each line separately
103 //l2p_fn(path, &bitmap[i*stride], i, w);
104 Line2path_span(path, &bitmap[i*stride], i, w);
105 }
106 Simplify(*path, path); // simplify resulting bitmap
107}
108
109void SkPathUtils::BitsToPath_Region(SkPath* path,
110 const char* bitmap,
111 int h, int w, int stride) {
112 SkRegion region;
113
114 // loop for each line
115 for (int y = 0; y < h; ++y){
116 bool inRun = 0;
117 int start = 1;
118 const char* line = &bitmap[y * stride];
119
120 // loop for each pixel
121 for (int i = 0; i < w; ++i) {
122 int curPixel = GetBit(line,i);
123
124 if ( (curPixel!=0) != inRun ) { // if transition
125 if (curPixel) { // if transition on
126 inRun = 1;
127 start = i; // mark beginning of span
128 }else { // if transition off add the span as a path
129 inRun = 0;
130 //add here
131 region.op(SkIRect::MakeXYWH(start, y, i-start, 1),
132 SkRegion::kUnion_Op );
133 }
134 }
135 }
136 if (inRun==1) { // close any open spans
137 int end = 0;
138 if ( GetBit(line,w-1) ) ++end;
139 // add the thing here
140 region.op(SkIRect::MakeXYWH(start, y, w-1-start+end, 1),
141 SkRegion::kUnion_Op );
142
143 } else if ( GetBit(line,w-1) ) { // if last pixel on add rect
144 // add the thing here
145 region.op(SkIRect::MakeXYWH(w-1, y, 1, 1),
146 SkRegion::kUnion_Op );
147 }
148 }
149 // convert region to path
150 region.getBoundaryPath(path);
151}