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
88f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkRandom.h"
963c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com#include "Test.h"
10589708bf7c706348b763e8277004cb160b202bdbrileya@google.com#include "gradients/SkClampRange.h"
1163c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com
1263c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.comstatic skiatest::Reporter* gReporter;
1386398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org#define R_ASSERT(cond) if (!(cond)) {      \
1486398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    SkDebugf("%d: %s\n", __LINE__, #cond); \
1586398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    REPORTER_ASSERT(gReporter, cond);      \
1613659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com}
1713659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com
1886398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org// Arbitrary sentinel values outside [0, 0xFFFF].
1986398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.orgstatic const int kV0 = -42, kV1 = -53, kRamp = -64;
2086398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org
2186398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.orgstatic void check_value(int64_t bigfx, int expected) {
2286398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    if (bigfx < 0) {
2386398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        R_ASSERT(expected == kV0);
2486398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    } else if (bigfx > 0xFFFF) {
2586398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        R_ASSERT(expected == kV1);
2686398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    } else if (bigfx == 0xFFFF) {
2786398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        // Either one is fine (and we do see both).
2886398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        R_ASSERT(expected == kV1 || expected == kRamp);
2986398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    } else {
3086398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        R_ASSERT(expected == kRamp);
3163c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    }
3263c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com}
3363c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com
3463c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.comstatic void slow_check(const SkClampRange& range,
3586398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org                       const SkFixed fx, SkFixed dx, int count) {
3663c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    SkASSERT(range.fCount0 + range.fCount1 + range.fCount2 == count);
3713659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com
3886398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    // If dx is large, fx will overflow if updated naively.  So we use more bits.
3986398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    int64_t bigfx = fx;
4086398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org
4133a94e2ba79d41de91d3412d8ae1504c187aacb1reed@google.com    for (int i = 0; i < range.fCount0; i++) {
4286398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        check_value(bigfx, range.fV0);
4386398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        bigfx += dx;
4433a94e2ba79d41de91d3412d8ae1504c187aacb1reed@google.com    }
4586398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org
4633a94e2ba79d41de91d3412d8ae1504c187aacb1reed@google.com    for (int i = 0; i < range.fCount1; i++) {
4786398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        check_value(bigfx, kRamp);
4886398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        bigfx += dx;
4933a94e2ba79d41de91d3412d8ae1504c187aacb1reed@google.com    }
5086398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org
5133a94e2ba79d41de91d3412d8ae1504c187aacb1reed@google.com    for (int i = 0; i < range.fCount2; i++) {
5286398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        check_value(bigfx, range.fV1);
5386398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org        bigfx += dx;
5463c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    }
5563c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com}
5663c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com
57e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org
5863c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.comstatic void test_range(SkFixed fx, SkFixed dx, int count) {
5963c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    SkClampRange range;
6086398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    range.init(fx, dx, count, kV0, kV1);
6163c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    slow_check(range, fx, dx, count);
6263c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com}
6363c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com
6463c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com#define ff(x)   SkIntToFixed(x)
6563c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com
66e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(ClampRange, reporter) {
6763c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    gReporter = reporter;
6863c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com
6963c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    test_range(0, 0, 20);
7063c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    test_range(0xFFFF, 0, 20);
7163c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    test_range(-ff(2), 0, 20);
7263c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    test_range( ff(2), 0, 20);
73d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
7463c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    test_range(-10, 1, 20);
7563c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    test_range(10, -1, 20);
7663c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    test_range(-10, 3, 20);
7763c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    test_range(10, -3, 20);
7813659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com
7913659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com    test_range(ff(1),  ff(16384),  100);
8013659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com    test_range(ff(-1), ff(-16384), 100);
8113659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com    test_range(ff(1)/2, ff(16384), 100);
8286398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    // TODO(reed): skia:2481, fix whatever bug this is, then uncomment
8386398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    //test_range(ff(1)/2, ff(-16384), 100);
8413659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com
85e0e7cfe44bb9d66d76120a79e5275c294bacaa22commit-bot@chromium.org    SkRandom rand;
86d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
8763c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    // test non-overflow cases
8863c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    for (int i = 0; i < 1000000; i++) {
8963c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com        SkFixed fx = rand.nextS() >> 1;
9063c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com        SkFixed sx = rand.nextS() >> 1;
9163c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com        int count = rand.nextU() % 1000 + 1;
9263c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com        SkFixed dx = (sx - fx) / count;
9363c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com        test_range(fx, dx, count);
9463c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    }
95d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
9686398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    // TODO(reed): skia:2481, fix whatever bug this is, then uncomment
9786398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    /*
9863c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    // test overflow cases
9913659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com    for (int i = 0; i < 100000; i++) {
10063c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com        SkFixed fx = rand.nextS();
10113659f1f8d2e705c565203d45870b1afcd47cf98reed@google.com        SkFixed dx = rand.nextS();
10263c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com        int count = rand.nextU() % 1000 + 1;
10363c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com        test_range(fx, dx, count);
10463c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com    }
10586398e5d9149eaad2fd2c8dba5557aca645d2385commit-bot@chromium.org    */
10663c1ad82fc4232daff1b686cc78bba4c6a42916dreed@google.com}
107