Skip to content

Commit

Permalink
[qtbase] Cherry-pick text rendering fix for isolated indic characters…
Browse files Browse the repository at this point in the history
…. Fixes MER#1281

Conflicts:
	tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
-> Changed omitted.

Original commit 0ec07b6

Improve the Unicode script itemization implementation

Make it closer to the Unicode specs (UAX#24):
* Common now inherits the preceding character's script, if any;
* In a combining character sequence, if the base character is
  of Common script, the entire sequence is treated like if it were
  of the first non-Inherited, non-Common script in the sequence.
See http://www.unicode.org/reports/tr24/tr24-21.html for more details.

[ChangeLog][QtGui] Fixed regression in arabic text rendering.

Task-number: QTBUG-28813
Task-number: QTBUG-29930 (related)
Task-number: QTBUG-35836
Change-Id: Id85761965b08ca94c674d5f3613fe58b82b2ce9c
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@digia.com>
Reviewed-by: Ahmed Saidi <justroftest@gmail.com>
  • Loading branch information
pvuorela committed Sep 1, 2015
1 parent 7ca28b1 commit f23ac1e
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 20 deletions.
38 changes: 34 additions & 4 deletions src/corelib/tools/qunicodetools.cpp
Expand Up @@ -645,7 +645,7 @@ 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)
// The Unicode script property. See http://www.unicode.org/reports/tr24/tr24-21.html
//
// ----------------------------------------------------------------------------

Expand All @@ -667,22 +667,52 @@ Q_CORE_EXPORT void initScripts(const ushort *string, int length, uchar *scripts)

const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ucs4);

if (Q_LIKELY(prop->script == script || prop->script == QChar::Script_Inherited))
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;
if (Q_UNLIKELY(FLAG(prop->category) & test)) {
// In cases where the base character itself has the Common script property value,
// and it is followed by one or more combining marks with a specific script property value,
// it may be even better for processing to let the base acquire the script property value
// from the first mark. This approach can be generalized by treating all the characters
// of a combining character sequence as having the script property value
// of the first non-Inherited, non-Common character in the sequence if there is one,
// and otherwise treating all the characters as having the Common script property value.
if (Q_LIKELY(script > QChar::Script_Common || prop->script <= QChar::Script_Common))
continue;

script = QChar::Script(prop->script);
}

if (Q_LIKELY(script != QChar::Script_Common)) {
// override preceding Common-s
while (sor > 0 && scripts[sor - 1] == QChar::Script_Common)
--sor;
} else {
// see if we are inheriting preceding run
if (sor > 0)
script = scripts[sor - 1];
}

while (sor < eor)
scripts[sor++] = script;

script = prop->script;
}
eor = length;
if (Q_LIKELY(script != QChar::Script_Common)) {
// override preceding Common-s
while (sor > 0 && scripts[sor - 1] == QChar::Script_Common)
--sor;
} else {
// see if we are inheriting preceding run
if (sor > 0)
script = scripts[sor - 1];
}
while (sor < eor)
scripts[sor++] = script;
}
Expand Down
17 changes: 1 addition & 16 deletions src/gui/text/qtextengine.cpp
Expand Up @@ -122,20 +122,9 @@ class Itemizer {
return;
const int end = start + length;
for (int i = start + 1; i < end; ++i) {
// According to the unicode spec we should be treating characters in the Common script
// (punctuation, spaces, etc) as being the same script as the surrounding text for the
// purpose of splitting up text. This is important because, for example, a fullstop
// (0x2E) can be used to indicate an abbreviation and so must be treated as part of a
// word. Thus it must be passed along with the word in languages that have to calculate
// word breaks. For example the thai word "ครม." has no word breaks but the word "ครม"
// does.
// Unfortuntely because we split up the strings for both wordwrapping and for setting
// the font and because Japanese and Chinese are also aliases of the script "Common",
// doing this would break too many things. So instead we only pass the full stop
// along, and nothing else.
if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel
&& m_analysis[i].flags == m_analysis[start].flags
&& (m_analysis[i].script == m_analysis[start].script || m_string[i] == QLatin1Char('.'))
&& m_analysis[i].script == m_analysis[start].script
&& m_analysis[i].flags < QScriptAnalysis::SpaceTabOrObject
&& i - start < MaxItemLength)
continue;
Expand Down Expand Up @@ -1477,26 +1466,22 @@ void QTextEngine::itemize() const
while (uc < e) {
switch (*uc) {
case QChar::ObjectReplacementCharacter:
analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::Object;
break;
case QChar::LineSeparator:
if (analysis->bidiLevel % 2)
--analysis->bidiLevel;
analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::LineOrParagraphSeparator;
if (option.flags() & QTextOption::ShowLineAndParagraphSeparators)
*const_cast<ushort*>(uc) = 0x21B5; // visual line separator
break;
case QChar::Tabulation:
analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::Tab;
analysis->bidiLevel = control.baseLevel();
break;
case QChar::Space:
case QChar::Nbsp:
if (option.flags() & QTextOption::ShowTabsAndSpaces) {
analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::Space;
analysis->bidiLevel = control.baseLevel();
break;
Expand Down

0 comments on commit f23ac1e

Please sign in to comment.