(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@d3fc/d3fc-rebind'), require('d3-scale'), require('d3-shape')) :
    typeof define === 'function' && define.amd ? define(['exports', '@d3fc/d3fc-rebind', 'd3-scale', 'd3-shape'], factory) :
    (global = global || self, factory(global.fc = global.fc || {}, global.fc, global.d3, global.d3));
}(this, function (exports, d3fcRebind, d3Scale, d3Shape) { 'use strict';

    var baseScale = (function () {
      var domain = [0, 1];
      var range = [-1, 1];

      var base = function base() {};

      base.domain = function () {
        if (!arguments.length) {
          return domain;
        }

        domain = arguments.length <= 0 ? undefined : arguments[0];
        return base;
      };

      base.range = function () {
        if (!arguments.length) {
          return range;
        }

        range = arguments.length <= 0 ? undefined : arguments[0];
        return base;
      };

      return base;
    });

    var bufferBuilder = (function () {
      var attributes = {};
      var uniforms = {};
      var elementIndices = null;

      var bufferBuilder = function bufferBuilder(programBuilder, program) {
        var gl = programBuilder.context();
        Object.keys(attributes).forEach(function (name) {
          var attribute = attributes[name];

          if (typeof attribute !== 'function') {
            throw new Error("Expected an attribute for ".concat(name, ", found ").concat(attribute));
          }

          var location = gl.getAttribLocation(program, name);
          attribute.location(location)(programBuilder);
        });
        Object.keys(uniforms).forEach(function (name) {
          var uniform = uniforms[name];

          if (typeof uniform !== 'function') {
            throw new Error("Expected a uniform for ".concat(name, ", found ").concat(uniform));
          }

          var location = gl.getUniformLocation(program, name);
          uniform.location(location)(programBuilder);
        });

        if (elementIndices !== null) {
          elementIndices(programBuilder);
        }
      };

      bufferBuilder.flush = function () {
        Object.values(attributes).forEach(function (attribute) {
          return attribute.clear();
        });
        Object.values(uniforms).forEach(function (uniform) {
          return uniform.clear();
        });
        if (elementIndices !== null) elementIndices.clear();
      };

      bufferBuilder.attribute = function () {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }

        if (args.length === 1) {
          return attributes[args[0]];
        }

        attributes[args[0]] = args[1];
        return bufferBuilder;
      };

      bufferBuilder.uniform = function () {
        for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
          args[_key2] = arguments[_key2];
        }

        if (args.length === 1) {
          return uniforms[args[0]];
        }

        uniforms[args[0]] = args[1];
        return bufferBuilder;
      };

      bufferBuilder.elementIndices = function () {
        if (!arguments.length) {
          return elementIndices;
        }

        elementIndices = arguments.length <= 0 ? undefined : arguments[0];
        return bufferBuilder;
      };

      return bufferBuilder;
    });

    var uniform = (function (initialData) {
      var location = -1;
      var data = initialData;
      var dirty = true;

      var build = function build(programBuilder) {
        if (!dirty) {
          return;
        }

        var gl = programBuilder.context();

        if (Array.isArray(data)) {
          switch (data.length) {
            case 1:
              gl.uniform1fv(location, data);
              break;

            case 2:
              gl.uniform2fv(location, data);
              break;

            case 3:
              gl.uniform3fv(location, data);
              break;

            case 4:
              gl.uniform4fv(location, data);
              break;

            default:
              throw new Error("Uniform supports up to 4 elements. ".concat(data.length, " provided."));
          }
        } else {
          gl.uniform1f(location, data);
        }

        dirty = false;
      };

      build.clear = function () {
        dirty = true;
      };

      build.location = function () {
        if (!arguments.length) {
          return location;
        }

        if (location !== (arguments.length <= 0 ? undefined : arguments[0])) {
          location = arguments.length <= 0 ? undefined : arguments[0];
          dirty = true;
        }

        return build;
      };

      build.data = function () {
        if (!arguments.length) {
          return data;
        }

        data = arguments.length <= 0 ? undefined : arguments[0];
        dirty = true;
        return build;
      };

      return build;
    });

    var drawModes = {
      POINTS: 0,
      LINES: 1,
      LINE_LOOP: 2,
      LINE_STRIP: 3,
      TRIANGLES: 4,
      TRIANGLE_STRIP: 5,
      TRIANGLE_FAN: 6
    };

    var programBuilder = (function () {
      var context = null;
      var program = null;
      var vertexShader = null;
      var fragmentShader = null;
      var programVertexShader = null;
      var programFragmentShader = null;
      var mode = drawModes.TRIANGLES;
      var buffers = bufferBuilder();
      var debug = false;
      var extInstancedArrays = null;
      var dirty = true;

      var build = function build(count) {
        if (context == null) {
          return;
        }

        var vertexShaderSource = vertexShader();
        var fragmentShaderSource = fragmentShader();

        if (newProgram(program, vertexShaderSource, fragmentShaderSource)) {
          program = createProgram(vertexShaderSource, fragmentShaderSource);
          programVertexShader = vertexShaderSource;
          programFragmentShader = fragmentShaderSource;
          dirty = false;
        }

        context.useProgram(program);
        buffers.uniform('uScreen', uniform([context.canvas.width, context.canvas.height]));
        buffers(build, program);

        if (mode !== drawModes.POINTS && mode !== drawModes.TRIANGLES) {
          throw Error("Expected mode TRIANGLES (".concat(drawModes.TRIANGLES, ") or POINTS (").concat(drawModes.POINTS, "). ").concat(mode, " received instead."));
        }

        if (buffers.elementIndices() == null) {
          throw Error('Element indices must be provided.');
        }

        extInstancedArrays.drawElementsInstancedANGLE(mode, buffers.elementIndices().data().length, context.UNSIGNED_SHORT, 0, count);
      };

      build.extInstancedArrays = function () {
        return extInstancedArrays;
      };

      build.context = function () {
        for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
          args[_key] = arguments[_key];
        }

        if (!args.length) {
          return context;
        }

        if (args[0] == null || args[0] !== context) {
          buffers.flush();
          dirty = true;
        }

        if (args[0] != null && args[0] !== context) {
          extInstancedArrays = args[0].getExtension('ANGLE_instanced_arrays');
        }

        context = args[0];
        return build;
      };

      build.buffers = function () {
        if (!arguments.length) {
          return buffers;
        }

        buffers = arguments.length <= 0 ? undefined : arguments[0];
        return build;
      };

      build.vertexShader = function () {
        if (!arguments.length) {
          return vertexShader;
        }

        vertexShader = arguments.length <= 0 ? undefined : arguments[0];
        return build;
      };

      build.fragmentShader = function () {
        if (!arguments.length) {
          return fragmentShader;
        }

        fragmentShader = arguments.length <= 0 ? undefined : arguments[0];
        return build;
      };

      build.mode = function () {
        if (!arguments.length) {
          return mode;
        }

        mode = arguments.length <= 0 ? undefined : arguments[0];
        return build;
      };

      build.debug = function () {
        if (!arguments.length) {
          return debug;
        }

        debug = arguments.length <= 0 ? undefined : arguments[0];
        return build;
      };

      return build;

      function newProgram(program, vertexShader, fragmentShader) {
        if (!program || dirty) {
          return true;
        }

        return vertexShader !== programVertexShader || fragmentShader !== programFragmentShader;
      }

      function createProgram(vertexShaderSource, fragmentShaderSource) {
        var vertexShader = loadShader(vertexShaderSource, context.VERTEX_SHADER);
        var fragmentShader = loadShader(fragmentShaderSource, context.FRAGMENT_SHADER);
        var program = context.createProgram();
        context.attachShader(program, vertexShader);
        context.attachShader(program, fragmentShader);
        context.linkProgram(program);

        if (debug && !context.getProgramParameter(program, context.LINK_STATUS)) {
          var message = context.getProgramInfoLog(program);
          context.deleteProgram(program);
          throw new Error("Failed to link program : ".concat(message, "\n            Vertex Shader : ").concat(vertexShaderSource, "\n            Fragment Shader : ").concat(fragmentShaderSource));
        }

        return program;
      }

      function loadShader(source, type) {
        var shader = context.createShader(type);
        context.shaderSource(shader, source);
        context.compileShader(shader);

        if (debug && !context.getShaderParameter(shader, context.COMPILE_STATUS)) {
          var message = context.getShaderInfoLog(shader);
          context.deleteShader(shader);
          throw new Error("Failed to compile shader : ".concat(message, "\n            Shader : ").concat(source));
        }

        return shader;
      }
    });

    var shaderBuilder = (function (base) {
      var shaderHeaders = [];
      var shaderBodies = [];

      var build = function build() {
        return base(shaderHeaders.join('\n'), shaderBodies.join('\n'));
      };

      function append(array, element) {
        array.push(element);
      }

      function insert(array, element, before) {
        var beforeIndex = array.indexOf(before);
        array.splice(beforeIndex >= 0 ? beforeIndex : array.length, 0, element);
      }

      function appendIfNotExists(array, element) {
        var elementIndex = array.indexOf(element);

        if (elementIndex === -1) {
          array.push(element);
        }
      }

      build.appendHeader = function (header) {
        append(shaderHeaders, header);
        return build;
      };

      build.insertHeader = function (header, before) {
        insert(shaderHeaders, header, before);
        return build;
      };

      build.appendHeaderIfNotExists = function (header) {
        appendIfNotExists(shaderHeaders, header);
        return build;
      };

      build.appendBody = function (body) {
        append(shaderBodies, body);
        return build;
      };

      build.insertBody = function (body, before) {
        insert(shaderBodies, body, before);
        return build;
      };

      build.appendBodyIfNotExists = function (body) {
        appendIfNotExists(shaderBodies, body);
        return build;
      };

      return build;
    }); // inf is precalculated here for use in some functions (e.g. log scale calculations)

    var vertexShaderBase = function vertexShaderBase(header, body) {
      return "\nprecision mediump float;\nfloat inf = 1.0 / 0.0;\n".concat(header, "\nvoid main() {\n    ").concat(body, "\n}");
    };
    var fragmentShaderBase = function fragmentShaderBase(header, body) {
      return "\nprecision mediump float;\n".concat(header, "\nvoid main() {\n    gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);\n    ").concat(body, "\n}");
    };

    var fillColor = {
      header: "attribute vec4 aFillColor;\n             varying vec4 vFillColor;",
      body: "vFillColor = aFillColor;"
    };
    var strokeColor = {
      header: "attribute vec4 aStrokeColor;\n             varying vec4 vStrokeColor;",
      body: "vStrokeColor = aStrokeColor;"
    };
    var circle = {
      header: "\n        attribute float aCrossValue;\n        attribute float aMainValue;\n        attribute float aSize;\n        attribute float aDefined;\n\n        uniform float uStrokeWidth;\n\n        varying float vSize;\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        vSize = 2.0 * sqrt(aSize / 3.14159);\n        gl_PointSize = vSize + uStrokeWidth + 1.0;\n        gl_Position = vec4(aCrossValue, aMainValue, 0, 1);"
    };
    var square = {
      header: "\n        attribute float aCrossValue;\n        attribute float aMainValue;\n        attribute float aSize;\n        attribute float aDefined;\n\n        uniform float uStrokeWidth;\n\n        varying float vSize;\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        vSize = sqrt(aSize);\n        gl_PointSize = vSize + uStrokeWidth + 1.0;\n        gl_Position = vec4(aCrossValue, aMainValue, 0, 1);"
    };
    var diamond = {
      header: "\n        attribute float aCrossValue;\n        attribute float aMainValue;\n        attribute float aSize;\n        attribute float aDefined;\n\n        uniform float uStrokeWidth;\n\n        varying float vSize;\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        vSize = sqrt(aSize);\n        gl_PointSize = 2.0 * (vSize + uStrokeWidth + 1.0);\n        gl_Position = vec4(aCrossValue, aMainValue, 0, 1);"
    };
    var triangle = {
      header: "\n        attribute float aCrossValue;\n        attribute float aMainValue;\n        attribute float aSize;\n        attribute float aDefined;\n\n        uniform float uStrokeWidth;\n\n        varying float vSize;\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        vSize = sqrt((16.0 * aSize) / (3.0 * sqrt(3.0)));\n        gl_PointSize = vSize + uStrokeWidth + 1.0;\n        gl_Position = vec4(aCrossValue, aMainValue, 0, 1);"
    };
    var cross = {
      header: "\n        attribute float aCrossValue;\n        attribute float aMainValue;\n        attribute float aSize;\n        attribute float aDefined;\n\n        uniform float uStrokeWidth;\n\n        varying float vSize;\n        varying float vStrokeWidthRatio;\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        vSize = 3.0 * sqrt(aSize / 5.0);\n        vStrokeWidthRatio = uStrokeWidth / (vSize + uStrokeWidth + 1.0);\n        gl_PointSize = vSize + uStrokeWidth + 1.0;\n        gl_Position = vec4(aCrossValue, aMainValue, 0, 1);"
    };
    var candlestick = {
      header: "\n        attribute float aCrossValue;\n        attribute float aBandwidth;\n        attribute float aHighValue;\n        attribute float aOpenValue;\n        attribute float aCloseValue;\n        attribute float aLowValue;\n        attribute vec3 aCorner;\n        attribute float aDefined;\n\n        uniform vec2 uScreen;\n        uniform float uStrokeWidth;\n\n        varying float vColorIndicator;\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        vColorIndicator = sign(aCloseValue - aOpenValue);\n\n        float isPositiveY = (sign(aCorner.y) + 1.0) / 2.0;\n        float isNotPositiveY = 1.0 - isPositiveY;\n        float isExtremeY = abs(aCorner.y) - 1.0;\n        float isNotExtremeY = 1.0 - isExtremeY;\n        float yValue =\n         (isPositiveY * isExtremeY * aLowValue) +\n         (isPositiveY * isNotExtremeY * aCloseValue) +\n         (isNotPositiveY * isNotExtremeY * aOpenValue) +\n         (isNotPositiveY * isExtremeY * aHighValue);\n\n        float lineWidthXDirection = (isNotExtremeY * aCorner.x) + (isExtremeY * aCorner.z);\n        float lineWidthYDirection = isNotExtremeY * sign(aCloseValue - aOpenValue) * aCorner.y;\n\n        float bandwidthModifier = aBandwidth * aCorner.x / 2.0;\n\n        float xModifier = (uStrokeWidth * lineWidthXDirection / 2.0) + bandwidthModifier;\n        float yModifier = uStrokeWidth * lineWidthYDirection / 2.0;\n\n        gl_Position = vec4(aCrossValue, yValue, 0, 1);"
    };
    var ohlc = {
      header: "\n        attribute float aCrossValue;\n        attribute float aBandwidth;\n        attribute float aHighValue;\n        attribute float aOpenValue;\n        attribute float aCloseValue;\n        attribute float aLowValue;\n        attribute vec3 aCorner;\n        attribute float aDefined;\n\n        uniform vec2 uScreen;\n        uniform float uStrokeWidth;\n\n        varying float vColorIndicator;\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        vColorIndicator = sign(aCloseValue - aOpenValue);\n\n        float isPositiveY = (sign(aCorner.y) + 1.0) / 2.0;\n        float isNotPositiveY = 1.0 - isPositiveY;\n        float isExtremeY = abs(aCorner.y) - 1.0;\n        float isNotExtremeY = 1.0 - isExtremeY;\n        float yValue =\n            (isPositiveY * isExtremeY * aLowValue) +\n            (isPositiveY * isNotExtremeY * aCloseValue) +\n            (isNotPositiveY * isNotExtremeY * aOpenValue) +\n            (isNotPositiveY * isExtremeY * aHighValue);\n\n        float lineWidthXDirection = isExtremeY * aCorner.z;\n        float lineWidthYDirection = isNotExtremeY * aCorner.z;\n\n        float bandwidthModifier = isNotExtremeY * aCorner.x * aBandwidth / 2.0;\n\n        float xModifier = (uStrokeWidth * lineWidthXDirection / 2.0) + bandwidthModifier;\n        float yModifier = uStrokeWidth * lineWidthYDirection / 2.0;\n\n        gl_Position = vec4(aCrossValue, yValue, 0, 1);"
    };
    var bar = {
      header: "\n        attribute float aCrossValue;\n        attribute float aBandwidth;\n        attribute float aMainValue;\n        attribute float aBaseValue;\n        attribute vec2 aCorner;\n        attribute float aDefined;\n\n        uniform vec2 uScreen;\n        uniform float uStrokeWidth;\n\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        float isBaseline = (1.0 - aCorner.y) / 2.0;\n        float yValue = (isBaseline * aBaseValue) + ((1.0 - isBaseline) * aMainValue);\n\n        float xModifier = aCorner.x * (aBandwidth) / 2.0;\n\n        gl_Position = vec4(aCrossValue, yValue, 0, 1);"
    };
    var preScaleLine = {
      header: "\n        attribute vec3 aCorner;\n        attribute float aCrossNextNextValue;\n        attribute float aMainNextNextValue;\n        attribute float aCrossNextValue;\n        attribute float aMainNextValue;\n        attribute float aCrossValue;\n        attribute float aMainValue;\n        attribute float aCrossPrevValue;\n        attribute float aMainPrevValue;\n        attribute float aDefined;\n        attribute float aDefinedNext;\n\n        uniform float uStrokeWidth;\n        uniform vec2 uScreen;\n\n        varying float vDefined;",
      body: "\n        vDefined = aDefined * aDefinedNext;\n        vec4 prev = vec4(aCrossPrevValue, aMainPrevValue, 0, 0);\n        vec4 curr = vec4(aCrossValue, aMainValue, 0, 0);\n        gl_Position = vec4(aCrossNextValue, aMainNextValue, 0, 1);\n        vec4 nextNext = vec4(aCrossNextNextValue, aMainNextNextValue, 0, 0);"
    };
    var postScaleLine = {
      body: "\n        vec4 currVertexPosition = gl_Position;\n        vec4 nextVertexPosition = gl_Position;\n\n        if (all(equal(curr.xy, prev.xy))) {\n            prev.xy = curr.xy + normalize(curr.xy - currVertexPosition.xy);\n        }\n        if (all(equal(curr.xy, currVertexPosition.xy))) {\n            currVertexPosition.xy = curr.xy + normalize(curr.xy - prev.xy);\n        }\n        vec2 A = normalize(normalize(curr.xy - prev.xy) * uScreen);\n        vec2 B = normalize(normalize(currVertexPosition.xy - curr.xy) * uScreen);\n        vec2 tangent = normalize(A + B);\n        vec2 miter = vec2(-tangent.y, tangent.x);\n        vec2 normalA = vec2(-A.y, A.x);\n        float miterLength = 1.0 / dot(miter, normalA);\n        vec2 point = normalize(A - B);\n        if (miterLength > 10.0 && sign(aCorner.x * dot(miter, point)) > 0.0) {\n            currVertexPosition.xy = curr.xy - (aCorner.x * aCorner.y * uStrokeWidth * normalA) / uScreen.xy;\n        } else {\n            currVertexPosition.xy = curr.xy + (aCorner.x * miter * uStrokeWidth * miterLength) / uScreen.xy;\n        }\n\n        if (all(equal(nextVertexPosition.xy, curr.xy))) {\n            curr.xy = nextVertexPosition.xy + normalize(nextVertexPosition.xy - nextNext.xy);\n        }\n        if (all(equal(nextVertexPosition.xy, nextNext.xy))) {\n            nextNext.xy = nextVertexPosition.xy + normalize(nextVertexPosition.xy - curr.xy);\n        }\n        vec2 C = normalize(normalize(nextVertexPosition.xy - curr.xy) * uScreen);\n        vec2 D = normalize(normalize(nextNext.xy - nextVertexPosition.xy) * uScreen);\n        vec2 tangentCD = normalize(C + D);\n        vec2 miterCD = vec2(-tangentCD.y, tangentCD.x);\n        vec2 normalC = vec2(-C.y, C.x);\n        float miterCDLength = 1.0 / dot(miterCD, normalC);\n        vec2 pointCD = normalize(C - D);\n        if (miterCDLength > 10.0 && sign(aCorner.x * dot(miterCD, pointCD)) > 0.0) {\n            nextVertexPosition.xy = nextVertexPosition.xy - (aCorner.x * aCorner.y * uStrokeWidth * normalC) / uScreen.xy;\n        } else {\n            nextVertexPosition.xy = nextVertexPosition.xy + (aCorner.x * miterCD * uStrokeWidth * miterCDLength) / uScreen.xy;\n        }\n\n        gl_Position.xy = ((1.0 - aCorner.z) * currVertexPosition.xy) + (aCorner.z * nextVertexPosition.xy);"
    };
    var errorBar = {
      header: "\n        attribute vec3 aCorner;\n        attribute float aCrossValue;\n        attribute float aBandwidth;\n        attribute float aHighValue;\n        attribute float aLowValue;\n        attribute float aDefined;\n\n        uniform vec2 uScreen;\n        uniform float uStrokeWidth;\n\n        varying float vDefined;",
      body: "\n        vDefined = aDefined;\n        float isLow = (aCorner.y + 1.0) / 2.0;\n        float yValue = isLow * aLowValue + (1.0 - isLow) * aHighValue;\n\n        float isEdgeCorner = abs(aCorner.x);\n        float lineWidthXDirection = (1.0 - isEdgeCorner) * aCorner.z;\n        float lineWidthYDirection = isEdgeCorner * aCorner.z;\n\n        gl_Position = vec4(aCrossValue, yValue, 0, 1);\n\n        float xModifier = (uStrokeWidth * lineWidthXDirection) + (aBandwidth * aCorner.x / 2.0);\n        float yModifier = (uStrokeWidth * lineWidthYDirection);"
    };
    var area = {
      header: "\n        attribute vec3 aCorner;\n        attribute float aCrossValue;\n        attribute float aMainValue;\n        attribute float aCrossNextValue;\n        attribute float aMainNextValue;\n        attribute float aBaseValue;\n        attribute float aBaseNextValue;\n        attribute float aDefined;\n        attribute float aDefinedNext;\n\n        varying float vDefined;\n\n        float when_lt(float a, float b) {\n            return max(sign(b - a), 0.0);\n        }\n\n        float and(float a, float b) {\n            return a * b;\n        }",
      body: "\n        vDefined = aDefined * aDefinedNext;\n        gl_Position = vec4(0, 0, 0, 1);\n\n        float hasIntercepted = when_lt((aMainNextValue - aBaseNextValue) * (aMainValue - aBaseValue), 0.0);\n        float useIntercept = and(aCorner.z, hasIntercepted);\n\n        float yGradient = (aMainNextValue - aMainValue) / (aCrossNextValue - aCrossValue);\n        float yConstant = aMainNextValue - (yGradient * aCrossNextValue);\n\n        float y0Gradient = (aBaseNextValue - aBaseValue) / (aCrossNextValue - aCrossValue);\n        float y0Constant = aBaseNextValue - (y0Gradient * aCrossNextValue);\n\n        float denominator = (yGradient - y0Gradient) + step(abs(yGradient - y0Gradient), 0.0);\n        float interceptXValue = (y0Constant - yConstant) / denominator;\n        float interceptYValue = (yGradient * interceptXValue) + yConstant;\n\n        gl_Position = vec4(interceptXValue * useIntercept, interceptYValue * useIntercept, 0, 1);\n\n        gl_Position.x += (1.0 - useIntercept) * ((aCorner.x * aCrossNextValue) + ((1.0 - aCorner.x) * aCrossValue));\n        gl_Position.y += (1.0 - useIntercept) * (1.0 - aCorner.y) * ((aCorner.x * aMainNextValue) + ((1.0 - aCorner.x) * aMainValue));\n        gl_Position.y += (1.0 - useIntercept) * aCorner.y * ((aCorner.x * aBaseNextValue) + ((1.0 - aCorner.x) * aBaseValue));"
    };
    var boxPlot = {
      header: "\n        attribute vec4 aCorner;\n        attribute float aCrossValue;\n        attribute float aBandwidth;\n        attribute float aCapWidth;\n        attribute float aHighValue;\n        attribute float aUpperQuartileValue;\n        attribute float aMedianValue;\n        attribute float aLowerQuartileValue;\n        attribute float aLowValue;\n        attribute float aDefined;\n\n        uniform vec2 uScreen;\n        uniform float uStrokeWidth;\n\n        varying float vDefined;\n    ",
      body: "\n        vDefined = aDefined;\n        float isExtremeY = sign(abs(aCorner.y) - 2.0) + 1.0;\n        float isNotExtremeY = 1.0 - isExtremeY;\n\n        float isNonZeroY = abs(sign(aCorner.y));\n        float isZeroY = 1.0 - isNonZeroY;\n\n        float isQuartileY = isNotExtremeY * isNonZeroY;\n\n        float isPositiveY = (sign(aCorner.y + 0.5) + 1.0) / 2.0;\n        float isNegativeY = 1.0 - isPositiveY;\n\n        float yValue =\n          (isExtremeY * isNegativeY) * aHighValue +\n          (isQuartileY * isNegativeY) * aUpperQuartileValue +\n          isZeroY * aMedianValue +\n          (isQuartileY * isPositiveY) * aLowerQuartileValue +\n          (isExtremeY * isPositiveY) * aLowValue;\n\n        gl_Position = vec4(aCrossValue, yValue, 0, 1);\n\n        float isHorizontal = aCorner.w;\n        float isVertical = 1.0 - isHorizontal;\n\n        float xDisplacement = aCorner.x * (isExtremeY * aCapWidth + isNotExtremeY * aBandwidth) / 2.0;\n\n        float xModifier = (isVertical * uStrokeWidth * aCorner.z / 2.0) + xDisplacement;\n        float yModifier = isHorizontal * uStrokeWidth * aCorner.z / 2.0;"
    };

    var circle$1 = {
      header: "\n        varying float vSize;\n        varying float vDefined;",
      body: "\n        float canFill = 1.0;\n        float distance = length(2.0 * gl_PointCoord - 1.0);\n        float canStroke = smoothstep(vSize - 2.0, vSize, distance * vSize);\n        if (distance > 1.0 || vDefined < 0.5) {\n            discard;\n            return;\n        }"
    };
    var square$1 = {
      header: "\n        varying float vSize;\n        varying float vDefined;",
      body: "\n        float canFill = 1.0;\n        if (vDefined < 0.5) {\n            discard;\n        }\n        vec2 pointCoordTransform = 2.0 * gl_PointCoord - 1.0;\n        float distance = max(abs(pointCoordTransform.x), abs(pointCoordTransform.y));\n        float canStroke = smoothstep(vSize - 2.0, vSize, distance * vSize);"
    }; // Diamond is symmetrical about the x, and y axes, so only consider x, y > 0.
    // (x, y) are the coordinates of the fragment within the gl point (after
    // transformed to be [-1, 1]).
    // a, b control the width, height of the triangle, so diamond is 2a, 2b.
    // Line L is a ray from the origin through (x, y), the distance function is then
    // the distance to (x, y) divided by the distance to where L intersects with the
    // diamond, this makes the distance function < 1 inside, 1 on the boundary, and
    // > 1 outside the diamond.
    //    |
    // b ---
    //    |\             L
    //    | -\          /
    //    |   \        /
    //    |    \      /
    //    |     -\   /
    //    |       \ /
    // Y ---       X
    //    |       / -\
    //    |      /    \
    //    |     /      \
    // y ---   X        -\
    //    |   /           \
    //    |  /             \
    //    | /               -\
    //    |/                  \
    //    +----|---|-----------|---
    //         x   X           a

    var diamond$1 = {
      header: "\n        varying float vSize;\n        varying float vDefined;\n        float a = 0.6;\n        float b = 1.0;\n    ",
      body: "\n        if (vDefined < 0.5) {\n            discard;\n        }\n\n        vec2 pointCoordTransform = 2.0 * gl_PointCoord - 1.0;\n\n        float x = abs(pointCoordTransform.x);\n        float y = abs(pointCoordTransform.y);\n\n        float X = (a * b * x) / (a * y + b * x);\n        float Y = (a * b * y) / (a * y + b * x);\n\n        float distance = length(vec2(x, y)) / length(vec2(X, Y));\n\n        if (distance > 1.0) {\n            discard;\n        }\n    "
    };
    var triangle$1 = {
      header: "\n        varying float vSize;\n        varying float vDefined;",
      body: "\n        float canFill = 1.0;\n        vec2 pointCoordTransform = 2.0 * gl_PointCoord - 1.0;\n        float topEdgesDistance = abs(pointCoordTransform.x) - ((pointCoordTransform.y - 0.6) / sqrt(3.0));\n        float bottomEdgeDistance = pointCoordTransform.y + 0.5;\n        float distance = max(topEdgesDistance, bottomEdgeDistance);\n        float canStroke = smoothstep(vSize - 2.0, vSize, distance * vSize);\n        if (distance > 1.0 || vDefined < 0.5) {\n            discard;\n        }"
    };
    var cross$1 = {
      header: "\n        varying float vSize;\n        varying float vStrokeWidthRatio;\n        varying float vDefined;",
      body: "\n        float canFill = 1.0;\n        vec2 pointCoordTransform = 2.0 * gl_PointCoord - 1.0;\n        float innerCornerDistance = min(abs(pointCoordTransform.x), abs(pointCoordTransform.y)) + 0.66 - vStrokeWidthRatio;\n        float outerEdgeDistance = max(abs(pointCoordTransform.x), abs(pointCoordTransform.y));\n        float distance = max(innerCornerDistance, outerEdgeDistance);\n        float canStroke = smoothstep(vSize - 2.0, vSize, distance * vSize);\n        if (distance > 1.0 || vDefined < 0.5) {\n            discard;\n        }"
    };
    var candlestick$1 = {
      header: "\n        varying float vColorIndicator;\n        varying float vDefined;",
      body: "\n        float canFill = 1.0;\n        float canStroke = 0.0;\n        if (vDefined < 0.5) {\n            discard;\n        }\n        gl_FragColor = vec4(0.4, 0.8, 0, 1);\n        if (vColorIndicator < 0.0) {\n            gl_FragColor = vec4(0.8, 0.4, 0, 1);\n        }"
    };
    var ohlc$1 = {
      header: "\n        varying float vColorIndicator;\n        varying float vDefined;",
      body: "\n        float canFill = 0.0;\n        float canStroke = 1.0;\n        if (vDefined < 0.5) {\n            discard;\n        }\n        gl_FragColor = vec4(0.4, 0.8, 0, 1);\n        if (vColorIndicator < 0.0) {\n            gl_FragColor = vec4(0.8, 0.4, 0, 1);\n        }"
    };
    var area$1 = {
      header: "\n        varying float vDefined;",
      body: "\n        float canFill = 1.0;\n        float canStroke = 0.0;\n        if (vDefined < 0.5) {\n            discard;\n        }\n        gl_FragColor = vec4(0.86, 0.86, 0.86, 1);"
    };
    var boxPlot$1 = {
      header: "\n        varying float vDefined;\n    ",
      body: "\n        float canFill = 0.0;\n        float canStroke = 1.0;\n\n        if (vDefined < 0.5) {\n            discard;\n        }"
    };
    var errorBar$1 = {
      header: "varying float vDefined;",
      body: "\n        float canFill = 0.0;\n        float canStroke = 1.0;\n        if (vDefined < 0.5) {\n            discard;\n        }"
    };
    var bar$1 = {
      header: "varying float vDefined;",
      body: "\n        float canFill = 1.0;\n        float canStroke = 0.0;\n\n        gl_FragColor = vec4(0.60, 0.60, 0.60, 1.0);\n\n        if (vDefined < 0.5) {\n            discard;\n        }"
    };
    var fillColor$1 = {
      header: "varying vec4 vFillColor;",
      body: "gl_FragColor = (canFill * vFillColor) + ((1.0 - canFill) * gl_FragColor);"
    };
    var strokeColor$1 = {
      header: "varying vec4 vStrokeColor;",
      body: "gl_FragColor = (canStroke * vStrokeColor) + ((1.0 - canStroke) * gl_FragColor);"
    };
    var line = {
      header: "varying float vDefined;",
      body: "\n        float canFill = 0.0;\n        float canStroke = 1.0;\n        if (vDefined < 0.5) {\n            discard;\n        }"
    };

    var areaShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(area.header).appendBody(area.body);
      fragmentShader.appendHeader(area$1.header).appendBody(area$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var types = {
      BYTE: 5120,
      UNSIGNED_BYTE: 5121,
      SHORT: 5122,
      UNSIGNED_SHORT: 5123,
      FLOAT: 5126
    };
    function length(type) {
      switch (type) {
        case types.BYTE:
        case types.UNSIGNED_BYTE:
          return 1;

        case types.SHORT:
        case types.UNSIGNED_SHORT:
          return 2;

        case types.FLOAT:
          return 4;

        default:
          throw new Error("Unknown type ".concat(type));
      }
    }
    function getArrayViewConstructor(type) {
      switch (type) {
        case types.BYTE:
          return Int8Array;

        case types.UNSIGNED_BYTE:
          return Uint8Array;

        case types.SHORT:
          return Int16Array;

        case types.UNSIGNED_SHORT:
          return Uint16Array;

        case types.FLOAT:
          return Float32Array;

        default:
          throw new Error("Unknown type ".concat(type));
      }
    }

    var baseAttributeBuilder = (function () {
      var location = -1;
      var buffer = null;
      var size = 1; // per vertex

      var type = types.FLOAT;
      var normalized = false;
      var stride = 0;
      var offset = 0;
      var divisor = 0;

      var baseAttribute = function baseAttribute(programBuilder) {
        var gl = programBuilder.context();

        if (buffer == null) {
          buffer = gl.createBuffer();
        }

        gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
        gl.vertexAttribPointer(location, size, type, normalized, stride, offset);
        gl.enableVertexAttribArray(location);
        var extInstancedArrays = programBuilder.extInstancedArrays();
        extInstancedArrays.vertexAttribDivisorANGLE(location, divisor);
      };

      baseAttribute.location = function () {
        if (!arguments.length) {
          return location;
        }

        location = arguments.length <= 0 ? undefined : arguments[0];
        return baseAttribute;
      };

      baseAttribute.buffer = function () {
        if (!arguments.length) {
          return buffer;
        }

        buffer = arguments.length <= 0 ? undefined : arguments[0];
        return baseAttribute;
      };

      baseAttribute.size = function () {
        if (!arguments.length) {
          return size;
        }

        size = arguments.length <= 0 ? undefined : arguments[0];
        return baseAttribute;
      };

      baseAttribute.type = function () {
        if (!arguments.length) {
          return type;
        }

        type = arguments.length <= 0 ? undefined : arguments[0];
        return baseAttribute;
      };

      baseAttribute.normalized = function () {
        if (!arguments.length) {
          return normalized;
        }

        normalized = arguments.length <= 0 ? undefined : arguments[0];
        return baseAttribute;
      };

      baseAttribute.stride = function () {
        if (!arguments.length) {
          return stride;
        }

        stride = arguments.length <= 0 ? undefined : arguments[0];
        return baseAttribute;
      };

      baseAttribute.offset = function () {
        if (!arguments.length) {
          return offset;
        }

        offset = arguments.length <= 0 ? undefined : arguments[0];
        return baseAttribute;
      };

      baseAttribute.divisor = function () {
        if (!arguments.length) {
          return divisor;
        }

        divisor = arguments.length <= 0 ? undefined : arguments[0];
        return baseAttribute;
      };

      return baseAttribute;
    });

    var defaultArrayViewFactory = (function () {
      var type = types.FLOAT;
      var cachedArray = new Float32Array(0);

      var factory = function factory(requiredLength) {
        var ArrayType = getArrayViewConstructor(type);

        if (cachedArray.length > requiredLength) {
          cachedArray = new ArrayType(cachedArray.buffer, 0, requiredLength);
        } else if (cachedArray.length !== requiredLength) {
          cachedArray = new ArrayType(requiredLength);
        }

        return cachedArray;
      };

      factory.type = function () {
        if (!arguments.length) {
          return type;
        }

        if (type !== (arguments.length <= 0 ? undefined : arguments[0])) {
          type = arguments.length <= 0 ? undefined : arguments[0];
          var ArrayType = getArrayViewConstructor(type);
          cachedArray = new ArrayType(0);
        }

        return factory;
      };

      return factory;
    });

    var attributeProjector = (function () {
      var dirty = true;
      var size = 1; // per vertex

      var type = types.FLOAT;
      var arrayViewFactory = defaultArrayViewFactory();

      var value = function value(d, i) {
        return d;
      };

      var data = null;

      var projector = function projector() {
        var length = data.length;
        var projectedData = arrayViewFactory.type(type)(length * size);

        if (size > 1) {
          for (var i = 0; i < length; i++) {
            var componentValues = value(data[i], i);

            if (componentValues.length !== size) {
              throw new Error("Expected components array of size ".concat(size, ", recieved array with length ").concat(componentValues.length, "."));
            }

            for (var component = 0; component < size; component++) {
              projectedData[i * size + component] = componentValues[component];
            }
          }
        } else {
          for (var _i = 0; _i < length; _i++) {
            var componentValue = value(data[_i], _i);

            if (Array.isArray(componentValue)) {
              throw new Error("Expected a single component value, recieved array with length ".concat(componentValue.length, "."));
            }

            projectedData[_i] = componentValue;
          }
        }

        dirty = false;
        return projectedData;
      };

      projector.dirty = function () {
        return dirty;
      };

      projector.clear = function () {
        dirty = true;
      };

      projector.size = function () {
        if (!arguments.length) {
          return size;
        }

        size = arguments.length <= 0 ? undefined : arguments[0];
        dirty = true;
        return projector;
      };

      projector.type = function () {
        if (!arguments.length) {
          return type;
        }

        type = arguments.length <= 0 ? undefined : arguments[0];
        dirty = true;
        return projector;
      };

      projector.arrayViewFactory = function () {
        if (!arguments.length) {
          return arrayViewFactory;
        }

        arrayViewFactory = arguments.length <= 0 ? undefined : arguments[0];
        dirty = true;
        return projector;
      };

      projector.value = function () {
        if (!arguments.length) {
          return value;
        }

        value = arguments.length <= 0 ? undefined : arguments[0];
        dirty = true;
        return projector;
      };

      projector.data = function () {
        if (!arguments.length) {
          return data;
        }

        data = arguments.length <= 0 ? undefined : arguments[0];
        dirty = true;
        return projector;
      };

      return projector;
    });

    var vertexAttribute = (function () {
      var base = baseAttributeBuilder();
      var projector = attributeProjector();

      var vertexAttribute = function vertexAttribute(programBuilder) {
        base.size(vertexAttribute.size()).type(vertexAttribute.type());
        base(programBuilder);

        if (!projector.dirty()) {
          return;
        }

        var projectedData = projector();
        var gl = programBuilder.context();
        gl.bindBuffer(gl.ARRAY_BUFFER, base.buffer());
        gl.bufferData(gl.ARRAY_BUFFER, projectedData, gl.DYNAMIC_DRAW);
      };

      vertexAttribute.clear = function () {
        base.buffer(null);
        projector.clear();
      };

      d3fcRebind.rebind(vertexAttribute, base, 'normalized', 'location');
      d3fcRebind.rebind(vertexAttribute, projector, 'data', 'value', 'size', 'type');
      return vertexAttribute;
    });

    var elementIndices = (function (initialData) {
      var buffer = null;
      var data = initialData;
      var dirty = true;

      var base = function base(programBuilder) {
        var gl = programBuilder.context();

        if (buffer == null) {
          buffer = gl.createBuffer();
        }

        gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer);

        if (!dirty) {
          return;
        }

        gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(data), gl.STATIC_DRAW);
        dirty = false;
      };

      base.clear = function () {
        buffer = null;
        dirty = true;
      };

      base.data = function () {
        if (!arguments.length) {
          return data;
        }

        dirty = true;
        data = arguments.length <= 0 ? undefined : arguments[0];
        return base;
      };

      return base;
    });

    var rebindCurry = (function (target, targetName, source, sourceName) {
      for (var _len = arguments.length, curriedArgs = new Array(_len > 4 ? _len - 4 : 0), _key = 4; _key < _len; _key++) {
        curriedArgs[_key - 4] = arguments[_key];
      }

      target[targetName] = function () {
        for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
          args[_key2] = arguments[_key2];
        }

        var result = source[sourceName].apply(source, curriedArgs.concat(args));

        if (result === source) {
          return target;
        }

        return result;
      };
    });

    var area$2 = (function () {
      var program = programBuilder().mode(drawModes.TRIANGLES);
      var xScale = baseScale();
      var yScale = baseScale();

      var decorate = function decorate() {};

      var cornerAttribute = vertexAttribute().size(3).type(types.UNSIGNED_BYTE).data([[0, 0, 0], [0, 1, 0], [1, 1, 1], [0, 0, 1], [1, 0, 0], [1, 1, 0]]);
      program.buffers().elementIndices(elementIndices([0, 1, 2, 3, 4, 5])).attribute('aCorner', cornerAttribute);

      var draw = function draw(numElements) {
        var shaderBuilder = areaShader();
        program.vertexShader(shaderBuilder.vertex()).fragmentShader(shaderBuilder.fragment());
        xScale(program, 'gl_Position', 0);
        yScale(program, 'gl_Position', 1);
        decorate(program);
        program(numElements - 1);
      };

      draw.decorate = function () {
        if (!arguments.length) {
          return decorate;
        }

        decorate = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.xScale = function () {
        if (!arguments.length) {
          return xScale;
        }

        xScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.yScale = function () {
        if (!arguments.length) {
          return yScale;
        }

        yScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      d3fcRebind.rebind(draw, program, 'context');
      rebindCurry(draw, 'crossValueAttribute', program.buffers(), 'attribute', 'aCrossValue');
      rebindCurry(draw, 'crossNextValueAttribute', program.buffers(), 'attribute', 'aCrossNextValue');
      rebindCurry(draw, 'mainValueAttribute', program.buffers(), 'attribute', 'aMainValue');
      rebindCurry(draw, 'mainNextValueAttribute', program.buffers(), 'attribute', 'aMainNextValue');
      rebindCurry(draw, 'baseValueAttribute', program.buffers(), 'attribute', 'aBaseValue');
      rebindCurry(draw, 'baseNextValueAttribute', program.buffers(), 'attribute', 'aBaseNextValue');
      rebindCurry(draw, 'definedAttribute', program.buffers(), 'attribute', 'aDefined');
      rebindCurry(draw, 'definedNextAttribute', program.buffers(), 'attribute', 'aDefinedNext');
      return draw;
    });

    var circlePointShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(circle.header).appendBody(circle.body);
      fragmentShader.appendHeader(circle$1.header).appendBody(circle$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var point = (function () {
      var program = programBuilder().mode(drawModes.POINTS); // hack to allow a consistent instanced render path

      var ignoredAttribute = vertexAttribute().data([0]);
      program.buffers().attribute('aIgnored', ignoredAttribute).elementIndices(elementIndices([0]));
      var xScale = baseScale();
      var yScale = baseScale();
      var type = circlePointShader();

      var decorate = function decorate() {};

      var draw = function draw(numElements) {
        program.vertexShader(type.vertex().appendHeader('attribute float aIgnored;').appendBody('gl_Position += aIgnored;')).fragmentShader(type.fragment());
        xScale(program, 'gl_Position', 0);
        yScale(program, 'gl_Position', 1);
        decorate(program);
        program(numElements);
      };

      draw.type = function () {
        if (!arguments.length) {
          return type;
        }

        type = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.decorate = function () {
        if (!arguments.length) {
          return decorate;
        }

        decorate = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.xScale = function () {
        if (!arguments.length) {
          return xScale;
        }

        xScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.yScale = function () {
        if (!arguments.length) {
          return yScale;
        }

        yScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      d3fcRebind.rebind(draw, program, 'context');
      rebindCurry(draw, 'crossValueAttribute', program.buffers(), 'attribute', 'aCrossValue');
      rebindCurry(draw, 'mainValueAttribute', program.buffers(), 'attribute', 'aMainValue');
      rebindCurry(draw, 'sizeAttribute', program.buffers(), 'attribute', 'aSize');
      rebindCurry(draw, 'definedAttribute', program.buffers(), 'attribute', 'aDefined');
      return draw;
    });

    var lineShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(preScaleLine.header).appendBody(preScaleLine.body);
      fragmentShader.appendHeader(line.header).appendBody(line.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var lineWidthShader = (function () {
      var width = 1;

      var lineWidth = function lineWidth(program) {
        program.buffers().uniform('uStrokeWidth', uniform(width));
      };

      lineWidth.lineWidth = function () {
        if (!arguments.length) {
          return width;
        }

        width = arguments.length <= 0 ? undefined : arguments[0];
        return lineWidth;
      };

      return lineWidth;
    });

    var line$1 = (function () {
      var program = programBuilder().mode(drawModes.TRIANGLES);
      var xScale = baseScale();
      var yScale = baseScale();

      var decorate = function decorate() {};

      var lineWidth = lineWidthShader();
      var cornerAttribute = vertexAttribute().size(3).type(types.BYTE).data([[-1, 0, 0], [1, 1, 0], [1, -1, 1], [-1, 0, 1], [1, 1, 1]]);
      program.buffers().elementIndices(elementIndices([0, 1, 2, 1, 2, 3, 0, 2, 3, 2, 3, 4])).attribute('aCorner', cornerAttribute);

      var draw = function draw(numElements) {
        var shaderBuilder = lineShader();
        program.vertexShader(shaderBuilder.vertex()).fragmentShader(shaderBuilder.fragment());
        xScale(program, 'prev', 0);
        yScale(program, 'prev', 1);
        xScale(program, 'curr', 0);
        yScale(program, 'curr', 1);
        xScale(program, 'gl_Position', 0);
        yScale(program, 'gl_Position', 1);
        xScale(program, 'nextNext', 0);
        yScale(program, 'nextNext', 1);
        program.vertexShader().appendBody(postScaleLine.body);
        lineWidth(program);
        decorate(program);
        program(numElements - 1);
      };

      draw.decorate = function () {
        if (!arguments.length) {
          return decorate;
        }

        decorate = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.xScale = function () {
        if (!arguments.length) {
          return xScale;
        }

        xScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.yScale = function () {
        if (!arguments.length) {
          return yScale;
        }

        yScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      d3fcRebind.rebind(draw, program, 'context');
      d3fcRebind.rebind(draw, lineWidth, 'lineWidth');
      rebindCurry(draw, 'crossPreviousValueAttribute', program.buffers(), 'attribute', 'aCrossPrevValue');
      rebindCurry(draw, 'crossValueAttribute', program.buffers(), 'attribute', 'aCrossValue');
      rebindCurry(draw, 'crossNextValueAttribute', program.buffers(), 'attribute', 'aCrossNextValue');
      rebindCurry(draw, 'crossNextNextValueAttribute', program.buffers(), 'attribute', 'aCrossNextNextValue');
      rebindCurry(draw, 'mainPreviousValueAttribute', program.buffers(), 'attribute', 'aMainPrevValue');
      rebindCurry(draw, 'mainValueAttribute', program.buffers(), 'attribute', 'aMainValue');
      rebindCurry(draw, 'mainNextValueAttribute', program.buffers(), 'attribute', 'aMainNextValue');
      rebindCurry(draw, 'mainNextNextValueAttribute', program.buffers(), 'attribute', 'aMainNextNextValue');
      rebindCurry(draw, 'definedAttribute', program.buffers(), 'attribute', 'aDefined');
      rebindCurry(draw, 'definedNextAttribute', program.buffers(), 'attribute', 'aDefinedNext');
      return draw;
    });

    var ohlcShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(ohlc.header).appendBody(ohlc.body);
      fragmentShader.appendHeader(ohlc$1.header).appendBody(ohlc$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var ohlc$2 = (function () {
      var program = programBuilder().mode(drawModes.TRIANGLES);
      var xScale = baseScale();
      var yScale = baseScale();
      var lineWidth = lineWidthShader();

      var decorate = function decorate() {};
      /*
       * x-y coordinate to locate the "corners" of the element.
       * X: -1: LEFT, 0: MIDDLE, 1: RIGHT
       * Y: -2: HIGH, -1: OPEN, 1: CLOSE, 2: LOW
       * Z - Follows convention for X/Y (appropriate direction will be selected by the shader): -1: LEFT/TOP, 1: RIGHT/BOTTOM
       */


      var cornerAttribute = vertexAttribute().size(3).type(types.BYTE).data([// Main stem
      [0, -2, -1], [0, -2, 1], [0, 2, 1], [0, 2, -1], // Open bar
      [-1, -1, -1], [-1, -1, 1], [0, -1, 1], [0, -1, -1], // Close bar
      [1, 1, 1], [0, 1, 1], [0, 1, -1], [1, 1, -1]]);
      program.buffers().elementIndices(elementIndices([// Main stem
      0, 1, 2, 0, 3, 2, // Open bar
      4, 5, 6, 4, 7, 6, // Close bar
      8, 9, 10, 10, 11, 8])).attribute('aCorner', cornerAttribute);

      var draw = function draw(numElements) {
        var shaderBuilder = ohlcShader();
        program.vertexShader(shaderBuilder.vertex()).fragmentShader(shaderBuilder.fragment());
        xScale(program, 'gl_Position', 0);
        yScale(program, 'gl_Position', 1);
        lineWidth(program);
        program.vertexShader().appendBody("\n          gl_Position.x += xModifier / uScreen.x;\n          gl_Position.y += yModifier / uScreen.y;\n        ");
        decorate(program);
        program(numElements);
      };

      draw.decorate = function () {
        if (!arguments.length) {
          return decorate;
        }

        decorate = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.xScale = function () {
        if (!arguments.length) {
          return xScale;
        }

        xScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.yScale = function () {
        if (!arguments.length) {
          return yScale;
        }

        yScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      d3fcRebind.rebind(draw, program, 'context');
      d3fcRebind.rebind(draw, lineWidth, 'lineWidth');
      rebindCurry(draw, 'crossValueAttribute', program.buffers(), 'attribute', 'aCrossValue');
      rebindCurry(draw, 'openValueAttribute', program.buffers(), 'attribute', 'aOpenValue');
      rebindCurry(draw, 'highValueAttribute', program.buffers(), 'attribute', 'aHighValue');
      rebindCurry(draw, 'lowValueAttribute', program.buffers(), 'attribute', 'aLowValue');
      rebindCurry(draw, 'closeValueAttribute', program.buffers(), 'attribute', 'aCloseValue');
      rebindCurry(draw, 'bandwidthAttribute', program.buffers(), 'attribute', 'aBandwidth');
      rebindCurry(draw, 'definedAttribute', program.buffers(), 'attribute', 'aDefined');
      return draw;
    });

    var barShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(bar.header).appendBody(bar.body);
      fragmentShader.appendHeader(bar$1.header).appendBody(bar$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    //     .-------------.------------.
    // (x-w/2, y1)    (x, y1)   (x+w/2, y1)
    //     |     \                    |
    //     |        \                 |
    //     |           \              |
    //     |              \           |
    //     |                 \        |
    //     |                    \     |
    //     |                       \  |
    //     αL            α            αR
    //     .-------------.------------.
    // (x-w/2, y0)     (x, y0)   (x+w/2, y0)
    // Drawing order
    // Triangle βL, αL, αR. (bottom)
    // β -> βL.
    // α -> αL.
    // α -> αR.
    // Triangle βL, αR, βR. (top)
    // β -> βL.
    // α -> αR.
    // β -> βR.

    var bar$2 = (function () {
      var program = programBuilder().mode(drawModes.TRIANGLES);
      var xScale = baseScale();
      var yScale = baseScale();

      var decorate = function decorate() {};

      var cornerAttribute = vertexAttribute().size(2).type(types.BYTE).data([[-1, -1], [1, 1], [-1, 1], [1, -1]]);
      program.buffers().elementIndices(elementIndices([0, 1, 2, 0, 1, 3])).attribute('aCorner', cornerAttribute);

      var draw = function draw(numElements) {
        var shaderBuilder = barShader();
        program.vertexShader(shaderBuilder.vertex()).fragmentShader(shaderBuilder.fragment());
        xScale(program, 'gl_Position', 0);
        yScale(program, 'gl_Position', 1);
        program.vertexShader().appendBody("\n            gl_Position.x += xModifier / uScreen.x * 2.0;\n        ");
        decorate(program);
        program(numElements);
      };

      draw.decorate = function () {
        if (!arguments.length) {
          return decorate;
        }

        decorate = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.xScale = function () {
        if (!arguments.length) {
          return xScale;
        }

        xScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.yScale = function () {
        if (!arguments.length) {
          return yScale;
        }

        yScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      d3fcRebind.rebind(draw, program, 'context');
      rebindCurry(draw, 'crossValueAttribute', program.buffers(), 'attribute', 'aCrossValue');
      rebindCurry(draw, 'mainValueAttribute', program.buffers(), 'attribute', 'aMainValue');
      rebindCurry(draw, 'baseValueAttribute', program.buffers(), 'attribute', 'aBaseValue');
      rebindCurry(draw, 'bandwidthAttribute', program.buffers(), 'attribute', 'aBandwidth');
      rebindCurry(draw, 'definedAttribute', program.buffers(), 'attribute', 'aDefined');
      return draw;
    });

    var errorBarShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(errorBar.header).appendBody(errorBar.body);
      fragmentShader.appendHeader(errorBar$1.header).appendBody(errorBar$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var errorBar$2 = (function () {
      var program = programBuilder().mode(drawModes.TRIANGLES);
      var xScale = baseScale();
      var yScale = baseScale();

      var decorate = function decorate() {};

      var lineWidth = lineWidthShader();
      /*
       * x-y coordinate to locate the "corners" of the element (ie errorbar). The `z` coordinate locates the corner relative to the line (this takes line width into account).
       * X: -1: LEFT, 0: MIDDLE, 1: RIGHT
       * Y: -1: HIGH, 1: LOW
       * Z: Follows X or Y convention, depending on the orientation of the line that the vertex is part of.
       */

      var cornerAttribute = vertexAttribute().size(3).type(types.BYTE).data([// Main stem
      [0, 1, 1], [0, 1, -1], [0, -1, -1], [0, -1, 1], // Top cap
      [1, -1, 1], [1, -1, -1], [-1, -1, -1], [-1, -1, 1], // Bottom cap
      [-1, 1, -1], [-1, 1, 1], [1, 1, 1], [1, 1, -1]]);
      program.buffers().elementIndices(elementIndices([// Main stem
      0, 1, 2, 0, 3, 2, // Top cap
      4, 5, 6, 4, 7, 6, // Bottom cap
      8, 9, 10, 8, 11, 10])).attribute('aCorner', cornerAttribute);

      var draw = function draw(numElements) {
        var shaderBuilder = errorBarShader();
        program.vertexShader(shaderBuilder.vertex()).fragmentShader(shaderBuilder.fragment());
        xScale(program, 'gl_Position', 0);
        yScale(program, 'gl_Position', 1);
        lineWidth(program);
        program.vertexShader().appendBody("\n                gl_Position.x += xModifier / uScreen.x * 2.0;\n                gl_Position.y += yModifier / uScreen.y * 2.0;\n            ");
        decorate(program);
        program(numElements);
      };

      draw.decorate = function () {
        if (!arguments.length) {
          return decorate;
        }

        decorate = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.xScale = function () {
        if (!arguments.length) {
          return xScale;
        }

        xScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.yScale = function () {
        if (!arguments.length) {
          return yScale;
        }

        yScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      d3fcRebind.rebind(draw, program, 'context');
      d3fcRebind.rebind(draw, lineWidth, 'lineWidth');
      rebindCurry(draw, 'crossValueAttribute', program.buffers(), 'attribute', 'aCrossValue');
      rebindCurry(draw, 'highValueAttribute', program.buffers(), 'attribute', 'aHighValue');
      rebindCurry(draw, 'lowValueAttribute', program.buffers(), 'attribute', 'aLowValue');
      rebindCurry(draw, 'bandwidthAttribute', program.buffers(), 'attribute', 'aBandwidth');
      rebindCurry(draw, 'definedAttribute', program.buffers(), 'attribute', 'aDefined');
      return draw;
    });

    var candlestickShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(candlestick.header).appendBody(candlestick.body);
      fragmentShader.appendHeader(candlestick$1.header).appendBody(candlestick$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var candlestick$2 = (function () {
      var program = programBuilder().mode(drawModes.TRIANGLES);
      var xScale = baseScale();
      var yScale = baseScale();
      var lineWidth = lineWidthShader();

      var decorate = function decorate() {};
      /*
       * x-y coordinate to locate the "corners" of the element.
       * X: -1: LEFT, 0: MIDDLE, 1: RIGHT
       * Y: -2: HIGH, -1: OPEN, 1: CLOSE, 2: LOW
       * Z: -1: LEFT, 1: RIGHT (only valid for HIGH/LOW corners)
       */


      var cornerAttribute = vertexAttribute().size(3).type(types.BYTE).data([// Vertical line
      [0, 2, 1], [0, 2, -1], [0, -2, -1], [0, -2, 1], // Central box
      [1, -1, 0], [-1, -1, 0], [-1, 1, 0], [1, 1, 0]]);
      program.buffers().elementIndices(elementIndices([// Vertical line
      0, 1, 2, 0, 3, 2, // Central box
      4, 5, 6, 4, 7, 6])).attribute('aCorner', cornerAttribute);

      var draw = function draw(numElements) {
        var shaderBuilder = candlestickShader();
        program.vertexShader(shaderBuilder.vertex()).fragmentShader(shaderBuilder.fragment());
        xScale(program, 'gl_Position', 0);
        yScale(program, 'gl_Position', 1);
        lineWidth(program);
        program.vertexShader().appendBody("\n          gl_Position.x += xModifier / uScreen.x;\n          gl_Position.y += yModifier / uScreen.y;\n        ");
        decorate(program);
        program(numElements);
      };

      draw.decorate = function () {
        if (!arguments.length) {
          return decorate;
        }

        decorate = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.xScale = function () {
        if (!arguments.length) {
          return xScale;
        }

        xScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.yScale = function () {
        if (!arguments.length) {
          return yScale;
        }

        yScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      d3fcRebind.rebind(draw, program, 'context');
      d3fcRebind.rebind(draw, lineWidth, 'lineWidth');
      rebindCurry(draw, 'crossValueAttribute', program.buffers(), 'attribute', 'aCrossValue');
      rebindCurry(draw, 'openValueAttribute', program.buffers(), 'attribute', 'aOpenValue');
      rebindCurry(draw, 'highValueAttribute', program.buffers(), 'attribute', 'aHighValue');
      rebindCurry(draw, 'lowValueAttribute', program.buffers(), 'attribute', 'aLowValue');
      rebindCurry(draw, 'closeValueAttribute', program.buffers(), 'attribute', 'aCloseValue');
      rebindCurry(draw, 'bandwidthAttribute', program.buffers(), 'attribute', 'aBandwidth');
      rebindCurry(draw, 'definedAttribute', program.buffers(), 'attribute', 'aDefined');
      return draw;
    });

    var boxPlotShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(boxPlot.header).appendBody(boxPlot.body);
      fragmentShader.appendHeader(boxPlot$1.header).appendBody(boxPlot$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    //            .------.------.
    //                   |
    //                   |
    //                   |
    //    βL2            β           βR2
    //     .-------------.------------.
    //     |                          |
    //     |                          |
    //     |                          |
    //     γL2            γ           γR2
    //     .-------------.------------.
    //     |                          |
    //     |                          |
    //     |                          |
    //    δL2            δ           δR2
    //     .-------------.------------.
    //                   |
    //                   |
    //                   |
    //           εL1     ε     εR1
    //            .------.------.
    // Line drawing order
    // αL1 -> αR1
    // α -> β
    // βL2 -> βR2
    // γL2 -> γR2
    // δL2 -> δR2
    // βL2 -> δL2
    // βR2 -> δR2
    // δ -> ε
    // εL1 -> εR1

    var boxPlot$2 = (function () {
      var program = programBuilder().mode(drawModes.TRIANGLES);
      var xScale = baseScale();
      var yScale = baseScale();

      var decorate = function decorate() {};

      var lineWidth = lineWidthShader();
      /*
       * x-y coordinate to locate the "corners" of the element (ie errorbar). The `z` coordinate locates the corner relative to the line (this takes line width into account).
       * X: -1: LEFT, 0: MIDDLE, 1: RIGHT
       * Y: -2: HIGH, -1: UPPER QUARTILE, 0: MEDIAN, 1: LOWER QUARTILE, 2: LOW
       * Z: Follows X or Y convention, depending on the orientation of the line that the vertex is part of.
       * W: Indicator to determine line orientation (needed because some corners are part of two lines). - 0: VERTICAL, 1: HORIZONTAL
       */

      var cornerAttribute = vertexAttribute().size(4).type(types.BYTE).data([// Top cap line
      [-1, -2, -1, 1], [1, -2, -1, 1], [1, -2, 1, 1], [-1, -2, 1, 1], // Top whisker line
      [0, -2, -1, 0], [0, -2, 1, 0], [0, -1, 1, 0], [0, -1, -1, 0], // Upper quartile line
      [-1, -1, -1, 1], [1, -1, -1, 1], [1, -1, 1, 1], [-1, -1, 1, 1], // Median line
      [-1, 0, -1, 1], [1, 0, -1, 1], [1, 0, 1, 1], [-1, 0, 1, 1], // Lower quartile line
      [-1, 1, -1, 1], [1, 1, -1, 1], [1, 1, 1, 1], [-1, 1, 1, 1], // Left box vertical line
      [-1, -1, -1, 0], [-1, -1, 1, 0], [-1, 1, 1, 0], [-1, 1, -1, 0], // Right box vertical line
      [1, -1, -1, 0], [1, -1, 1, 0], [1, 1, 1, 0], [1, 1, -1, 0], // Bottom whisker line
      [0, 2, -1, 0], [0, 2, 1, 0], [0, 1, 1, 0], [0, 1, -1, 0], // Bottom cap line
      [-1, 2, -1, 1], [1, 2, -1, 1], [1, 2, 1, 1], [-1, 2, 1, 1]]);
      program.buffers().elementIndices(elementIndices([// Top cap line
      0, 1, 2, 0, 2, 3, // Top whisker line
      4, 5, 6, 4, 6, 7, // Upper quartile line
      8, 9, 10, 8, 10, 11, // Median line
      12, 13, 14, 12, 14, 15, // Lower quartile line
      16, 17, 18, 16, 18, 19, // Left box vertical line
      20, 21, 22, 20, 22, 23, // Right box vertical line
      24, 25, 26, 24, 26, 27, // Bottom whisker line
      28, 29, 30, 28, 30, 31, // Bottom cap line
      32, 33, 34, 32, 34, 35])).attribute('aCorner', cornerAttribute);

      var draw = function draw(numElements) {
        var shaderBuilder = boxPlotShader();
        program.vertexShader(shaderBuilder.vertex()).fragmentShader(shaderBuilder.fragment());
        xScale(program, 'gl_Position', 0);
        yScale(program, 'gl_Position', 1);
        lineWidth(program);
        program.vertexShader().appendBody("\n            gl_Position.x += xModifier / uScreen.x * 2.0;\n            gl_Position.y += yModifier / uScreen.y * 2.0;\n        ");
        decorate(program);
        program(numElements);
      };

      draw.decorate = function () {
        if (!arguments.length) {
          return decorate;
        }

        decorate = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.xScale = function () {
        if (!arguments.length) {
          return xScale;
        }

        xScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      draw.yScale = function () {
        if (!arguments.length) {
          return yScale;
        }

        yScale = arguments.length <= 0 ? undefined : arguments[0];
        return draw;
      };

      d3fcRebind.rebind(draw, program, 'context');
      d3fcRebind.rebind(draw, lineWidth, 'lineWidth');
      rebindCurry(draw, 'crossValueAttribute', program.buffers(), 'attribute', 'aCrossValue');
      rebindCurry(draw, 'highValueAttribute', program.buffers(), 'attribute', 'aHighValue');
      rebindCurry(draw, 'upperQuartileValueAttribute', program.buffers(), 'attribute', 'aUpperQuartileValue');
      rebindCurry(draw, 'medianValueAttribute', program.buffers(), 'attribute', 'aMedianValue');
      rebindCurry(draw, 'lowerQuartileValueAttribute', program.buffers(), 'attribute', 'aLowerQuartileValue');
      rebindCurry(draw, 'lowValueAttribute', program.buffers(), 'attribute', 'aLowValue');
      rebindCurry(draw, 'bandwidthAttribute', program.buffers(), 'attribute', 'aBandwidth');
      rebindCurry(draw, 'capAttribute', program.buffers(), 'attribute', 'aCapWidth');
      rebindCurry(draw, 'definedAttribute', program.buffers(), 'attribute', 'aDefined');
      return draw;
    });

    var adjacentElementAttribute = (function () {
      var minOffset = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
      var maxOffset = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;

      if (minOffset > 0 || maxOffset < 0) {
        throw new Error("Offset values (".concat(minOffset, " & ").concat(maxOffset, ") must straddle 0 "));
      }

      var base = baseAttributeBuilder().divisor(1);
      var projector = attributeProjector();

      var adjacentAttribute = function adjacentAttribute(programBuilder) {
        var elementSize = adjacentAttribute.size() * length(adjacentAttribute.type());
        var bufferOffset = Math.abs(minOffset) * elementSize;
        base.offset(bufferOffset).size(adjacentAttribute.size()).type(adjacentAttribute.type());
        base(programBuilder);

        if (!projector.dirty()) {
          return;
        }

        var projectedData = projector();
        var bufferPadding = maxOffset * elementSize;
        var bufferLength = bufferOffset + projectedData.length * length(adjacentAttribute.type()) + bufferPadding;
        var gl = programBuilder.context();
        gl.bindBuffer(gl.ARRAY_BUFFER, base.buffer());
        gl.bufferData(gl.ARRAY_BUFFER, bufferLength, gl.DYNAMIC_DRAW);
        gl.bufferSubData(gl.ARRAY_BUFFER, bufferOffset, projectedData);
      };

      adjacentAttribute.offset = function (offset) {
        if (minOffset > offset || offset > maxOffset) {
          throw new Error("Requested offset ".concat(offset, " exceeds bounds (").concat(minOffset, " & ").concat(maxOffset, ") "));
        }

        var offsetAttribute = function offsetAttribute(programBuilder) {
          base.offset((offset - minOffset) * adjacentAttribute.size() * length(adjacentAttribute.type()));
          base(programBuilder);
        };

        d3fcRebind.rebind(offsetAttribute, base, 'location');
        d3fcRebind.rebind(offsetAttribute, adjacentAttribute, 'clear');
        return offsetAttribute;
      };

      adjacentAttribute.clear = function () {
        base.buffer(null);
        projector.clear();
      };

      d3fcRebind.rebind(adjacentAttribute, base, 'normalized', 'location');
      d3fcRebind.rebind(adjacentAttribute, projector, 'data', 'value', 'size', 'type');
      return adjacentAttribute;
    });

    var elementAttribute = (function () {
      var base = baseAttributeBuilder().divisor(1);
      var projector = attributeProjector();

      var elementAttribute = function elementAttribute(programBuilder) {
        base.size(elementAttribute.size()).type(elementAttribute.type());
        base(programBuilder);

        if (!projector.dirty()) {
          return;
        }

        var projectedData = projector();
        var gl = programBuilder.context();
        gl.bindBuffer(gl.ARRAY_BUFFER, base.buffer());
        gl.bufferData(gl.ARRAY_BUFFER, projectedData, gl.DYNAMIC_DRAW);
      };

      elementAttribute.clear = function () {
        base.buffer(null);
        projector.clear();
      };

      d3fcRebind.rebind(elementAttribute, base, 'normalized', 'location');
      d3fcRebind.rebind(elementAttribute, projector, 'data', 'value', 'size', 'type');
      return elementAttribute;
    });

    var linear = (function () {
      var base = baseScale();

      var prefix = function prefix(component) {
        return "linear".concat(component);
      };

      var scale = function scale(programBuilder, identifier, component) {
        programBuilder.vertexShader().appendHeaderIfNotExists("uniform vec4 ".concat(prefix(component), "Offset;")).appendHeaderIfNotExists("uniform vec4 ".concat(prefix(component), "Scale;")).appendBody("".concat(identifier, " = ").concat(identifier, " + ").concat(prefix(component), "Offset;")).appendBody("".concat(identifier, " = ").concat(identifier, " * ").concat(prefix(component), "Scale;"));
        var domainSize = base.domain()[1] - base.domain()[0];
        var rangeSize = base.range()[1] - base.range()[0];
        var translate = base.range()[0] * (domainSize / rangeSize) - base.domain()[0];
        var scaleFactor = rangeSize / domainSize;
        var offset = [0, 0, 0, 0];
        var scale = [1, 1, 1, 1];
        offset[component] = translate;
        scale[component] = scaleFactor;
        programBuilder.buffers().uniform("".concat(prefix(component), "Offset"), uniform(offset)).uniform("".concat(prefix(component), "Scale"), uniform(scale));
      };

      d3fcRebind.rebindAll(scale, base);
      return scale;
    });

    var log = (function () {
      var glBase = baseScale();
      var base = 10;

      function log(v, base) {
        return Math.log10(v) / Math.log10(base);
      }

      var prefix = function prefix(component) {
        return "log".concat(component);
      };

      var scale = function scale(programBuilder, identifier, component) {
        var logPart = "".concat(prefix(component), "Offset + (").concat(prefix(component), "Scale * clamp(log(").concat(identifier, ") / log(").concat(prefix(component), "Base), -inf, inf))");
        programBuilder.vertexShader().appendHeaderIfNotExists("uniform vec4 ".concat(prefix(component), "Offset;")).appendHeaderIfNotExists("uniform vec4 ".concat(prefix(component), "Scale;")).appendHeaderIfNotExists("uniform vec4 ".concat(prefix(component), "Include;")).appendHeaderIfNotExists("uniform float ".concat(prefix(component), "Base;")).appendBody("".concat(identifier, " = (").concat(prefix(component), "Include * (").concat(logPart, ")) + ((1.0 - ").concat(prefix(component), "Include) * ").concat(identifier, ");"));
        var domainSize = log(glBase.domain()[1], base) - log(glBase.domain()[0], base);
        var rangeSize = glBase.range()[1] - glBase.range()[0];
        var scaleFactor = rangeSize / domainSize;
        var translate = glBase.range()[0] - scaleFactor * log(glBase.domain()[0], base);
        var offset = [0, 0, 0, 0];
        var scale = [0, 0, 0, 0];
        var include = [0, 0, 0, 0];
        offset[component] = translate;
        scale[component] = scaleFactor;
        include[component] = 1;
        programBuilder.buffers().uniform("".concat(prefix(component), "Offset"), uniform(offset)).uniform("".concat(prefix(component), "Scale"), uniform(scale)).uniform("".concat(prefix(component), "Include"), uniform(include)).uniform("".concat(prefix(component), "Base"), uniform(base));
      };

      scale.base = function () {
        if (!arguments.length) {
          return base;
        }

        base = arguments.length <= 0 ? undefined : arguments[0];
        return scale;
      };

      d3fcRebind.rebindAll(scale, glBase);
      return scale;
    });

    var pow = (function () {
      var base = baseScale();
      var exponent = 1;

      function pow(b, e) {
        return Math.sign(b) * Math.pow(Math.abs(b), e);
      }

      var prefix = function prefix(component) {
        return "pow".concat(component);
      };

      var scale = function scale(programBuilder, identifier, component) {
        var powPart = "".concat(prefix(component), "Offset + (").concat(prefix(component), "Scale * sign(").concat(identifier, ") * pow(abs(").concat(identifier, "), vec4(").concat(prefix(component), "Exp)))");
        programBuilder.vertexShader().appendHeaderIfNotExists("uniform vec4 ".concat(prefix(component), "Offset;")).appendHeaderIfNotExists("uniform vec4 ".concat(prefix(component), "Scale;")).appendHeaderIfNotExists("uniform vec4 ".concat(prefix(component), "Include;")).appendHeaderIfNotExists("uniform float ".concat(prefix(component), "Exp;")).appendBody("".concat(identifier, " = (").concat(prefix(component), "Include * (").concat(powPart, ")) + ((1.0 - ").concat(prefix(component), "Include) * ").concat(identifier, ");"));
        var domainSize = pow(base.domain()[1], exponent) - pow(base.domain()[0], exponent);
        var rangeSize = base.range()[1] - base.range()[0];
        var scaleFactor = rangeSize / domainSize;
        var translate = base.range()[0] - scaleFactor * pow(base.domain()[0], exponent);
        var offset = [0, 0, 0, 0];
        var scale = [0, 0, 0, 0];
        var include = [0, 0, 0, 0];
        offset[component] = translate;
        scale[component] = scaleFactor;
        include[component] = 1;
        programBuilder.buffers().uniform("".concat(prefix(component), "Offset"), uniform(offset)).uniform("".concat(prefix(component), "Scale"), uniform(scale)).uniform("".concat(prefix(component), "Include"), uniform(include)).uniform("".concat(prefix(component), "Exp"), uniform(exponent));
      };

      scale.exponent = function () {
        if (!arguments.length) {
          return exponent;
        }

        exponent = arguments.length <= 0 ? undefined : arguments[0];
        return scale;
      };

      d3fcRebind.rebindAll(scale, base);
      return scale;
    });

    // determine the scale type.

    var scaleLinearCopy = d3Scale.scaleLinear().copy.toString();
    var scaleLogCopy = d3Scale.scaleLog().copy.toString();
    var scalePowCopy = d3Scale.scalePow().copy.toString();
    var scaleTimeCopy = d3Scale.scaleTime().copy.toString();
    var scaleMapper = (function (scale) {
      switch (scale.copy.toString()) {
        case scaleLinearCopy:
        case scaleTimeCopy:
          {
            return {
              scale: d3Scale.scaleIdentity(),
              webglScale: linear().domain(scale.domain())
            };
          }

        case scaleLogCopy:
          {
            return {
              scale: d3Scale.scaleIdentity(),
              webglScale: log().domain(scale.domain()).base(scale.base())
            };
          }

        case scalePowCopy:
          {
            return {
              scale: d3Scale.scaleIdentity(),
              webglScale: pow().domain(scale.domain()).exponent(scale.exponent())
            };
          }

        default:
          {
            return {
              scale: scale,
              webglScale: linear().domain(scale.range())
            };
          }
      }
    });

    var squarePointShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(square.header).appendBody(square.body);
      fragmentShader.appendHeader(square$1.header).appendBody(square$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var trianglePointShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(triangle.header).appendBody(triangle.body);
      fragmentShader.appendHeader(triangle$1.header).appendBody(triangle$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var crossPointShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(cross.header).appendBody(cross.body);
      fragmentShader.appendHeader(cross$1.header).appendBody(cross$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var diamondPointShader = (function () {
      var vertexShader = shaderBuilder(vertexShaderBase);
      var fragmentShader = shaderBuilder(fragmentShaderBase);
      vertexShader.appendHeader(diamond.header).appendBody(diamond.body);
      fragmentShader.appendHeader(diamond$1.header).appendBody(diamond$1.body);
      return {
        vertex: function vertex() {
          return vertexShader;
        },
        fragment: function fragment() {
          return fragmentShader;
        }
      };
    });

    var symbolMapper = (function (symbol) {
      switch (symbol) {
        case d3Shape.symbolCircle:
          return circlePointShader();

        case d3Shape.symbolSquare:
          return squarePointShader();

        case d3Shape.symbolTriangle:
          return trianglePointShader();

        case d3Shape.symbolCross:
          return crossPointShader();

        case d3Shape.symbolDiamond:
          return diamondPointShader();

        default:
          throw new Error("Unrecognised symbol: ".concat(symbol));
      }
    });

    var constantAttribute = (function (initialValue) {
      var base = baseAttributeBuilder().divisor(1);
      var value = initialValue;
      var dirty = true;

      var constantAttribute = function constantAttribute(programBuilder) {
        base(programBuilder);

        if (!dirty) {
          return;
        }

        if (!Array.isArray(value)) {
          throw new Error("Expected an array, received: ".concat(value));
        }

        if (value.length !== base.size()) {
          throw new Error("Expected array of length: ".concat(base.size(), ", recieved array of length: ").concat(value.length));
        }

        var gl = programBuilder.context();
        gl["vertexAttrib".concat(value.length, "fv")](base.location(), value);
        gl.disableVertexAttribArray(base.location());
        dirty = false;
      };

      constantAttribute.clear = function () {
        dirty = true;
      };

      constantAttribute.value = function () {
        if (!arguments.length) {
          return value;
        }

        value = arguments.length <= 0 ? undefined : arguments[0];
        dirty = true;
        return constantAttribute;
      };

      d3fcRebind.rebind(constantAttribute, base, 'normalized', 'size', 'location');
      return constantAttribute;
    });

    var fillColor$2 = (function () {
      var initialValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0, 0, 1];
      var attribute = elementAttribute().size(4);
      var value = initialValue;
      var dirty = true;

      var fillColor$2 = function fillColor$2(programBuilder) {
        programBuilder.vertexShader().appendHeaderIfNotExists(fillColor.header).appendBodyIfNotExists(fillColor.body);
        programBuilder.fragmentShader().appendHeaderIfNotExists(fillColor$1.header).appendBodyIfNotExists(fillColor$1.body);

        if (!dirty) {
          return;
        }

        if (Array.isArray(value)) {
          programBuilder.buffers().attribute('aFillColor', constantAttribute(value).size(4));
        } else if (typeof value === 'function') {
          attribute.value(value);
          programBuilder.buffers().attribute('aFillColor', attribute);
        } else {
          throw new Error("Expected value to be an array or function, received ".concat(value));
        }

        dirty = false;
      };

      fillColor$2.value = function () {
        if (!arguments.length) {
          return value;
        }

        if (value !== (arguments.length <= 0 ? undefined : arguments[0])) {
          value = arguments.length <= 0 ? undefined : arguments[0];
          dirty = true;
        }

        return fillColor$2;
      };

      d3fcRebind.rebind(fillColor$2, attribute, 'data');
      return fillColor$2;
    });

    var strokeColor$2 = (function () {
      var initialValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [0, 0, 0, 1];
      var attribute = elementAttribute().size(4);
      var value = initialValue;
      var dirty = true;

      var strokeColor$2 = function strokeColor$2(programBuilder) {
        programBuilder.vertexShader().appendHeaderIfNotExists(strokeColor.header).appendBodyIfNotExists(strokeColor.body);
        programBuilder.fragmentShader().appendHeaderIfNotExists(strokeColor$1.header).appendBodyIfNotExists(strokeColor$1.body);

        if (!dirty) {
          return;
        }

        if (Array.isArray(value)) {
          programBuilder.buffers().attribute('aStrokeColor', constantAttribute(value).size(4));
        } else if (typeof value === 'function') {
          attribute.value(value);
          programBuilder.buffers().attribute('aStrokeColor', attribute);
        } else {
          throw new Error("Expected value to be an array or function, received ".concat(value));
        }

        dirty = false;
      };

      strokeColor$2.value = function () {
        if (!arguments.length) {
          return value;
        }

        if (value !== (arguments.length <= 0 ? undefined : arguments[0])) {
          value = arguments.length <= 0 ? undefined : arguments[0];
          dirty = true;
        }

        return strokeColor$2;
      };

      d3fcRebind.rebind(strokeColor$2, attribute, 'data');
      return strokeColor$2;
    });

    exports.webglAdjacentElementAttribute = adjacentElementAttribute;
    exports.webglBaseAttribute = baseAttributeBuilder;
    exports.webglBufferBuilder = bufferBuilder;
    exports.webglElementAttribute = elementAttribute;
    exports.webglElementIndices = elementIndices;
    exports.webglFillColor = fillColor$2;
    exports.webglProgramBuilder = programBuilder;
    exports.webglScaleLinear = linear;
    exports.webglScaleLog = log;
    exports.webglScaleMapper = scaleMapper;
    exports.webglScalePow = pow;
    exports.webglSeriesArea = area$2;
    exports.webglSeriesBar = bar$2;
    exports.webglSeriesBoxPlot = boxPlot$2;
    exports.webglSeriesCandlestick = candlestick$2;
    exports.webglSeriesErrorBar = errorBar$2;
    exports.webglSeriesLine = line$1;
    exports.webglSeriesOhlc = ohlc$2;
    exports.webglSeriesPoint = point;
    exports.webglShaderBuilder = shaderBuilder;
    exports.webglStrokeColor = strokeColor$2;
    exports.webglSymbolMapper = symbolMapper;
    exports.webglTypes = types;
    exports.webglUniform = uniform;
    exports.webglVertexAttribute = vertexAttribute;

    Object.defineProperty(exports, '__esModule', { value: true });

}));
