static void GradientColour(double z, Gradient grad, out double r, out double g, out double b, out double a) { r = g = b = a = 0; if (grad == null) { return; } z = Math.Min(1.0, Math.Max(0.0, z)); var seg = GetSegmentAt(grad, z); double middle, factor = 0; double seglen = seg.right - seg.left; if (seglen < double.Epsilon) { middle = 0.5; z = 0.5; } else { middle = (seg.middle - seg.left) / seglen; z = (z - seg.left) / seglen; } switch (seg.type) { case GradType.Linear: factor = CalcLinearFactor(middle, z); break; case GradType.Curved: if (middle < double.Epsilon) { middle = double.Epsilon; } factor = Math.Pow(z, Math.Log(0.5) / Math.Log(middle)); break; case GradType.Sine: z = CalcLinearFactor(middle, z); factor = (Math.Sin((-Math.PI / 2.0) + Math.PI * z) + 1.0) / 2.0; break; case GradType.SphereInc: z = CalcLinearFactor(middle, z) - 1.0; factor = Math.Sqrt(1.0 - z * z); break; case GradType.SphereDec: z = CalcLinearFactor(middle, z); factor = 1.0 - Math.Sqrt(1.0 - z * z); break; default: throw new ArgumentException("Corrupt gradient"); } a = seg.a0 + (seg.a1 - seg.a0) * factor; if (seg.color == GradColor.RGB) { r = seg.r0 + (seg.r1 - seg.r0) * factor; g = seg.g0 + (seg.g1 - seg.g0) * factor; b = seg.b0 + (seg.b1 - seg.b0) * factor; } else { double h0, s0, v0; ColorHelpers.RGBtoHSV(seg.r0, seg.g0, seg.b0, out h0, out s0, out v0); double h1, s1, v1; ColorHelpers.RGBtoHSV(seg.r1, seg.g1, seg.b1, out h1, out s1, out v1); s0 = s0 + (s1 - s0) * factor; v0 = v0 + (v1 - v0) * factor; switch (seg.color) { case GradColor.HSVccw: if (h0 < h1) { h0 = h0 + (h1 - h0) * factor; } else { h0 = h0 + (1.0 - (h0 - h1)) * factor; if (h0 > 1.0) { h0 -= 1.0; } } break; case GradColor.HSVcw: if (h1 < h0) { h0 = h0 - (h0 - h1) * factor; } else { h0 = h0 - (1.0 - (h1 - h0)) * factor; if (h0 < 0.0) { h0 += 1.0; } } break; default: throw new ArgumentException("unknown colour model"); } ColorHelpers.HSVtoRGB(h0, s0, v0, out r, out g, out b); } }
static GradSegment ParseSeg(string line) { int element = 0; StringBuilder chunk = new StringBuilder(); double num = double.NaN; GradSegment seg = new GradSegment(); line += " "; foreach (char c in line) { if (!char.IsWhiteSpace(c)) { chunk.Append(c); continue; } double.TryParse(chunk.ToString(), out num); if (double.IsInfinity(num) || double.IsNaN(num)) { throw new ArgumentOutOfRangeException("unexpected value found"); } switch (element) { case 00: seg.left = num; break; case 01: seg.middle = num; break; case 02: seg.right = num; break; case 03: seg.r0 = num; break; case 04: seg.g0 = num; break; case 05: seg.b0 = num; break; case 06: seg.a0 = num; break; case 07: seg.r1 = num; break; case 08: seg.g1 = num; break; case 09: seg.b1 = num; break; case 10: seg.a1 = num; break; case 11: seg.type = (GradType)((int)num); break; case 12: seg.color = (GradColor)((int)num); break; } chunk.Clear(); element++; } if (seg.color == GradColor.HSVshort || seg.color == GradColor.HSVlong) { double h0, s0, v0, h1, s1, v1; ColorHelpers.RGBtoHSV(seg.r0, seg.g0, seg.b0, out h0, out s0, out v0); ColorHelpers.RGBtoHSV(seg.r1, seg.g1, seg.b1, out h1, out s1, out v1); seg.color = GradHSVType(seg.color, h0, h1); } if (!Enum.IsDefined(typeof(GradColor), seg.color)) { throw new ArgumentOutOfRangeException("unknown colour model"); } return(seg); }