3 using System.Globalization;
4 using Xamarin.Forms.Internals;
6 namespace Xamarin.Forms
8 [Xaml.ProvideCompiled("Xamarin.Forms.Core.XamlC.ColorTypeConverter")]
9 [Xaml.TypeConversion(typeof(Color))]
10 public class ColorTypeConverter : TypeConverter
13 // HEX #rgb, #argb, #rrggbb, #aarrggbb
14 // RGB rgb(255,0,0), rgb(100%,0%,0%) values in range 0-255 or 0%-100%
15 // RGBA rgba(255, 0, 0, 0.8), rgba(100%, 0%, 0%, 0.8) opacity is 0.0-1.0
16 // HSL hsl(120, 100%, 50%) h is 0-360, s and l are 0%-100%
17 // HSLA hsla(120, 100%, 50%, .8) opacity is 0.0-1.0
18 // Predefined color case insensitive
19 public override object ConvertFromInvariantString(string value)
24 if (value.StartsWith("#", StringComparison.Ordinal))
25 return Color.FromHex(value);
27 if (value.StartsWith("rgba", StringComparison.OrdinalIgnoreCase)) {
28 var op = value.IndexOf('(');
29 var cp = value.LastIndexOf(')');
30 if (op < 0 || cp < 0 || cp < op)
31 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
32 var quad = value.Substring(op + 1, cp - op - 1).Split(',');
34 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
35 var r = ParseColorValue(quad[0], 255, acceptPercent: true);
36 var g = ParseColorValue(quad[1], 255, acceptPercent: true);
37 var b = ParseColorValue(quad[2], 255, acceptPercent: true);
38 var a = ParseOpacity(quad[3]);
39 return new Color(r, g, b, a);
42 if (value.StartsWith("rgb", StringComparison.OrdinalIgnoreCase)) {
43 var op = value.IndexOf('(');
44 var cp = value.LastIndexOf(')');
45 if (op < 0 || cp < 0 || cp < op)
46 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
47 var triplet = value.Substring(op + 1, cp - op - 1).Split(',');
48 if (triplet.Length != 3)
49 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
50 var r = ParseColorValue(triplet[0], 255, acceptPercent: true);
51 var g = ParseColorValue(triplet[1], 255, acceptPercent: true);
52 var b = ParseColorValue(triplet[2], 255, acceptPercent: true);
53 return new Color(r, g, b);
56 if (value.StartsWith("hsla", StringComparison.OrdinalIgnoreCase)) {
57 var op = value.IndexOf('(');
58 var cp = value.LastIndexOf(')');
59 if (op < 0 || cp < 0 || cp < op)
60 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
61 var quad = value.Substring(op + 1, cp - op - 1).Split(',');
63 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
64 var h = ParseColorValue(quad[0], 360, acceptPercent: false);
65 var s = ParseColorValue(quad[1], 100, acceptPercent: true);
66 var l = ParseColorValue(quad[2], 100, acceptPercent: true);
67 var a = ParseOpacity(quad[3]);
68 return Color.FromHsla(h, s, l, a);
71 if (value.StartsWith("hsl", StringComparison.OrdinalIgnoreCase)) {
72 var op = value.IndexOf('(');
73 var cp = value.LastIndexOf(')');
74 if (op < 0 || cp < 0 || cp < op)
75 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
76 var triplet = value.Substring(op + 1, cp - op - 1).Split(',');
77 if (triplet.Length != 3)
78 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
79 var h = ParseColorValue(triplet[0], 360, acceptPercent: false);
80 var s = ParseColorValue(triplet[1], 100, acceptPercent: true);
81 var l = ParseColorValue(triplet[2], 100, acceptPercent: true);
82 return Color.FromHsla(h, s, l);
85 string[] parts = value.Split('.');
86 if (parts.Length == 1 || (parts.Length == 2 && parts[0] == "Color"))
88 string color = parts[parts.Length - 1];
89 switch (color.ToLowerInvariant()) {
90 case "default": return Color.Default;
91 case "accent": return Color.Accent;
92 case "aliceblue": return Color.AliceBlue;
93 case "antiquewhite": return Color.AntiqueWhite;
94 case "aqua": return Color.Aqua;
95 case "aquamarine": return Color.Aquamarine;
96 case "azure": return Color.Azure;
97 case "beige": return Color.Beige;
98 case "bisque": return Color.Bisque;
99 case "black": return Color.Black;
100 case "blanchedalmond": return Color.BlanchedAlmond;
101 case "blue": return Color.Blue;
102 case "blueViolet": return Color.BlueViolet;
103 case "brown": return Color.Brown;
104 case "burlywood": return Color.BurlyWood;
105 case "cadetblue": return Color.CadetBlue;
106 case "chartreuse": return Color.Chartreuse;
107 case "chocolate": return Color.Chocolate;
108 case "coral": return Color.Coral;
109 case "cornflowerblue": return Color.CornflowerBlue;
110 case "cornsilk": return Color.Cornsilk;
111 case "crimson": return Color.Crimson;
112 case "cyan": return Color.Cyan;
113 case "darkblue": return Color.DarkBlue;
114 case "darkcyan": return Color.DarkCyan;
115 case "darkgoldenrod": return Color.DarkGoldenrod;
116 case "darkgray": return Color.DarkGray;
117 case "darkgreen": return Color.DarkGreen;
118 case "darkkhaki": return Color.DarkKhaki;
119 case "darkmagenta": return Color.DarkMagenta;
120 case "darkolivegreen": return Color.DarkOliveGreen;
121 case "darkorange": return Color.DarkOrange;
122 case "darkorchid": return Color.DarkOrchid;
123 case "darkred": return Color.DarkRed;
124 case "darksalmon": return Color.DarkSalmon;
125 case "darkseagreen": return Color.DarkSeaGreen;
126 case "darkslateblue": return Color.DarkSlateBlue;
127 case "darkslategray": return Color.DarkSlateGray;
128 case "darkturquoise": return Color.DarkTurquoise;
129 case "darkviolet": return Color.DarkViolet;
130 case "deeppink": return Color.DeepPink;
131 case "deepskyblue": return Color.DeepSkyBlue;
132 case "dimgray": return Color.DimGray;
133 case "dodgerblue": return Color.DodgerBlue;
134 case "firebrick": return Color.Firebrick;
135 case "floralwhite": return Color.FloralWhite;
136 case "forestgreen": return Color.ForestGreen;
137 case "fuchsia": return Color.Fuchsia;
138 case "gainsboro": return Color.Gainsboro;
139 case "ghostwhite": return Color.GhostWhite;
140 case "gold": return Color.Gold;
141 case "goldenrod": return Color.Goldenrod;
142 case "gray": return Color.Gray;
143 case "green": return Color.Green;
144 case "greenyellow": return Color.GreenYellow;
145 case "honeydew": return Color.Honeydew;
146 case "hotpink": return Color.HotPink;
147 case "indianred": return Color.IndianRed;
148 case "indigo": return Color.Indigo;
149 case "ivory": return Color.Ivory;
150 case "khaki": return Color.Khaki;
151 case "lavender": return Color.Lavender;
152 case "lavenderblush": return Color.LavenderBlush;
153 case "lawngreen": return Color.LawnGreen;
154 case "lemonchiffon": return Color.LemonChiffon;
155 case "lightblue": return Color.LightBlue;
156 case "lightcoral": return Color.LightCoral;
157 case "lightcyan": return Color.LightCyan;
158 case "lightgoldenrodyellow": return Color.LightGoldenrodYellow;
160 case "lightgray": return Color.LightGray;
161 case "lightgreen": return Color.LightGreen;
162 case "lightpink": return Color.LightPink;
163 case "lightsalmon": return Color.LightSalmon;
164 case "lightseagreen": return Color.LightSeaGreen;
165 case "lightskyblue": return Color.LightSkyBlue;
166 case "lightslategray": return Color.LightSlateGray;
167 case "lightsteelblue": return Color.LightSteelBlue;
168 case "lightyellow": return Color.LightYellow;
169 case "lime": return Color.Lime;
170 case "limegreen": return Color.LimeGreen;
171 case "linen": return Color.Linen;
172 case "magenta": return Color.Magenta;
173 case "maroon": return Color.Maroon;
174 case "mediumaquamarine": return Color.MediumAquamarine;
175 case "mediumblue": return Color.MediumBlue;
176 case "mediumorchid": return Color.MediumOrchid;
177 case "mediumpurple": return Color.MediumPurple;
178 case "mediumseagreen": return Color.MediumSeaGreen;
179 case "mediumslateblue": return Color.MediumSlateBlue;
180 case "mediumspringgreen": return Color.MediumSpringGreen;
181 case "mediumturquoise": return Color.MediumTurquoise;
182 case "mediumvioletred": return Color.MediumVioletRed;
183 case "midnightblue": return Color.MidnightBlue;
184 case "mintcream": return Color.MintCream;
185 case "mistyrose": return Color.MistyRose;
186 case "moccasin": return Color.Moccasin;
187 case "navajowhite": return Color.NavajoWhite;
188 case "navy": return Color.Navy;
189 case "oldlace": return Color.OldLace;
190 case "olive": return Color.Olive;
191 case "olivedrab": return Color.OliveDrab;
192 case "orange": return Color.Orange;
193 case "orangered": return Color.OrangeRed;
194 case "orchid": return Color.Orchid;
195 case "palegoldenrod": return Color.PaleGoldenrod;
196 case "palegreen": return Color.PaleGreen;
197 case "paleturquoise": return Color.PaleTurquoise;
198 case "palevioletred": return Color.PaleVioletRed;
199 case "papayawhip": return Color.PapayaWhip;
200 case "peachpuff": return Color.PeachPuff;
201 case "peru": return Color.Peru;
202 case "pink": return Color.Pink;
203 case "plum": return Color.Plum;
204 case "powderblue": return Color.PowderBlue;
205 case "purple": return Color.Purple;
206 case "red": return Color.Red;
207 case "rosybrown": return Color.RosyBrown;
208 case "royalblue": return Color.RoyalBlue;
209 case "saddlebrown": return Color.SaddleBrown;
210 case "salmon": return Color.Salmon;
211 case "sandybrown": return Color.SandyBrown;
212 case "seagreen": return Color.SeaGreen;
213 case "seashell": return Color.SeaShell;
214 case "sienna": return Color.Sienna;
215 case "silver": return Color.Silver;
216 case "skyblue": return Color.SkyBlue;
217 case "slateblue": return Color.SlateBlue;
218 case "slategray": return Color.SlateGray;
219 case "snow": return Color.Snow;
220 case "springgreen": return Color.SpringGreen;
221 case "steelblue": return Color.SteelBlue;
222 case "tan": return Color.Tan;
223 case "teal": return Color.Teal;
224 case "thistle": return Color.Thistle;
225 case "tomato": return Color.Tomato;
226 case "transparent": return Color.Transparent;
227 case "turquoise": return Color.Turquoise;
228 case "violet": return Color.Violet;
229 case "wheat": return Color.Wheat;
230 case "white": return Color.White;
231 case "whitesmoke": return Color.WhiteSmoke;
232 case "yellow": return Color.Yellow;
233 case "yellowgreen": return Color.YellowGreen;
235 var field = typeof(Color).GetFields().FirstOrDefault(fi => fi.IsStatic && string.Equals(fi.Name, color, StringComparison.OrdinalIgnoreCase));
237 return (Color)field.GetValue(null);
238 var property = typeof(Color).GetProperties().FirstOrDefault(pi => string.Equals(pi.Name, color, StringComparison.OrdinalIgnoreCase) && pi.CanRead && pi.GetMethod.IsStatic);
239 if (property != null)
240 return (Color)property.GetValue(null, null);
244 throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(Color)}");
247 static double ParseColorValue(string elem, int maxValue, bool acceptPercent)
250 if (elem.EndsWith("%", StringComparison.Ordinal) && acceptPercent) {
252 elem = elem.Substring(0, elem.Length - 1);
254 return double.Parse(elem, NumberStyles.Number, CultureInfo.InvariantCulture).Clamp(0, maxValue) / maxValue;
257 static double ParseOpacity(string elem)
259 return double.Parse(elem, NumberStyles.Number, CultureInfo.InvariantCulture).Clamp(0, 1);