////////////////////////////////////////////////////////////////////////////////
//
//  Licensed to the Apache Software Foundation (ASF) under one or more
//  contributor license agreements.  See the NOTICE file distributed with
//  this work for additional information regarding copyright ownership.
//  The ASF licenses this file to You under the Apache License, Version 2.0
//  (the "License"); you may not use this file except in compliance with
//  the License.  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

<languageVersion : 1.0;>

kernel ColorDodge

<   namespace : "Flame";

    vendor : "Adobe";

    version : 1;

    description : "ColorDodge blend mode";

>

{

    input image4 dst;

    input image4 src;

    output pixel4 result;



    void

    evaluatePixel()

    {

        pixel4 a = sampleNearest(dst,outCoord()); // cb

        pixel4 b = sampleNearest(src,outCoord()); // cs

        

        // remove premultiplied (srcCP/srcA, dstCP/dstA)

        pixel3 cb = a.rgb;

        pixel3 cs = b.rgb;

        if (a.a > 0.0) {

            cb.rgb = a.rgb / a.a;

        }

        if (b.a > 0.0) {

            cs.rgb = b.rgb / b.a;

        }

        

        // dstA' = (1-srcA)*dstA + srcA

        result.a = (1.0-b.a)*a.a + b.a;

        

        // temp for Blend(srcCP/srcA, dstCP/dstA)

        pixel3 blendResult;

        

        // = 0, if cb = 0 (*** this case is AE/PS and AGM only, not PDF spec)

        // = 1, if cb >= (1 -cs)

        // = cb / (1 -cs), otherwise

        

        if (cb.r == 0.0) {

            blendResult.r = 0.0;

        } else if ( cb.r >= (1.0 - cs.r)) {

            blendResult.r = 1.0;

        } else {

            blendResult.r = cb.r / (1.0 - cs.r);

        }

        

        if (cb.g == 0.0) {

            blendResult.g = 0.0;

        } else if ( cb.g >= (1.0 - cs.g)) {

            blendResult.g = 1.0;

        } else {

            blendResult.g = cb.g / (1.0 - cs.g);

        }

        

        if (cb.b == 0.0) {

            blendResult.b = 0.0;

        } else if ( cb.b >= (1.0 - cs.b)) {

            blendResult.b = 1.0;

        } else {

            blendResult.b = cb.b / (1.0 - cs.b);

        }

                

        // dstCP' = (1-srcA)*dstCP + (1-dstA)*srcCP + srcA*dstA*Blend(srcCP/srcA, dstCP/dstA)

        result.rgb = (1.0-b.a)*a.rgb + (1.0-a.a)*b.rgb + b.a*a.a*blendResult.rgb;

    }

}

