Introduce QChar::JoiningType enum and QChar::joiningType() method

This aimed to disctinct joining types "L", "T", and "U" from just "U".
Unicode 6.3.0 has introduced a character with joining type "L" and
Unicode 7.0 will add a few more characters of joining type "L", so
we'll have to deal with it anyways.

[ChangeLog][QtCore][QChar] Added JoiningType enum and joiningType()
 method that deprecates the old QChar::Joining enum and joining() method.

Change-Id: I4be3a3f745d944e689feb9b62d4ca86d1cf371b0
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Konstantin Ritt 2014-01-26 02:42:37 +02:00 committed by The Qt Project
parent b04d87b226
commit b80fcbdba6
6 changed files with 162 additions and 59 deletions

View File

@ -127,9 +127,9 @@ QT_BEGIN_NAMESPACE
Separator_* or an exceptional code point from Other_Control category).
QChar also provides direction(), which indicates the "natural"
writing direction of this character. The joining() function
writing direction of this character. The joiningType() function
indicates how the character joins with it's neighbors (needed
mostly for Arabic) and finally hasMirrored(), which indicates
mostly for Arabic or Syriac) and finally hasMirrored(), which indicates
whether the character needs to be mirrored when it is printed in
it's "unnatural" writing direction.
@ -457,8 +457,30 @@ QT_BEGIN_NAMESPACE
\sa decomposition()
*/
/*!
\enum QChar::JoiningType
since 5.3
This enum type defines the Unicode joining type attributes. See the
\l{http://www.unicode.org/}{Unicode Standard} for a description of the values.
In order to conform to C/C++ naming conventions "Joining_" is prepended
to the codes used in the Unicode Standard.
\value Joining_None
\value Joining_Causing
\value Joining_Dual
\value Joining_Right
\value Joining_Left
\value Joining_Transparent
\sa joiningType()
*/
#if QT_DEPRECATED_SINCE(5, 3)
/*!
\enum QChar::Joining
\deprecated in 5.3, use JoiningType instead.
This enum type defines the Unicode joining attributes. See the
\l{http://www.unicode.org/}{Unicode Standard} for a description
@ -471,6 +493,7 @@ QT_BEGIN_NAMESPACE
\sa joining()
*/
#endif
/*!
\enum QChar::CombiningClass
@ -1052,8 +1075,33 @@ QChar::Direction QChar::direction(uint ucs4)
return (QChar::Direction) qGetProp(ucs4)->direction;
}
/*!
\fn QChar::JoiningType QChar::joiningType() const
\since 5.3
Returns information about the joining type attributes of the character
(needed for certain languages such as Arabic or Syriac).
*/
/*!
\overload
\since 5.3
Returns information about the joining type attributes of the UCS-4-encoded
character specified by \a ucs4
(needed for certain languages such as Arabic or Syriac).
*/
QChar::JoiningType QChar::joiningType(uint ucs4)
{
if (ucs4 > LastValidCodePoint)
return QChar::Joining_None;
return QChar::JoiningType(qGetProp(ucs4)->joining);
}
#if QT_DEPRECATED_SINCE(5, 3)
/*!
\fn QChar::Joining QChar::joining() const
\deprecated in 5.3, use joiningType() instead.
Returns information about the joining properties of the character
(needed for certain languages such as Arabic).
@ -1061,6 +1109,8 @@ QChar::Direction QChar::direction(uint ucs4)
/*!
\overload
\deprecated in 5.3, use joiningType() instead.
Returns information about the joining properties of the UCS-4-encoded
character specified by \a ucs4 (needed for certain languages such as Arabic).
*/
@ -1068,8 +1118,15 @@ QChar::Joining QChar::joining(uint ucs4)
{
if (ucs4 > LastValidCodePoint)
return QChar::OtherJoining;
return (QChar::Joining) qGetProp(ucs4)->joining;
switch (qGetProp(ucs4)->joining) {
case QChar::Joining_Causing: return QChar::Center;
case QChar::Joining_Dual: return QChar::Dual;
case QChar::Joining_Right: return QChar::Right;
default: break;
}
return QChar::OtherJoining;
}
#endif
/*!
\fn bool QChar::hasMirrored() const

View File

@ -288,10 +288,21 @@ public:
Fraction
};
enum JoiningType {
Joining_None,
Joining_Causing,
Joining_Dual,
Joining_Right,
Joining_Left,
Joining_Transparent
};
#if QT_DEPRECATED_SINCE(5, 3)
enum Joining
{
OtherJoining, Dual, Right, Center
};
#endif
enum CombiningClass
{
@ -340,7 +351,17 @@ public:
inline Category category() const { return QChar::category(ucs); }
inline Direction direction() const { return QChar::direction(ucs); }
inline Joining joining() const { return QChar::joining(ucs); }
inline JoiningType joiningType() const { return QChar::joiningType(ucs); }
#if QT_DEPRECATED_SINCE(5, 3)
QT_DEPRECATED inline Joining joining() const {
switch (QChar::joiningType(ucs)) {
case QChar::Joining_Causing: return QChar::Center;
case QChar::Joining_Dual: return QChar::Dual;
case QChar::Joining_Right: return QChar::Right;
default: return QChar::OtherJoining;
}
}
#endif
inline unsigned char combiningClass() const { return QChar::combiningClass(ucs); }
inline QChar mirroredChar() const { return QChar::mirroredChar(ucs); }
@ -427,7 +448,10 @@ public:
static Category QT_FASTCALL category(uint ucs4);
static Direction QT_FASTCALL direction(uint ucs4);
static Joining QT_FASTCALL joining(uint ucs4);
static JoiningType QT_FASTCALL joiningType(uint ucs4);
#if QT_DEPRECATED_SINCE(5, 3)
QT_DEPRECATED static Joining QT_FASTCALL joining(uint ucs4);
#endif
static unsigned char QT_FASTCALL combiningClass(uint ucs4);
static uint QT_FASTCALL mirroredChar(uint ucs4);

View File

@ -908,7 +908,17 @@ public:
QChar::Category category() const { return QChar(*this).category(); }
QChar::Direction direction() const { return QChar(*this).direction(); }
QChar::Joining joining() const { return QChar(*this).joining(); }
QChar::JoiningType joiningType() const { return QChar(*this).joiningType(); }
#if QT_DEPRECATED_SINCE(5, 3)
QT_DEPRECATED QChar::Joining joining() const {
switch (QChar(*this).joiningType()) {
case QChar::Joining_Causing: return QChar::Center;
case QChar::Joining_Dual: return QChar::Dual;
case QChar::Joining_Right: return QChar::Right;
default: return QChar::OtherJoining;
}
}
#endif
bool hasMirrored() const { return QChar(*this).hasMirrored(); }
QChar mirroredChar() const { return QChar(*this).mirroredChar(); }
QString decomposition() const { return QChar(*this).decomposition(); }

View File

@ -2537,8 +2537,8 @@ static inline bool nextCharJoins(const QString &string, int pos)
++pos;
if (pos == string.length())
return false;
// ### U+A872 has joining type L
return string.at(pos) == QChar(0xA872) || string.at(pos).joining() != QChar::OtherJoining;
QChar::JoiningType joining = string.at(pos).joiningType();
return joining != QChar::Joining_None && joining != QChar::Joining_Transparent;
}
static inline bool prevCharJoins(const QString &string, int pos)
@ -2547,8 +2547,8 @@ static inline bool prevCharJoins(const QString &string, int pos)
--pos;
if (pos == 0)
return false;
QChar::Joining joining = string.at(pos - 1).joining();
return (joining == QChar::Dual || joining == QChar::Center);
QChar::JoiningType joining = string.at(pos - 1).joiningType();
return joining == QChar::Joining_Dual || joining == QChar::Joining_Causing;
}
static inline bool isRetainableControlCode(QChar c)

View File

@ -74,7 +74,7 @@ private slots:
void isSpaceSpecial();
void category();
void direction();
void joining();
void joiningType();
void combiningClass();
void digitValue();
void mirroredChar();
@ -483,30 +483,32 @@ void tst_QChar::direction()
QVERIFY(QChar::direction(0x2FA17u) == QChar::DirL);
}
void tst_QChar::joining()
void tst_QChar::joiningType()
{
QVERIFY(QChar('a').joining() == QChar::OtherJoining);
QVERIFY(QChar('0').joining() == QChar::OtherJoining);
QVERIFY(QChar((ushort)0x627).joining() == QChar::Right);
QVERIFY(QChar((ushort)0x5d0).joining() == QChar::OtherJoining);
QVERIFY(QChar('a').joiningType() == QChar::Joining_None);
QVERIFY(QChar('0').joiningType() == QChar::Joining_None);
QVERIFY(QChar((ushort)0x0627).joiningType() == QChar::Joining_Right);
QVERIFY(QChar((ushort)0x05d0).joiningType() == QChar::Joining_None);
QVERIFY(QChar((ushort)0x00ad).joiningType() == QChar::Joining_Transparent);
QVERIFY(QChar::joining((ushort)'a') == QChar::OtherJoining);
QVERIFY(QChar::joining((ushort)'0') == QChar::OtherJoining);
QVERIFY(QChar::joining((ushort)0x627) == QChar::Right);
QVERIFY(QChar::joining((ushort)0x5d0) == QChar::OtherJoining);
QVERIFY(QChar::joiningType((ushort)'a') == QChar::Joining_None);
QVERIFY(QChar::joiningType((ushort)'0') == QChar::Joining_None);
QVERIFY(QChar::joiningType((ushort)0x0627) == QChar::Joining_Right);
QVERIFY(QChar::joiningType((ushort)0x05d0) == QChar::Joining_None);
QVERIFY(QChar::joiningType((ushort)0x00ad) == QChar::Joining_Transparent);
QVERIFY(QChar::joining((uint)'a') == QChar::OtherJoining);
QVERIFY(QChar::joining((uint)'0') == QChar::OtherJoining);
QVERIFY(QChar::joining((uint)0x627) == QChar::Right);
QVERIFY(QChar::joining((uint)0x5d0) == QChar::OtherJoining);
QVERIFY(QChar::joiningType((uint)'a') == QChar::Joining_None);
QVERIFY(QChar::joiningType((uint)'0') == QChar::Joining_None);
QVERIFY(QChar::joiningType((uint)0x0627) == QChar::Joining_Right);
QVERIFY(QChar::joiningType((uint)0x05d0) == QChar::Joining_None);
QVERIFY(QChar::joiningType((uint)0x00ad) == QChar::Joining_Transparent);
QVERIFY(QChar::joining(0xE01DAu) == QChar::OtherJoining);
QVERIFY(QChar::joining(0xf0000u) == QChar::OtherJoining);
QVERIFY(QChar::joining(0xE0030u) == QChar::OtherJoining);
QVERIFY(QChar::joining(0x2FA17u) == QChar::OtherJoining);
QVERIFY(QChar::joiningType(0xE01DAu) == QChar::Joining_Transparent);
QVERIFY(QChar::joiningType(0xf0000u) == QChar::Joining_None);
QVERIFY(QChar::joiningType(0xE0030u) == QChar::Joining_Transparent);
QVERIFY(QChar::joiningType(0x2FA17u) == QChar::Joining_None);
// ### U+A872 has joining type L
QVERIFY(QChar::joining((uint)0xA872) == QChar::OtherJoining);
QVERIFY(QChar::joiningType((uint)0xA872) == QChar::Joining_Left);
}
void tst_QChar::combiningClass()

View File

@ -246,30 +246,30 @@ static void initDirectionMap()
}
enum Joining {
enum JoiningType {
Joining_None,
Joining_Left,
Joining_Causing,
Joining_Dual,
Joining_Right,
Joining_Left,
Joining_Transparent
, Joining_Unassigned
};
static QHash<QByteArray, Joining> joining_map;
static QHash<QByteArray, JoiningType> joining_map;
static void initJoiningMap()
{
struct JoiningList {
Joining joining;
JoiningType joining;
const char *name;
} joinings[] = {
{ Joining_None, "U" },
{ Joining_Left, "L" },
{ Joining_Causing, "C" },
{ Joining_Dual, "D" },
{ Joining_Right, "R" },
{ Joining_Left, "L" },
{ Joining_Transparent, "T" },
{ Joining_Unassigned, 0 }
};
@ -719,8 +719,8 @@ static const char *property_string =
" ushort category : 8; /* 5 used */\n"
" ushort direction : 8; /* 5 used */\n"
" ushort combiningClass : 8;\n"
" ushort joining : 2;\n"
" signed short digitValue : 6; /* 5 used */\n"
" ushort joining : 3;\n"
" signed short digitValue : 5; /* 5 used */\n"
" signed short mirrorDiff : 16;\n"
" signed short lowerCaseDiff : 16;\n"
" signed short upperCaseDiff : 16;\n"
@ -792,7 +792,7 @@ struct PropertyFlags {
QChar::Category category : 5;
QChar::Direction direction : 5;
// from ArabicShaping.txt
QChar::Joining joining : 2;
QChar::JoiningType joining : 3;
// from DerivedAge.txt
QChar::UnicodeVersion age : 4;
int digitValue;
@ -944,7 +944,7 @@ struct UnicodeData {
mirroredChar = 0;
decompositionType = QChar::NoDecomposition;
p.joining = QChar::OtherJoining;
p.joining = QChar::Joining_None;
p.age = QChar::Unicode_Unassigned;
p.mirrorDiff = 0;
p.digitValue = -1;
@ -1171,7 +1171,7 @@ static void readUnicodeData()
if (d[0].contains('<')) {
data.decompositionType = decompositionMap.value(d[0], QChar::NoDecomposition);
if (data.decompositionType == QChar::NoDecomposition)
qFatal("unassigned decomposition type: %s", d[0].constData());
qFatal("unhandled decomposition type: %s", d[0].constData());
d.takeFirst();
} else {
data.decompositionType = QChar::Canonical;
@ -1261,24 +1261,34 @@ static void readArabicShaping()
int codepoint = l[0].toInt(&ok, 16);
Q_ASSERT(ok);
Joining joining = joining_map.value(l[2].trimmed(), Joining_Unassigned);
if (joining == Joining_Unassigned)
qFatal("unassigned or unhandled joining value: %s", l[2].constData());
if (joining == Joining_Left) {
qWarning("ACHTUNG!!! joining type '%s' has been met for U+%X; the current implementation needs to be revised!",
l[2].trimmed().constData(), codepoint);
}
UnicodeData &d = UnicodeData::valueRef(codepoint);
if (joining == Joining_Right)
d.p.joining = QChar::Right;
else if (joining == Joining_Dual)
d.p.joining = QChar::Dual;
else if (joining == Joining_Causing)
d.p.joining = QChar::Center;
else
d.p.joining = QChar::OtherJoining;
JoiningType joining = joining_map.value(l[2].trimmed(), Joining_Unassigned);
switch (joining) {
case Joining_Unassigned:
qFatal("%x: unassigned or unhandled joining type: %s", codepoint, l[2].constData());
break;
case Joining_Transparent:
if (d.p.category != QChar::Mark_NonSpacing && d.p.category != QChar::Mark_Enclosing && d.p.category != QChar::Other_Format) {
qFatal("%x: joining type '%s' was met; the current implementation needs to be revised!",
codepoint, l[2].constData());
}
// fall through
default:
d.p.joining = QChar::JoiningType(joining);
break;
}
}
// Code points that are not explicitly listed in ArabicShaping.txt are either of joining type T or U:
// - Those that not explicitly listed that are of General Category Mn, Me, or Cf have joining type T.
// - All others not explicitly listed have joining type U.
for (int codepoint = 0; codepoint <= QChar::LastValidCodePoint; ++codepoint) {
UnicodeData &d = UnicodeData::valueRef(codepoint);
if (d.p.joining == QChar::Joining_None) {
if (d.p.category == QChar::Mark_NonSpacing || d.p.category == QChar::Mark_Enclosing || d.p.category == QChar::Other_Format)
d.p.joining = QChar::Joining_Transparent;
}
}
}
@ -2332,10 +2342,10 @@ static QByteArray createPropertyInfo()
// " ushort combiningClass : 8;\n"
out += QByteArray::number( p.combiningClass );
out += ", ";
// " ushort joining : 2;\n"
// " ushort joining : 3;\n"
out += QByteArray::number( p.joining );
out += ", ";
// " signed short digitValue : 6; /* 5 used */\n"
// " signed short digitValue : 5; /* 5 used */\n"
out += QByteArray::number( p.digitValue );
out += ", ";
// " signed short mirrorDiff : 16;\n"