1 2 /* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 #include "SampleCode.h" 9 #include "SkView.h" 10 #include "SkCanvas.h" 11 #include "SkColorFilter.h" 12 #include "SkDevice.h" 13 #include "SkPaint.h" 14 #include "SkShader.h" 15 16 static int inflate5To8(int x) { 17 return (x << 3) | (x >> 2); 18 } 19 20 static int trunc5(int x) { 21 return x >> 3; 22 } 23 24 #define SK_R16_BITS 5 25 26 #ifdef SK_DEBUG 27 static int round5_slow(int x) { 28 int orig = x & 7; 29 int fake = x >> 5; 30 int trunc = x >> 3; 31 32 int diff = fake - orig; 33 34 int bias = 0; 35 if (diff > 4) { 36 bias = -1; 37 } else if (diff < -4) { 38 bias = 1; 39 } 40 return trunc + bias; 41 } 42 #endif 43 44 static int round5_fast(int x) { 45 int result = x + 3 - (x >> 5) + (x >> 7); 46 result >>= 3; 47 #ifdef SK_DEBUG 48 { 49 int r2 = round5_slow(x); 50 SkASSERT(r2 == result); 51 } 52 #endif 53 return result; 54 } 55 56 static void test_5bits() { 57 int e0 = 0; 58 int e1 = 0; 59 int e2 = 0; 60 int ae0 = 0; 61 int ae1 = 0; 62 int ae2 = 0; 63 for (int i = 0; i < 256; i++) { 64 int t0 = trunc5(i); 65 int t1 = round5_fast(i); 66 int t2 = trunc5(i); 67 int v0 = inflate5To8(t0); 68 int v1 = inflate5To8(t1); 69 int v2 = inflate5To8(t2); 70 int err0 = i - v0; 71 int err1 = i - v1; 72 int err2 = i - v2; 73 SkDebugf("--- %3d : trunc=%3d (%2d) round:%3d (%2d) \n"/*new:%d (%2d)\n"*/, i, 74 v0, err0, v1, err1, v2, err2); 75 76 77 e0 += err0; 78 e1 += err1; 79 e2 += err2; 80 ae0 += SkAbs32(err0); 81 ae1 += SkAbs32(err1); 82 ae2 += SkAbs32(err2); 83 } 84 SkDebugf("--- trunc: %d %d round: %d %d new: %d %d\n", e0, ae0, e1, ae1, e2, ae2); 85 } 86 87 // No longer marked static, since it is externed in SampleUnpremul. 88 SkShader* createChecker(); 89 SkShader* createChecker() { 90 SkBitmap bm; 91 bm.allocN32Pixels(2, 2); 92 bm.lockPixels(); 93 *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(0xFFFFFFFF); 94 *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(0xFFCCCCCC); 95 SkMatrix m; 96 m.setScale(12, 12); 97 return SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, 98 SkShader::kRepeat_TileMode, &m); 99 } 100 101 static SkBitmap createBitmap(int n) { 102 SkBitmap bitmap; 103 bitmap.allocN32Pixels(n, n); 104 bitmap.eraseColor(SK_ColorTRANSPARENT); 105 106 SkCanvas canvas(bitmap); 107 SkRect r; 108 r.set(0, 0, SkIntToScalar(n), SkIntToScalar(n)); 109 r.inset(SK_Scalar1, SK_Scalar1); 110 111 SkPaint paint; 112 paint.setAntiAlias(true); 113 114 paint.setColor(SK_ColorRED); 115 canvas.drawOval(r, paint); 116 117 r.inset(SK_Scalar1*n/4, SK_Scalar1*n/4); 118 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 119 paint.setColor(0x800000FF); 120 canvas.drawOval(r, paint); 121 122 return bitmap; 123 } 124 125 class ColorFilterView : public SampleView { 126 SkBitmap fBitmap; 127 SkShader* fShader; 128 enum { 129 N = 64 130 }; 131 public: 132 ColorFilterView() { 133 fBitmap = createBitmap(N); 134 fShader = createChecker(); 135 136 if (false) { // avoid bit rot, suppress warning 137 test_5bits(); 138 } 139 } 140 141 virtual ~ColorFilterView() { 142 fShader->unref(); 143 } 144 145 protected: 146 // overrides from SkEventSink 147 virtual bool onQuery(SkEvent* evt) { 148 if (SampleCode::TitleQ(*evt)) { 149 SampleCode::TitleR(evt, "ColorFilter"); 150 return true; 151 } 152 return this->INHERITED::onQuery(evt); 153 } 154 155 virtual void onDrawBackground(SkCanvas* canvas) { 156 SkPaint paint; 157 paint.setShader(fShader); 158 canvas->drawPaint(paint); 159 } 160 161 virtual void onDrawContent(SkCanvas* canvas) { 162 if (false) { 163 SkPaint p; 164 p.setAntiAlias(true); 165 SkRect r = { 20.4f, 10, 20.6f, 20 }; 166 canvas->drawRect(r, p); 167 r.set(30.9f, 10, 31.1f, 20); 168 canvas->drawRect(r, p); 169 return; 170 } 171 172 static const SkXfermode::Mode gModes[] = { 173 SkXfermode::kClear_Mode, 174 SkXfermode::kSrc_Mode, 175 SkXfermode::kDst_Mode, 176 SkXfermode::kSrcOver_Mode, 177 SkXfermode::kDstOver_Mode, 178 SkXfermode::kSrcIn_Mode, 179 SkXfermode::kDstIn_Mode, 180 SkXfermode::kSrcOut_Mode, 181 SkXfermode::kDstOut_Mode, 182 SkXfermode::kSrcATop_Mode, 183 SkXfermode::kDstATop_Mode, 184 SkXfermode::kXor_Mode, 185 SkXfermode::kPlus_Mode, 186 SkXfermode::kModulate_Mode, 187 }; 188 189 static const SkColor gColors[] = { 190 0xFF000000, 191 0x80000000, 192 0xFF00FF00, 193 0x8000FF00, 194 0x00000000, 195 }; 196 197 float scale = 1.5f; 198 SkPaint paint; 199 canvas->translate(N / 8, N / 8); 200 201 for (size_t y = 0; y < SK_ARRAY_COUNT(gColors); y++) { 202 for (size_t x = 0; x < SK_ARRAY_COUNT(gModes); x++) { 203 SkColorFilter* cf = SkColorFilter::CreateModeFilter(gColors[y], gModes[x]); 204 SkSafeUnref(paint.setColorFilter(cf)); 205 canvas->drawBitmap(fBitmap, x * N * 1.25f, y * N * scale, &paint); 206 } 207 } 208 209 } 210 211 private: 212 typedef SampleView INHERITED; 213 }; 214 215 ////////////////////////////////////////////////////////////////////////////// 216 217 static SkView* MyFactory() { return new ColorFilterView; } 218 static SkViewRegister reg(MyFactory); 219