Index: samplecode/SampleBitmap2Path.cpp |
diff --git a/samplecode/SampleBitmap2Path.cpp b/samplecode/SampleBitmap2Path.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6144108224ef144b355983ff5b40322b5aaea77a |
--- /dev/null |
+++ b/samplecode/SampleBitmap2Path.cpp |
@@ -0,0 +1,163 @@ |
+/* |
+ * Copyright 2013 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "SampleCode.h" |
+#include "SkView.h" |
+#include "SkCanvas.h" |
+#include "SkPathOps.h" |
+ |
+#define SQRT_2 1.41421356237f |
+typedef void (*line2path)(SkPath*, const char*, int, int); |
+ |
+static int getBit( const char *buffer, int x ) { |
+ int byte = x >> 8; |
+ int bit = x & 7; |
+ |
+ return buffer[byte] & (1 << 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 + SkFloatToScalar(0.5f), |
+ lineIdx + SkFloatToScalar(0.5f), |
+ SkFloatToScalar(SQRT_2 / 2.0f)); |
+ /* I'm shifting the center of the circles by half a pixel |
+ * (to align with corresponding rectangular pixels) |
+ * Should I instead be shifting the rect pixels such that |
+ * their path centers are consistent with the original bitmap |
+ * pixels? |
+ */ |
+ } |
+ } |
+} |
+ |
+static void line2path_span(SkPath* path, const char* line, |
+ int lineIdx, int width) { |
+ bool state = 0; |
reed1
2013/06/14 18:59:39
does state mean "inside a run of pixels"?
|
+ int start = 1; |
+ |
+ for (int i = 0; i < width; ++i) { |
+ 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
|
+ if (state==1) { |
+ int end = 0; |
+ if (getBit(line,i)) ++end; |
+ path->addRect(SkRect::MakeXYWH(start, lineIdx, |
+ i + end - start, 1), |
+ SkPath::kCW_Direction); |
+ } else if (getBit(line,i)) { |
+ path->addRect(SkRect::MakeXYWH(i, lineIdx, 1, 1), |
+ SkPath::kCW_Direction); |
+ } |
+ state = 0; |
+ }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
|
+ if (getBit(line,i)) { // if transition on |
+ state = 1; //mark beginning of span |
+ start = i; |
+ }else { // if transition off |
+ state = 0; |
+ path->addRect(SkRect::MakeXYWH(start, lineIdx, i-start, 1), |
+ SkPath::kCW_Direction); |
+ } |
+ } |
+ } |
+} |
+ |
+static void bitmap2path(SkPath* path, |
+ const char* bitmap, |
+ const line2path l2p_fn, |
+ int h, int w, 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); |
+ } |
+} |
+ |
+ |
+class Bitmap2Path : public SampleView { |
+public: |
+ Bitmap2Path() { |
+ } |
+ |
+protected: |
+ // overrides from SkEventSink |
+ virtual bool onQuery(SkEvent* evt) { |
+ if (SampleCode::TitleQ(*evt)) { |
+ SampleCode::TitleR(evt, "Bitmap2Path"); |
+ return true; |
+ } |
+ return this->INHERITED::onQuery(evt); |
+ } |
+ |
+ virtual void onDrawContent(SkCanvas* canvas) { |
+ char raw_bits[] = { |
+ 0x99, 0x00, |
+ 0x5a, 0x00, |
+ 0x3c, 0x00, |
+ 0x18, 0x00, |
+ 0x99, 0x00, |
+ 0x5a, 0x00, |
+ 0x3c, 0x00, |
+ 0x18, 0x00, |
+ }; |
+ |
+ // pointer into memory for binary bitmap |
+ const char* bitmap = (char*) &raw_bits; |
+ int h=8, w=8, str=2; |
+ |
+ // array of funtion pointers for modes (allows looping) |
+ const int numModes = 3; |
+ const line2path l2p_fns[numModes] = {line2path_pixel, |
+ line2path_pixelCircle, |
+ line2path_span}; |
+ |
+ // select paint for drawing binary pixels -- BLACK |
+ SkPaint paint; |
+ paint.setAntiAlias(true); |
+ paint.setStyle(SkPaint::kFill_Style); |
+ paint.setColor(SK_ColorBLACK); |
+ |
+ // for each mode |
+ for (int i = 0; i < numModes; ++i) { |
+ //convert bitmap to path |
+ SkPath path, simple; |
+ |
+ // generate and simplify path |
+ bitmap2path(&path, bitmap, l2p_fns[i], h, w, str); |
+ Simplify(path, &simple); |
+ |
+ //draw to canvas |
+ canvas->save(); |
+ canvas->scale(10, 10); |
+ canvas->translate(i * 10, 0); |
+ canvas->drawPath(simple, paint); |
+ canvas->restore(); |
+ } |
+ } |
+ |
+private: |
+ typedef SkView INHERITED; |
+}; |
+ |
+////////////////////////////////////////////////////////////////////////////// |
+ |
+static SkView* MyFactory() { return new Bitmap2Path; } |
+static SkViewRegister reg(MyFactory); |