SampleColorFilter.cpp revision ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976e
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 */
89ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SampleCode.h"
99ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkView.h"
109ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkCanvas.h"
119ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkColorFilter.h"
129ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkDevice.h"
139ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkPaint.h"
149ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com#include "SkShader.h"
159ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1679b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic int inflate5To8(int x) {
1779b3b7e916d874f78208d33b00a554270c19b72areed@google.com    return (x << 3) | (x >> 2);
1879b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
1979b3b7e916d874f78208d33b00a554270c19b72areed@google.com
2079b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic int trunc5(int x) {
2179b3b7e916d874f78208d33b00a554270c19b72areed@google.com    return x >> 3;
2279b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
2379b3b7e916d874f78208d33b00a554270c19b72areed@google.com
2479b3b7e916d874f78208d33b00a554270c19b72areed@google.com#define SK_R16_BITS 5
2579b3b7e916d874f78208d33b00a554270c19b72areed@google.com
2679b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic int round5_slow(int x) {
2779b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int orig = x & 7;
2879b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int fake = x >> 5;
2979b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int trunc = x >> 3;
3079b3b7e916d874f78208d33b00a554270c19b72areed@google.com
3179b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int diff = fake - orig;
3279b3b7e916d874f78208d33b00a554270c19b72areed@google.com
3379b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int bias = 0;
3479b3b7e916d874f78208d33b00a554270c19b72areed@google.com    if (diff > 4) {
3579b3b7e916d874f78208d33b00a554270c19b72areed@google.com        bias = -1;
3679b3b7e916d874f78208d33b00a554270c19b72areed@google.com    } else if (diff < -4) {
3779b3b7e916d874f78208d33b00a554270c19b72areed@google.com        bias = 1;
3879b3b7e916d874f78208d33b00a554270c19b72areed@google.com    }
3979b3b7e916d874f78208d33b00a554270c19b72areed@google.com    return trunc + bias;
4079b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
4179b3b7e916d874f78208d33b00a554270c19b72areed@google.com
4279b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic int round5_fast(int x) {
4379b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int result = x + 3 - (x >> 5) + (x >> 7);
4479b3b7e916d874f78208d33b00a554270c19b72areed@google.com    result >>= 3;
4579b3b7e916d874f78208d33b00a554270c19b72areed@google.com
4679b3b7e916d874f78208d33b00a554270c19b72areed@google.com    {
4779b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int r2 = round5_slow(x);
4879b3b7e916d874f78208d33b00a554270c19b72areed@google.com        SkASSERT(r2 == result);
4979b3b7e916d874f78208d33b00a554270c19b72areed@google.com    }
5079b3b7e916d874f78208d33b00a554270c19b72areed@google.com    return result;
5179b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
5279b3b7e916d874f78208d33b00a554270c19b72areed@google.com
5379b3b7e916d874f78208d33b00a554270c19b72areed@google.comstatic void test_5bits() {
5479b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int e0 = 0;
5579b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int e1 = 0;
5679b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int e2 = 0;
5779b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int ae0 = 0;
5879b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int ae1 = 0;
5979b3b7e916d874f78208d33b00a554270c19b72areed@google.com    int ae2 = 0;
6079b3b7e916d874f78208d33b00a554270c19b72areed@google.com    for (int i = 0; i < 256; i++) {
6179b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int t0 = trunc5(i);
6279b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int t1 = round5_fast(i);
6379b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int t2 = trunc5(i);
6479b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int v0 = inflate5To8(t0);
6579b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int v1 = inflate5To8(t1);
6679b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int v2 = inflate5To8(t2);
6779b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int err0 = i - v0;
6879b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int err1 = i - v1;
6979b3b7e916d874f78208d33b00a554270c19b72areed@google.com        int err2 = i - v2;
7079b3b7e916d874f78208d33b00a554270c19b72areed@google.com        SkDebugf("--- %3d : trunc=%3d (%2d) round:%3d (%2d) \n"/*new:%d (%2d)\n"*/, i,
7179b3b7e916d874f78208d33b00a554270c19b72areed@google.com                 v0, err0, v1, err1, v2, err2);
7279b3b7e916d874f78208d33b00a554270c19b72areed@google.com
7379b3b7e916d874f78208d33b00a554270c19b72areed@google.com
7479b3b7e916d874f78208d33b00a554270c19b72areed@google.com        e0 += err0;
7579b3b7e916d874f78208d33b00a554270c19b72areed@google.com        e1 += err1;
7679b3b7e916d874f78208d33b00a554270c19b72areed@google.com        e2 += err2;
7779b3b7e916d874f78208d33b00a554270c19b72areed@google.com        ae0 += SkAbs32(err0);
7879b3b7e916d874f78208d33b00a554270c19b72areed@google.com        ae1 += SkAbs32(err1);
7979b3b7e916d874f78208d33b00a554270c19b72areed@google.com        ae2 += SkAbs32(err2);
8079b3b7e916d874f78208d33b00a554270c19b72areed@google.com    }
8179b3b7e916d874f78208d33b00a554270c19b72areed@google.com    SkDebugf("--- trunc: %d %d  round: %d %d new: %d %d\n", e0, ae0, e1, ae1, e2, ae2);
8279b3b7e916d874f78208d33b00a554270c19b72areed@google.com}
8379b3b7e916d874f78208d33b00a554270c19b72areed@google.com
849ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comstatic SkShader* createChecker() {
859ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkBitmap bm;
869ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 2);
879ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    bm.allocPixels();
889ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    bm.lockPixels();
899ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = SkPreMultiplyColor(0xFFFFFFFF);
909ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    *bm.getAddr32(0, 1) = *bm.getAddr32(1, 0) = SkPreMultiplyColor(0xFFCCCCCC);
919ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode,
929ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com                                               SkShader::kRepeat_TileMode);
939ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
949ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkMatrix m;
959ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    m.setScale(12, 12);
969ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    s->setLocalMatrix(m);
979ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    return s;
989ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com}
999ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1009ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comstatic SkBitmap createBitmap(int n) {
1019ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkBitmap bitmap;
1029ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    bitmap.setConfig(SkBitmap::kARGB_8888_Config, n, n);
1039ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    bitmap.allocPixels();
1049ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    bitmap.eraseColor(0);
1059ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1069ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkCanvas canvas(bitmap);
1079ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkRect r;
1089ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    r.set(0, 0, SkIntToScalar(n), SkIntToScalar(n));
1099ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    r.inset(SK_Scalar1, SK_Scalar1);
1109ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1119ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkPaint paint;
1129ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    paint.setAntiAlias(true);
1139ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1149ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    paint.setColor(SK_ColorRED);
1159ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    canvas.drawOval(r, paint);
1169ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1179ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    r.inset(SK_Scalar1*n/4, SK_Scalar1*n/4);
1189ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
1199ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    paint.setColor(0x800000FF);
1209ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    canvas.drawOval(r, paint);
1219ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1229ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    return bitmap;
1239ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com}
1249ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1259ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comclass ColorFilterView : public SampleView {
1269ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkBitmap fBitmap;
1279ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    SkShader* fShader;
1289ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    enum {
1299ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        N = 64
1309ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    };
1319ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.compublic:
1329ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    ColorFilterView() {
1339ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        fBitmap = createBitmap(N);
1349ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        fShader = createChecker();
13579b3b7e916d874f78208d33b00a554270c19b72areed@google.com
13679b3b7e916d874f78208d33b00a554270c19b72areed@google.com//        test_5bits();
1379ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
1389ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1399ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    virtual ~ColorFilterView() {
1409ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        fShader->unref();
1419ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
1429ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1439ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comprotected:
1449ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    // overrides from SkEventSink
1459ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    virtual bool onQuery(SkEvent* evt) {
1469ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        if (SampleCode::TitleQ(*evt)) {
1479ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SampleCode::TitleR(evt, "ColorFilter");
1489ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            return true;
1499ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        }
1509ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        return this->INHERITED::onQuery(evt);
1519ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
1529ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1539ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    virtual void onDrawBackground(SkCanvas* canvas) {
1549ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        SkPaint paint;
1559ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        paint.setShader(fShader);
1569ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        canvas->drawPaint(paint);
1579ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
1589ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1599ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    virtual void onDrawContent(SkCanvas* canvas) {
1609ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        if (false) {
1619ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkPaint p;
1629ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            p.setAntiAlias(true);
1639ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkRect r = { 20.4f, 10, 20.6f, 20 };
1649ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            canvas->drawRect(r, p);
1659ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            r.set(30.9f, 10, 31.1f, 20);
1669ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            canvas->drawRect(r, p);
1679ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            return;
1689ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        }
1699ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1709ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        static const SkXfermode::Mode gModes[] = {
17197c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kClear_Mode,
1729ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kSrc_Mode,
1739ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kDst_Mode,
17497c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kSrcOver_Mode,
17597c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kDstOver_Mode,
1769ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kSrcIn_Mode,
1779ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kDstIn_Mode,
1789ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kSrcOut_Mode,
1799ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kDstOut_Mode,
1809ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kSrcATop_Mode,
1819ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            SkXfermode::kDstATop_Mode,
18297c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kXor_Mode,
18397c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kPlus_Mode,
18497c88c255cff3dbb8343c5d090526fdbedad6dd6Scroggo            SkXfermode::kMultiply_Mode,
1859ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        };
1869ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1879ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        static const SkColor gColors[] = {
1889ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0xFF000000,
1899ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0x80000000,
1909ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0xFF00FF00,
1919ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0x8000FF00,
1929ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            0x00000000,
1939ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        };
1949ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1959ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        float scale = 1.5f;
1969ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        SkPaint paint;
1979ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        canvas->translate(N / 8, N / 8);
1989ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
1999ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        for (size_t y = 0; y < SK_ARRAY_COUNT(gColors); y++) {
2009ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            for (size_t x = 0; x < SK_ARRAY_COUNT(gModes); x++) {
2019ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com                SkColorFilter* cf = SkColorFilter::CreateModeFilter(gColors[y], gModes[x]);
2029ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com                SkSafeUnref(paint.setColorFilter(cf));
2039ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com                canvas->drawBitmap(fBitmap, x * N * 1.25f, y * N * scale, &paint);
2049ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com            }
2059ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com        }
2069ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
2079ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    }
2089ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
2099ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comprivate:
2109ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com    typedef SampleView INHERITED;
2119ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com};
2129ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
2139ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com//////////////////////////////////////////////////////////////////////////////
2149ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
2159ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comstatic SkView* MyFactory() { return new ColorFilterView; }
2169ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.comstatic SkViewRegister reg(MyFactory);
2179ac5e228c6e1eee04d2f2c2ab89d493439ff3056reed@google.com
218