summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp39
-rw-r--r--src/corelib/tools/qunicodetools.cpp45
-rw-r--r--src/corelib/tools/qunicodetools_p.h3
-rw-r--r--src/gui/text/qtextengine.cpp16
4 files changed, 70 insertions, 33 deletions
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp
index 51b4ece4b1..5e8aed579d 100644
--- a/src/corelib/tools/qtextboundaryfinder.cpp
+++ b/src/corelib/tools/qtextboundaryfinder.cpp
@@ -53,39 +53,24 @@ public:
static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int length, QCharAttributes *attributes)
{
+ const ushort *string = reinterpret_cast<const ushort *>(chars);
+
QVarLengthArray<QUnicodeTools::ScriptItem> scriptItems;
+ {
+ QVarLengthArray<uchar> scripts(length);
- const ushort *string = reinterpret_cast<const ushort *>(chars);
- const ushort *unicode = string;
- // correctly assign script, isTab and isObject to the script analysis
- const ushort *uc = unicode;
- const ushort *e = uc + length;
- uchar script = QChar::Script_Common;
- uchar lastScript = QChar::Script_Common;
- const ushort *start = uc;
- while (uc < e) {
- int s = QChar::script(*uc);
- if (s != QChar::Script_Inherited)
- script = s;
- if (*uc == QChar::ObjectReplacementCharacter || *uc == QChar::LineSeparator || *uc == 9)
- script = QChar::Script_Common;
- if (script != lastScript) {
- if (uc != start) {
+ QUnicodeTools::initScripts(string, length, scripts.data());
+
+ int start = 0;
+ for (int i = start + 1; i <= length; ++i) {
+ if (i == length || scripts[i] != scripts[start]) {
QUnicodeTools::ScriptItem item;
- item.position = start - string;
- item.script = lastScript;
+ item.position = start;
+ item.script = scripts[start];
scriptItems.append(item);
- start = uc;
+ start = i;
}
- lastScript = script;
}
- ++uc;
- }
- if (uc != start) {
- QUnicodeTools::ScriptItem item;
- item.position = start - string;
- item.script = lastScript;
- scriptItems.append(item);
}
QUnicodeTools::CharAttributeOptions options = 0;
diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/tools/qunicodetools.cpp
index 3102035684..4d5c978fd5 100644
--- a/src/corelib/tools/qunicodetools.cpp
+++ b/src/corelib/tools/qunicodetools.cpp
@@ -635,6 +635,51 @@ Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
}
}
+
+// ----------------------------------------------------------------------------
+//
+// The Unicode script property. See http://www.unicode.org/reports/tr24/ (some very old version)
+//
+// ----------------------------------------------------------------------------
+
+Q_CORE_EXPORT void initScripts(const ushort *string, int length, uchar *scripts)
+{
+ int sor = 0;
+ int eor = -1;
+ uchar script = QChar::Script_Common;
+ for (int i = 0; i < length; ++i) {
+ eor = i;
+ uint ucs4 = string[i];
+ if (QChar::isHighSurrogate(ucs4) && i + 1 < length) {
+ ushort low = string[i + 1];
+ if (QChar::isLowSurrogate(low)) {
+ ucs4 = QChar::surrogateToUcs4(ucs4, low);
+ ++i;
+ }
+ }
+
+ const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ucs4);
+
+ if (Q_LIKELY(prop->script == script || prop->script == QChar::Script_Inherited))
+ continue;
+
+ // Never break between a combining mark (gc= Mc, Mn or Me) and its base character.
+ // Thus, a combining mark — whatever its script property value is — should inherit
+ // the script property value of its base character.
+ static const int test = (FLAG(QChar::Mark_NonSpacing) | FLAG(QChar::Mark_SpacingCombining) | FLAG(QChar::Mark_Enclosing));
+ if (Q_UNLIKELY(FLAG(prop->category) & test))
+ continue;
+
+ while (sor < eor)
+ scripts[sor++] = script;
+
+ script = prop->script;
+ }
+ eor = length;
+ while (sor < eor)
+ scripts[sor++] = script;
+}
+
} // namespace QUnicodeTools
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qunicodetools_p.h b/src/corelib/tools/qunicodetools_p.h
index 5a4f1659c4..5db3126159 100644
--- a/src/corelib/tools/qunicodetools_p.h
+++ b/src/corelib/tools/qunicodetools_p.h
@@ -96,6 +96,9 @@ Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
const ScriptItem *items, int numItems,
QCharAttributes *attributes, CharAttributeOptions options = DefaultOptionsCompat);
+
+Q_CORE_EXPORT void initScripts(const ushort *string, int length, uchar *scripts);
+
} // namespace QUnicodeTools
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index b312eae93e..a0deeddb33 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1309,6 +1309,8 @@ void QTextEngine::itemize() const
if (!length)
return;
+ const ushort *string = reinterpret_cast<const ushort *>(layoutData->string.unicode());
+
bool ignore = ignoreBidi;
bool rtl = isRightToLeft();
@@ -1342,9 +1344,15 @@ void QTextEngine::itemize() const
layoutData->hasBidi = bidiItemize(const_cast<QTextEngine *>(this), analysis, control);
}
- const ushort *uc = reinterpret_cast<const ushort *>(layoutData->string.unicode());
+ {
+ QVarLengthArray<uchar> scripts(length);
+ QUnicodeTools::initScripts(string, length, scripts.data());
+ for (int i = 0; i < length; ++i)
+ analysis[i].script = scripts.at(i);
+ }
+
+ const ushort *uc = string;
const ushort *e = uc + length;
- uchar lastScript = QChar::Script_Common;
while (uc < e) {
switch (*uc) {
case QChar::ObjectReplacementCharacter:
@@ -1374,13 +1382,9 @@ void QTextEngine::itemize() const
}
// fall through
default:
- analysis->script = QChar::script(*uc);
- if (analysis->script == QChar::Script_Inherited)
- analysis->script = lastScript;
analysis->flags = QScriptAnalysis::None;
break;
}
- lastScript = analysis->script;
analysis->script = hbscript_to_script(script_to_hbscript(analysis->script)); // retain the old behavior
++uc;
++analysis;