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