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