1 /* 2 * Copyright 2011 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 #include "sk_tool_utils.h" 8 #include "Sample.h" 9 #include "SkCanvas.h" 10 #include "SkColorFilter.h" 11 #include "SkPaint.h" 12 #include "SkShader.h" 13 14 static int inflate5To8(int x) { 15 return (x << 3) | (x >> 2); 16 } 17 18 static int trunc5(int x) { 19 return x >> 3; 20 } 21 22 #define SK_R16_BITS 5 23 24 #ifdef SK_DEBUG 25 static int round5_slow(int x) { 26 int orig = x & 7; 27 int fake = x >> 5; 28 int trunc = x >> 3; 29 30 int diff = fake - orig; 31 32 int bias = 0; 33 if (diff > 4) { 34 bias = -1; 35 } else if (diff < -4) { 36 bias = 1; 37 } 38 return trunc + bias; 39 } 40 #endif 41 42 static int round5_fast(int x) { 43 int result = x + 3 - (x >> 5) + (x >> 7); 44 result >>= 3; 45 #ifdef SK_DEBUG 46 { 47 int r2 = round5_slow(x); 48 SkASSERT(r2 == result); 49 } 50 #endif 51 return result; 52 } 53 54 static void test_5bits() { 55 int e0 = 0; 56 int e1 = 0; 57 int e2 = 0; 58 int ae0 = 0; 59 int ae1 = 0; 60 int ae2 = 0; 61 for (int i = 0; i < 256; i++) { 62 int t0 = trunc5(i); 63 int t1 = round5_fast(i); 64 int t2 = trunc5(i); 65 int v0 = inflate5To8(t0); 66 int v1 = inflate5To8(t1); 67 int v2 = inflate5To8(t2); 68 int err0 = i - v0; 69 int err1 = i - v1; 70 int err2 = i - v2; 71 SkDebugf("--- %3d : trunc=%3d (%2d) round:%3d (%2d) \n"/*new:%d (%2d)\n"*/, i, 72 v0, err0, v1, err1, v2, err2); 73 74 75 e0 += err0; 76 e1 += err1; 77 e2 += err2; 78 ae0 += SkAbs32(err0); 79 ae1 += SkAbs32(err1); 80 ae2 += SkAbs32(err2); 81 } 82 SkDebugf("--- trunc: %d %d round: %d %d new: %d %d\n", e0, ae0, e1, ae1, e2, ae2); 83 } 84 85 static SkBitmap createBitmap(int n) { 86 SkBitmap bitmap; 87 bitmap.allocN32Pixels(n, n); 88 bitmap.eraseColor(SK_ColorTRANSPARENT); 89 90 SkCanvas canvas(bitmap); 91 SkRect r; 92 r.set(0, 0, SkIntToScalar(n), SkIntToScalar(n)); 93 r.inset(SK_Scalar1, SK_Scalar1); 94 95 SkPaint paint; 96 paint.setAntiAlias(true); 97 98 paint.setColor(SK_ColorRED); 99 canvas.drawOval(r, paint); 100 101 r.inset(SK_Scalar1*n/4, SK_Scalar1*n/4); 102 paint.setBlendMode(SkBlendMode::kSrc); 103 paint.setColor(0x800000FF); 104 canvas.drawOval(r, paint); 105 106 return bitmap; 107 } 108 109 class ColorFilterView : public Sample { 110 SkBitmap fBitmap; 111 sk_sp<SkShader> fShader; 112 enum { 113 N = 64 114 }; 115 116 protected: 117 void onOnceBeforeDraw() override { 118 fBitmap = createBitmap(N); 119 fShader = sk_tool_utils::create_checkerboard_shader( 120 0xFFCCCCCC, 0xFFFFFFFF, 12); 121 122 if (false) { // avoid bit rot, suppress warning 123 test_5bits(); 124 } 125 } 126 127 bool onQuery(Sample::Event* evt) override { 128 if (Sample::TitleQ(*evt)) { 129 Sample::TitleR(evt, "ColorFilter"); 130 return true; 131 } 132 return this->INHERITED::onQuery(evt); 133 } 134 135 void onDrawBackground(SkCanvas* canvas) override { 136 SkPaint paint; 137 paint.setShader(fShader); 138 canvas->drawPaint(paint); 139 } 140 141 void onDrawContent(SkCanvas* canvas) override { 142 if (false) { 143 SkPaint p; 144 p.setAntiAlias(true); 145 SkRect r = { 20.4f, 10, 20.6f, 20 }; 146 canvas->drawRect(r, p); 147 r.set(30.9f, 10, 31.1f, 20); 148 canvas->drawRect(r, p); 149 return; 150 } 151 152 static const SkBlendMode gModes[] = { 153 SkBlendMode::kClear, 154 SkBlendMode::kSrc, 155 SkBlendMode::kDst, 156 SkBlendMode::kSrcOver, 157 SkBlendMode::kDstOver, 158 SkBlendMode::kSrcIn, 159 SkBlendMode::kDstIn, 160 SkBlendMode::kSrcOut, 161 SkBlendMode::kDstOut, 162 SkBlendMode::kSrcATop, 163 SkBlendMode::kDstATop, 164 SkBlendMode::kXor, 165 SkBlendMode::kPlus, 166 SkBlendMode::kModulate, 167 }; 168 169 static const SkColor gColors[] = { 170 0xFF000000, 171 0x80000000, 172 0xFF00FF00, 173 0x8000FF00, 174 0x00000000, 175 }; 176 177 float scale = 1.5f; 178 SkPaint paint; 179 canvas->translate(N / 8, N / 8); 180 181 for (size_t y = 0; y < SK_ARRAY_COUNT(gColors); y++) { 182 for (size_t x = 0; x < SK_ARRAY_COUNT(gModes); x++) { 183 paint.setColorFilter(SkColorFilter::MakeModeFilter(gColors[y], gModes[x])); 184 canvas->drawBitmap(fBitmap, x * N * 1.25f, y * N * scale, &paint); 185 } 186 } 187 188 } 189 190 private: 191 typedef Sample INHERITED; 192 }; 193 194 ////////////////////////////////////////////////////////////////////////////// 195 196 DEF_SAMPLE( return new ColorFilterView(); ) 197