/// Evolver Copyright 2000, Morgan McGuire
/// matrix@alum.mit.edu   http://graphics3d.com/matrix
import java.awt.*;

public final class ColorGradient extends ZeroArgumentOperator implements ELOperator 
{
  static ELMatrix icon = null;

  public void apply(ELMatrix argument[], ELMatrix out, ELEnvironment environment)
  {

    int width = out.getWidth();
    int height = out.getHeight();


    if ((width == 128) && (height == 128)) {
      fastApply(argument, out, environment);
      return;
    }

    checkArguments(argument);
    
    // For extra performance, pull the arrays into locals so we avoid
    // excess dereferences.
    float red[] = out.red;
    float grn[] = out.grn;
    float blu[] = out.blu;

    float xSpan = (width - 1);
    float ySpan = (width - 1);
    
    for(int y = height - 1; y >= 0; y--) {
      int i = y * width + (width - 1);
      for(int x = width - 1; x >= 0; x--) {
        red[i] = (x / xSpan) * 2.0f - 1.0f;
        blu[i] = (y / ySpan) * 2.0f - 1.0f;
        grn[i] = red[i] * 0.5f - blu[i] * 0.5f;
        i--;
      }      
    }
  }

  static float coeff[];
  static {
    coeff = new float[128];
    for(int x = 127; x >= 0; x--) {
      coeff[x] = (x / 127.0f) * 2.0f - 1.0f;
    }
  }

  public void fastApply(ELMatrix argument[], ELMatrix out, ELEnvironment environment)
  {
    int width = out.getWidth();
    int height = out.getHeight();

    if (!((width == 128) && (height == 128))) {
      throw new Error("Not available for optimization");
    }

    checkArguments(argument);
    
    final float coeff[] = this.coeff;

    // For extra performance, pull the arrays into locals so we avoid
    // excess dereferences.
    float red[] = out.red;
    float grn[] = out.grn;
    float blu[] = out.blu;

    for(int y = height - 1; y >= 0; y--) {
      int i = (y << 7) + 127;
      float b = coeff[y];
      float b2 = b * -0.5f;
      for(int x = width - 1; x >= 0; x--) {
        red[i] = coeff[x];
        blu[i] = b;
        grn[i] = red[i] * 0.5f + b2;
        i--;
      }      
    }
  }

  public String name()
  {
    return "ColorGradient";
  }

  public String description()
  {
    return "A color gradient";
  } 

  public void paintIcon(Graphics2D graphics, int x, int y, int width, int height)
  {
    if (icon == null) {
      icon = ELMatrix.alloc(width, height);
      apply(new ELMatrix[]{}, icon, null);
    }

    icon.drawImage(graphics, x, y, width, height);
  }

}
