QColor: provide QLatin1String overloads of functions taking QString

The inefficiency of QColor(const char*) came to light by
a recent refactoring which showed that the existing char*
overload of qt_get_hex_rgb() was never called.

So, provide a QLatin1String interface for named colors
that allows user code to reach that internal function
without converting to QString first.

Change-Id: I74df7b570ef28c00e35ca4adf46c4b7c7e9994b3
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Anton Kudryavtsev <a.kudryavtsev@netris.ru>
bb10
Marc Mutz 2016-08-19 09:48:14 +02:00
parent ceb3c2ea62
commit 0889e9da20
3 changed files with 77 additions and 28 deletions

View File

@ -323,7 +323,6 @@ static bool get_named_rgb_no_space(const char *name_no_space, QRgb *rgb)
return false;
}
#ifdef QCOLOR_THIS_IS_CURRENTLY_UNUSED_BUT_WILL_BE_USED_SOON
static bool get_named_rgb(const char *name, int len, QRgb* rgb)
{
if (len > 255)
@ -338,7 +337,6 @@ static bool get_named_rgb(const char *name, int len, QRgb* rgb)
return get_named_rgb_no_space(name_no_space, rgb);
}
#endif
static bool get_named_rgb(const QChar *name, int len, QRgb *rgb)
{
@ -796,12 +794,14 @@ QColor::QColor(Spec spec) Q_DECL_NOTHROW
/*!
\fn QColor::QColor(const char *name)
\overload
\sa setNamedColor(), name(), isValid()
*/
Constructs a named color in the same way as setNamedColor() using
the given \a name.
The color is left invalid if the \a name cannot be parsed.
/*!
\fn QColor::QColor(QLatin1String name)
\overload
\since 5.8
\sa setNamedColor(), name(), isValid()
*/
@ -881,6 +881,16 @@ void QColor::setNamedColor(const QString &name)
setColorFromString(name);
}
/*!
\overload
\since 5.8
*/
void QColor::setNamedColor(QLatin1String name)
{
setColorFromString(name);
}
/*!
\since 4.7
@ -897,16 +907,26 @@ bool QColor::isValidColor(const QString &name)
return !name.isEmpty() && QColor().setColorFromString(name);
}
bool QColor::setColorFromString(const QString &name)
/*!
\overload
\since 5.8
*/
bool QColor::isValidColor(QLatin1String name) Q_DECL_NOTHROW
{
if (name.isEmpty()) {
return name.size() && QColor().setColorFromString(name);
}
template <typename String>
bool QColor::setColorFromString(const String &name)
{
if (!name.size()) {
invalidate();
return true;
}
if (name.startsWith(QLatin1Char('#'))) {
if (name[0] == QLatin1Char('#')) {
QRgb rgba;
if (get_hex_rgb(name.constData(), name.length(), &rgba)) {
if (get_hex_rgb(name.data(), name.size(), &rgba)) {
setRgba(rgba);
return true;
} else {
@ -917,7 +937,7 @@ bool QColor::setColorFromString(const QString &name)
#ifndef QT_NO_COLORNAMES
QRgb rgb;
if (get_named_rgb(name.constData(), name.length(), &rgb)) {
if (get_named_rgb(name.data(), name.size(), &rgb)) {
setRgba(rgb);
return true;
} else

View File

@ -73,7 +73,8 @@ public:
QColor(QRgb rgb) Q_DECL_NOTHROW;
QColor(QRgba64 rgba64) Q_DECL_NOTHROW;
QColor(const QString& name);
QColor(const char *name);
QColor(const char *aname) : QColor(QLatin1String(aname)) {}
QColor(QLatin1String name);
QColor(Spec spec) Q_DECL_NOTHROW;
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
@ -93,7 +94,9 @@ public:
// ### Qt 6: merge overloads
QString name() const;
QString name(NameFormat format) const;
void setNamedColor(const QString& name);
void setNamedColor(QLatin1String name);
static QStringList colorNames();
@ -219,11 +222,13 @@ public:
operator QVariant() const;
static bool isValidColor(const QString &name);
static bool isValidColor(QLatin1String) Q_DECL_NOTHROW;
private:
void invalidate() Q_DECL_NOTHROW;
bool setColorFromString(const QString &name);
template <typename String>
bool setColorFromString(const String &name);
Spec cspec;
union {
@ -272,8 +277,8 @@ inline QColor::QColor() Q_DECL_NOTHROW
inline QColor::QColor(int r, int g, int b, int a)
{ setRgb(r, g, b, a); }
inline QColor::QColor(const char *aname)
{ setNamedColor(QLatin1String(aname)); }
inline QColor::QColor(QLatin1String aname)
{ setNamedColor(aname); }
inline QColor::QColor(const QString& aname)
{ setNamedColor(aname); }

View File

@ -52,6 +52,7 @@ private slots:
void name();
void namehex_data();
void namehex();
void setNamedColor_data();
void setNamedColor();
void constructNamedColorWithSpace();
@ -525,26 +526,49 @@ static const int rgbTblSize = sizeof(rgbTbl) / sizeof(RGBData);
#undef rgb
void tst_QColor::setNamedColor()
void tst_QColor::setNamedColor_data()
{
for (int i = 0; i < rgbTblSize; ++i) {
QTest::addColumn<QColor>("byCtor");
QTest::addColumn<QColor>("bySetNamedColor");
QTest::addColumn<QColor>("expected");
for (const auto e : rgbTbl) {
QColor expected;
expected.setRgba(rgbTbl[i].value);
expected.setRgba(e.value);
QColor color;
color.setNamedColor(QLatin1String(rgbTbl[i].name));
QCOMPARE(color, expected);
#define ROW(expr) \
do { \
QColor bySetNamedColor; \
bySetNamedColor.setNamedColor(expr); \
auto byCtor = QColor(expr); \
QTest::newRow(e.name + QByteArrayLiteral(#expr)) \
<< byCtor << bySetNamedColor << expected; \
} while (0) \
/*end*/
ROW(QLatin1String(e.name));
ROW(QString(QLatin1String(e.name)));
// name should be case insensitive
color.setNamedColor(QString(rgbTbl[i].name).toUpper());
QCOMPARE(color, expected);
ROW(QLatin1String(QByteArray(e.name).toUpper()));
ROW(QString(e.name).toUpper());
// spaces should be ignored
color.setNamedColor(QString(rgbTbl[i].name).insert(1, ' '));
QCOMPARE(color, expected);
ROW(QLatin1String(QByteArray(e.name).insert(1, ' ')));
ROW(QString(e.name).insert(1, ' '));
#undef ROW
}
}
void tst_QColor::setNamedColor()
{
QFETCH(QColor, byCtor);
QFETCH(QColor, bySetNamedColor);
QFETCH(QColor, expected);
QCOMPARE(byCtor, expected);
QCOMPARE(bySetNamedColor, expected);
}
void tst_QColor::constructNamedColorWithSpace()
{
QColor whiteSmoke("white smoke");
@ -556,7 +580,7 @@ void tst_QColor::colorNames()
QStringList all = QColor::colorNames();
QCOMPARE(all.size(), rgbTblSize);
for (int i = 0; i < all.size(); ++i)
QCOMPARE(all.at(i), QString::fromLatin1(rgbTbl[i].name));
QCOMPARE(all.at(i), QLatin1String(rgbTbl[i].name));
}
void tst_QColor::spec()