CGFunction CyclicGradientFunction(SizeF regionSize,
ref PointF start, ref PointF end)
{
PointF mstart, mend;
double dx, dy;
int x_rep_start = 0, x_rep_end = 0;
int y_rep_start = 0, y_rep_end = 0;
int rep_start, rep_end;
// figure out how many times we'd need to repeat the gradient pattern
// to cover the whole (transformed) surface area
mstart = start;
mend = end;
dx = Math.Abs(mend.X - mstart.X);
dy = Math.Abs(mend.Y - mstart.Y);
//if (dx > 1e-6)
// Changed this to 1e-4 because of the floating point precision with 1e-6 was causing
// problems.
if (dx > 1e-4)
{
x_rep_start = (int)Math.Ceiling(Math.Min(mstart.X, mend.X) / dx);
x_rep_end = (int)Math.Ceiling((regionSize.Width - Math.Max(mstart.X, mend.X)) / dx);
if (mend.X < mstart.X)
{
int swap = x_rep_end;
x_rep_end = x_rep_start;
x_rep_start = swap;
}
}
//if (dy > 1e-6)
// Changed this to 1e-4 because of the floating point precision with 1e-6 was causing
// problems.
if (dy > 1e-4)
{
y_rep_start = (int)Math.Ceiling(Math.Min(mstart.Y, mend.Y) / dy);
y_rep_end = (int)Math.Ceiling((regionSize.Height - Math.Max(mstart.Y, mend.Y)) / dy);
if (mend.Y < mstart.Y)
{
int swap = y_rep_end;
y_rep_end = y_rep_start;
y_rep_start = swap;
}
}
rep_start = Math.Max(x_rep_start, y_rep_start);
rep_end = Math.Max(x_rep_end, y_rep_end);
// extend the line between start and end by rep_start times from the start
// and rep_end times from the end
dx = end.X - start.X;
dy = end.Y - start.Y;
start.X = start.X - (float)dx * rep_start;
start.Y = start.Y - (float)dy * rep_start;
end.X = end.X + (float)dx * rep_end;
end.Y = end.Y + (float)dy * rep_end;
// set the input range for the function -- the function knows how to
// map values outside of 0.0 .. 1.0 to that range for the type of wrap mode.
// See the CGFunctionEvaluate funtion for the mapping of values.
nfloat[] validDomain = { 0, 1 };
validDomain[0] = 0.0f - 1.0f * rep_start;
validDomain[1] = 1.0f + 1.0f * rep_end;
//Console.WriteLine("start point [0] : {0} end point [1] : {1}", start, end);
nfloat[] validRange = new nfloat[8]
{ 0, 1.0f, 0, 1.0f, 0, 1.0f, 0, 1.0f }; // R, G, B, A
CGFunction.CGFunctionEvaluate eval;
CGFunction cgf;
unsafe {
eval = GradientLerp;
//eval = DrawGradient;
cgf = new CGFunction(validDomain, validRange,
eval);
}
return cgf;
}