System.Drawing.Drawing2D.LinearGradientBrush.CyclicGradientFunction C# (CSharp) Method

CyclicGradientFunction() private method

private CyclicGradientFunction ( SizeF regionSize, PointF &start, PointF &end ) : CGFunction
regionSize SizeF
start PointF
end PointF
return CGFunction
        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;
        }