Skip to content

Commit 723efc7

Browse files
authored
Merge pull request #418 from waf/fix-parser-and-registry-bugs-with-refactor
Fix ColorTool parser and registry bugs, and refactor
2 parents 2d1055d + f8f4f26 commit 723efc7

17 files changed

+883
-774
lines changed

tools/ColorTool/ColorTool/ColorScheme.cs

+58-18
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,74 @@
11
//
2-
// Copyright (C) Microsoft. All rights reserved.
2+
// Copyright (C) Microsoft. All rights reserved.
33
// Licensed under the terms described in the LICENSE file in the root of this project.
44
//
55

66
using System;
7+
using System.Drawing;
78
using System.Linq;
89

910
namespace ColorTool
1011
{
12+
/// <summary>
13+
/// Represents a colorscheme that can be applied to a console.
14+
/// </summary>
1115
public class ColorScheme
1216
{
13-
public uint[] colorTable = null;
14-
public ConsoleAttributes consoleAttributes;
17+
public ColorScheme(uint[] colorTable, ConsoleAttributes consoleAttributes)
18+
{
19+
ColorTable = colorTable;
20+
ConsoleAttributes = consoleAttributes;
21+
}
22+
23+
public uint[] ColorTable { get; }
24+
public ConsoleAttributes ConsoleAttributes { get; }
25+
26+
public ushort? ScreenColorAttributes =>
27+
CalculateBackgroundForegroundAttributes(
28+
this.ConsoleAttributes.Background,
29+
this.ConsoleAttributes.Foreground
30+
);
31+
32+
public ushort? PopupColorAttributes =>
33+
CalculateBackgroundForegroundAttributes(
34+
this.ConsoleAttributes.PopupBackground,
35+
this.ConsoleAttributes.PopupForeground
36+
);
37+
38+
public Color this[int index] => UIntToColor(ColorTable[index]);
39+
40+
private static Color UIntToColor(uint color)
41+
{
42+
byte r = (byte)(color >> 0);
43+
byte g = (byte)(color >> 8);
44+
byte b = (byte)(color >> 16);
45+
return Color.FromArgb(r, g, b);
46+
}
1547

48+
private ushort? CalculateBackgroundForegroundAttributes(uint? background, uint? foreground)
49+
{
50+
if(!(background.HasValue && foreground.HasValue))
51+
{
52+
return null;
53+
}
54+
int fgidx = this.CalculateIndex(foreground.Value);
55+
int bgidx = this.CalculateIndex(background.Value);
56+
var attributes = (ushort)(fgidx | (bgidx << 4));
57+
return attributes;
58+
}
1659

1760
public int CalculateIndex(uint value) =>
18-
colorTable.Select((color, idx) => Tuple.Create(color, idx))
61+
ColorTable.Select((color, idx) => Tuple.Create(color, idx))
1962
.OrderBy(Difference(value))
2063
.First().Item2;
2164

2265
private static Func<Tuple<uint, int>, double> Difference(uint c1) =>
23-
// heuristic 1: nearest neighbor in RGB space
24-
// tup => Distance(RGB(c1), RGB(tup.Item1));
25-
// heuristic 2: nearest neighbor in RGB space
26-
// tup => Distance(HSV(c1), HSV(tup.Item1));
27-
// heuristic 3: weighted RGB L2 distance
28-
tup => WeightedRGBSimilarity(c1, tup.Item1);
66+
// heuristic 1: nearest neighbor in RGB space
67+
// tup => Distance(RGB(c1), RGB(tup.Item1));
68+
// heuristic 2: nearest neighbor in RGB space
69+
// tup => Distance(HSV(c1), HSV(tup.Item1));
70+
// heuristic 3: weighted RGB L2 distance
71+
tup => WeightedRGBSimilarity(c1, tup.Item1);
2972

3073
private static double WeightedRGBSimilarity(uint c1, uint c2)
3174
{
@@ -36,9 +79,6 @@ private static double WeightedRGBSimilarity(uint c1, uint c2)
3679
return Math.Sqrt(dist[0] * (2 + rbar / 256.0) + dist[1] * 4 + dist[2] * (2 + (255 - rbar) / 256.0));
3780
}
3881

39-
private static double Distance(uint[] c1c, uint[] c2c)
40-
=> Math.Sqrt(c1c.Zip(c2c, (a, b) => Math.Pow((int)a - (int)b, 2)).Sum());
41-
4282
internal static uint[] RGB(uint c) => new[] { c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF };
4383

4484
internal static uint[] HSV(uint c)
@@ -77,17 +117,17 @@ internal void Dump()
77117

78118
for (int i = 0; i < 16; ++i)
79119
{
80-
_dump($"Color[{i}]", colorTable[i]);
120+
_dump($"Color[{i}]", ColorTable[i]);
81121
}
82122

83-
if (consoleAttributes.foreground != null)
123+
if (ConsoleAttributes.Foreground != null)
84124
{
85-
_dump("FG ", consoleAttributes.foreground.Value);
125+
_dump("FG ", ConsoleAttributes.Foreground.Value);
86126
}
87127

88-
if (consoleAttributes.background != null)
128+
if (ConsoleAttributes.Background != null)
89129
{
90-
_dump("BG ", consoleAttributes.background.Value);
130+
_dump("BG ", ConsoleAttributes.Background.Value);
91131
}
92132
}
93133
}
+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
//
2+
// Copyright (C) Microsoft. All rights reserved.
3+
// Licensed under the terms described in the LICENSE file in the root of this project.
4+
//
5+
6+
using System;
7+
using System.Collections.Generic;
8+
9+
namespace ColorTool
10+
{
11+
/// <summary>
12+
/// Displays the color table that demonstrates the current colorscheme.
13+
/// </summary>
14+
static class ColorTable
15+
{
16+
private const int DarkBlack = 0;
17+
private const int DarkBlue = 1;
18+
private const int DarkGreen = 2;
19+
private const int DarkCyan = 3;
20+
private const int DarkRed = 4;
21+
private const int DarkMagenta = 5;
22+
private const int DarkYellow = 6;
23+
private const int DarkWhite = 7;
24+
private const int BrightBlack = 8;
25+
private const int BrightBlue = 9;
26+
private const int BrightGreen = 10;
27+
private const int BrightCyan = 11;
28+
private const int BrightRed = 12;
29+
private const int BrightMagenta = 13;
30+
private const int BrightYellow = 14;
31+
private const int BrightWhite = 15;
32+
33+
// This is the order of colors when output by the table.
34+
private static readonly IReadOnlyList<int> Foregrounds = new[]
35+
{
36+
BrightWhite,
37+
DarkBlack,
38+
BrightBlack,
39+
DarkRed,
40+
BrightRed,
41+
DarkGreen,
42+
BrightGreen,
43+
DarkYellow,
44+
BrightYellow,
45+
DarkBlue,
46+
BrightBlue,
47+
DarkMagenta,
48+
BrightMagenta,
49+
DarkCyan,
50+
BrightCyan,
51+
DarkWhite,
52+
BrightWhite
53+
};
54+
55+
private static readonly IReadOnlyList<int> Backgrounds = new[]
56+
{
57+
DarkBlack,
58+
DarkRed,
59+
DarkGreen,
60+
DarkYellow,
61+
DarkBlue,
62+
DarkMagenta,
63+
DarkCyan,
64+
DarkWhite
65+
};
66+
67+
private const string TestText = " gYw ";
68+
69+
private static readonly IReadOnlyList<string> AnsiForegroundSequences = new[]
70+
{
71+
"m",
72+
"1m",
73+
"30m",
74+
"1;30m",
75+
"31m",
76+
"1;31m",
77+
"32m",
78+
"1;32m",
79+
"33m",
80+
"1;33m",
81+
"34m",
82+
"1;34m",
83+
"35m",
84+
"1;35m",
85+
"36m",
86+
"1;36m",
87+
"37m",
88+
"1;37m"
89+
};
90+
91+
private static readonly IReadOnlyList<string> AnsiBackgroundSequences = new[]
92+
{
93+
"m",
94+
"40m",
95+
"41m",
96+
"42m",
97+
"43m",
98+
"44m",
99+
"45m",
100+
"46m",
101+
"47m"
102+
};
103+
104+
public static void PrintTable()
105+
{
106+
ConsoleColor[] colors = (ConsoleColor[])ConsoleColor.GetValues(typeof(ConsoleColor));
107+
// Save the current background and foreground colors.
108+
ConsoleColor currentBackground = Console.BackgroundColor;
109+
ConsoleColor currentForeground = Console.ForegroundColor;
110+
111+
Console.Write("\t");
112+
for (int bg = 0; bg < AnsiBackgroundSequences.Count; bg++)
113+
{
114+
if (bg > 0) Console.Write(" ");
115+
Console.Write(" ");
116+
Console.Write(bg == 0 ? " " : AnsiBackgroundSequences[bg]);
117+
Console.Write(" ");
118+
}
119+
Console.WriteLine();
120+
121+
for (int fg = 0; fg < AnsiForegroundSequences.Count; fg++)
122+
{
123+
Console.ForegroundColor = currentForeground;
124+
Console.BackgroundColor = currentBackground;
125+
126+
if (fg >= 0) Console.Write(AnsiForegroundSequences[fg] + "\t");
127+
128+
if (fg == 0) Console.ForegroundColor = currentForeground;
129+
else Console.ForegroundColor = colors[Foregrounds[fg - 1]];
130+
131+
for (int bg = 0; bg < AnsiBackgroundSequences.Count; bg++)
132+
{
133+
if (bg > 0) Console.Write(" ");
134+
if (bg == 0)
135+
Console.BackgroundColor = currentBackground;
136+
else Console.BackgroundColor = colors[Backgrounds[bg - 1]];
137+
Console.Write(TestText);
138+
Console.BackgroundColor = currentBackground;
139+
}
140+
Console.Write("\n");
141+
}
142+
Console.Write("\n");
143+
144+
// Reset foreground and background colors
145+
Console.ForegroundColor = currentForeground;
146+
Console.BackgroundColor = currentBackground;
147+
}
148+
149+
public static void PrintTableWithVt()
150+
{
151+
Console.Write("\t");
152+
for (int bg = 0; bg < AnsiBackgroundSequences.Count; bg++)
153+
{
154+
if (bg > 0) Console.Write(" ");
155+
Console.Write(" ");
156+
Console.Write(bg == 0 ? " " : AnsiBackgroundSequences[bg]);
157+
Console.Write(" ");
158+
}
159+
Console.WriteLine();
160+
161+
for (int fg = 0; fg < AnsiForegroundSequences.Count; fg++)
162+
{
163+
Console.Write("\x1b[m");
164+
165+
if (fg >= 0)
166+
{
167+
Console.Write(AnsiForegroundSequences[fg] + "\t");
168+
}
169+
170+
if (fg == 0)
171+
{
172+
Console.Write("\x1b[39m");
173+
}
174+
else
175+
{
176+
Console.Write("\x1b[" + AnsiForegroundSequences[fg]);
177+
}
178+
179+
for (int bg = 0; bg < AnsiBackgroundSequences.Count; bg++)
180+
{
181+
if (bg > 0)
182+
{
183+
Console.Write(" ");
184+
}
185+
if (bg == 0)
186+
{
187+
Console.Write("\x1b[49m");
188+
}
189+
else
190+
{
191+
Console.Write("\x1b[" + AnsiBackgroundSequences[bg]);
192+
}
193+
194+
Console.Write(TestText);
195+
Console.Write("\x1b[49m");
196+
}
197+
Console.Write("\n");
198+
}
199+
Console.Write("\n");
200+
201+
// Reset foreground and background colors
202+
Console.Write("\x1b[m");
203+
}
204+
}
205+
}

tools/ColorTool/ColorTool/ColorTool.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFramework>net46</TargetFramework>
5+
<TargetFramework>net461</TargetFramework>
66
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
7+
<LangVersion>latest</LangVersion>
78
</PropertyGroup>
89
</Project>

tools/ColorTool/ColorTool/ConsoleAPI.cs

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// Copyright (C) Microsoft. All rights reserved.
2+
// Copyright (C) Microsoft. All rights reserved.
33
// Licensed under the terms described in the LICENSE file in the root of this project.
44
//
55

@@ -8,9 +8,11 @@
88

99
namespace ColorTool
1010
{
11-
class ConsoleAPI
11+
static class ConsoleAPI
1212
{
13-
////////////////////////////////////////////////////////////////////////
13+
private const int StdOutputHandle = -11;
14+
public const int ColorTableSize = 16;
15+
1416
[StructLayout(LayoutKind.Sequential)]
1517
public struct COORD
1618
{
@@ -58,7 +60,7 @@ public static CONSOLE_SCREEN_BUFFER_INFO_EX Create()
5860
}
5961
}
6062

61-
public static int STD_OUTPUT_HANDLE = -11;
63+
public static IntPtr GetStdOutputHandle() => GetStdHandle(StdOutputHandle);
6264

6365
[DllImport("kernel32.dll", SetLastError = true)]
6466
public static extern IntPtr GetStdHandle(int nStdHandle);
@@ -83,13 +85,10 @@ IntPtr lpReserved
8385

8486
[DllImport("kernel32.dll", SetLastError = true)]
8587
public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
86-
////////////////////////////////////////////////////////////////////////
8788

8889
public static uint RGB(int r, int g, int b)
8990
{
9091
return (uint)r + (((uint)g) << 8) + (((uint)b) << 16);
9192
}
92-
93-
public const int COLOR_TABLE_SIZE = 16;
9493
}
9594
}

0 commit comments

Comments
 (0)