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