unsafe static void EvaluateCallback(IntPtr info, float *input, float *output) { GCHandle lgc = GCHandle.FromIntPtr(info); CGFunction container = (CGFunction)lgc.Target; container.evaluate(input, output); }
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; }