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
17static int inflate5To8(int x) {
18    return (x << 3) | (x >> 2);
19}
20
21static int trunc5(int x) {
22    return x >> 3;
23}
24
25#define SK_R16_BITS 5
26
27#ifdef SK_DEBUG
28static 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
45static 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
57static 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
88static 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
112class ColorFilterView : public SampleView {
113    SkBitmap fBitmap;
114    SkShader* fShader;
115    enum {
116        N = 64
117    };
118public:
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
129    virtual ~ColorFilterView() {
130        fShader->unref();
131    }
132
133protected:
134    // overrides from SkEventSink
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
143    virtual void onDrawBackground(SkCanvas* canvas) {
144        SkPaint paint;
145        paint.setShader(fShader);
146        canvas->drawPaint(paint);
147    }
148
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
199private:
200    typedef SampleView INHERITED;
201};
202
203//////////////////////////////////////////////////////////////////////////////
204
205static SkView* MyFactory() { return new ColorFilterView; }
206static SkViewRegister reg(MyFactory);
207