1064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org/*
2064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org *  CAUTION: EXPERIMENTAL CODE
3064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org *
4064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org *  This code is not to be used and will not be supported
5064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org *  if it fails on you. DO NOT USE!
6064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org *
7064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org */
8064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
9064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org#include "SkPathUtils.h"
10064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
11064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org#include "SkPath.h"
12064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org#include "SkPathOps.h" // this can't be found, how do I link it?
13064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org#include "SkRegion.h"
14064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
15064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.orgtypedef void (*line2path)(SkPath*, const char*, int, int);
16064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org#define SQRT_2 1.41421356237f
17064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org#define ON  0xFF000000 // black pixel
18064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org#define OFF 0x00000000 // transparent pixel
19064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
20064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org// assumes stride is in bytes
21064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org/*
22064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.orgstatic void FillRandomBits( int chars, char* bits ){
23064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    SkTime time;
24e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org    SkRandom rand = SkRandom( time.GetMSecs() );
25064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
26064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    for (int i = 0; i < chars; ++i){
27064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        bits[i] = rand.nextU();
28064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    }
29064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org}OA
300d55dd7d2c07a77b22478bed9b30ff44ceecad68skia.committer@gmail.com*/
31064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
32064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.orgstatic int GetBit( const char* buffer, int x ) {
33064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    int byte = x >> 3;
34064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    int bit = x & 7;
35064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
36064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    return buffer[byte] & (128 >> bit);
37064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org}
38064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
39064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org/*
40064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.orgstatic void Line2path_pixel(SkPath* path, const char* line,
41064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                            int lineIdx, int width) {
42064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    for (int i = 0; i < width; ++i) {
43064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        // simply makes every ON pixel into a rect path
44064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        if (GetBit(line,i)) {
45064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            path->addRect(SkRect::MakeXYWH(i, lineIdx, 1, 1),
46064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                          SkPath::kCW_Direction);
47064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        }
48064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    }
49064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org}
50064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
51064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.orgstatic void Line2path_pixelCircle(SkPath* path, const char* line,
52064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                                  int lineIdx, int width) {
53064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    for (int i = 0; i < width; ++i) {
54064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        // simply makes every ON pixel into a circle path
55064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        if (GetBit(line,i)) {
56064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            path->addCircle(i + SK_ScalarHalf,
57064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                            lineIdx + SK_ScalarHalf,
584b413c8bb123e42ca4b9c7bfa6bc2167283cb84ccommit-bot@chromium.org                            SQRT_2 / 2.0f);
59064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        }
60064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    }
61064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org}
62064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org*/
63064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
64064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.orgstatic void Line2path_span(SkPath* path, const char* line,
65064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                           int lineIdx, int width) {
66064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    bool inRun = 0;
67064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    int start = 1;
68064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
69064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    for (int i = 0; i < width; ++i) {
70064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        int curPixel = GetBit(line,i);
71064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
72064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        if ( (curPixel!=0) != inRun ) { // if transition
73064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            if (curPixel) { // if transition on
74064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                inRun = 1;
75064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                start = i; // mark beginning of span
76064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            }else { // if transition off add the span as a path
77064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                inRun = 0;
786b4231225f38f966b6c6ba07332877b8be469b17dierk@google.com                path->addRect(SkRect::MakeXYWH(SkIntToScalar(start), SkIntToScalar(lineIdx),
7919b8438ffba0de8e280016705f2976bd0a21dff2dierk@google.com                                               SkIntToScalar(i-start), SK_Scalar1),
80064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                              SkPath::kCW_Direction);
81064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            }
82064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        }
83064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    }
84064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
85064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    if (inRun==1) { // close any open spans
86064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        int end = 0;
87064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        if ( GetBit(line,width-1) ) ++end;
886b4231225f38f966b6c6ba07332877b8be469b17dierk@google.com        path->addRect(SkRect::MakeXYWH(SkIntToScalar(start), SkIntToScalar(lineIdx),
896b4231225f38f966b6c6ba07332877b8be469b17dierk@google.com                                       SkIntToScalar(width - 1 + end - start), SK_Scalar1),
90064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                      SkPath::kCW_Direction);
916bee4ec36af9cd515e74bbc75f449815a8ffd842dierk@google.com    } else if ( GetBit(line, width - 1) ) { // if last pixel on add
926b4231225f38f966b6c6ba07332877b8be469b17dierk@google.com        path->addRect(SkRect::MakeXYWH(width - SK_Scalar1, SkIntToScalar(lineIdx),
9374887b6eddea9816c60313c6d5cfa744ccb90425dierk@google.com                                       SK_Scalar1, SK_Scalar1),
94064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                      SkPath::kCW_Direction);
95064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    }
96064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org}
97064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
98064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.orgvoid SkPathUtils::BitsToPath_Path(SkPath* path,
99064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                        const char* bitmap,
100d43f6449129f11c9823bdeb0fb8ac38ab6d76a28commit-bot@chromium.org                        int w, int h, int stride) {
101064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    // loop for every line in bitmap
102064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    for (int i = 0; i < h; ++i) {
103064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        // fn ptr handles each line separately
104064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        //l2p_fn(path, &bitmap[i*stride], i, w);
105064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        Line2path_span(path, &bitmap[i*stride], i, w);
106064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    }
107d43f6449129f11c9823bdeb0fb8ac38ab6d76a28commit-bot@chromium.org    Simplify(*path, path); // simplify resulting path.
108064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org}
109064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
110064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.orgvoid SkPathUtils::BitsToPath_Region(SkPath* path,
111064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                               const char* bitmap,
112d43f6449129f11c9823bdeb0fb8ac38ab6d76a28commit-bot@chromium.org                               int w, int h, int stride) {
113064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    SkRegion region;
114064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org
115064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    // loop for each line
116064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    for (int y = 0; y < h; ++y){
117064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        bool inRun = 0;
118064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        int start = 1;
119064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        const char* line = &bitmap[y * stride];
1200d55dd7d2c07a77b22478bed9b30ff44ceecad68skia.committer@gmail.com
1210d55dd7d2c07a77b22478bed9b30ff44ceecad68skia.committer@gmail.com        // loop for each pixel
122064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        for (int i = 0; i < w; ++i) {
123064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            int curPixel = GetBit(line,i);
1240d55dd7d2c07a77b22478bed9b30ff44ceecad68skia.committer@gmail.com
125064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            if ( (curPixel!=0) != inRun ) { // if transition
126064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                if (curPixel) { // if transition on
127064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                    inRun = 1;
128064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                    start = i; // mark beginning of span
129064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                }else { // if transition off add the span as a path
130064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                    inRun = 0;
131064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                    //add here
132064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                    region.op(SkIRect::MakeXYWH(start, y, i-start, 1),
133064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                              SkRegion::kUnion_Op );
134064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                }
135064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            }
136064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        }
137064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        if (inRun==1) { // close any open spans
138064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            int end = 0;
139064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            if ( GetBit(line,w-1) ) ++end;
140064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            // add the thing here
141064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            region.op(SkIRect::MakeXYWH(start, y, w-1-start+end, 1),
142064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                      SkRegion::kUnion_Op );
1430d55dd7d2c07a77b22478bed9b30ff44ceecad68skia.committer@gmail.com
144064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        } else if ( GetBit(line,w-1) ) { // if last pixel on add rect
145064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            // add the thing here
146064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org            region.op(SkIRect::MakeXYWH(w-1, y, 1, 1),
147064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org                      SkRegion::kUnion_Op );
148064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org        }
149064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    }
150064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    // convert region to path
151064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org    region.getBoundaryPath(path);
152064779aa18694b68536c113f7d5b74ccbe38d3bacommit-bot@chromium.org}
153