Fix alpha handling in CSS syntax in wxColour in non-"C" locale.
Use locale-independent functions to parse and generate the floating point alpha representation in CSS syntax for colours to make it work in locales which don't use period as decimal separator. Closes #13077. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@67356 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -101,10 +101,48 @@ bool wxColourBase::FromString(const wxString& str)
|
||||
alpha = wxALPHA_OPAQUE;
|
||||
if ( str.length() > 3 && (str[3] == wxT('a') || str[3] == wxT('A')) )
|
||||
{
|
||||
float a;
|
||||
// TODO: use locale-independent function
|
||||
if ( wxSscanf(str.wx_str() + 4, wxT("( %d , %d , %d , %f )"),
|
||||
&red, &green, &blue, &a) != 4 )
|
||||
// We can't use sscanf() for the alpha value as sscanf() uses the
|
||||
// current locale while the floating point numbers in CSS always
|
||||
// use point as decimal separator, regardless of locale. So parse
|
||||
// the tail of the string manually by putting it in a buffer and
|
||||
// using wxString::ToCDouble() below. Notice that we can't use "%s"
|
||||
// for this as it stops at white space and we need "%c" to avoid
|
||||
// this and really get all the rest of the string into the buffer.
|
||||
|
||||
const unsigned len = str.length(); // always big enough
|
||||
wxCharBuffer alphaBuf(len);
|
||||
char * const alphaPtr = alphaBuf.data();
|
||||
|
||||
for ( unsigned n = 0; n < len; n++ )
|
||||
alphaPtr[n] = '\0';
|
||||
|
||||
// Construct the format string which ensures that the last argument
|
||||
// receives all the rest of the string.
|
||||
wxString formatStr;
|
||||
formatStr << wxS("( %d , %d , %d , %") << len << 'c';
|
||||
|
||||
// Notice that we use sscanf() here because if the string is not
|
||||
// ASCII it can't represent a valid RGB colour specification anyhow
|
||||
// and like this we can be sure that %c corresponds to "char *"
|
||||
// while with wxSscanf() it depends on the type of the string
|
||||
// passed as first argument: if it is a wide string, then %c
|
||||
// expects "wchar_t *" matching parameter under MSW for example.
|
||||
if ( sscanf(str.c_str() + 4,
|
||||
formatStr,
|
||||
&red, &green, &blue, alphaPtr) != 4 )
|
||||
return false;
|
||||
|
||||
// Notice that we must explicitly specify the length to get rid of
|
||||
// trailing NULs.
|
||||
wxString alphaStr(alphaPtr, wxStrlen(alphaPtr));
|
||||
if ( alphaStr.empty() || alphaStr.Last() != ')' )
|
||||
return false;
|
||||
|
||||
alphaStr.RemoveLast();
|
||||
alphaStr.Trim();
|
||||
|
||||
double a;
|
||||
if ( !alphaStr.ToCDouble(&a) )
|
||||
return false;
|
||||
|
||||
alpha = wxRound(a * 255);
|
||||
@@ -181,9 +219,9 @@ wxString wxColourBase::GetAsString(long flags) const
|
||||
}
|
||||
else // use rgba() form
|
||||
{
|
||||
// TODO: use locale-independent function
|
||||
colName.Printf(wxT("rgba(%d, %d, %d, %.3f)"),
|
||||
red, green, blue, Alpha() / 255.);
|
||||
colName.Printf(wxT("rgba(%d, %d, %d, %s)"),
|
||||
red, green, blue,
|
||||
wxString::FromCDouble(Alpha() / 255., 3));
|
||||
}
|
||||
}
|
||||
else if ( flags & wxC2S_HTML_SYNTAX )
|
||||
|
@@ -20,6 +20,23 @@
|
||||
#include "wx/colour.h"
|
||||
#include "asserthelper.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Check the colour components, with and without alpha.
|
||||
//
|
||||
// NB: These are macros and not functions to have correct line numbers in case
|
||||
// of failure.
|
||||
#define ASSERT_EQUAL_RGB(c, r, g, b) \
|
||||
CPPUNIT_ASSERT_EQUAL( r, (int)c.Red() ); \
|
||||
CPPUNIT_ASSERT_EQUAL( g, (int)c.Green() ); \
|
||||
CPPUNIT_ASSERT_EQUAL( b, (int)c.Blue() )
|
||||
|
||||
#define ASSERT_EQUAL_RGBA(c, r, g, b, a) \
|
||||
ASSERT_EQUAL_RGB(c, r, g, b); \
|
||||
CPPUNIT_ASSERT_EQUAL( a, (int)c.Alpha() )
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// test class
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -32,9 +49,11 @@ public:
|
||||
private:
|
||||
CPPUNIT_TEST_SUITE( ColourTestCase );
|
||||
CPPUNIT_TEST( GetSetRGB );
|
||||
CPPUNIT_TEST( FromString );
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
void GetSetRGB();
|
||||
void FromString();
|
||||
|
||||
DECLARE_NO_COPY_CLASS(ColourTestCase)
|
||||
};
|
||||
@@ -78,3 +97,19 @@ void ColourTestCase::GetSetRGB()
|
||||
#endif // __WXX11__
|
||||
}
|
||||
|
||||
void ColourTestCase::FromString()
|
||||
{
|
||||
ASSERT_EQUAL_RGB( wxColour("rgb(11, 22, 33)"), 11, 22, 33 );
|
||||
ASSERT_EQUAL_RGBA( wxColour("rgba(11, 22, 33, 0.5)"), 11, 22, 33, 128 );
|
||||
ASSERT_EQUAL_RGBA( wxColour("rgba( 11, 22, 33, 0.5 )"), 11, 22, 33, 128 );
|
||||
|
||||
ASSERT_EQUAL_RGB( wxColour("#aabbcc"), 0xaa, 0xbb, 0xcc );
|
||||
|
||||
ASSERT_EQUAL_RGB( wxColour("red"), 0xff, 0, 0 );
|
||||
|
||||
wxColour col;
|
||||
CPPUNIT_ASSERT( !wxFromString("rgb(1, 2)", &col) );
|
||||
CPPUNIT_ASSERT( !wxFromString("rgba(1, 2, 3.456)", &col) );
|
||||
CPPUNIT_ASSERT( !wxFromString("rgba(1, 2, 3.456, foo)", &col) );
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user