Use snprintf instead of std::stringstream when converting color values to strings
authorTim Mayberry <mojofunk@gmail.com>
Tue, 6 Sep 2016 04:27:10 +0000 (14:27 +1000)
committerTim Mayberry <mojofunk@gmail.com>
Tue, 18 Apr 2017 23:36:59 +0000 (09:36 +1000)
std::ostream/stringstream will use the current locale to determine the numeric
formatting. If the locale uses grouping then thousands separators will be
inserted in the output which produces an invalid color string in
UIConfiguration::reset_gtk_theme() and when converting colors to strings in
UIConfiguration::store_color_theme()

This has not been a problem so far because it appears that LocaleGuard does not
reset the LC_NUMERIC value for the global C++ locale. So if a LocaleGuard is
created at any time before these functions are called(even if it goes out of
scope) the numeric formatting used by std::streams will use the "C" locale
formatting facets.

gtk2_ardour/ui_config.cc
gtk2_ardour/ui_config.h

index 4254350353e8807915aa933de53217b5cd335b9d..3af884abba83f63f3e42c41a10cffbc09f26813b 100644 (file)
@@ -138,23 +138,23 @@ void
 UIConfiguration::reset_gtk_theme ()
 {
        LocaleGuard lg;
-       stringstream ss;
-
-       ss << "gtk_color_scheme = \"" << hex;
+       std::string color_scheme_string("gtk_color_scheme = \"");
 
        for (ColorAliases::iterator g = color_aliases.begin(); g != color_aliases.end(); ++g) {
 
                if (g->first.find ("gtk_") == 0) {
                        const string gtk_name = g->first.substr (4);
-                       ss << gtk_name << ":#" << std::setw (6) << setfill ('0') << (color (g->second) >> 8) << ';';
+                       ArdourCanvas::Color a_color = color (g->second);
+
+                       color_scheme_string += gtk_name + ":#" + color_to_hex_string_no_alpha (a_color) + ';';
                }
        }
 
-       ss << '"' << dec << endl;
+       color_scheme_string += '"';
 
        /* reset GTK color scheme */
 
-       Gtk::Settings::get_default()->property_gtk_color_scheme() = ss.str();
+       Gtk::Settings::get_default()->property_gtk_color_scheme() = color_scheme_string;
 }
 
 void
@@ -243,7 +243,6 @@ UIConfiguration::load_defaults ()
                warning << string_compose (_("Could not find default UI configuration file %1"), default_ui_config_file_name) << endmsg;
        }
 
-
        if (ret == 0) {
                /* reload color theme */
                load_color_theme (false);
@@ -371,9 +370,7 @@ UIConfiguration::store_color_theme ()
        for (Colors::const_iterator i = colors.begin(); i != colors.end(); ++i) {
                XMLNode* node = new XMLNode (X_("Color"));
                node->set_property (X_("name"), i->first);
-               stringstream ss;
-               ss << "0x" << setw (8) << setfill ('0') << hex << i->second;
-               node->set_property (X_("value"), ss.str());
+               node->set_property (X_("value"), color_to_hex_string (i->second));
                parent->add_child_nocopy (*node);
        }
        root->add_child_nocopy (*parent);
@@ -799,3 +796,28 @@ UIConfiguration::load_rc_file (bool themechange, bool allow_own)
 
        Gtkmm2ext::UI::instance()->load_rcfile (rc_file_path, themechange);
 }
+
+std::string
+UIConfiguration::color_to_hex_string (ArdourCanvas::Color c)
+{
+       char buf[16];
+       int retval = g_snprintf (buf, sizeof(buf), "%08x", c);
+
+       if (retval < 0 || retval >= (int)sizeof(buf)) {
+               assert(false);
+       }
+       return buf;
+}
+
+std::string
+UIConfiguration::color_to_hex_string_no_alpha (ArdourCanvas::Color c)
+{
+       c >>= 8; // shift/remove alpha
+       char buf[16];
+       int retval = g_snprintf (buf, sizeof(buf), "%06x", c);
+
+       if (retval < 0 || retval >= (int)sizeof(buf)) {
+               assert(false);
+       }
+       return buf;
+}
index 2fac5e571dc9fa62b994b8c275e5da30f4be23cb..977ec20351125d081a5a3aa3809e9aac7243eb1d 100644 (file)
@@ -83,6 +83,9 @@ private:
        ArdourCanvas::HSV  color_hsv (const std::string&) const;
        ArdourCanvas::SVAModifier modifier (const std::string&) const;
 
+       static std::string color_to_hex_string (ArdourCanvas::Color c);
+       static std::string color_to_hex_string_no_alpha (ArdourCanvas::Color c);
+
        sigc::signal<void>  ColorsChanged;
 
        void reset_dpi ();