aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils/SkPathUtils.cpp
blob: fdca09aa6307dab132580206fefbe64518365513 (plain)
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);
}