/*
 * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

// maximum number of fractions/colors supported by this shader
const int MAX_FRACTIONS = 12;
// gradient texture size (in texels)
const float TEXTURE_WIDTH = 16.0;
// size of a single texel
const float FULL_TEXEL_X = 1.0 / TEXTURE_WIDTH;
// size of half of a single texel
const float HALF_TEXEL_X = FULL_TEXEL_X / 2.0;

// array of gradient stops/fractions and corresponding scale factors
//   fractions[i].x = gradientStop[i]
//   fractions[i].y = scaleFactor[i]
param float4 fractions[MAX_FRACTIONS];

// texture containing gradient colors
param sampler colors;
param float offset;

float4 sampleGradient(float dist)
{
    int i;
    float relFraction = 0.0;
    unroll(11, 0) for (i = 0; i < MAX_FRACTIONS-1; i++) {
        relFraction +=
            clamp((dist - fractions[i].x) * fractions[i].y, 0.0, 1.0);
    }
    // we offset by half a texel so that we find the linearly interpolated
    // color between the two texel centers of interest
    float tc = HALF_TEXEL_X + (FULL_TEXEL_X * relFraction);
    return sample(colors, float2(tc, offset));
}

float4 cycleNone(float dist)
{
    if (dist <= 0.0) {
        return sample(colors, float2(0.0, offset));
    } else if (dist >= 1.0) {
        return sample(colors, float2(1.0, offset));
    } else {
        return sampleGradient(dist);
    }
}

float4 cycleReflect(float dist)
{
    dist = 1.0 - (abs(fract(dist * 0.5) - 0.5) * 2.0);
    return sampleGradient(dist);
}

float4 cycleRepeat(float dist)
{
    dist = fract(dist);
    return sampleGradient(dist);
}
