The other day I was writing some code to create a rainbow when I realized that it would look a lot better if the color transition were gradiated and not so banded. So I wrote some code to create a gradiated box and gradiated arcs. I came to realize that I was having to repeat much of the same code for different types of things and decided to create a class that generates the gradient for me. That led to the code below.
dbGradient.h:
///////////////////////////////////
// a class for providing gradient
// colors for Dark GDK
#ifndef _DBGRADIENT_H_LAC
#define _DBGRADIENT_H_LAC
class dbGradient
{
private:
int counter;
int Span;
float redSlope;
float greenSlope;
float blueSlope;
int startRed;
int startGreen;
int startBlue;
int endRed;
int endGreen;
int endBlue;
public:
dbGradient ()
{
Span = 0;
counter = 1; // always assure that we don't
// react on bad start up
}
dbGradient (int dbStartColor, int dbEndColor, int span)
{ // user our startup call for this c'tor
Start (dbStartColor, dbEndColor, span);
}
void Start (int dbStartColor, int dbEndColor, int span);
int Next ();
int Indexed (int index);
bool Still ();
};
#endif
dbGradient.cpp
#include "dbGradient.h"
#include "DarkGDK.h"
int dbGradient::Next()
{
// if we've run out the counter, return black
if (counter > Span || counter < 0) return dbRGB (0, 0, 0)
// otherwise get the next color
int newColor = dbRGB (startRed + counter * redSlope,
startGreen + counter * greenSlope,
startBlue + counter * blueSlope);
counter++; // and set the counter for the next color
return newColor; //
}
void dbGradient::Start(int dbStartColor, int dbEndColor, int span)
{
counter = 0; // this c'tor always resets the object
Span = span; // set's maximum value for the counter
if (span < 1) Span = 1; // can't allow negative numbers here
startRed = dbRGBR (dbStartColor);
startGreen = dbRGBG (dbStartColor);
startBlue = dbRGBB (dbStartColor);
endRed = dbRGBR (dbEndColor);
endGreen = dbRGBG (dbEndColor);
endBlue = dbRGBB (dbEndColor);
redSlope = (float) (endRed - startRed) / float (span);
greenSlope = (float) (endGreen - startGreen) / float (span);
blueSlope = (float) (endBlue - startBlue) / float (span);
}
bool dbGradient::Still()
{
// if counter exceeds our span then we have nothing more to give
if (counter > Span) return false; // so return a false
return true; // otherwise return true
}
int dbGradient::Indexed (int index)
{
// return Black if outside range
if (index < 0 || index > Span) return dbRGB (0, 0, 0);
return dbRGB (startRed + counter * redSlope,
startGreen + counter * greenSlope,
startBlue + counter * blueSlope);
}
The code is predicated on the concept that there's always a starting color and an ending color with a finite number of points between them, whether they be the radius or arcs or lines in a rectangle. You begin by declaring the dbGradient object. You can also set the operating parameters at the same time as you declare the object or you can use the Start method later to assign the starting color, the ending color and the span (number of points to cover.)
dbGradient Grad;
or
dbGradient Grad (dbRed, dbGreen, 512);
In order to retrieve each successive output color in the stream you call the Next() method
int nextColor = Grad.Next();
In order to check to see if there are any more colors in the output steam you use the Still() method. It returns a true/false result depending on whether or not you reached the end of the span.
for (int i = 0; Grad.Still(); i++) {
dbInk (Grad.Next(), dbBlack);
dbLine (i, 0, i, 128); // draws a color line
}
The beauty of this method is that you can use it in a number of different situations and by judicious calculation of the span passed to the object use the object to control your loops.
I've also included an Indexed(int i) method that lets you ask for a specific point in the series if you need to be creative.
Any attempt to give dbGradient a negative number for the span will simply set the span to 1. Any attempt to exceed the span limit or provide a negative index will result in dbGradient returning the color black.
I suspect I may add a Reset() method that resets the counter to zero without resetting the colors.
Of course the above depends on having set a default bitmap.
I'll try to provide some more specific code in a later post.
Lilith, Night Butterfly