//Blender is a steppable Percentage object
//that uses an integer math implementation
//for blending Percentage values over integer steps (ie pixel by pixel.)


public class Blender {
    static final int N = 4; //N is the number of blending components, r,g,b,z
    
    //definitions for the default rgbz configuration
    static final int R = 0;
    static final int G = 1;
    static final int B = 2;
    static final int Z = 3;    
    
    int value[] ;	 //the current color (each component separate)
    int dv[];
    
    
    ////
    // constructor
    // This object is meant to be reused,
    //so we have separate construction and initialization
    Blender() {
	value = new int[N];
	dv    = new int[N];
    }
    
    //init the i'th component from v1 to v2  (both PctInts) 
    //over d (FracInt) steps
    public void init(int i, int v1, int v2, int d) {
	//initialize the value
	value[i] = v1;
	//find the (fracInt) increment
	dv[i] = PctInt.divFI(v2 - value[i],d);
    }
    
    //init the Blender using two Vertices, and a distance d (FracInt)
    //uses default rgbz configuration.
    public void init(Vertex3D v1, Vertex3D v2, int d) {
	int i, temp_val;
 	init(R,v1.r,v2.r,d);
 	init(G,v1.g,v2.g,d);
 	init(B,v1.b,v2.b,d);
// 	init(R,PctInt.from_float(v1.r),PctInt.from_float(v2.r),d);
// 	init(G,PctInt.from_float(v1.g),PctInt.from_float(v2.g),d);
// 	init(B,PctInt.from_float(v1.b),PctInt.from_float(v2.b),d);
 	init(Z,PctInt.from_float(v1.z),PctInt.from_float(v2.z),d);
    }
    
    //init the Blender using two Blender endpoints, and a distance d (FracInt).
    public void init(Blender B1, Blender B2, int d) {
	int i, temp_val;
	for (i=0;i<N;i++) {
	    value[i] = B1.value[i];
	    temp_val = B2.value[i];
	    //find the (PctInt) increment
	    dv[i] = PctInt.divFI(temp_val - value[i],d);
	}
    }
    
    private final void check_bounds(int i) {
	//check bounds and floor and ceiling as appropriate
	if (value[i] < 0) value[i] = 0;
	if (value[i] > PctInt.ONE) value[i] = PctInt.ONE;
    }

    //step the Blender an integer step.
    public final void step() {
	int i;
	for (i=0;i<N;i++) {
	    value[i] += dv[i];
	    check_bounds(i);
	}
    }

    
    //step a floating point number of steps
    public final void step(float f) {
	int i;
	for (i=0;i<4;i++) {
	    value[i] += PctInt.multFI(dv[i],FracInt.from_float(f));
	    check_bounds(i);
	}
    }
    
    //step a FracInt number of steps
    public final void step(int f) {
	int i;
	for (i=0;i<4;i++) {
	    value[i] += PctInt.multFI(dv[i],f);
	    check_bounds(i);
	}
    }
    
    public final int get(int i) {
	return value[i]; //PctInt!!
    }

    //specialized function to get the z portion of the 
    //defalut rgbz configuration
    public final int getZ() {
	return value[Z];
    }

    //specialized function to get packed int argb value for the rgbz blend
    public final int getARGB() {
	//put everything together:
	return ((((value[B] >>> (PctInt.BITS - 8)) & 0xff) ) |      //green
		(((value[G] >>> (PctInt.BITS - 8)) & 0xff) << 8) |  //blue
		(((value[R] >>> (PctInt.BITS - 8)) & 0xff) << 16) | //red
		(0xff << 24));                                      //alpha
    }
} 



