<commit_before>/*
 * Copyright <NAME> 2013.
 */

/**
 * Generate shaders for compositing a linear stack of layers.
 */
var compositingShader = {};

/**
 * @param {Array.<Object>} layers The array of layers to composit. May contain
 * objects specifying PictureBuffers and objects specifying BaseRasterizers
 * which are blended to the previous PictureBuffer.
 * @return {string} The fragment shader source for compositing the given layer
 * stack.
 */
compositingShader.getFragmentSource = function(layers) {
    var src = ['precision highp float;'];
    var i;
    for (i = 0; i < layers.length; ++i) {
        if (layers[i].type === CanvasCompositor.Element.buffer) {
            // TODO: assert(layers[i].buffer.visible);
            src.push('uniform sampler2D uLayer' + i + ';');
            src.push('uniform float uOpacity' + i + ';');
        } else {
            src.push('uniform sampler2D uLayer' + i + ';');
            src.push('uniform vec4 uColor' + i + ';');
        }
    }
    src.push('varying vec2 vTexCoord;');
    src.push('void main(void) {');
    src.push('  // already premultiplied:');
    src.push('  vec4 color = vec4(0, 0, 0, 0);');
    var blendingSource = function(dstColor, srcColor) {
        src.push('  ' + dstColor + ' = ' + srcColor +
                 ' + ' + dstColor + ' * (1.0 - ' + srcColor + '.w);');
    };
    i = 0;
    while (i < layers.length) {
        // TODO: assert(layers[i].type === CanvasCompositor.Element.buffer);
        // TODO: assert(layers[i].buffer.visible);
        var bufferColor = 'layer' + i + 'Color';
        var bufferOpacity = 'uOpacity' + i;
        src.push('  vec4 ' + bufferColor +
                ' = texture2D(uLayer' + i + ', vTexCoord);');
        ++i;
        while (i < layers.length &&
               layers[i].type === CanvasCompositor.Element.rasterizer) {
            if (layers[i].rasterizer.format === GLRasterizerFormat.alpha) {
                src.push('  float layer' + i + 'Alpha' +
                    ' = texture2D(uLayer' + i + ', vTexCoord).w;');
            } else {
                src.push('  vec4 layer' + i +
                    ' = texture2D(uLayer' + i + ', vTexCoord);');
                src.push('  float layer' + i + 'Alpha = ' +
                         'layer' + i + '.x + ' +
                         'layer' + i + '.y / 256.0;');
            }
            src.push('  vec4 layer' + i + 'Color = layer' + i + 'Alpha *' +
                     ' uColor' + i + ';');
            if (layers[i].mode === BrushEvent.Mode.normal) {
                blendingSource(bufferColor, 'layer' + i + 'Color');
            } else if (layers[i].mode === BrushEvent.Mode.erase) {
                src.push('  ' + bufferColor + ' = ' + bufferColor +
                         ' * (1.0 - layer' + i + 'Color.w);');
            } else {
                src.push('  float blendedAlpha' + i + ' = layer' + i +
                         'Color.w + ' + bufferColor + '.w * (1.0 - layer' + i +
                         'Color.w);');
                var bufferUnpremul = '(' + bufferColor + '.xyz / ' +
                                     bufferColor + '.w)';
                if (layers[i].mode === BrushEvent.Mode.multiply) {
                    src.push('  ' + bufferColor + ' = vec4(' + bufferUnpremul +
                             ' * (1.0 - (1.0 - uColor' + i + '.xyz) * layer' +
                             i + 'Color.w) * blendedAlpha' + i +
                             ', blendedAlpha' + i + ');');
                } else {
                    console.log('Unexpected mode in shader generation ' +
                                layers[i].mode);
                }
            }
            ++i;
        }
        src.push('  ' + bufferColor + ' *= ' + bufferOpacity + ';');
        blendingSource('color', bufferColor);
    }
    src.push('  gl_FragColor = color;');
    src.push('}');
    return src.join('\n');
};


/**
 * @param {Object} glManager The state manager returned by glStateManager() in
 * utilgl.<commit_msg>Make specifying blending modes in compositing_shader simpler<commit_after>/*
 * Copyright <NAME> 2013.
 */

/**
 * Generate shaders for compositing a linear stack of layers.
 */
var compositingShader = {};

/**
 * @param {Array.<Object>} layers The array of layers to composit. May contain
 * objects specifying PictureBuffers and objects specifying BaseRasterizers
 * which are blended to the previous PictureBuffer.
 * @return {string} The fragment shader source for compositing the given layer
 * stack.
 */
compositingShader.getFragmentSource = function(layers) {
    var src = ['precision highp float;'];
    var i;
    for (i = 0; i < layers.length; ++i) {
        if (layers[i].type === CanvasCompositor.Element.buffer) {
            // TODO: assert(layers[i].buffer.visible);
            src.push('uniform sampler2D uLayer' + i + ';');
            src.push('uniform float uOpacity' + i + ';');
        } else {
            src.push('uniform sampler2D uLayer' + i + ';');
            src.push('uniform vec4 uColor' + i + ';');
        }
    }
    src.push('varying vec2 vTexCoord;');
    src.push('void main(void) {');
    src.push('  // already premultiplied:');
    src.push('  vec4 color = vec4(0, 0, 0, 0);');
    var blendingSource = function(dstColor, srcColor) {
        src.push('  ' + dstColor + ' = ' + srcColor +
                 ' + ' + dstColor + ' * (1.0 - ' + srcColor + '.w);');
    };
    // Add rasterizer layer blending operation to src. The given blending
    // equation eq must use unpremultiplied vec3 srcColor, unpremultiplied vec3
    // dstColor and srcAlpha to produce a vec3 value.
    var blendEq = function(eq) {
        src.push('  float blendedAlpha' + i + ' = layer' + i + 'Color.w + ' +
                 bufferColor + '.w * (1.0 - layer' + i + 'Color.w);');
        // Unpremultiplied colors:
        eq = eq.replace(/srcColor/g, 'uColor' + i + '.xyz');
        eq = eq.replace(/dstColor/g, '(' + bufferColor + '.xyz / ' +
                        bufferColor + '.w)');
        eq = eq.replace(/srcAlpha/g, 'layer' + i + 'Color.w');
        src.push('  ' + bufferColor + ' = vec4(' + eq +
            ' * blendedAlpha' + i + ', blendedAlpha' + i + ');');
    };
    i = 0;
    while (i < layers.length) {
        // TODO: assert(layers[i].type === CanvasCompositor.Element.buffer);
        // TODO: assert(layers[i].buffer.visible);
        var bufferColor = 'layer' + i + 'Color';
        var bufferOpacity = 'uOpacity' + i;
        src.push('  vec4 ' + bufferColor +
                ' = texture2D(uLayer' + i + ', vTexCoord);');
        ++i;
        while (i < layers.length &&
               layers[i].type === CanvasCompositor.Element.rasterizer) {
            if (layers[i].rasterizer.format === GLRasterizerFormat.alpha) {
                src.push('  float layer' + i + 'Alpha' +
                    ' = texture2D(uLayer' + i + ', vTexCoord).w;');
            } else {
                src.push('  vec4 layer' + i +
                    ' = texture2D(uLayer' + i + ', vTexCoord);');
                src.push('  float layer' + i + 'Alpha = ' +
                         'layer' + i + '.x + ' +
                         'layer' + i + '.y / 256.0;');
            }
            src.push('  vec4 layer' + i + 'Color = layer' + i + 'Alpha *' +
                     ' uColor' + i + ';');
            if (layers[i].mode === BrushEvent.Mode.normal) {
                blendingSource(bufferColor, 'layer' + i + 'Color');
            } else if (layers[i].mode === BrushEvent.Mode.erase) {
                src.push('  ' + bufferColor + ' = ' + bufferColor +
                         ' * (1.0 - layer' + i + 'Color.w);');
            } else {
                if (layers[i].mode === BrushEvent.Mode.multiply) {
                    blendEq('dstColor * (1.0 + srcAlpha * (srcColor - 1.0))');
                } else {
                    console.log('Unexpected mode in shader generation ' +
                                layers[i].mode);
                }
            }
            ++i;
        }
        src.push('  ' + bufferColor + ' *= ' + bufferOpacity + ';');
        blendingSource('color', bufferColor);
    }
    src.push('  gl_FragColor = color;');
    src.push('}');
    return src.join('\n');
};


/**
 * @param {Object} glManager The state manager returned by glStateManager() in
 * utilgl.
{'fraction_non_alphanumeric': 0.16193215869591274, 'fraction_numerical': 0.009229294018938032, 'mean_word_length': 1.6881443298969072, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4472647', 'n_tokens_mistral': 2603, 'n_tokens_neox': 2504, 'n_words': 592}