OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2013 Google Inc. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license that can be | |
5 * found in the LICENSE file. | |
6 */ | |
7 | |
8 #include "SampleCode.h" | |
9 #include "SkView.h" | |
10 #include "SkCanvas.h" | |
11 #include "SkPathOps.h" | |
12 | |
13 #define SQRT_2 1.41421356237f | |
14 typedef void (*line2path)(SkPath*, const char*, int, int); | |
15 | |
16 static int getBit( const char *buffer, int x ) { | |
17 int byte = x >> 8; | |
18 int bit = x & 7; | |
19 | |
20 return buffer[byte] & (1 << bit); | |
21 } | |
22 | |
23 static void line2path_pixel(SkPath* path, const char* line, | |
24 int lineIdx, int width) { | |
25 for (int i = 0; i < width; ++i) { | |
26 // simply makes every ON pixel into a rect path | |
27 if (getBit(line,i)) { | |
28 path->addRect(SkRect::MakeXYWH(i, lineIdx, 1, 1), | |
29 SkPath::kCW_Direction); | |
30 } | |
31 } | |
32 } | |
33 | |
34 static void line2path_pixelCircle(SkPath* path, const char* line, | |
35 int lineIdx, int width) { | |
36 for (int i = 0; i < width; ++i) { | |
37 // simply makes every ON pixel into a circle path | |
38 if (getBit(line,i)) { | |
39 path->addCircle(i + SkFloatToScalar(0.5f), | |
40 lineIdx + SkFloatToScalar(0.5f), | |
41 SkFloatToScalar(SQRT_2 / 2.0f)); | |
42 /* I'm shifting the center of the circles by half a pixel | |
43 * (to align with corresponding rectangular pixels) | |
44 * Should I instead be shifting the rect pixels such that | |
45 * their path centers are consistent with the original bitmap | |
46 * pixels? | |
47 */ | |
48 } | |
49 } | |
50 } | |
51 | |
52 static void line2path_span(SkPath* path, const char* line, | |
53 int lineIdx, int width) { | |
54 bool state = 0; | |
reed1
2013/06/14 18:59:39
does state mean "inside a run of pixels"?
| |
55 int start = 1; | |
56 | |
57 for (int i = 0; i < width; ++i) { | |
58 if (i==width-1) { // if the end of a scanline, close open paths | |
reed1
2013/06/14 18:59:39
rather than check for this every time through the
| |
59 if (state==1) { | |
60 int end = 0; | |
61 if (getBit(line,i)) ++end; | |
62 path->addRect(SkRect::MakeXYWH(start, lineIdx, | |
63 i + end - start, 1), | |
64 SkPath::kCW_Direction); | |
65 } else if (getBit(line,i)) { | |
66 path->addRect(SkRect::MakeXYWH(i, lineIdx, 1, 1), | |
67 SkPath::kCW_Direction); | |
68 } | |
69 state = 0; | |
70 }else if ( (getBit(line,i)!=0) != state ) { // if transition | |
reed1
2013/06/14 18:59:39
yick -- we're calling getBit more than once per-bi
| |
71 if (getBit(line,i)) { // if transition on | |
72 state = 1; //mark beginning of span | |
73 start = i; | |
74 }else { // if transition off | |
75 state = 0; | |
76 path->addRect(SkRect::MakeXYWH(start, lineIdx, i-start, 1), | |
77 SkPath::kCW_Direction); | |
78 } | |
79 } | |
80 } | |
81 } | |
82 | |
83 static void bitmap2path(SkPath* path, | |
84 const char* bitmap, | |
85 const line2path l2p_fn, | |
86 int h, int w, int stride) { | |
87 // loop for every line in bitmap | |
88 for (int i = 0; i < h; ++i) { | |
89 // fn ptr handles each line separately | |
90 l2p_fn(path, &bitmap[i*stride], i, w); | |
91 } | |
92 } | |
93 | |
94 | |
95 class Bitmap2Path : public SampleView { | |
96 public: | |
97 Bitmap2Path() { | |
98 } | |
99 | |
100 protected: | |
101 // overrides from SkEventSink | |
102 virtual bool onQuery(SkEvent* evt) { | |
103 if (SampleCode::TitleQ(*evt)) { | |
104 SampleCode::TitleR(evt, "Bitmap2Path"); | |
105 return true; | |
106 } | |
107 return this->INHERITED::onQuery(evt); | |
108 } | |
109 | |
110 virtual void onDrawContent(SkCanvas* canvas) { | |
111 char raw_bits[] = { | |
112 0x99, 0x00, | |
113 0x5a, 0x00, | |
114 0x3c, 0x00, | |
115 0x18, 0x00, | |
116 0x99, 0x00, | |
117 0x5a, 0x00, | |
118 0x3c, 0x00, | |
119 0x18, 0x00, | |
120 }; | |
121 | |
122 // pointer into memory for binary bitmap | |
123 const char* bitmap = (char*) &raw_bits; | |
124 int h=8, w=8, str=2; | |
125 | |
126 // array of funtion pointers for modes (allows looping) | |
127 const int numModes = 3; | |
128 const line2path l2p_fns[numModes] = {line2path_pixel, | |
129 line2path_pixelCircle, | |
130 line2path_span}; | |
131 | |
132 // select paint for drawing binary pixels -- BLACK | |
133 SkPaint paint; | |
134 paint.setAntiAlias(true); | |
135 paint.setStyle(SkPaint::kFill_Style); | |
136 paint.setColor(SK_ColorBLACK); | |
137 | |
138 // for each mode | |
139 for (int i = 0; i < numModes; ++i) { | |
140 //convert bitmap to path | |
141 SkPath path, simple; | |
142 | |
143 // generate and simplify path | |
144 bitmap2path(&path, bitmap, l2p_fns[i], h, w, str); | |
145 Simplify(path, &simple); | |
146 | |
147 //draw to canvas | |
148 canvas->save(); | |
149 canvas->scale(10, 10); | |
150 canvas->translate(i * 10, 0); | |
151 canvas->drawPath(simple, paint); | |
152 canvas->restore(); | |
153 } | |
154 } | |
155 | |
156 private: | |
157 typedef SkView INHERITED; | |
158 }; | |
159 | |
160 ////////////////////////////////////////////////////////////////////////////// | |
161 | |
162 static SkView* MyFactory() { return new Bitmap2Path; } | |
163 static SkViewRegister reg(MyFactory); | |
OLD | NEW |