1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
8b0cce2c1d37d4bf5b89da6c70062209ac4e0e643halcanary#include "sk_tool_utils.h"
99ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SampleCode.h"
109ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkView.h"
119ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkCanvas.h"
129ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkColorFilter.h"
139ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkDevice.h"
149ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkPaint.h"
159ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkShader.h"
169ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1779b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic int inflate5To8(int x) {
1879b3b7e916d874f78208d33b00a554270c19b72areed@google.com    return (x << 3) | (x >> 2);
1979b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
2079b3b7e916d874f78208d33b00a554270c19b72areed@google.com
2179b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic int trunc5(int x) {
2279b3b7e916d874f78208d33b00a554270c19b72areed@google.com    return x >> 3;
2379b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
2479b3b7e916d874f78208d33b00a554270c19b72areed@google.com
2579b3b7e916d874f78208d33b00a554270c19b72areed@google.com#define SK_R16_BITS 5
2679b3b7e916d874f78208d33b00a554270c19b72areed@google.com
270e51577a14f903ffeafa117a75954baeb173ffb9humper@google.com#ifdef SK_DEBUG
28ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.comstatic int round5_slow(int x) {
2979b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int orig = x & 7;
3079b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int fake = x >> 5;
3179b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int trunc = x >> 3;
3279b3b7e916d874f78208d33b00a554270c19b72areed@google.com
3379b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int diff = fake - orig;
3479b3b7e916d874f78208d33b00a554270c19b72areed@google.com
3579b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int bias = 0;
3679b3b7e916d874f78208d33b00a554270c19b72areed@google.com    if (diff > 4) {
3779b3b7e916d874f78208d33b00a554270c19b72areed@google.com        bias = -1;
3879b3b7e916d874f78208d33b00a554270c19b72areed@google.com    } else if (diff < -4) {
3979b3b7e916d874f78208d33b00a554270c19b72areed@google.com        bias = 1;
4079b3b7e916d874f78208d33b00a554270c19b72areed@google.com    }
4179b3b7e916d874f78208d33b00a554270c19b72areed@google.com    return trunc + bias;
4279b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
430e51577a14f903ffeafa117a75954baeb173ffb9humper@google.com#endif
4479b3b7e916d874f78208d33b00a554270c19b72areed@google.com
4579b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic int round5_fast(int x) {
4679b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int result = x + 3 - (x >> 5) + (x >> 7);
4779b3b7e916d874f78208d33b00a554270c19b72areed@google.com    result >>= 3;
480e51577a14f903ffeafa117a75954baeb173ffb9humper@google.com#ifdef SK_DEBUG
4979b3b7e916d874f78208d33b00a554270c19b72areed@google.com    {
5079b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int r2 = round5_slow(x);
5179b3b7e916d874f78208d33b00a554270c19b72areed@google.com        SkASSERT(r2 == result);
5279b3b7e916d874f78208d33b00a554270c19b72areed@google.com    }
530e51577a14f903ffeafa117a75954baeb173ffb9humper@google.com#endif
5479b3b7e916d874f78208d33b00a554270c19b72areed@google.com    return result;
5579b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
5679b3b7e916d874f78208d33b00a554270c19b72areed@google.com
5779b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic void test_5bits() {
5879b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int e0 = 0;
5979b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int e1 = 0;
6079b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int e2 = 0;
6179b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int ae0 = 0;
6279b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int ae1 = 0;
6379b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int ae2 = 0;
6479b3b7e916d874f78208d33b00a554270c19b72areed@google.com    for (int i = 0; i < 256; i++) {
6579b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int t0 = trunc5(i);
6679b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int t1 = round5_fast(i);
6779b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int t2 = trunc5(i);
6879b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int v0 = inflate5To8(t0);
6979b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int v1 = inflate5To8(t1);
7079b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int v2 = inflate5To8(t2);
7179b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int err0 = i - v0;
7279b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int err1 = i - v1;
7379b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int err2 = i - v2;
7479b3b7e916d874f78208d33b00a554270c19b72areed@google.com        SkDebugf("--- %3d : trunc=%3d (%2d) round:%3d (%2d) \n"/*new:%d (%2d)\n"*/, i,
7579b3b7e916d874f78208d33b00a554270c19b72areed@google.com                 v0, err0, v1, err1, v2, err2);
76ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
7779b3b7e916d874f78208d33b00a554270c19b72areed@google.com
7879b3b7e916d874f78208d33b00a554270c19b72areed@google.com        e0 += err0;
7979b3b7e916d874f78208d33b00a554270c19b72areed@google.com        e1 += err1;
8079b3b7e916d874f78208d33b00a554270c19b72areed@google.com        e2 += err2;
8179b3b7e916d874f78208d33b00a554270c19b72areed@google.com        ae0 += SkAbs32(err0);
8279b3b7e916d874f78208d33b00a554270c19b72areed@google.com        ae1 += SkAbs32(err1);
8379b3b7e916d874f78208d33b00a554270c19b72areed@google.com        ae2 += SkAbs32(err2);
8479b3b7e916d874f78208d33b00a554270c19b72areed@google.com    }
8579b3b7e916d874f78208d33b00a554270c19b72areed@google.com    SkDebugf("--- trunc: %d %d  round: %d %d new: %d %d\n", e0, ae0, e1, ae1, e2, ae2);
8679b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
8779b3b7e916d874f78208d33b00a554270c19b72areed@google.com
889ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comstatic SkBitmap createBitmap(int n) {
899ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkBitmap bitmap;
90a8c183125f2861067daf432cada06d431a795cd0commit-bot@chromium.org    bitmap.allocN32Pixels(n, n);
91dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com    bitmap.eraseColor(SK_ColorTRANSPARENT);
92ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
939ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkCanvas canvas(bitmap);
949ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkRect r;
959ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    r.set(0, 0, SkIntToScalar(n), SkIntToScalar(n));
969ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    r.inset(SK_Scalar1, SK_Scalar1);
979ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
989ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkPaint paint;
999ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    paint.setAntiAlias(true);
100ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1019ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    paint.setColor(SK_ColorRED);
1029ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    canvas.drawOval(r, paint);
1039ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1049ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    r.inset(SK_Scalar1*n/4, SK_Scalar1*n/4);
1059ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
1069ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    paint.setColor(0x800000FF);
1079ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    canvas.drawOval(r, paint);
108ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1099ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    return bitmap;
1109ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com}
1119ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1129ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comclass ColorFilterView : public SampleView {
1139ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkBitmap fBitmap;
1149ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkShader* fShader;
1159ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    enum {
1169ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        N = 64
1179ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    };
1189ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.compublic:
1199ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    ColorFilterView() {
1209ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        fBitmap = createBitmap(N);
121b0cce2c1d37d4bf5b89da6c70062209ac4e0e643halcanary        fShader = sk_tool_utils::create_checkerboard_shader(
122878fa0204bc246ec5fbaca4aa3c81aaefccc30a1halcanary                0xFFCCCCCC, 0xFFFFFFFF, 12);
123ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
12402939ce4bddd3223d9e8cc98d4abd02939b7f70acaryclark@google.com        if (false) { // avoid bit rot, suppress warning
12502939ce4bddd3223d9e8cc98d4abd02939b7f70acaryclark@google.com            test_5bits();
12602939ce4bddd3223d9e8cc98d4abd02939b7f70acaryclark@google.com        }
1279ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
1289ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1299ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    virtual ~ColorFilterView() {
1309ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        fShader->unref();
1319ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
1329ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1339ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comprotected:
1349ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    // overrides from SkEventSink
1359ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    virtual bool onQuery(SkEvent* evt) {
1369ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        if (SampleCode::TitleQ(*evt)) {
1379ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SampleCode::TitleR(evt, "ColorFilter");
1389ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            return true;
1399ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        }
1409ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        return this->INHERITED::onQuery(evt);
1419ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
1429ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1439ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    virtual void onDrawBackground(SkCanvas* canvas) {
1449ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        SkPaint paint;
1459ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        paint.setShader(fShader);
1469ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        canvas->drawPaint(paint);
1479ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
1489ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1499ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    virtual void onDrawContent(SkCanvas* canvas) {
1509ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        if (false) {
1519ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkPaint p;
1529ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            p.setAntiAlias(true);
1539ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkRect r = { 20.4f, 10, 20.6f, 20 };
1549ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            canvas->drawRect(r, p);
1559ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            r.set(30.9f, 10, 31.1f, 20);
1569ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            canvas->drawRect(r, p);
1579ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            return;
1589ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        }
159ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1609ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        static const SkXfermode::Mode gModes[] = {
16197c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kClear_Mode,
1629ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kSrc_Mode,
1639ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kDst_Mode,
16497c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kSrcOver_Mode,
16597c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kDstOver_Mode,
1669ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kSrcIn_Mode,
1679ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kDstIn_Mode,
1689ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kSrcOut_Mode,
1699ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kDstOut_Mode,
1709ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kSrcATop_Mode,
1719ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kDstATop_Mode,
17297c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kXor_Mode,
17397c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kPlus_Mode,
1748d3cd7a170c810e3816bf00220cbef51e7b16795reed@google.com            SkXfermode::kModulate_Mode,
1759ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        };
176ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1779ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        static const SkColor gColors[] = {
1789ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0xFF000000,
1799ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0x80000000,
1809ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0xFF00FF00,
1819ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0x8000FF00,
1829ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0x00000000,
1839ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        };
1849ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1859ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        float scale = 1.5f;
1869ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        SkPaint paint;
1879ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        canvas->translate(N / 8, N / 8);
1889ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1899ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        for (size_t y = 0; y < SK_ARRAY_COUNT(gColors); y++) {
1909ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            for (size_t x = 0; x < SK_ARRAY_COUNT(gModes); x++) {
1919ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com                SkColorFilter* cf = SkColorFilter::CreateModeFilter(gColors[y], gModes[x]);
1929ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com                SkSafeUnref(paint.setColorFilter(cf));
1939ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com                canvas->drawBitmap(fBitmap, x * N * 1.25f, y * N * scale, &paint);
1949ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            }
1959ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        }
196ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1979ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
198ae933ce0ea5fd9d21cb6ef2cee7e729d32690aacrmistry@google.com
1999ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comprivate:
2009ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    typedef SampleView INHERITED;
2019ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com};
2029ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
2039ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com//////////////////////////////////////////////////////////////////////////////
2049ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
2059ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comstatic SkView* MyFactory() { return new ColorFilterView; }
2069ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comstatic SkViewRegister reg(MyFactory);
207