Skip to content

Commit 42d5cfe

Browse files
committed
Use FrozenDictionary to improve searching for a known color
1 parent 41e09d8 commit 42d5cfe

File tree

4 files changed

+183
-171
lines changed

4 files changed

+183
-171
lines changed
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
using System;
2+
#if NET5_0_OR_GREATER
3+
using System.Collections.Frozen;
4+
#endif
5+
using System.Collections.Generic;
6+
7+
namespace HtmlToOpenXml;
8+
9+
/// <summary>
10+
/// Helper class to translate a named color to its ARGB representation.
11+
/// </summary>
12+
partial struct HtmlColor
13+
{
14+
private static readonly IReadOnlyDictionary<string, HtmlColor> namedColors = InitKnownColors();
15+
16+
private static HtmlColor GetNamedColor (ReadOnlySpan<char> name)
17+
{
18+
// the longest built-in Color's name is much lower than this check, so we should not allocate here in a typical usage
19+
Span<char> loweredValue = name.Length <= 128 ? stackalloc char[name.Length] : new char[name.Length];
20+
21+
name.ToLowerInvariant(loweredValue);
22+
23+
namedColors.TryGetValue(loweredValue.ToString(), out var color);
24+
return color;
25+
}
26+
27+
private static IReadOnlyDictionary<string, HtmlColor> InitKnownColors()
28+
{
29+
var colors = new Dictionary<string, HtmlColor>()
30+
{
31+
{ "black", Black },
32+
{ "white", FromArgb(255,255,255) },
33+
{ "aliceblue", FromArgb(240, 248, 255) },
34+
{ "lightsalmon", FromArgb(255, 160, 122) },
35+
{ "antiquewhite", FromArgb(250, 235, 215) },
36+
{ "lightseagreen", FromArgb(32, 178, 170) },
37+
{ "aqua", FromArgb(0, 255, 255) },
38+
{ "lightskyblue", FromArgb(135, 206, 250) },
39+
{ "aquamarine", FromArgb(127, 255, 212) },
40+
{ "lightslategray", FromArgb(119, 136, 153) },
41+
{ "azure", FromArgb(240, 255, 255) },
42+
{ "lightsteelblue", FromArgb(176, 196, 222) },
43+
{ "beige", FromArgb(245, 245, 220) },
44+
{ "lightyellow", FromArgb(255, 255, 224) },
45+
{ "bisque", FromArgb(255, 228, 196) },
46+
{ "lime", FromArgb(0, 255, 0) },
47+
{ "limegreen", FromArgb(50, 205, 50) },
48+
{ "blanchedalmond", FromArgb(255, 255, 205) },
49+
{ "linen", FromArgb(250, 240, 230) },
50+
{ "blue", FromArgb(0, 0, 255) },
51+
{ "magenta", FromArgb(255, 0, 255) },
52+
{ "blueviolet", FromArgb(138, 43, 226) },
53+
{ "maroon", FromArgb(128, 0, 0) },
54+
{ "brown", FromArgb(165, 42, 42) },
55+
{ "mediumaquamarine", FromArgb(102, 205, 170) },
56+
{ "burlywood", FromArgb(222, 184, 135) },
57+
{ "mediumblue", FromArgb(0, 0, 205) },
58+
{ "cadetblue", FromArgb(95, 158, 160) },
59+
{ "mediumprchid", FromArgb(186, 85, 211) },
60+
{ "chartreuse", FromArgb(127, 255, 0) },
61+
{ "mediumpurple", FromArgb(147, 112, 219) },
62+
{ "chocolate", FromArgb(210, 105, 30) },
63+
{ "mediumseagreen", FromArgb(60, 179, 113) },
64+
{ "coral", FromArgb(255, 127, 80) },
65+
{ "mediumslateblue", FromArgb(123, 104, 238) },
66+
{ "cornflowerblue", FromArgb(100, 149, 237) },
67+
{ "mediumspringbreen", FromArgb(0, 250, 154) },
68+
{ "cornsilk", FromArgb(255, 248, 220) },
69+
{ "mediumturquoise", FromArgb(72, 209, 204) },
70+
{ "crimson", FromArgb(220, 20, 60) },
71+
{ "mediumvioletred", FromArgb(199, 21, 112) },
72+
{ "cyan", FromArgb(0, 255, 255) },
73+
{ "midnightblue", FromArgb(25, 25, 112) },
74+
{ "darkblue", FromArgb(0, 0, 139) },
75+
{ "mintcream", FromArgb(245, 255, 250) },
76+
{ "darkcyan", FromArgb(0, 139, 139) },
77+
{ "mistyrose", FromArgb(255, 228, 225) },
78+
{ "darkgoldenrod", FromArgb(184, 134, 11) },
79+
{ "moccasin", FromArgb(255, 228, 181) },
80+
{ "darkgray", FromArgb(169, 169, 169) },
81+
{ "navajowhite", FromArgb(255, 222, 173) },
82+
{ "darkgreen", FromArgb(0, 100, 0) },
83+
{ "navy", FromArgb(0, 0, 128) },
84+
{ "darkkhaki", FromArgb(189, 183, 107) },
85+
{ "oldlace", FromArgb(253, 245, 230) },
86+
{ "darkmagenta", FromArgb(139, 0, 139) },
87+
{ "olive", FromArgb(128, 128, 0) },
88+
{ "darkolivegreen", FromArgb(85, 107, 47) },
89+
{ "olivedrab", FromArgb(107, 142, 45) },
90+
{ "darkorange", FromArgb(255, 140, 0) },
91+
{ "orange", FromArgb(255, 165, 0) },
92+
{ "darkorchid", FromArgb(153, 50, 204) },
93+
{ "orangered", FromArgb(255, 69, 0) },
94+
{ "darkred", FromArgb(139, 0, 0) },
95+
{ "orchid", FromArgb(218, 112, 214) },
96+
{ "darksalmon", FromArgb(233, 150, 122) },
97+
{ "palegoldenrod", FromArgb(238, 232, 170) },
98+
{ "darkseagreen", FromArgb(143, 188, 143) },
99+
{ "palegreen", FromArgb(152, 251, 152) },
100+
{ "darkslateblue", FromArgb(72, 61, 139) },
101+
{ "paleturquoise", FromArgb(175, 238, 238) },
102+
{ "darkslategray", FromArgb(40, 79, 79) },
103+
{ "palevioletred", FromArgb(219, 112, 147) },
104+
{ "darkturquoise", FromArgb(0, 206, 209) },
105+
{ "papayawhip", FromArgb(255, 239, 213) },
106+
{ "darkviolet", FromArgb(148, 0, 211) },
107+
{ "peachpuff", FromArgb(255, 218, 155) },
108+
{ "deeppink", FromArgb(255, 20, 147) },
109+
{ "peru", FromArgb(205, 133, 63) },
110+
{ "deepskyblue", FromArgb(0, 191, 255) },
111+
{ "pink", FromArgb(255, 192, 203) },
112+
{ "dimgray", FromArgb(105, 105, 105) },
113+
{ "plum", FromArgb(221, 160, 221) },
114+
{ "dodgerblue", FromArgb(30, 144, 255) },
115+
{ "powderblue", FromArgb(176, 224, 230) },
116+
{ "firebrick", FromArgb(178, 34, 34) },
117+
{ "purple", FromArgb(128, 0, 128) },
118+
{ "floralwhite", FromArgb(255, 250, 240) },
119+
{ "red", FromArgb(255, 0, 0) },
120+
{ "forestgreen", FromArgb(34, 139, 34) },
121+
{ "rosybrown", FromArgb(188, 143, 143) },
122+
{ "fuschia", FromArgb(255, 0, 255) },
123+
{ "royalblue", FromArgb(65, 105, 225) },
124+
{ "gainsboro", FromArgb(220, 220, 220) },
125+
{ "saddlebrown", FromArgb(139, 69, 19) },
126+
{ "ghostwhite", FromArgb(248, 248, 255) },
127+
{ "salmon", FromArgb(250, 128, 114) },
128+
{ "gold", FromArgb(255, 215, 0) },
129+
{ "sandybrown", FromArgb(244, 164, 96) },
130+
{ "goldenrod", FromArgb(218, 165, 32) },
131+
{ "seagreen", FromArgb(46, 139, 87) },
132+
{ "gray", FromArgb(128, 128, 128) },
133+
{ "seashell", FromArgb(255, 245, 238) },
134+
{ "green", FromArgb(0, 128, 0) },
135+
{ "sienna", FromArgb(160, 82, 45) },
136+
{ "greenyellow", FromArgb(173, 255, 47) },
137+
{ "silver", FromArgb(192, 192, 192) },
138+
{ "honeydew", FromArgb(240, 255, 240) },
139+
{ "skyblue", FromArgb(135, 206, 235) },
140+
{ "hotpink", FromArgb(255, 105, 180) },
141+
{ "slateblue", FromArgb(106, 90, 205) },
142+
{ "indianred", FromArgb(205, 92, 92) },
143+
{ "slategray", FromArgb(112, 128, 144) },
144+
{ "indigo", FromArgb(75, 0, 130) },
145+
{ "snow", FromArgb(255, 250, 250) },
146+
{ "ivory", FromArgb(255, 240, 240) },
147+
{ "springgreen", FromArgb(0, 255, 127) },
148+
{ "khaki", FromArgb(240, 230, 140) },
149+
{ "steelblue", FromArgb(70, 130, 180) },
150+
{ "lavender", FromArgb(230, 230, 250) },
151+
{ "tan", FromArgb(210, 180, 140) },
152+
{ "lavenderblush", FromArgb(255, 240, 245) },
153+
{ "teal", FromArgb(0, 128, 128) },
154+
{ "lawngreen", FromArgb(124, 252, 0) },
155+
{ "thistle", FromArgb(216, 191, 216) },
156+
{ "lemonchiffon", FromArgb(255, 250, 205) },
157+
{ "tomato", FromArgb(253, 99, 71) },
158+
{ "lightblue", FromArgb(173, 216, 230) },
159+
{ "turquoise", FromArgb(64, 224, 208) },
160+
{ "lightcoral", FromArgb(240, 128, 128) },
161+
{ "violet", FromArgb(238, 130, 238) },
162+
{ "lightcyan", FromArgb(224, 255, 255) },
163+
{ "wheat", FromArgb(245, 222, 179) },
164+
{ "lightgoldenrodyellow", FromArgb(250, 250, 210) },
165+
{ "lightgreen", FromArgb(144, 238, 144) },
166+
{ "whitesmoke", FromArgb(245, 245, 245) },
167+
{ "lightgray", FromArgb(211, 211, 211) },
168+
{ "yellow", FromArgb(255, 255, 0) },
169+
{ "Lightpink", FromArgb(255, 182, 193) },
170+
{ "yellowgreen", FromArgb(154, 205, 50) },
171+
{ "transparent", FromArgb(0, 0, 0, 0) }
172+
};
173+
174+
#if NET5_0_OR_GREATER
175+
return colors.ToFrozenDictionary();
176+
#else
177+
return colors;
178+
#endif
179+
}
180+
}

src/Html2OpenXml/Primitives/HtmlColor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ namespace HtmlToOpenXml;
1717
/// <summary>
1818
/// Represents an ARGB color.
1919
/// </summary>
20-
readonly struct HtmlColor : IEquatable<HtmlColor>
20+
readonly partial struct HtmlColor : IEquatable<HtmlColor>
2121
{
2222
private static readonly char[] hexDigits = {
2323
'0', '1', '2', '3', '4', '5', '6', '7',
@@ -115,7 +115,7 @@ public static HtmlColor Parse(string? htmlColor)
115115
throw;
116116
}
117117

118-
return HtmlColorTranslator.FromHtml(htmlColor);
118+
return GetNamedColor(htmlColor.AsSpan());
119119
}
120120

121121
/// <summary>

src/Html2OpenXml/Utilities/HtmlColorTranslator.cs

Lines changed: 0 additions & 168 deletions
This file was deleted.

test/HtmlToOpenXml.Tests/StyleTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public void UseVariantStyle_ReturnsAppliedStyle()
2525
Type = args.Type,
2626
BasedOn = new BasedOn { Val = "Normal" },
2727
StyleRunProperties = new() {
28-
Color = new() { Val = HtmlColorTranslator.FromHtml("red").ToHexString() }
28+
Color = new() { Val = HtmlColor.Parse("red").ToHexString() }
2929
}
3030
});
3131
};

0 commit comments

Comments
 (0)