[ColorPicker]Custom color formats (#22141)

* [ColorPicker] Development: custom color formats, first steps

* ColorPicker development of custom format handling.

* Custom color format developmnet.
Added common helper class for format string
Fixed settings loading
Added numbering if default name exists   (My format (1))

* Custom color format implementation.
Extended the colorPicker settings with the format string
Updated the color to string conversion

* Custom color format in color picker, development.
Adding edit, delete buttons. Implement functionality
Re-arranging settings panel (newly created formats at the top)
Implementing details (valid parameters, more format elements, more types)

* Minor commit

* Development color picker custom formats. "Last" steps.
Replacing hard coded english strings with resources, polishing.

* Adding help to the format edit dialog.

* Undoing changes unwillingly commited in Host module

* Fixing bug unable to delete a custom format after renaming it - use the colorformat object as reference (and not the name)
Modifying the default custom formula
Removing unnecessary using directives

* Udating the default user defined color format

* Removing unnecessary using directive

* ColorPicker Implementing custom color formats: adding custom formats to the default format selection (dropdown box).

* Fix binding of name and example

* Custom color formats, implemented steps:
vorwarts compatibility loading settings.
Fixed UI as requested (removed one settings panel, added button to the first panel)

* Minor change in the UI: description modified

* ColorPicker Custom Color Formats develepoment.
Added conversion from old predefined formats to customizable formats.
Extended default settings (in case settings file is deleted/corrupted).
Minor fixes.

* Fixing color format parameters.
Implementing 3 different Saturation calculations, 2 Hue calculations and 2 Lightness calculations (depending color format)

* Color Picker: New/Edit Color format. Fixing bug when cancelling addition/edit

* ColorPicker. Updating help section, available parameters

* Fix spellchecker

* Remove the MinWidth so that scrollviewers can be drawn

* ColorPicker bugfix: Not allowing to delete the last color format.
This commit is contained in:
Laszlo Nemeth
2022-12-02 17:44:53 +01:00
committed by GitHub
parent 77dfaab17e
commit ec0fb6a4c7
35 changed files with 2324 additions and 1092 deletions

View File

@@ -0,0 +1,498 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
namespace ManagedCommon
{
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
public static class ColorFormatHelper
{
/// <summary>
/// Convert a given <see cref="Color"/> to a CMYK color (cyan, magenta, yellow, black key)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The cyan[0..1], magenta[0..1], yellow[0..1] and black key[0..1] of the converted color</returns>
public static (double cyan, double magenta, double yellow, double blackKey) ConvertToCMYKColor(Color color)
{
// special case for black (avoid division by zero)
if (color.R == 0 && color.G == 0 && color.B == 0)
{
return (0d, 0d, 0d, 1d);
}
var red = color.R / 255d;
var green = color.G / 255d;
var blue = color.B / 255d;
var blackKey = 1d - Math.Max(Math.Max(red, green), blue);
// special case for black (avoid division by zero)
if (1d - blackKey == 0d)
{
return (0d, 0d, 0d, 1d);
}
var cyan = (1d - red - blackKey) / (1d - blackKey);
var magenta = (1d - green - blackKey) / (1d - blackKey);
var yellow = (1d - blue - blackKey) / (1d - blackKey);
return (cyan, magenta, yellow, blackKey);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HSB color (hue, saturation, brightness)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], saturation [0..1] and brightness [0..1] of the converted color</returns>
public static (double hue, double saturation, double brightness) ConvertToHSBColor(Color color)
{
// HSB and HSV represents the same color space
return ConvertToHSVColor(color);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HSV color (hue, saturation, value)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], saturation [0..1] and value [0..1] of the converted color</returns>
public static (double hue, double saturation, double value) ConvertToHSVColor(Color color)
{
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
return (color.GetHue(), max == 0d ? 0d : (max - min) / max, max);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HSI color (hue, saturation, intensity)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], saturation [0..1] and intensity [0..1] of the converted color</returns>
public static (double hue, double saturation, double intensity) ConvertToHSIColor(Color color)
{
// special case for black
if (color.R == 0 && color.G == 0 && color.B == 0)
{
return (0d, 0d, 0d);
}
var red = color.R / 255d;
var green = color.G / 255d;
var blue = color.B / 255d;
var intensity = (red + green + blue) / 3d;
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
return (color.GetHue(), 1d - (min / intensity), intensity);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HSL color (hue, saturation, lightness)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], saturation [0..1] and lightness [0..1] values of the converted color</returns>
public static (double hue, double saturation, double lightness) ConvertToHSLColor(Color color)
{
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
var lightness = (max + min) / 2d;
if (lightness == 0d || min == max)
{
return (color.GetHue(), 0d, lightness);
}
else if (lightness > 0d && lightness <= 0.5d)
{
return (color.GetHue(), (max - min) / (max + min), lightness);
}
return (color.GetHue(), (max - min) / (2d - (max + min)), lightness);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a HWB color (hue, whiteness, blackness)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue [0°..360°], whiteness [0..1] and blackness [0..1] of the converted color</returns>
public static (double hue, double whiteness, double blackness) ConvertToHWBColor(Color color)
{
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
return (color.GetHue(), min, 1 - max);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a CIE LAB color (LAB)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The lightness [0..100] and two chromaticities [-128..127]</returns>
public static (double lightness, double chromaticityA, double chromaticityB) ConvertToCIELABColor(Color color)
{
var xyz = ConvertToCIEXYZColor(color);
var lab = GetCIELABColorFromCIEXYZ(xyz.x, xyz.y, xyz.z);
return lab;
}
/// <summary>
/// Convert a given <see cref="Color"/> to a CIE XYZ color (XYZ)
/// The constants of the formula matches this Wikipedia page, but at a higher precision:
/// https://en.wikipedia.org/wiki/SRGB#The_reverse_transformation_(sRGB_to_CIE_XYZ)
/// This page provides a method to calculate the constants:
/// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The X [0..1], Y [0..1] and Z [0..1]</returns>
public static (double x, double y, double z) ConvertToCIEXYZColor(Color color)
{
double r = color.R / 255d;
double g = color.G / 255d;
double b = color.B / 255d;
// inverse companding, gamma correction must be undone
double rLinear = (r > 0.04045) ? Math.Pow((r + 0.055) / 1.055, 2.4) : (r / 12.92);
double gLinear = (g > 0.04045) ? Math.Pow((g + 0.055) / 1.055, 2.4) : (g / 12.92);
double bLinear = (b > 0.04045) ? Math.Pow((b + 0.055) / 1.055, 2.4) : (b / 12.92);
return (
(rLinear * 0.41239079926595948) + (gLinear * 0.35758433938387796) + (bLinear * 0.18048078840183429),
(rLinear * 0.21263900587151036) + (gLinear * 0.71516867876775593) + (bLinear * 0.07219231536073372),
(rLinear * 0.01933081871559185) + (gLinear * 0.11919477979462599) + (bLinear * 0.95053215224966058)
);
}
/// <summary>
/// Convert a CIE XYZ color <see cref="double"/> to a CIE LAB color (LAB) adapted to sRGB D65 white point
/// The constants of the formula used come from this wikipedia page:
/// https://en.wikipedia.org/wiki/CIELAB_color_space#Converting_between_CIELAB_and_CIEXYZ_coordinates
/// </summary>
/// <param name="x">The <see cref="x"/> represents a mix of the three CIE RGB curves</param>
/// <param name="y">The <see cref="y"/> represents the luminance</param>
/// <param name="z">The <see cref="z"/> is quasi-equal to blue (of CIE RGB)</param>
/// <returns>The lightness [0..100] and two chromaticities [-128..127]</returns>
private static (double lightness, double chromaticityA, double chromaticityB)
GetCIELABColorFromCIEXYZ(double x, double y, double z)
{
// sRGB reference white (x=0.3127, y=0.3290, Y=1.0), actually CIE Standard Illuminant D65 truncated to 4 decimal places,
// then converted to XYZ using the formula:
// X = x * (Y / y)
// Y = Y
// Z = (1 - x - y) * (Y / y)
double x_n = 0.9504559270516717;
double y_n = 1.0;
double z_n = 1.0890577507598784;
// Scale XYZ values relative to reference white
x /= x_n;
y /= y_n;
z /= z_n;
// XYZ to CIELab transformation
double delta = 6d / 29;
double m = (1d / 3) * Math.Pow(delta, -2);
double t = Math.Pow(delta, 3);
double fx = (x > t) ? Math.Pow(x, 1.0 / 3.0) : (x * m) + (16.0 / 116.0);
double fy = (y > t) ? Math.Pow(y, 1.0 / 3.0) : (y * m) + (16.0 / 116.0);
double fz = (z > t) ? Math.Pow(z, 1.0 / 3.0) : (z * m) + (16.0 / 116.0);
double l = (116 * fy) - 16;
double a = 500 * (fx - fy);
double b = 200 * (fy - fz);
return (l, a, b);
}
/// <summary>
/// Convert a given <see cref="Color"/> to a natural color (hue, whiteness, blackness)
/// </summary>
/// <param name="color">The <see cref="Color"/> to convert</param>
/// <returns>The hue, whiteness [0..1] and blackness [0..1] of the converted color</returns>
public static (string hue, double whiteness, double blackness) ConvertToNaturalColor(Color color)
{
var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
return (GetNaturalColorFromHue(color.GetHue()), min, 1 - max);
}
/// <summary>
/// Return the natural color for the given hue value
/// </summary>
/// <param name="hue">The hue value to convert</param>
/// <returns>A natural color</returns>
private static string GetNaturalColorFromHue(double hue)
{
if (hue < 60d)
{
return $"R{Math.Round(hue / 0.6d, 0)}";
}
if (hue < 120d)
{
return $"Y{Math.Round((hue - 60d) / 0.6d, 0)}";
}
if (hue < 180d)
{
return $"G{Math.Round((hue - 120d) / 0.6d, 0)}";
}
if (hue < 240d)
{
return $"C{Math.Round((hue - 180d) / 0.6d, 0)}";
}
if (hue < 300d)
{
return $"B{Math.Round((hue - 240d) / 0.6d, 0)}";
}
return $"M{Math.Round((hue - 300d) / 0.6d, 0)}";
}
private static readonly Dictionary<string, char> DefaultFormatTypes = new Dictionary<string, char>()
{
{ "Re", 'b' }, // red byte
{ "Gr", 'b' }, // green byte
{ "Bl", 'b' }, // blue byte
{ "Al", 'b' }, // alpha byte
{ "Cy", 'p' }, // cyan percent
{ "Ma", 'p' }, // magenta percent
{ "Ye", 'p' }, // yellow percent
{ "Bk", 'p' }, // black key percent
{ "Hu", 'i' }, // hue int
{ "Hn", 'i' }, // hue natural string
{ "Si", 'p' }, // saturation (HSI) percent
{ "Sl", 'p' }, // saturation (HSL) percent
{ "Sb", 'p' }, // saturation (HSB) percent
{ "Br", 'p' }, // brightness percent
{ "In", 'p' }, // intensity percent
{ "Ll", 'p' }, // lightness (HSL) percent
{ "Lc", 'p' }, // lightness(CIELAB)percent
{ "Va", 'p' }, // value percent
{ "Wh", 'p' }, // whiteness percent
{ "Bn", 'p' }, // blackness percent
{ "Ca", 'p' }, // chromaticityA percent
{ "Cb", 'p' }, // chromaticityB percent
{ "Xv", 'i' }, // X value int
{ "Yv", 'i' }, // Y value int
{ "Zv", 'i' }, // Z value int
{ "Dv", 'i' }, // Decimal value int
{ "Na", 's' }, // Color name string
};
private static readonly Dictionary<char, string> FormatTypeToStringFormatters = new Dictionary<char, string>()
{
{ 'b', "b" }, // 0..255 byte
{ 'h', "x1" }, // hex lowercase one digit
{ 'H', "X1" }, // hex uppercase one digit
{ 'x', "x2" }, // hex lowercase two digits
{ 'X', "X2" }, // hex uppercase two digits
{ 'f', "0.##" }, // float with leading zero, 2 digits
{ 'F', ".##" }, // float without leading zero, 2 digits
{ 'p', "%" }, // percent value
{ 'i', "i" }, // int value
{ 's', "s" }, // string value
};
public static string GetStringRepresentation(Color? color, string formatString)
{
if (color == null)
{
color = Color.Moccasin; // example color
}
// convert all %?? expressions to strings
int formatterPosition = formatString.IndexOf('%', 0);
while (formatterPosition != -1)
{
if (formatterPosition >= formatString.Length - 2)
{
// the formatter % was the last character, we are done
break;
}
char paramFormat;
string paramType = formatString.Substring(formatterPosition + 1, 2);
int paramCount = 3;
if (DefaultFormatTypes.ContainsKey(paramType))
{
// check the next char, which could be a formatter
if (formatterPosition >= formatString.Length - 3)
{
// not enough characters, end of string, no formatter, use the default one
paramFormat = DefaultFormatTypes[paramType];
paramCount = 2;
}
else
{
paramFormat = formatString[formatterPosition + 3];
// check if it a valid formatter
if (!FormatTypeToStringFormatters.ContainsKey(paramFormat))
{
paramFormat = DefaultFormatTypes[paramType];
paramCount = 2;
}
}
formatString = string.Concat(formatString.AsSpan(0, formatterPosition), GetStringRepresentation(color.Value, paramFormat, paramType), formatString.AsSpan(formatterPosition + paramCount + 1));
}
// search for the next occurence of the formatter char
formatterPosition = formatString.IndexOf('%', formatterPosition + 1);
}
return formatString;
}
private static string GetStringRepresentation(Color color, char paramFormat, string paramType)
{
if (!DefaultFormatTypes.ContainsKey(paramType) || !FormatTypeToStringFormatters.ContainsKey(paramFormat))
{
return string.Empty;
}
switch (paramType)
{
case "Re": return ColorByteFormatted(color.R, paramFormat);
case "Gr": return ColorByteFormatted(color.G, paramFormat);
case "Bl": return ColorByteFormatted(color.B, paramFormat);
case "Al": return ColorByteFormatted(color.A, paramFormat);
case "Cy":
var (cyan, _, _, _) = ConvertToCMYKColor(color);
cyan = Math.Round(cyan * 100);
return cyan.ToString(CultureInfo.InvariantCulture);
case "Ma":
var (_, magenta, _, _) = ConvertToCMYKColor(color);
magenta = Math.Round(magenta * 100);
return magenta.ToString(CultureInfo.InvariantCulture);
case "Ye":
var (_, _, yellow, _) = ConvertToCMYKColor(color);
yellow = Math.Round(yellow * 100);
return yellow.ToString(CultureInfo.InvariantCulture);
case "Bk":
var (_, _, _, blackKey) = ConvertToCMYKColor(color);
blackKey = Math.Round(blackKey * 100);
return blackKey.ToString(CultureInfo.InvariantCulture);
case "Hu":
var (hue, _, _) = ConvertToHSBColor(color);
hue = Math.Round(hue);
return hue.ToString(CultureInfo.InvariantCulture);
case "Hn":
var (hueNatural, _, _) = ConvertToNaturalColor(color);
return hueNatural;
case "Sb":
var (_, saturationB, _) = ConvertToHSBColor(color);
saturationB = Math.Round(saturationB * 100);
return saturationB.ToString(CultureInfo.InvariantCulture);
case "Si":
var (_, saturationI, _) = ConvertToHSIColor(color);
saturationI = Math.Round(saturationI * 100);
return saturationI.ToString(CultureInfo.InvariantCulture);
case "Sl":
var (_, saturationL, _) = ConvertToHSLColor(color);
saturationL = Math.Round(saturationL * 100);
return saturationL.ToString(CultureInfo.InvariantCulture);
case "Va": // value and brightness are the same values
case "Br":
var (_, _, brightness) = ConvertToHSBColor(color);
brightness = Math.Round(brightness * 100);
return brightness.ToString(CultureInfo.InvariantCulture);
case "In":
var (_, _, intensity) = ConvertToHSIColor(color);
intensity = Math.Round(intensity * 100);
return intensity.ToString(CultureInfo.InvariantCulture);
case "Ll":
var (_, _, lightnessL) = ConvertToHSLColor(color);
lightnessL = Math.Round(lightnessL * 100);
return lightnessL.ToString(CultureInfo.InvariantCulture);
case "Lc":
var (lightnessC, _, _) = ConvertToCIELABColor(color);
lightnessC = Math.Round(lightnessC, 2);
return lightnessC.ToString(CultureInfo.InvariantCulture);
case "Wh":
var (_, whiteness, _) = ConvertToHWBColor(color);
whiteness = Math.Round(whiteness * 100);
return whiteness.ToString(CultureInfo.InvariantCulture);
case "Bn":
var (_, _, blackness) = ConvertToHWBColor(color);
blackness = Math.Round(blackness * 100);
return blackness.ToString(CultureInfo.InvariantCulture);
case "Ca":
var (_, chromaticityA, _) = ConvertToCIELABColor(color);
chromaticityA = Math.Round(chromaticityA, 2);
return chromaticityA.ToString(CultureInfo.InvariantCulture);
case "Cb":
var (_, _, chromaticityB) = ConvertToCIELABColor(color);
chromaticityB = Math.Round(chromaticityB, 2);
return chromaticityB.ToString(CultureInfo.InvariantCulture);
case "Xv":
var (x, _, _) = ConvertToCIEXYZColor(color);
x = Math.Round(x * 100, 4);
return x.ToString(CultureInfo.InvariantCulture);
case "Yv":
var (_, y, _) = ConvertToCIEXYZColor(color);
y = Math.Round(y * 100, 4);
return y.ToString(CultureInfo.InvariantCulture);
case "Zv":
var (_, _, z) = ConvertToCIEXYZColor(color);
z = Math.Round(z * 100, 4);
return z.ToString(CultureInfo.InvariantCulture);
case "Dv":
return (color.R + (color.G * 256) + (color.B * 65536)).ToString(CultureInfo.InvariantCulture);
case "Na":
return ColorNameHelper.GetColorName(color);
default: return string.Empty;
}
}
private static string ColorByteFormatted(byte colorByteValue, char paramFormat)
{
switch (paramFormat)
{
case 'b': return colorByteValue.ToString(CultureInfo.InvariantCulture);
case 'h':
case 'H':
return (colorByteValue / 16).ToString(FormatTypeToStringFormatters[paramFormat], CultureInfo.InvariantCulture);
case 'x':
case 'X':
return colorByteValue.ToString(FormatTypeToStringFormatters[paramFormat], CultureInfo.InvariantCulture);
case 'f':
case 'F':
return (colorByteValue / 255d).ToString(FormatTypeToStringFormatters[paramFormat], CultureInfo.InvariantCulture);
default: return colorByteValue.ToString(CultureInfo.InvariantCulture);
}
}
public static string GetDefaultFormat(string formatName)
{
switch (formatName)
{
case "HEX": return "%Rex%Grx%Blx";
case "RGB": return "rgb(%Re, %Gr, %Bl)";
case "HSL": return "hsl(%Hu, %Sl%, %Ll%)";
case "HSV": return "hsv(%Hu, %Sb%, %Va%)";
case "CMYK": return "cmyk(%Cy%, %Ma%, %Ye%, %Bk%)";
case "HSB": return "hsb(%Hu, %Sb%, %Br%)";
case "HSI": return "hsi(%Hu, %Si%, %In%)";
case "HWB": return "hwb(%Hu, %Wh%, %Bn%)";
case "NCol": return "%Hn, %Wh%, %Bn%";
case "CIELAB": return "CIELab(%Lc, %Ca, %Cb)";
case "CIEXYZ": return "XYZ(%Xv, %Yv, %Zv)";
case "VEC4": return "(%Reff, %Grff, %Blff, 1f)";
case "Decimal": return "%Dv";
case "HEX Int": return "0xFF%ReX%GrX%BlX";
default: return string.Empty;
}
}
}
}

View File

@@ -0,0 +1,263 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Drawing;
namespace ManagedCommon
{
public static class ColorNameHelper
{
public const float DBLEPSILON = 2.2204460492503131e-16f;
// For the purposes of naming colors, there are four steps that we go through.
//
// 1. For numerical ease, we convert the HSL values from the range [0, 1]
// to the range [0, 255].
//
// 2. If luminosity is sufficiently high or low (> 240 or < 20), or if
// saturation is sufficiently low (<= 20), then we declare that we're in the
// achromatic range. In this case, we return either white, black, or three
// different shades of gray (depending on luminosity).
//
// 3. If we do have a chromatic color, the first thing we need to determine
// about it is what the hue limits are for its saturation value - at different
// levels of saturation, we have different hue values that we'll consider the
// boundaries for different classes of named colors. The hue limits for various
// saturation values are as below.
//
// The numbers correspond to the following color buckets, with 0 meaning that
// that bucket does not apply to the given saturation value:
//
// 1 - coral, 2 - red, 3 - orange, 4 - brown, 5 - tan, 6 - gold, 7 - yellow, 8 - olive green (with brown),
// 9 - olive green (with green) 10 - lime green, 11 - green - 12 - bright green 13 - teal, 14 - aqua,
// 15 - turquoise, 16 - pale blue, 17 - blue, 18 - blue-gray, 19 - indigo, 20 - purple, 21 - pink, 22 - brown, 23 - red
private static int[] hueLimitsForSatLevel1 = // Sat: 20-75
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
8, 0, 0, 44, 0, 0, 0, 63, 0, 0, 122, 0, 134, 0, 0, 0, 0, 166, 176, 241, 0, 256, 0,
};
private static int[] hueLimitsForSatLevel2 = // Sat: 75-115
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
0, 10, 0, 32, 46, 0, 0, 0, 61, 0, 106, 0, 136, 144, 0, 0, 0, 158, 166, 241, 0, 0, 256,
};
private static int[] hueLimitsForSatLevel3 = // Sat: 115-150
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
0, 8, 0, 0, 39, 46, 0, 0, 0, 71, 120, 0, 131, 144, 0, 0, 163, 0, 177, 211, 249, 0, 256,
};
private static int[] hueLimitsForSatLevel4 = // Sat: 150-240
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
0, 11, 26, 0, 0, 38, 45, 0, 0, 56, 100, 121, 129, 0, 140, 0, 180, 0, 0, 224, 241, 0, 256,
};
private static int[] hueLimitsForSatLevel5 = // Sat: 240-255
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
0, 13, 27, 0, 0, 36, 45, 0, 0, 59, 118, 0, 127, 136, 142, 0, 185, 0, 0, 216, 239, 0, 256,
};
// 4. Once we have the color bucket, next we have three sub-buckets that we need to worry about,
// corresponding to three different levels of luminosity. For example, if we're in the "blue" bucket,
// that might correspond to light blue, blue, or dark blue, depending on luminosity.
// For each bucket, the luminosity cutoffs for the purposes of discerning between light, mid, and dark colors
// are different, so we define luminosity limits for low and high luminosity for each bucket, as follows:
private static int[] lumLimitsForHueIndexLow =
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
130, 100, 115, 100, 100, 100, 110, 75, 100, 90, 100, 100, 100, 100, 80, 100, 100, 100, 100, 100, 100, 100, 100,
};
private static int[] lumLimitsForHueIndexHigh =
{
// 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
170, 170, 170, 155, 170, 170, 170, 170, 170, 115, 170, 170, 170, 170, 170, 170, 170, 170, 150, 150, 170, 140, 165,
};
// 5. Finally, once we have a luminosity sub-bucket in the saturation color bucket, we have everything we need
// to retrieve a name. For each of the 23 buckets, we have names associated with light, mid, and dark variations
// of that color, which are defined as follows:
private static string[] colorNamesLight =
{
CommonResources.TEXT_COLOR_CORAL,
CommonResources.TEXT_COLOR_ROSE,
CommonResources.TEXT_COLOR_LIGHTORANGE,
CommonResources.TEXT_COLOR_TAN,
CommonResources.TEXT_COLOR_TAN,
CommonResources.TEXT_COLOR_LIGHTYELLOW,
CommonResources.TEXT_COLOR_LIGHTYELLOW,
CommonResources.TEXT_COLOR_TAN,
CommonResources.TEXT_COLOR_LIGHTGREEN,
CommonResources.TEXT_COLOR_LIME,
CommonResources.TEXT_COLOR_LIGHTGREEN,
CommonResources.TEXT_COLOR_LIGHTGREEN,
CommonResources.TEXT_COLOR_AQUA,
CommonResources.TEXT_COLOR_SKYBLUE,
CommonResources.TEXT_COLOR_LIGHTTURQUOISE,
CommonResources.TEXT_COLOR_PALEBLUE,
CommonResources.TEXT_COLOR_LIGHTBLUE,
CommonResources.TEXT_COLOR_ICEBLUE,
CommonResources.TEXT_COLOR_PERIWINKLE,
CommonResources.TEXT_COLOR_LAVENDER,
CommonResources.TEXT_COLOR_PINK,
CommonResources.TEXT_COLOR_TAN,
CommonResources.TEXT_COLOR_ROSE,
};
private static string[] colorNamesMid =
{
CommonResources.TEXT_COLOR_CORAL,
CommonResources.TEXT_COLOR_RED,
CommonResources.TEXT_COLOR_ORANGE,
CommonResources.TEXT_COLOR_BROWN,
CommonResources.TEXT_COLOR_TAN,
CommonResources.TEXT_COLOR_GOLD,
CommonResources.TEXT_COLOR_YELLOW,
CommonResources.TEXT_COLOR_OLIVEGREEN,
CommonResources.TEXT_COLOR_OLIVEGREEN,
CommonResources.TEXT_COLOR_GREEN,
CommonResources.TEXT_COLOR_GREEN,
CommonResources.TEXT_COLOR_BRIGHTGREEN,
CommonResources.TEXT_COLOR_TEAL,
CommonResources.TEXT_COLOR_AQUA,
CommonResources.TEXT_COLOR_TURQUOISE,
CommonResources.TEXT_COLOR_PALEBLUE,
CommonResources.TEXT_COLOR_BLUE,
CommonResources.TEXT_COLOR_BLUEGRAY,
CommonResources.TEXT_COLOR_INDIGO,
CommonResources.TEXT_COLOR_PURPLE,
CommonResources.TEXT_COLOR_PINK,
CommonResources.TEXT_COLOR_BROWN,
CommonResources.TEXT_COLOR_RED,
};
private static string[] colorNamesDark =
{
CommonResources.TEXT_COLOR_BROWN,
CommonResources.TEXT_COLOR_DARKRED,
CommonResources.TEXT_COLOR_BROWN,
CommonResources.TEXT_COLOR_BROWN,
CommonResources.TEXT_COLOR_BROWN,
CommonResources.TEXT_COLOR_DARKYELLOW,
CommonResources.TEXT_COLOR_DARKYELLOW,
CommonResources.TEXT_COLOR_BROWN,
CommonResources.TEXT_COLOR_DARKGREEN,
CommonResources.TEXT_COLOR_DARKGREEN,
CommonResources.TEXT_COLOR_DARKGREEN,
CommonResources.TEXT_COLOR_DARKGREEN,
CommonResources.TEXT_COLOR_DARKTEAL,
CommonResources.TEXT_COLOR_DARKTEAL,
CommonResources.TEXT_COLOR_DARKTEAL,
CommonResources.TEXT_COLOR_DARKBLUE,
CommonResources.TEXT_COLOR_DARKBLUE,
CommonResources.TEXT_COLOR_BLUEGRAY,
CommonResources.TEXT_COLOR_INDIGO,
CommonResources.TEXT_COLOR_DARKPURPLE,
CommonResources.TEXT_COLOR_PLUM,
CommonResources.TEXT_COLOR_BROWN,
CommonResources.TEXT_COLOR_DARKRED,
};
public static string GetColorName(Color color)
{
var (hue, sat, lum) = ColorFormatHelper.ConvertToHSLColor(color);
hue = (hue == 0 ? 0 : hue / 360) * 255; // this implementation is using normalization to 0-255 instead of 0-360°
sat = sat * 255;
lum = lum * 255;
// First, if we're in the achromatic state, return the appropriate achromatic color name.
if (lum > 240)
{
return CommonResources.TEXT_COLOR_WHITE;
}
else if (lum < 20)
{
return CommonResources.TEXT_COLOR_BLACK;
}
if (sat <= 20)
{
if (lum > 170)
{
return CommonResources.TEXT_COLOR_LIGHTGRAY;
}
else if (lum > 100)
{
return CommonResources.TEXT_COLOR_GRAY;
}
else
{
return CommonResources.TEXT_COLOR_DARKGRAY;
}
}
// If we have a chromatic color, we need to first get the hue limits for the saturation value.
int[] pHueLimits;
if (sat > 20 && sat <= 75)
{
pHueLimits = hueLimitsForSatLevel1;
}
else if (sat > 75 && sat <= 115)
{
pHueLimits = hueLimitsForSatLevel2;
}
else if (sat > 115 && sat <= 150)
{
pHueLimits = hueLimitsForSatLevel3;
}
else if (sat > 150 && sat <= 240)
{
pHueLimits = hueLimitsForSatLevel4;
}
else
{
pHueLimits = hueLimitsForSatLevel5;
}
// Now that we have that, we can get the color index, which represents which
// of the 23 buckets we're located in.
int colorIndex = -1;
for (int i = 0; i < colorNamesMid.Length; ++i)
{
if (hue < pHueLimits[i])
{
colorIndex = i;
break;
}
}
// Assuming we got a color index (and we always should get one), then next we need to
// figure out which luminosity sub-bucket we're located in.
// Once we have that, we'll return the color name from the appropriate array.
if (colorIndex != -1)
{
if (lum > lumLimitsForHueIndexHigh[colorIndex])
{
return colorNamesLight[colorIndex];
}
else if (lum < lumLimitsForHueIndexLow[colorIndex])
{
return colorNamesDark[colorIndex];
}
else
{
return colorNamesMid[colorIndex];
}
}
return string.Empty;
}
public static bool AreClose(double a, double b)
{
return (float)Math.Abs(a - b) <= DBLEPSILON * (float)Math.Abs(a);
}
}
}

View File

@@ -0,0 +1,441 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace ManagedCommon {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class CommonResources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal CommonResources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ManagedCommon.CommonResources", typeof(CommonResources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to Aqua.
/// </summary>
public static string TEXT_COLOR_AQUA {
get {
return ResourceManager.GetString("TEXT_COLOR_AQUA", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Black.
/// </summary>
public static string TEXT_COLOR_BLACK {
get {
return ResourceManager.GetString("TEXT_COLOR_BLACK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Blue.
/// </summary>
public static string TEXT_COLOR_BLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_BLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Blue gray.
/// </summary>
public static string TEXT_COLOR_BLUEGRAY {
get {
return ResourceManager.GetString("TEXT_COLOR_BLUEGRAY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Bright green.
/// </summary>
public static string TEXT_COLOR_BRIGHTGREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_BRIGHTGREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Brown.
/// </summary>
public static string TEXT_COLOR_BROWN {
get {
return ResourceManager.GetString("TEXT_COLOR_BROWN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Coral.
/// </summary>
public static string TEXT_COLOR_CORAL {
get {
return ResourceManager.GetString("TEXT_COLOR_CORAL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark blue.
/// </summary>
public static string TEXT_COLOR_DARKBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark gray.
/// </summary>
public static string TEXT_COLOR_DARKGRAY {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKGRAY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark green.
/// </summary>
public static string TEXT_COLOR_DARKGREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKGREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark purple.
/// </summary>
public static string TEXT_COLOR_DARKPURPLE {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKPURPLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark red.
/// </summary>
public static string TEXT_COLOR_DARKRED {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKRED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark teal.
/// </summary>
public static string TEXT_COLOR_DARKTEAL {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKTEAL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Dark yellow.
/// </summary>
public static string TEXT_COLOR_DARKYELLOW {
get {
return ResourceManager.GetString("TEXT_COLOR_DARKYELLOW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Gold.
/// </summary>
public static string TEXT_COLOR_GOLD {
get {
return ResourceManager.GetString("TEXT_COLOR_GOLD", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Gray.
/// </summary>
public static string TEXT_COLOR_GRAY {
get {
return ResourceManager.GetString("TEXT_COLOR_GRAY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Green.
/// </summary>
public static string TEXT_COLOR_GREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_GREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Ice blue.
/// </summary>
public static string TEXT_COLOR_ICEBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_ICEBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Indigo.
/// </summary>
public static string TEXT_COLOR_INDIGO {
get {
return ResourceManager.GetString("TEXT_COLOR_INDIGO", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lavender.
/// </summary>
public static string TEXT_COLOR_LAVENDER {
get {
return ResourceManager.GetString("TEXT_COLOR_LAVENDER", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light blue.
/// </summary>
public static string TEXT_COLOR_LIGHTBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light gray.
/// </summary>
public static string TEXT_COLOR_LIGHTGRAY {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTGRAY", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light green.
/// </summary>
public static string TEXT_COLOR_LIGHTGREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTGREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light orange.
/// </summary>
public static string TEXT_COLOR_LIGHTORANGE {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTORANGE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light turquoise.
/// </summary>
public static string TEXT_COLOR_LIGHTTURQUOISE {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTTURQUOISE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Light yellow.
/// </summary>
public static string TEXT_COLOR_LIGHTYELLOW {
get {
return ResourceManager.GetString("TEXT_COLOR_LIGHTYELLOW", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Lime.
/// </summary>
public static string TEXT_COLOR_LIME {
get {
return ResourceManager.GetString("TEXT_COLOR_LIME", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Olive green.
/// </summary>
public static string TEXT_COLOR_OLIVEGREEN {
get {
return ResourceManager.GetString("TEXT_COLOR_OLIVEGREEN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Orange.
/// </summary>
public static string TEXT_COLOR_ORANGE {
get {
return ResourceManager.GetString("TEXT_COLOR_ORANGE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pale blue.
/// </summary>
public static string TEXT_COLOR_PALEBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_PALEBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Periwinkle.
/// </summary>
public static string TEXT_COLOR_PERIWINKLE {
get {
return ResourceManager.GetString("TEXT_COLOR_PERIWINKLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Pink.
/// </summary>
public static string TEXT_COLOR_PINK {
get {
return ResourceManager.GetString("TEXT_COLOR_PINK", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Plum.
/// </summary>
public static string TEXT_COLOR_PLUM {
get {
return ResourceManager.GetString("TEXT_COLOR_PLUM", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Purple.
/// </summary>
public static string TEXT_COLOR_PURPLE {
get {
return ResourceManager.GetString("TEXT_COLOR_PURPLE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Red.
/// </summary>
public static string TEXT_COLOR_RED {
get {
return ResourceManager.GetString("TEXT_COLOR_RED", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Rose.
/// </summary>
public static string TEXT_COLOR_ROSE {
get {
return ResourceManager.GetString("TEXT_COLOR_ROSE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Sky blue.
/// </summary>
public static string TEXT_COLOR_SKYBLUE {
get {
return ResourceManager.GetString("TEXT_COLOR_SKYBLUE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Tan.
/// </summary>
public static string TEXT_COLOR_TAN {
get {
return ResourceManager.GetString("TEXT_COLOR_TAN", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Teal.
/// </summary>
public static string TEXT_COLOR_TEAL {
get {
return ResourceManager.GetString("TEXT_COLOR_TEAL", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Turquoise.
/// </summary>
public static string TEXT_COLOR_TURQUOISE {
get {
return ResourceManager.GetString("TEXT_COLOR_TURQUOISE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to White.
/// </summary>
public static string TEXT_COLOR_WHITE {
get {
return ResourceManager.GetString("TEXT_COLOR_WHITE", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Yellow.
/// </summary>
public static string TEXT_COLOR_YELLOW {
get {
return ResourceManager.GetString("TEXT_COLOR_YELLOW", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,288 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="TEXT_COLOR_WHITE" xml:space="preserve">
<value>White</value>
<comment>White color</comment>
</data>
<data name="TEXT_COLOR_BLACK" xml:space="preserve">
<value>Black</value>
<comment>Black color</comment>
</data>
<data name="TEXT_COLOR_LIGHTGRAY" xml:space="preserve">
<value>Light gray</value>
<comment>Light gray color</comment>
</data>
<data name="TEXT_COLOR_GRAY" xml:space="preserve">
<value>Gray</value>
<comment>Gray color</comment>
</data>
<data name="TEXT_COLOR_DARKGRAY" xml:space="preserve">
<value>Dark gray</value>
<comment>Dark gray color</comment>
</data>
<data name="TEXT_COLOR_CORAL" xml:space="preserve">
<value>Coral</value>
<comment>Coral color</comment>
</data>
<data name="TEXT_COLOR_ROSE" xml:space="preserve">
<value>Rose</value>
<comment>Rose color</comment>
</data>
<data name="TEXT_COLOR_LIGHTORANGE" xml:space="preserve">
<value>Light orange</value>
<comment>Light orange color</comment>
</data>
<data name="TEXT_COLOR_TAN" xml:space="preserve">
<value>Tan</value>
<comment>Tan color</comment>
</data>
<data name="TEXT_COLOR_LIGHTYELLOW" xml:space="preserve">
<value>Light yellow</value>
<comment>Light yellow color</comment>
</data>
<data name="TEXT_COLOR_LIGHTGREEN" xml:space="preserve">
<value>Light green</value>
<comment>Light green color</comment>
</data>
<data name="TEXT_COLOR_LIME" xml:space="preserve">
<value>Lime</value>
<comment>Lime color</comment>
</data>
<data name="TEXT_COLOR_AQUA" xml:space="preserve">
<value>Aqua</value>
<comment>Aqua color</comment>
</data>
<data name="TEXT_COLOR_SKYBLUE" xml:space="preserve">
<value>Sky blue</value>
<comment>Sky blue color</comment>
</data>
<data name="TEXT_COLOR_LIGHTTURQUOISE" xml:space="preserve">
<value>Light turquoise</value>
<comment>Light turquoise color</comment>
</data>
<data name="TEXT_COLOR_PALEBLUE" xml:space="preserve">
<value>Pale blue</value>
<comment>Pale blue color</comment>
</data>
<data name="TEXT_COLOR_LIGHTBLUE" xml:space="preserve">
<value>Light blue</value>
<comment>Light blue color</comment>
</data>
<data name="TEXT_COLOR_ICEBLUE" xml:space="preserve">
<value>Ice blue</value>
<comment>Ice blue color</comment>
</data>
<data name="TEXT_COLOR_PERIWINKLE" xml:space="preserve">
<value>Periwinkle</value>
<comment>Periwinkle color</comment>
</data>
<data name="TEXT_COLOR_LAVENDER" xml:space="preserve">
<value>Lavender</value>
<comment>Lavender color</comment>
</data>
<data name="TEXT_COLOR_PINK" xml:space="preserve">
<value>Pink</value>
<comment>Pink color</comment>
</data>
<data name="TEXT_COLOR_RED" xml:space="preserve">
<value>Red</value>
<comment>Red color</comment>
</data>
<data name="TEXT_COLOR_ORANGE" xml:space="preserve">
<value>Orange</value>
<comment>Orange color</comment>
</data>
<data name="TEXT_COLOR_BROWN" xml:space="preserve">
<value>Brown</value>
<comment>Brown color</comment>
</data>
<data name="TEXT_COLOR_GOLD" xml:space="preserve">
<value>Gold</value>
<comment>Gold color</comment>
</data>
<data name="TEXT_COLOR_YELLOW" xml:space="preserve">
<value>Yellow</value>
<comment>Yellow color</comment>
</data>
<data name="TEXT_COLOR_OLIVEGREEN" xml:space="preserve">
<value>Olive green</value>
<comment>Olive green color</comment>
</data>
<data name="TEXT_COLOR_GREEN" xml:space="preserve">
<value>Green</value>
<comment>Green color</comment>
</data>
<data name="TEXT_COLOR_BRIGHTGREEN" xml:space="preserve">
<value>Bright green</value>
<comment>Rose color</comment>
</data>
<data name="TEXT_COLOR_TEAL" xml:space="preserve">
<value>Teal</value>
<comment>Teal color</comment>
</data>
<data name="TEXT_COLOR_TURQUOISE" xml:space="preserve">
<value>Turquoise</value>
<comment>Turquoise color</comment>
</data>
<data name="TEXT_COLOR_BLUE" xml:space="preserve">
<value>Blue</value>
<comment>Blue color</comment>
</data>
<data name="TEXT_COLOR_BLUEGRAY" xml:space="preserve">
<value>Blue gray</value>
<comment>Blue gray color</comment>
</data>
<data name="TEXT_COLOR_INDIGO" xml:space="preserve">
<value>Indigo</value>
<comment>Indigo color</comment>
</data>
<data name="TEXT_COLOR_PURPLE" xml:space="preserve">
<value>Purple</value>
<comment>Purple color</comment>
</data>
<data name="TEXT_COLOR_DARKRED" xml:space="preserve">
<value>Dark red</value>
<comment>Dark red color</comment>
</data>
<data name="TEXT_COLOR_DARKYELLOW" xml:space="preserve">
<value>Dark yellow</value>
<comment>Dark yellow color</comment>
</data>
<data name="TEXT_COLOR_DARKGREEN" xml:space="preserve">
<value>Dark green</value>
<comment>Dark green color</comment>
</data>
<data name="TEXT_COLOR_DARKTEAL" xml:space="preserve">
<value>Dark teal</value>
<comment>Dark teal color</comment>
</data>
<data name="TEXT_COLOR_DARKBLUE" xml:space="preserve">
<value>Dark blue</value>
<comment>Dark blue color</comment>
</data>
<data name="TEXT_COLOR_DARKPURPLE" xml:space="preserve">
<value>Dark purple</value>
<comment>Dark purple color</comment>
</data>
<data name="TEXT_COLOR_PLUM" xml:space="preserve">
<value>Plum</value>
<comment>Plum color</comment>
</data>
</root>

View File

@@ -20,4 +20,19 @@
<ProjectReference Include="..\ManagedTelemetry\Telemetry\ManagedTelemetry.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="CommonResources.Designer.cs">
<DependentUpon>CommonResources.resx</DependentUpon>
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="CommonResources.resx">
<SubType>Designer</SubType>
<LastGenOutput>CommonResources.Designer.cs</LastGenOutput>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>