unsafe static void EvaluateCallback(IntPtr info, float *input, float *output)
        {
            GCHandle   lgc       = GCHandle.FromIntPtr(info);
            CGFunction container = (CGFunction)lgc.Target;

            container.evaluate(input, output);
        }
Beispiel #2
0
        public static CGShading CreateAxial(CGColorSpace colorspace, PointF start, PointF end, CGFunction function, bool extendStart, bool extendEnd)
        {
            if (colorspace == null)
                throw new ArgumentNullException ("colorspace");
            if (colorspace.Handle == IntPtr.Zero)
                throw new ObjectDisposedException ("colorspace");
            if (function == null)
                throw new ArgumentNullException ("function");
            if (function.Handle == IntPtr.Zero)
                throw new ObjectDisposedException ("function");

            return new CGShading (CGShadingCreateAxial (colorspace.Handle, start, end, function.Handle, extendStart, extendEnd));
        }
        public static CGShading CreateRadial(CGColorSpace colorspace, PointF start, float startRadius, PointF end, float endRadius,
                                             CGFunction function, bool extendStart, bool extendEnd)
        {
            if (colorspace == null)
            {
                throw new ArgumentNullException("colorspace");
            }
            if (colorspace.Handle == IntPtr.Zero)
            {
                throw new ObjectDisposedException("colorspace");
            }
            if (function == null)
            {
                throw new ArgumentNullException("function");
            }
            if (function.Handle == IntPtr.Zero)
            {
                throw new ObjectDisposedException("function");
            }

            return(new CGShading(CGShadingCreateRadial(colorspace.Handle, start, startRadius, end, endRadius,
                                                       function.Handle, extendStart, extendEnd), true));
        }
        // Based on CreateRepetingGradientFunction from cairo-quartz-surface.c
        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.
            float[] 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);

            float[] validRange = new float[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;
        }