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