Skip to content

Commit a86158e

Browse files
committed
Move functions around so it makes more sense, rebase
1 parent e9b2e20 commit a86158e

File tree

2 files changed

+91
-91
lines changed

2 files changed

+91
-91
lines changed

src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Knowncolors.cs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -226,26 +226,6 @@ public static SolidColorBrush SolidColorBrushFromUint(uint argb)
226226

227227
return scp;
228228
}
229-
230-
/// <summary>
231-
/// Matches the input string against known color formats.
232-
/// </summary>
233-
/// <param name="colorString">The color string to categorize.</param>
234-
/// <returns>A <see cref="ColorKind"/> specifying the input string format.</returns>
235-
/// <remarks><see cref="ColorKind.KnownColor"/> is used as a fallback value.</remarks>
236-
internal static ColorKind MatchColor(ReadOnlySpan<char> colorString)
237-
{
238-
if ((colorString.Length is 4 or 5 or 7 or 9) && (colorString[0] == '#'))
239-
return ColorKind.NumericColor;
240-
241-
if (colorString.StartsWith("sc#", StringComparison.Ordinal))
242-
return ColorKind.ScRgbColor;
243-
244-
if (colorString.StartsWith(Parsers.ContextColor, StringComparison.OrdinalIgnoreCase))
245-
return ColorKind.ContextColor;
246-
247-
return ColorKind.KnownColor;
248-
}
249229
#endif
250230

251231
/// <summary>

src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Parsers.cs

Lines changed: 91 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ namespace MS.Internal;
1111
/// </summary>
1212
internal static partial class Parsers
1313
{
14+
/// <summary>
15+
/// The prefix for any <see cref="ColorKind.ContextColor"/> format.
16+
/// </summary>
17+
private const string ContextColor = "ContextColor ";
18+
1419
/// <summary>
1520
/// Map from an ASCII char to its hex value, e.g. arr['b'] == 11. 0xFF means it's not a hex digit.
1621
/// </summary>
@@ -83,75 +88,24 @@ private static Color ParseHexColor(ReadOnlySpan<char> trimmedColor)
8388
return Color.FromArgb((byte)a, (byte)r, (byte)g, (byte)b);
8489
}
8590

86-
internal const string ContextColor = "ContextColor ";
87-
88-
private static Color ParseContextColor(ReadOnlySpan<char> trimmedColor, IFormatProvider formatProvider, ITypeDescriptorContext context)
89-
{
90-
if (!trimmedColor.StartsWith(ContextColor, StringComparison.OrdinalIgnoreCase))
91-
throw new FormatException(SR.Parsers_IllegalToken);
92-
93-
// Skip "ContextColor " prefix
94-
ReadOnlySpan<char> tokens = trimmedColor.Slice(ContextColor.Length).Trim();
95-
96-
// Check whether the format is at least e.g. "file://profile.icc 1.0"
97-
Span<Range> splitSegments = stackalloc Range[4];
98-
99-
if (tokens.Split(splitSegments, ' ') < 2)
100-
throw new FormatException(SR.Parsers_IllegalToken);
101-
102-
// Retrieve "file://profile.icc" part
103-
string profileString = tokens[splitSegments[0]].ToString();
104-
// Skip "file://profile.icc" part
105-
ReadOnlySpan<char> colorPart = tokens.Slice(profileString.Length);
106-
107-
// Retrieve alpha value
108-
ValueTokenizerHelper tokenizer = new(colorPart, formatProvider);
109-
float alpha = float.Parse(tokenizer.NextTokenRequired(), formatProvider);
110-
111-
// While we do not support colors with more than 8 channels, the underlying initialization code will take care of it,
112-
// so here we just silently count the color values and let it throw NotImplementedException in the color translation code-path.
113-
int numTokens = colorPart.Count(',');
114-
Span<float> values = stackalloc float[numTokens];
115-
116-
for (int i = 0; i < values.Length; i++)
117-
values[i] = float.Parse(tokenizer.NextTokenRequired(), formatProvider);
118-
119-
UriHolder uriHolder = TypeConverterHelper.GetUriFromUriContext(context, profileString);
120-
Uri profileUri = uriHolder.BaseUri is not null ? new Uri(uriHolder.BaseUri, uriHolder.OriginalUri) : uriHolder.OriginalUri;
121-
122-
// If the number of color values found does not match the number of channels in the profile, FromAValues will throw
123-
return Color.FromAValues(alpha, values, profileUri);
124-
}
125-
126-
private static Color ParseScRgbColor(ReadOnlySpan<char> trimmedColor, IFormatProvider formatProvider)
91+
/// <summary>
92+
/// Matches the input string against known color formats.
93+
/// </summary>
94+
/// <param name="colorString">The color string to categorize.</param>
95+
/// <returns>A <see cref="ColorKind"/> specifying the input string format.</returns>
96+
/// <remarks><see cref="ColorKind.KnownColor"/> is used as a fallback value.</remarks>
97+
private static ColorKind MatchColor(ReadOnlySpan<char> colorString)
12798
{
128-
if (!trimmedColor.StartsWith("sc#", StringComparison.Ordinal))
129-
throw new FormatException(SR.Parsers_IllegalToken);
99+
if ((colorString.Length is 4 or 5 or 7 or 9) && (colorString[0] == '#'))
100+
return ColorKind.NumericColor;
130101

131-
// Skip prefix (sc#)
132-
ReadOnlySpan<char> tokens = trimmedColor.Slice(3);
102+
if (colorString.StartsWith("sc#", StringComparison.Ordinal))
103+
return ColorKind.ScRgbColor;
133104

134-
// The tokenizer helper will tokenize a list based on the IFormatProvider.
135-
ValueTokenizerHelper tokenizer = new(tokens, formatProvider);
136-
Span<float> values = stackalloc float[4];
105+
if (colorString.StartsWith(ContextColor, StringComparison.OrdinalIgnoreCase))
106+
return ColorKind.ContextColor;
137107

138-
for (int i = 0; i < 3; i++)
139-
values[i] = float.Parse(tokenizer.NextTokenRequired(), formatProvider);
140-
141-
if (tokenizer.NextToken())
142-
{
143-
values[3] = float.Parse(tokenizer.GetCurrentToken(), formatProvider);
144-
145-
// We should be out of tokens at this point
146-
if (tokenizer.NextToken())
147-
{
148-
throw new FormatException(SR.Parsers_IllegalToken);
149-
}
150-
151-
return Color.FromScRgb(values[0], values[1], values[2], values[3]);
152-
}
153-
154-
return Color.FromScRgb(1.0f, values[0], values[1], values[2]);
108+
return ColorKind.KnownColor;
155109
}
156110

157111
/// <summary>
@@ -173,7 +127,7 @@ internal static Color ParseColor(string color, IFormatProvider formatProvider)
173127
internal static Color ParseColor(string color, IFormatProvider formatProvider, ITypeDescriptorContext context)
174128
{
175129
ReadOnlySpan<char> trimmedColor = color.AsSpan().Trim();
176-
ColorKind colorKind = KnownColors.MatchColor(trimmedColor);
130+
ColorKind colorKind = MatchColor(trimmedColor);
177131

178132
// Check that our assumption stays true
179133
Debug.Assert(colorKind is ColorKind.NumericColor or ColorKind.ContextColor or ColorKind.ScRgbColor or ColorKind.KnownColor);
@@ -193,18 +147,16 @@ internal static Color ParseColor(string color, IFormatProvider formatProvider, I
193147
}
194148

195149
/// <summary>
196-
/// ParseBrush
197-
/// <param name="brush"> string with brush description </param>
198-
/// <param name="formatProvider">IFormatProvider for processing string</param>
199-
/// <param name="context">ITypeDescriptorContext</param>
150+
/// Parses a brush from the <paramref name="brush"/> string. This is in essence same as <see cref="ParseColor"/>,
151+
/// but instead of getting a <see cref="Color"/> out, you get a <see cref="SolidColorBrush"/> instance.
200152
/// </summary>
201153
internal static Brush ParseBrush(string brush, IFormatProvider formatProvider, ITypeDescriptorContext context)
202154
{
203155
ReadOnlySpan<char> trimmedColor = brush.AsSpan().Trim();
204156
if (trimmedColor.IsEmpty)
205157
throw new FormatException(SR.Parser_Empty);
206158

207-
ColorKind colorKind = KnownColors.MatchColor(trimmedColor);
159+
ColorKind colorKind = MatchColor(trimmedColor);
208160

209161
// Check that our assumption stays true
210162
Debug.Assert(colorKind is ColorKind.NumericColor or ColorKind.ContextColor or ColorKind.ScRgbColor or ColorKind.KnownColor);
@@ -227,6 +179,74 @@ internal static Brush ParseBrush(string brush, IFormatProvider formatProvider, I
227179
return solidColorBrush is not null ? solidColorBrush : throw new FormatException(SR.Parsers_IllegalToken);
228180
}
229181

182+
private static Color ParseContextColor(ReadOnlySpan<char> trimmedColor, IFormatProvider formatProvider, ITypeDescriptorContext context)
183+
{
184+
if (!trimmedColor.StartsWith(ContextColor, StringComparison.OrdinalIgnoreCase))
185+
throw new FormatException(SR.Parsers_IllegalToken);
186+
187+
// Skip "ContextColor " prefix
188+
ReadOnlySpan<char> tokens = trimmedColor.Slice(ContextColor.Length).Trim();
189+
190+
// Check whether the format is at least e.g. "file://profile.icc 1.0"
191+
Span<Range> splitSegments = stackalloc Range[4];
192+
193+
if (tokens.Split(splitSegments, ' ') < 2)
194+
throw new FormatException(SR.Parsers_IllegalToken);
195+
196+
// Retrieve "file://profile.icc" part
197+
string profileString = tokens[splitSegments[0]].ToString();
198+
// Skip "file://profile.icc" part
199+
ReadOnlySpan<char> colorPart = tokens.Slice(profileString.Length);
200+
201+
// Retrieve alpha value
202+
ValueTokenizerHelper tokenizer = new(colorPart, formatProvider);
203+
float alpha = float.Parse(tokenizer.NextTokenRequired(), formatProvider);
204+
205+
// While we do not support colors with more than 8 channels, the underlying initialization code will take care of it,
206+
// so here we just silently count the color values and let it throw NotImplementedException in the color translation code-path.
207+
int numTokens = colorPart.Count(',');
208+
Span<float> values = stackalloc float[numTokens];
209+
210+
for (int i = 0; i < values.Length; i++)
211+
values[i] = float.Parse(tokenizer.NextTokenRequired(), formatProvider);
212+
213+
UriHolder uriHolder = TypeConverterHelper.GetUriFromUriContext(context, profileString);
214+
Uri profileUri = uriHolder.BaseUri is not null ? new Uri(uriHolder.BaseUri, uriHolder.OriginalUri) : uriHolder.OriginalUri;
215+
216+
// If the number of color values found does not match the number of channels in the profile, FromAValues will throw
217+
return Color.FromAValues(alpha, values, profileUri);
218+
}
219+
220+
private static Color ParseScRgbColor(ReadOnlySpan<char> trimmedColor, IFormatProvider formatProvider)
221+
{
222+
if (!trimmedColor.StartsWith("sc#", StringComparison.Ordinal))
223+
throw new FormatException(SR.Parsers_IllegalToken);
224+
225+
// Skip prefix (sc#)
226+
ReadOnlySpan<char> tokens = trimmedColor.Slice(3);
227+
228+
// The tokenizer helper will tokenize a list based on the IFormatProvider.
229+
ValueTokenizerHelper tokenizer = new(tokens, formatProvider);
230+
Span<float> values = stackalloc float[4];
231+
232+
for (int i = 0; i < 3; i++)
233+
values[i] = float.Parse(tokenizer.NextTokenRequired(), formatProvider);
234+
235+
if (tokenizer.NextToken())
236+
{
237+
values[3] = float.Parse(tokenizer.GetCurrentToken(), formatProvider);
238+
239+
// We should be out of tokens at this point
240+
if (tokenizer.NextToken())
241+
{
242+
throw new FormatException(SR.Parsers_IllegalToken);
243+
}
244+
245+
return Color.FromScRgb(values[0], values[1], values[2], values[3]);
246+
}
247+
248+
return Color.FromScRgb(1.0f, values[0], values[1], values[2]);
249+
}
230250

231251
/// <summary>
232252
/// ParseTransform - parse a Transform from a string

0 commit comments

Comments
 (0)