/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

// This master effect implements clamping on the layout coordinate and requires specifying the
// border colors that are used when outside the clamped boundary. Gradients with the
// SkShader::kClamp_TileMode should use the colors at their first and last stop (after adding dummy
// stops for t=0,t=1) as the border color. This will automatically replicate the edge color, even if
// when there is a hard stop.
//
// The SkShader::kDecal_TileMode can be produced by specifying transparent black as the border
// colors, regardless of the gradient's stop colors.

in fragmentProcessor colorizer;
in fragmentProcessor gradLayout;

layout(ctype=SkPMColor4f, tracked) in uniform half4 leftBorderColor;  // t < 0.0
layout(ctype=SkPMColor4f, tracked) in uniform half4 rightBorderColor; // t > 1.0

layout(key) in bool makePremul;
// Trust the creator that this matches the color spec of the gradient
in bool colorsAreOpaque;

void main() {
    half4 t = process(gradLayout);
    // If t.x is below 0, use the left border color without invoking the child processor. If any t.x
    // is above 1, use the right border color. Otherwise, t is in the [0, 1] range assumed by the
    // colorizer FP, so delegate to the child processor.
    if (!gradLayout.preservesOpaqueInput && t.y < 0) {
        // layout has rejected this fragment (rely on sksl to remove this branch if the layout FP
        // preserves opacity is false)
        sk_OutColor = half4(0);
    } else if (t.x < 0) {
        sk_OutColor = leftBorderColor;
    } else if (t.x > 1.0) {
        sk_OutColor = rightBorderColor;
    } else {
        sk_OutColor = process(colorizer, t);
    }

    @if(makePremul) {
        sk_OutColor.xyz *= sk_OutColor.w;
    }
}

//////////////////////////////////////////////////////////////////////////////

// If the layout does not preserve opacity, remove the opaque optimization,
// but otherwise respect the provided color opacity state (which should take
// into account the opacity of the border colors).
@optimizationFlags {
    kCompatibleWithCoverageAsAlpha_OptimizationFlag |
    (colorsAreOpaque && gradLayout->preservesOpaqueInput() ? kPreservesOpaqueInput_OptimizationFlag
                                                           : kNone_OptimizationFlags)
}