// VERTEX_SHADER
uniform vec2 u_start_point;
uniform vec2 u_end_point;
uniform float u_color_stops[8 * 5];
uniform int u_num_color_stops;

_OUT_ vec2 startPoint;
_OUT_ vec2 endPoint;
_OUT_ float maxDist;
_OUT_ vec2 gradient;
_OUT_ float gradientLength;
_OUT_ vec4 color_stops[8];
_OUT_ float color_offsets[8];

void main() {
  gl_Position = u_projection * u_modelview * vec4(aPosition, 0.0, 1.0);

  startPoint = (u_modelview * vec4(u_start_point, 0, 1)).xy;
  endPoint   = (u_modelview * vec4(u_end_point,   0, 1)).xy;
  maxDist    = length(endPoint - startPoint);

  // Gradient direction
  gradient = endPoint - startPoint;
  gradientLength = length(gradient);

  for (int i = 0; i < u_num_color_stops; i ++) {
    color_offsets[i] = u_color_stops[(i * 5) + 0];
    color_stops[i].r = u_color_stops[(i * 5) + 1];
    color_stops[i].g = u_color_stops[(i * 5) + 2];
    color_stops[i].b = u_color_stops[(i * 5) + 3];
    color_stops[i].a = u_color_stops[(i * 5) + 4];
  }
}

// FRAGMENT_SHADER:
#ifdef GSK_LEGACY
uniform int u_num_color_stops;
#else
uniform highp int u_num_color_stops; // Why? Because it works like this.
#endif

_IN_ vec2 startPoint;
_IN_ vec2 endPoint;
_IN_ float maxDist;
_IN_ vec2 gradient;
_IN_ float gradientLength;
_IN_ vec4 color_stops[8];
_IN_ float color_offsets[8];

void main() {
  // Position relative to startPoint
  vec2 pos = get_frag_coord() - startPoint;

  // Current pixel, projected onto the line between the start point and the end point
  // The projection will be relative to the start point!
  vec2 proj = (dot(gradient, pos) / (gradientLength * gradientLength)) * gradient;

  // Offset of the current pixel
  float offset = length(proj) / maxDist;

  vec4 color = color_stops[0];
  for (int i = 1; i < u_num_color_stops; i ++) {
    if (offset >= color_offsets[i - 1])  {
      float o = (offset - color_offsets[i - 1]) / (color_offsets[i] - color_offsets[i - 1]);
      color = mix(color_stops[i - 1], color_stops[i], clamp(o, 0.0, 1.0));
    }
  }

  /* Pre-multiply */
  color.rgb *= color.a;

  setOutputColor(color * u_alpha);
}
