From 6d4d97364531d62eb658097db33c7799d9865a07 Mon Sep 17 00:00:00 2001 From: Twan van Laarhoven Date: Tue, 12 May 2020 22:48:56 +0200 Subject: [PATCH] Add support for HTML style hex colors, #ff0000 = red, etc. --- CHANGES.txt | 1 + doc/type/color.txt | 8 ++++++-- src/gfx/color.cpp | 31 ++++++++++++++++++++++++++++--- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 5144bb93..8f0c0b1c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -19,6 +19,7 @@ Bug fixes: Template features: * Added tag to change the font inside a text field. + * Colors can now be written using hex notation, #rrggbb / #rrggbbaa, and short hex notation (#rgb / #rgba) Scripting: * Added type_name function diff --git a/doc/type/color.txt b/doc/type/color.txt index 908a0c0c..bd9e97ff 100644 --- a/doc/type/color.txt +++ b/doc/type/color.txt @@ -5,13 +5,17 @@ In files and scritps a color can be represented as
rgb(red_component, green_component, blue_component)
where red_component, green_component and blue_component are numbers between 0 and 255 (inclusive). -In some places MSE also supports colors with a transparency value, notated as +In most places MSE also supports colors with a transparency value, notated as
rgba(red_component, green_component, blue_component, alpha_component)
An alpha value of @0@ indicates a transparent color, an alpha value of @255@ is completely opaque. +You can also use HTML style hexadecimal colors, +
#rgb, #rgba, #rrggbb, #rrggbbaa
+For example, #ff0000 is red, as is #f00 + --Named colors-- MSE also supports named colors, for instance @"white"@ is the same as @rgb(255,255,255)@. -For a full list of supported colors, see [[http://www.wxwidgets.org/manuals/stable/wx_wxcolourdatabase.html|the wxWidgets documentation]]. +For a full list of supported colors, see [[https://docs.wxwidgets.org/3.0/classwx_colour_database.html|the wxWidgets documentation]]. In addition, the named color @"transparent"@ stands for the completely transparent color, @rgba(0,0,0,0)@. In scripts named colors are represented as [[type:string]]s. diff --git a/src/gfx/color.cpp b/src/gfx/color.cpp index cb246d41..5f286a9b 100644 --- a/src/gfx/color.cpp +++ b/src/gfx/color.cpp @@ -26,6 +26,18 @@ template <> void Writer::handle(const Color& col) { handle(format_color(col)); } +int parse_hex(Char c) { + if (c >= '0' && c <= '9') return c - '0'; + if (c >= 'A' && c <= 'F') return c - 'A' + 10; + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + return -1; +} +int parse_hex(Char c1, Char c2) { + int x1 = parse_hex(c1); + int x2 = parse_hex(c2); + if (x1 >= 0 && x2 >= 0) return 16*x1 + x2; + return -1; +} optional parse_color(const String& v) { UInt r,g,b,a; @@ -33,6 +45,21 @@ optional parse_color(const String& v) { return Color(r, g, b); } else if (wxSscanf(v.c_str(),_("rgba(%u,%u,%u,%u)"),&r,&g,&b,&a)) { return Color(r, g, b, a); + } else if (v.size() > 0 && v[0] == '#') { + if (v.size() == 4) { + int r = parse_hex(v[1]), g = parse_hex(v[2]), b = parse_hex(v[3]); + if (r >= 0 && g >= 0 && b >= 0) return Color(17 * r, 17 * g, 17 * b); + } else if (v.size() == 5) { + int r = parse_hex(v[1]), g = parse_hex(v[2]), b = parse_hex(v[3]), a = parse_hex(v[4]); + if (r >= 0 && g >= 0 && b >= 0 && a >= 0) return Color(17 * r, 17 * g, 17 * b, 17 * a); + } else if (v.size() == 7) { + int r = parse_hex(v[1], v[2]), g = parse_hex(v[3],v[4]), b = parse_hex(v[5],v[6]); + if (r >= 0 && g >= 0 && b >= 0) return Color(r, g, b); + } else if (v.size() == 9) { + int r = parse_hex(v[1], v[2]), g = parse_hex(v[3],v[4]), b = parse_hex(v[5],v[6]), a = parse_hex(v[7],v[8]); + if (r >= 0 && g >= 0 && b >= 0 && a >= 0) return Color(r, g, b, a); + } + return nullopt; } else if (v == _("transparent")) { return Color(0,0,0,0); } else { @@ -41,7 +68,7 @@ optional parse_color(const String& v) { if (c.Ok()) { return Color(c); } else { - return optional(); + return nullopt; } } } @@ -49,8 +76,6 @@ optional parse_color(const String& v) { String format_color(Color col) { if (col.Alpha() == 255) { return String::Format(_("rgb(%u,%u,%u)"), col.Red(), col.Green(), col.Blue()); - } else if (col.Alpha() == 0) { - return _("transparent"); } else { return String::Format(_("rgba(%u,%u,%u,%u)"), col.Red(), col.Green(), col.Blue(), col.Alpha()); }