private static XDocument GenerateSPColor(string newHexColor) { XDocument doc = XDocument.Parse(_baseXml); var allSlots = doc.Descendants().Where(d => d.Name.LocalName == "color").ToList(); var baseColorNode = allSlots.FirstOrDefault(n => n.FirstAttribute.Value == "AccentText"); string hexColor = baseColorNode.Attributes().Where(a => a.Name == "value").Select(a => a.Value).Single(); Color baseColor = ColorTranslator.FromHtml("#" + hexColor); Color newColor = ColorTranslator.FromHtml(newHexColor); List <string> consistentSlots = new List <string> { "ErrorText", "SearchURL", "TileText", "TileBackgroundOverlay" }; HSLColor hslBaseColor = HSLColor.FromRgbColor(baseColor); HSLColor hslNewColor = HSLColor.FromRgbColor(newColor); foreach (XElement slotColor in allSlots) { var slotHexColor = slotColor.Attributes().Where(a => a.Name == "value").Select(a => a.Value).Single(); Color currentColor = ColorTranslator.FromHtml("#" + slotHexColor); HSLColor hslCurrentColor = HSLColor.FromRgbColor(currentColor); string slotName = slotColor.Attributes().Where(a => a.Name == "name").Select(a => a.Value).Single(); if (!consistentSlots.Contains(slotName) && hslCurrentColor.Hue != 0.0 && hslCurrentColor.Saturation != 0.0) { if (ColorsEqualIgnoringOpacity(baseColor, currentColor)) { slotColor.Attributes().Single(a => a.Name == "value").Value = ColorTranslator.ToHtml(newColor).Trim('#'); } else { double hueDifference = (double)hslCurrentColor.Hue - (double)hslBaseColor.Hue; float hue = hslNewColor.Hue + (float)hueDifference; float luminance = hslNewColor.Luminance; float saturation = hslNewColor.Luminance + (hslCurrentColor.Luminance - hslBaseColor.Luminance); HSLColor hslCalcColor = new HSLColor(hue, saturation, luminance); Color calcColor = Color.FromArgb((int)currentColor.A, hslCalcColor.ToRgbColor()); slotColor.Attributes().Single(a => a.Name == "value").Value = ColorTranslator.ToHtml(calcColor).Trim('#'); } } } return(doc); }