Skip to content

Commit 049bcdf

Browse files
[XSG] Simplify ColorConverter (#31660)
* Simplify color converter for the XAML source generator * Fix test * Fix compilation * Bring back cast to IXmlLineInfo * Move parsing and conversion functions to ColorUtils * Use ColorUtils in the source generator * Fix default colors * Make parsing to be closer to the original implementation * Only consider public Colors fields * Fix RD test
1 parent 984ef4d commit 049bcdf

File tree

7 files changed

+522
-523
lines changed

7 files changed

+522
-523
lines changed

src/Controls/src/Core/Platform/Android/TabbedPageManager.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -734,13 +734,13 @@ int GetDefaultColor()
734734
// instead of leaving the application in a broken state
735735
if (IsDarkTheme)
736736
{
737-
defaultColor = ColorUtils.SetAlphaComponent(
737+
defaultColor = AndroidX.Core.Graphics.ColorUtils.SetAlphaComponent(
738738
ContextCompat.GetColor(_context.Context, Resource.Color.primary_dark_material_light),
739739
153); // 60% opacity
740740
}
741741
else
742742
{
743-
defaultColor = ColorUtils.SetAlphaComponent(
743+
defaultColor = AndroidX.Core.Graphics.ColorUtils.SetAlphaComponent(
744744
ContextCompat.GetColor(_context.Context, Resource.Color.primary_dark_material_dark),
745745
153); // 60% opacity
746746
}

src/Controls/src/SourceGen/Controls.SourceGen.csproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
<Compile Include="..\..\..\Core\src\Services\Crc64HashAlgorithm.cs">
5353
<Link>Crc64HashAlgorithm.cs</Link>
5454
</Compile>
55+
<Compile Include="..\..\..\Graphics\src\Graphics\ColorUtils.cs" Link="ColorUtils.cs" />
56+
<Compile Include="..\..\..\Graphics\src\Graphics\NumericExtensions.cs" Link="NumericExtensions.cs" />
5557
</ItemGroup>
5658

5759
<ItemGroup>

src/Controls/src/SourceGen/TypeConverters/ColorConverter.cs

Lines changed: 20 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,88 +5,39 @@
55
using System.Xml;
66
using Microsoft.CodeAnalysis;
77
using Microsoft.Maui.Controls.Xaml;
8+
using Microsoft.Maui.Graphics;
9+
10+
using static Microsoft.Maui.Controls.SourceGen.GeneratorHelpers;
811

912
namespace Microsoft.Maui.Controls.SourceGen.TypeConverters;
1013

1114
internal class ColorConverter : ISGTypeConverter
1215
{
13-
private static readonly HashSet<string> KnownNamedColors = new(StringComparer.OrdinalIgnoreCase)
14-
{
15-
"AliceBlue", "AntiqueWhite", "Aqua", "Aquamarine", "Azure", "Beige", "Bisque", "Black",
16-
"BlanchedAlmond", "Blue", "BlueViolet", "Brown", "BurlyWood", "CadetBlue", "Chartreuse",
17-
"Chocolate", "Coral", "CornflowerBlue", "Cornsilk", "Crimson", "Cyan", "DarkBlue",
18-
"DarkCyan", "DarkGoldenrod", "DarkGray", "DarkGreen", "DarkGrey", "DarkKhaki",
19-
"DarkMagenta", "DarkOliveGreen", "DarkOrange", "DarkOrchid", "DarkRed", "DarkSalmon",
20-
"DarkSeaGreen", "DarkSlateBlue", "DarkSlateGray", "DarkSlateGrey", "DarkTurquoise",
21-
"DarkViolet", "DeepPink", "DeepSkyBlue", "DimGray", "DimGrey", "DodgerBlue", "Firebrick",
22-
"FloralWhite", "ForestGreen", "Fuchsia", "Gainsboro", "GhostWhite", "Gold", "Goldenrod",
23-
"Gray", "Green", "GreenYellow", "Grey", "Honeydew", "HotPink", "IndianRed", "Indigo",
24-
"Ivory", "Khaki", "Lavender", "LavenderBlush", "LawnGreen", "LemonChiffon", "LightBlue",
25-
"LightCoral", "LightCyan", "LightGoldenrodYellow", "LightGray", "LightGreen", "LightGrey",
26-
"LightPink", "LightSalmon", "LightSeaGreen", "LightSkyBlue", "LightSlateGray", "LightSlateGrey",
27-
"LightSteelBlue", "LightYellow", "Lime", "LimeGreen", "Linen", "Magenta", "Maroon",
28-
"MediumAquamarine", "MediumBlue", "MediumOrchid", "MediumPurple", "MediumSeaGreen",
29-
"MediumSlateBlue", "MediumSpringGreen", "MediumTurquoise", "MediumVioletRed", "MidnightBlue",
30-
"MintCream", "MistyRose", "Moccasin", "NavajoWhite", "Navy", "OldLace", "Olive", "OliveDrab",
31-
"Orange", "OrangeRed", "Orchid", "PaleGoldenrod", "PaleGreen", "PaleTurquoise", "PaleVioletRed",
32-
"PapayaWhip", "PeachPuff", "Peru", "Pink", "Plum", "PowderBlue", "Purple", "Red", "RosyBrown",
33-
"RoyalBlue", "SaddleBrown", "Salmon", "SandyBrown", "SeaGreen", "SeaShell", "Sienna", "Silver",
34-
"SkyBlue", "SlateBlue", "SlateGray", "SlateGrey", "Snow", "SpringGreen", "SteelBlue", "Tan",
35-
"Teal", "Thistle", "Tomato", "Transparent", "Turquoise", "Violet", "Wheat", "White",
36-
"WhiteSmoke", "Yellow", "YellowGreen"
37-
};
38-
39-
// #rgb, #rrggbb, #aarrggbb are all valid
40-
private const string RxColorHexPattern = @"^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}([0-9a-fA-F]{2})?)$";
41-
private static readonly Lazy<Regex> RxColorHex = new(() => new Regex(RxColorHexPattern, RegexOptions.Compiled | RegexOptions.Singleline));
42-
43-
// RGB, RGBA, HSL, HSLA, HSV, HSVA function patterns
44-
private const string RxFuncPattern = "^(?<func>rgba|argb|rgb|hsla|hsl|hsva|hsv)\\(((?<v>\\d%?),){2}((?<v>\\d%?)|(?<v>\\d%?),(?<v>\\d%?))\\);?$";
45-
private static readonly Lazy<Regex> RxFuncExpr = new(() => new Regex(RxFuncPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline));
46-
4716
public IEnumerable<string> SupportedTypes => new[] { "Color", "Microsoft.Maui.Graphics.Color" };
4817

4918
public string Convert(string value, BaseNode node, ITypeSymbol toType, SourceGenContext context, LocalVariable? parentVar = null)
5019
{
51-
var xmlLineInfo = (IXmlLineInfo)node;
52-
if (!string.IsNullOrEmpty(value))
20+
if (ColorUtils.TryParse(value, out float red, out float green, out float blue, out float alpha))
5321
{
54-
// Any named colors are ok. Surrounding white spaces are ok. Case insensitive.
55-
var actualColorName = KnownNamedColors.FirstOrDefault(c => string.Equals(c, value.Trim(), StringComparison.OrdinalIgnoreCase));
56-
if (actualColorName is not null)
57-
{
58-
var colorsType = context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Graphics.Colors")!;
59-
return $"{colorsType.ToFQDisplayString()}.{actualColorName}";
60-
}
61-
62-
// Check for HEX Color string
63-
if (RxColorHex.Value.IsMatch(value))
64-
{
65-
var colorType = context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Graphics.Color")!;
66-
return $"{colorType.ToFQDisplayString()}.FromArgb(\"{value}\")";
67-
}
68-
69-
var match = RxFuncExpr.Value.Match(value);
70-
71-
var funcName = match?.Groups?["func"]?.Value;
72-
var funcValues = match?.Groups?["v"]?.Captures;
73-
74-
if (!string.IsNullOrEmpty(funcName) && funcValues is not null)
75-
{
76-
// ie: argb() needs 4 parameters:
77-
if (funcValues.Count == funcName?.Length)
78-
{
79-
var colorType = context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Graphics.Color")!;
80-
return $"{colorType.ToFQDisplayString()}.Parse(\"{value}\")";
81-
}
82-
}
22+
var colorType = context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Graphics.Color")!;
23+
return $"new {colorType.ToFQDisplayString()}({FormatInvariant(red)}f, {FormatInvariant(green)}f, {FormatInvariant(blue)}f, {FormatInvariant(alpha)}f) /* {value} */";
24+
}
8325

84-
// As a last resort, try Color.Parse() for any other valid color formats
85-
var colorType2 = context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Graphics.Color")!;
86-
return $"{colorType2.ToFQDisplayString()}.Parse(\"{value}\")";
26+
if (GetNamedColorField(value) is IFieldSymbol colorsField)
27+
{
28+
return $"{colorsField.ContainingType.ToFQDisplayString()}.{colorsField.Name}";
8729
}
8830

89-
context.ReportConversionFailed(xmlLineInfo, value, toType, Descriptors.ConversionFailed);
31+
context.ReportConversionFailed((IXmlLineInfo)node, value, toType, Descriptors.ConversionFailed);
9032
return "default";
33+
34+
IFieldSymbol? GetNamedColorField(string name)
35+
{
36+
return context.Compilation.GetTypeByMetadataName("Microsoft.Maui.Graphics.Colors")
37+
?.GetMembers()
38+
.OfType<IFieldSymbol>()
39+
.Where(f => f.IsPublic() && f.IsStatic && f.IsReadOnly && f.Type.ToFQDisplayString() == "global::Microsoft.Maui.Graphics.Color")
40+
.FirstOrDefault(f => string.Equals(f.Name, name, StringComparison.OrdinalIgnoreCase));
41+
}
9142
}
9243
}

src/Controls/tests/SourceGen.UnitTests/InitializeComponent/ResourceDictionary.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public partial class __TypeDBD64C1C77CDA760
3737
{
3838
private partial void InitializeComponent()
3939
{
40-
var color = global::Microsoft.Maui.Graphics.Color.FromArgb("#FF4B14");
40+
var color = new global::Microsoft.Maui.Graphics.Color(1f, 0.29411766f, 0.078431375f, 1f) /* #FF4B14 */;
4141
global::Microsoft.Maui.VisualDiagnostics.RegisterSourceInfo(color!, new global::System.Uri(@"Styles.xaml;assembly=SourceGeneratorDriver.Generated", global::System.UriKind.Relative), 6, 4);
4242
var __root = this;
4343
global::Microsoft.Maui.VisualDiagnostics.RegisterSourceInfo(__root!, new global::System.Uri(@"Styles.xaml;assembly=SourceGeneratorDriver.Generated", global::System.UriKind.Relative), 2, 2);

0 commit comments

Comments
 (0)