Bug Fix - #372 Color blending/mapping broken

- Corrected problem in unit test that expected the wrong result.
- Fixed Color::Color (const std::string&) so that the foreground and
  background are now considered two different colors, are upgraded
  separately, if necessary, and then blended.  The problem affected
  all instances of "<256-color> on <16-color>".  Hooray for unit
  tests.
This commit is contained in:
Paul Beckingham 2010-02-06 16:54:07 -05:00
parent 89ae64c5fb
commit 579ebe6130
3 changed files with 49 additions and 42 deletions

View file

@ -83,6 +83,8 @@
+ Fixed bug #371 which caused task to mis-apply certain color rules, like + Fixed bug #371 which caused task to mis-apply certain color rules, like
color.alternate, which was (a) not applied first, and (b) not blended color.alternate, which was (a) not applied first, and (b) not blended
with the other color rules (thanks to Richard Querin). with the other color rules (thanks to Richard Querin).
+ Fixed bug #372 which incorrectly mapped 16-color backgrounds into the
256-color space.
------ old releases ------------------------------ ------ old releases ------------------------------

View file

@ -105,6 +105,12 @@ Color::Color (const std::string& spec)
std::vector <std::string> words; std::vector <std::string> words;
split (words, modifiable_spec, ' '); split (words, modifiable_spec, ' ');
// Construct the color as two separate colors, then blend them later. This
// make it possible to declare a color such as "color1 on black", and have
// the upgrade work properly.
unsigned int fg_value = 0;
unsigned int bg_value = 0;
bool bg = false; bool bg = false;
int index; int index;
std::string word; std::string word;
@ -113,9 +119,9 @@ Color::Color (const std::string& spec)
{ {
word = lowerCase (trim (*it)); word = lowerCase (trim (*it));
if (word == "bold") value |= _COLOR_BOLD; if (word == "bold") fg_value |= _COLOR_BOLD;
else if (word == "bright") value |= _COLOR_BRIGHT; else if (word == "bright") bg_value |= _COLOR_BRIGHT;
else if (word == "underline") value |= _COLOR_UNDERLINE; else if (word == "underline") fg_value |= _COLOR_UNDERLINE;
else if (word == "on") bg = true; else if (word == "on") bg = true;
// X where X is one of black, red, blue ... // X where X is one of black, red, blue ...
@ -123,13 +129,13 @@ Color::Color (const std::string& spec)
{ {
if (bg) if (bg)
{ {
value |= _COLOR_HASBG; bg_value |= _COLOR_HASBG;
value |= index << 8; bg_value |= index << 8;
} }
else else
{ {
value |= _COLOR_HASFG; fg_value |= _COLOR_HASFG;
value |= index; fg_value |= index;
} }
} }
@ -141,20 +147,18 @@ Color::Color (const std::string& spec)
if (index < 0 || index > 23) if (index < 0 || index > 23)
throw std::string ("The color '") + *it + "' is not recognized."; throw std::string ("The color '") + *it + "' is not recognized.";
upgrade ();
if (bg) if (bg)
{ {
value |= _COLOR_HASBG; bg_value |= _COLOR_HASBG;
value |= (index + 232) << 8; bg_value |= (index + 232) << 8;
bg_value |= _COLOR_256;
} }
else else
{ {
value |= _COLOR_HASFG; fg_value |= _COLOR_HASFG;
value |= index + 232; fg_value |= index + 232;
fg_value |= _COLOR_256;
} }
value |= _COLOR_256;
} }
// rgbRGB, where 0 <= R,G,B <= 5. // rgbRGB, where 0 <= R,G,B <= 5.
@ -175,20 +179,18 @@ Color::Color (const std::string& spec)
index = 16 + r*36 + g*6 + b; index = 16 + r*36 + g*6 + b;
upgrade ();
if (bg) if (bg)
{ {
value |= _COLOR_HASBG; bg_value |= _COLOR_HASBG;
value |= index << 8; bg_value |= index << 8;
bg_value |= _COLOR_256;
} }
else else
{ {
value |= _COLOR_HASFG; fg_value |= _COLOR_HASFG;
value |= index; fg_value |= index;
fg_value |= _COLOR_256;
} }
value |= _COLOR_256;
} }
// colorN, where 0 <= N <= 255. // colorN, where 0 <= N <= 255.
@ -202,20 +204,24 @@ Color::Color (const std::string& spec)
if (bg) if (bg)
{ {
value |= _COLOR_HASBG; bg_value |= _COLOR_HASBG;
value |= index << 8; bg_value |= index << 8;
bg_value |= _COLOR_256;
} }
else else
{ {
value |= _COLOR_HASFG; fg_value |= _COLOR_HASFG;
value |= index; fg_value |= index;
fg_value |= _COLOR_256;
} }
value |= _COLOR_256;
} }
else if (word != "") else if (word != "")
throw std::string ("The color '") + *it + "' is not recognized."; throw std::string ("The color '") + *it + "' is not recognized.";
} }
// Now combine the fg and bg into a single color.
value = fg_value;
blend (Color (bg_value));
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
@ -392,18 +398,17 @@ void Color::upgrade ()
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/* // Sample color codes:
red \033[31m // red \033[31m
bold red \033[91m // bold red \033[91m
underline red \033[4;31m // underline red \033[4;31m
bold underline red \033[1;4;31m // bold underline red \033[1;4;31m
//
on red \033[41m // on red \033[41m
on bright red \033[101m // on bright red \033[101m
//
256 fg \033[38;5;Nm // 256 fg \033[38;5;Nm
256 bg \033[48;5;Nm // 256 bg \033[48;5;Nm
*/
std::string Color::colorize (const std::string& input) std::string Color::colorize (const std::string& input)
{ {
if (value == 0) if (value == 0)

View file

@ -102,7 +102,7 @@ int main (int argc, char** argv)
t.is (Color::colorize ("foo", "white"), std::string ("\033[37mfoo\033[0m"), "white -> ^[[37m"); t.is (Color::colorize ("foo", "white"), std::string ("\033[37mfoo\033[0m"), "white -> ^[[37m");
// 16-color backgrounds. // 16-color backgrounds.
t.is (Color::colorize ("foo", "on bright black"), std::string ("\033[90mfoo\033[0m"), "on bright black -> ^[[90m"); t.is (Color::colorize ("foo", "on bright black"), std::string ("\033[100mfoo\033[0m"), "on bright black -> ^[[100m");
t.is (Color::colorize ("foo", "on black"), std::string ("\033[40mfoo\033[0m"), "on black -> ^[[40m"); t.is (Color::colorize ("foo", "on black"), std::string ("\033[40mfoo\033[0m"), "on black -> ^[[40m");
t.is (Color::colorize ("foo", "on red"), std::string ("\033[41mfoo\033[0m"), "on red -> ^[[41m"); t.is (Color::colorize ("foo", "on red"), std::string ("\033[41mfoo\033[0m"), "on red -> ^[[41m");