Chromium Code Reviews| 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); |