1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com */
7e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org
843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com#include "SkColor.h"
943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com#include "SkColorFilter.h"
108f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkColorPriv.h"
116c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org#include "SkLumaColorFilter.h"
128b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h"
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h"
148f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkRandom.h"
158f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkXfermode.h"
168f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
1743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
18353482251e61971a8cf3a60bbb6910f482be634freed@google.comstatic SkColorFilter* reincarnate_colorfilter(SkFlattenable* obj) {
198b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkWriteBuffer wb;
20cefc8650905f25bcb3a722dfadfca59651202726djsollen@google.com    wb.writeFlattenable(obj);
2143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
228b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    size_t size = wb.bytesWritten();
2343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    SkAutoSMalloc<1024> storage(size);
2443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    // make a copy into storage
25c73dd5c6880739f26216f198c757028fd28df1a4djsollen@google.com    wb.writeToMemory(storage.get());
2643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
278b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkReadBuffer rb(storage.get(), size);
28353482251e61971a8cf3a60bbb6910f482be634freed@google.com    return rb.readColorFilter();
2943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com}
3043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
3143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com///////////////////////////////////////////////////////////////////////////////
3243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
3343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com#define ILLEGAL_MODE    ((SkXfermode::Mode)-1)
3443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
35e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(ColorFilter, reporter) {
36e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org    SkRandom rand;
3743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
3843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    for (int mode = 0; mode <= SkXfermode::kLastMode; mode++) {
3943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        SkColor color = rand.nextU();
4043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
4143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        // ensure we always get a filter, by avoiding the possibility of a
4243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        // special case that would return NULL (if color's alpha is 0 or 0xFF)
4343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        color = SkColorSetA(color, 0x7F);
4443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
4543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        SkColorFilter* cf = SkColorFilter::CreateModeFilter(color,
4643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com                                                        (SkXfermode::Mode)mode);
4743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
4843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        // allow for no filter if we're in Dst mode (its a no op)
4943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        if (SkXfermode::kDst_Mode == mode && NULL == cf) {
5043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            continue;
5143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        }
5243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
5343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        SkAutoUnref aur(cf);
5443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        REPORTER_ASSERT(reporter, cf);
5543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
5643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        SkColor c = ~color;
5743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        SkXfermode::Mode m = ILLEGAL_MODE;
5843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
5943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        SkColor expectedColor = color;
6043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        SkXfermode::Mode expectedMode = (SkXfermode::Mode)mode;
6143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
6243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com//        SkDebugf("--- mc [%d %x] ", mode, color);
6343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
6443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        REPORTER_ASSERT(reporter, cf->asColorMode(&c, &m));
6543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        // handle special-case folding by the factory
6643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        if (SkXfermode::kClear_Mode == mode) {
6743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            if (c != expectedColor) {
6843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com                expectedColor = 0;
6943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            }
7043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            if (m != expectedMode) {
7143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com                expectedMode = SkXfermode::kSrc_Mode;
7243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            }
73d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com        }
7443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
7543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com//        SkDebugf("--- got [%d %x] expected [%d %x]\n", m, c, expectedMode, expectedColor);
7643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
7743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        REPORTER_ASSERT(reporter, c == expectedColor);
7843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        REPORTER_ASSERT(reporter, m == expectedMode);
79d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
8043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        {
81353482251e61971a8cf3a60bbb6910f482be634freed@google.com            SkColorFilter* cf2 = reincarnate_colorfilter(cf);
8243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            SkAutoUnref aur2(cf2);
8343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            REPORTER_ASSERT(reporter, cf2);
8443c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
8543c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            SkColor c2 = ~color;
8643c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            SkXfermode::Mode m2 = ILLEGAL_MODE;
8743c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            REPORTER_ASSERT(reporter, cf2->asColorMode(&c2, &m2));
8843c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            REPORTER_ASSERT(reporter, c2 == expectedColor);
8943c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com            REPORTER_ASSERT(reporter, m2 == expectedMode);
9043c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com        }
9143c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com    }
9243c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com}
9343c50c8c77df82c5cffb55cae2d386e59802b88freed@google.com
946c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
956c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
96e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(LumaColorFilter, reporter) {
976c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    SkPMColor in, out;
986c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    SkAutoTUnref<SkColorFilter> lf(SkLumaColorFilter::Create());
996c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
100d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org    // Applying luma to white produces black with the same transparency.
1016c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    for (unsigned i = 0; i < 256; ++i) {
1026c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        in = SkPackARGB32(i, i, i, i);
1036c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        lf->filterSpan(&in, 1, &out);
104d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkGetPackedA32(out) == i);
105d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkGetPackedR32(out) == 0);
106d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkGetPackedG32(out) == 0);
107d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkGetPackedB32(out) == 0);
1086c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    }
1096c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
1106c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    // Applying luma to black yields transparent black (luminance(black) == 0)
1116c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    for (unsigned i = 0; i < 256; ++i) {
1126c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        in = SkPackARGB32(i, 0, 0, 0);
1136c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        lf->filterSpan(&in, 1, &out);
1146c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        REPORTER_ASSERT(reporter, out == SK_ColorTRANSPARENT);
1156c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    }
1166c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org
117d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org    // For general colors, a luma filter generates black with an attenuated alpha channel.
1186c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    for (unsigned i = 1; i < 256; ++i) {
1196c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        in = SkPackARGB32(i, i, i / 2, i / 3);
1206c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        lf->filterSpan(&in, 1, &out);
1216c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        REPORTER_ASSERT(reporter, out != in);
1226c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org        REPORTER_ASSERT(reporter, SkGetPackedA32(out) <= i);
123d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkGetPackedR32(out) == 0);
124d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkGetPackedG32(out) == 0);
125d494b09f554d470fc6411d0924879bbfb0cb0e95commit-bot@chromium.org        REPORTER_ASSERT(reporter, SkGetPackedB32(out) == 0);
1266c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org    }
1276c1ee2d4e727357451c8a6fcf4a08e75890b5d6dcommit-bot@chromium.org}
128