diff options
| author | Konstantin Ritt <ritt.ks@gmail.com> | 2012-08-26 04:09:09 +0300 |
|---|---|---|
| committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-09-22 00:47:40 +0200 |
| commit | ceb9a8232ca0fe9bc823b61ee3ca8bcdc0aa01c5 (patch) | |
| tree | d088f6fa8e4025b75ddd034240c74fb987fd7ebe /src/corelib/tools/qunicodetools.cpp | |
| parent | ed5fe1b95e818101d00e9415d8881ac836c505eb (diff) | |
A step out from Harfbuzz (reduce dependency)
Introduce QCharAttributes and use it instead of HB_CharAttributes everywhere in Qt
(in Harfbuzz, the HB_CharAttributes is only used in the text segmentation algorithm
which has been moved from HB to Qt (well, most of it)).
Rename some members to better reflect their meaning,
remember to keep HB_CharAttributes in sync with QCharAttributes.
Also replace HB_ScriptItem with a (temporary) QUnicodeTools::ScriptItem struct
that will be replaced with a more efficient/friendly solution a bit later.
The soft hyphen and the mandatory break detection has been factored out
of the default text breaking algorithm to a higher level in order to refactor
the QCharAttributes bitfields and to optimize the implementation for the common case.
Change-Id: Ieb365623ae954430f1c8b2dfcd65c82973143eec
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/corelib/tools/qunicodetools.cpp')
| -rw-r--r-- | src/corelib/tools/qunicodetools.cpp | 76 |
1 files changed, 49 insertions, 27 deletions
diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/tools/qunicodetools.cpp index f8db6cbac30..ffb9512229c 100644 --- a/src/corelib/tools/qunicodetools.cpp +++ b/src/corelib/tools/qunicodetools.cpp @@ -42,6 +42,9 @@ #include "qunicodetools_p.h" #include "qunicodetables_p.h" +#include "qvarlengtharray.h" + +#include <harfbuzz-shaper.h> #define FLAG(x) (1 << (x)) @@ -77,7 +80,7 @@ static const uchar breakTable[QUnicodeTables::GraphemeBreak_LVT + 1][QUnicodeTab } // namespace GB -static void getGraphemeBreaks(const ushort *string, quint32 len, HB_CharAttributes *attributes) +static void getGraphemeBreaks(const ushort *string, quint32 len, QCharAttributes *attributes) { QUnicodeTables::GraphemeBreakClass lcls = QUnicodeTables::GraphemeBreak_LF; // to meet GB1 for (quint32 i = 0; i != len; ++i) { @@ -94,7 +97,8 @@ static void getGraphemeBreaks(const ushort *string, quint32 len, HB_CharAttribut const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ucs4); QUnicodeTables::GraphemeBreakClass cls = (QUnicodeTables::GraphemeBreakClass) prop->graphemeBreakClass; - attributes[pos].charStop = GB::breakTable[lcls][cls]; + if (Q_LIKELY(GB::breakTable[lcls][cls])) + attributes[pos].graphemeBoundary = true; lcls = cls; } @@ -127,7 +131,7 @@ static const uchar breakTable[QUnicodeTables::WordBreak_ExtendNumLet + 1][QUnico } // namespace WB -static void getWordBreaks(const ushort *string, quint32 len, HB_CharAttributes *attributes) +static void getWordBreaks(const ushort *string, quint32 len, QCharAttributes *attributes) { QUnicodeTables::WordBreakClass cls = QUnicodeTables::WordBreak_LF; // to meet WB1 for (quint32 i = 0; i != len; ++i) { @@ -175,7 +179,7 @@ static void getWordBreaks(const ushort *string, quint32 len, HB_CharAttributes * } cls = ncls; if (action == WB::Break) - attributes[pos].wordBoundary = true; + attributes[pos].wordBreak = true; } } @@ -217,7 +221,7 @@ static const uchar breakTable[BAfter + 1][QUnicodeTables::SentenceBreak_Close + } // namespace SB -static void getSentenceBreaks(const ushort *string, quint32 len, HB_CharAttributes *attributes) +static void getSentenceBreaks(const ushort *string, quint32 len, QCharAttributes *attributes) { uchar state = SB::BAfter; // to meet SB1 for (quint32 i = 0; i != len; ++i) { @@ -402,12 +406,11 @@ static const uchar breakTable[QUnicodeTables::LineBreak_CB + 1][QUnicodeTables:: } // namespace LB -static void getLineBreaks(const ushort *string, quint32 len, HB_CharAttributes *attributes) +static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *attributes) { quint32 nestart = 0; LB::NS::Class nelast = LB::NS::XX; - uint lucs4 = 0; QUnicodeTables::LineBreakClass lcls = QUnicodeTables::LineBreak_LF; // to meet LB10 QUnicodeTables::LineBreakClass cls = lcls; for (quint32 i = 0; i != len; ++i) { @@ -443,7 +446,7 @@ static void getLineBreaks(const ushort *string, quint32 len, HB_CharAttributes * case LB::NS::Break: // do not change breaks before and after the expression for (quint32 j = nestart + 1; j < pos; ++j) - attributes[j].lineBreakType = HB_NoBreak; + attributes[j].lineBreak = false; // fall through case LB::NS::None: nelast = LB::NS::XX; // reset state @@ -457,12 +460,10 @@ static void getLineBreaks(const ushort *string, quint32 len, HB_CharAttributes * } } - HB_LineBreakType lineBreakType = HB_NoBreak; - if (Q_UNLIKELY(lcls >= QUnicodeTables::LineBreak_CR)) { // LB4: BK!, LB5: (CRxLF|CR|LF|NL)! if (lcls > QUnicodeTables::LineBreak_CR || ncls != QUnicodeTables::LineBreak_LF) - lineBreakType = HB_ForcedBreak; + attributes[pos].lineBreak = true; goto next; } @@ -479,18 +480,16 @@ static void getLineBreaks(const ushort *string, quint32 len, HB_CharAttributes * switch (LB::breakTable[cls][ncls < QUnicodeTables::LineBreak_SA ? ncls : QUnicodeTables::LineBreak_AL]) { case LB::DirectBreak: - lineBreakType = HB_Break; - if (lucs4 == QChar::SoftHyphen) - lineBreakType = HB_SoftHyphen; + attributes[pos].lineBreak = true; break; case LB::IndirectBreak: if (lcls == QUnicodeTables::LineBreak_SP) - lineBreakType = HB_Break; + attributes[pos].lineBreak = true; break; case LB::CombiningIndirectBreak: if (lcls != QUnicodeTables::LineBreak_SP) goto next_no_cls_update; - lineBreakType = HB_Break; + attributes[pos].lineBreak = true; break; case LB::CombiningProhibitedBreak: if (lcls != QUnicodeTables::LineBreak_SP) @@ -504,24 +503,21 @@ static void getLineBreaks(const ushort *string, quint32 len, HB_CharAttributes * next: cls = ncls; - lucs4 = ucs4; next_no_cls_update: lcls = ncls; - if (Q_LIKELY(lineBreakType != HB_NoBreak)) - attributes[pos].lineBreakType = lineBreakType; } if (Q_UNLIKELY(LB::NS::actionTable[nelast][LB::NS::XX] == LB::NS::Break)) { // LB25: do not break lines inside numbers for (quint32 j = nestart + 1; j < len; ++j) - attributes[j].lineBreakType = HB_NoBreak; + attributes[j].lineBreak = false; } - attributes[0].lineBreakType = HB_NoBreak; // LB2 + attributes[0].lineBreak = false; // LB2 } -static void getWhiteSpaces(const ushort *string, quint32 len, HB_CharAttributes *attributes) +static void getWhiteSpaces(const ushort *string, quint32 len, QCharAttributes *attributes) { for (quint32 i = 0; i != len; ++i) { uint ucs4 = string[i]; @@ -540,14 +536,14 @@ static void getWhiteSpaces(const ushort *string, quint32 len, HB_CharAttributes Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length, - const HB_ScriptItem *items, int numItems, - HB_CharAttributes *attributes, CharAttributeOptions options) + const ScriptItem *items, int numItems, + QCharAttributes *attributes, CharAttributeOptions options) { if (length <= 0) return; if (!(options & DontClearAttributes)) - ::memset(attributes, 0, length * sizeof(HB_CharAttributes)); + ::memset(attributes, 0, length * sizeof(QCharAttributes)); if (options & GraphemeBreaks) getGraphemeBreaks(string, length, attributes); @@ -562,8 +558,34 @@ Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length, if (!items || numItems <= 0) return; - if (!qt_initcharattributes_default_algorithm_only) - HB_GetTailoredCharAttributes(string, length, items, numItems, attributes); + if (!qt_initcharattributes_default_algorithm_only) { + QVarLengthArray<HB_ScriptItem, 64> scriptItems; + scriptItems.reserve(numItems); + int start = 0; + for (int i = start + 1; i < numItems; ++i) { + if (items[i].script == items[start].script) + continue; + HB_ScriptItem item; + item.pos = items[start].position; + item.length = items[i].position - items[start].position; + item.script = (HB_Script)items[start].script; + item.bidiLevel = 0; // unused + scriptItems.append(item); + start = i; + } + if (items[start].position + 1 < length) { + HB_ScriptItem item; + item.pos = items[start].position; + item.length = length - items[start].position; + item.script = (HB_Script)items[start].script; + item.bidiLevel = 0; // unused + scriptItems.append(item); + } + Q_STATIC_ASSERT(sizeof(QCharAttributes) == sizeof(HB_CharAttributes)); + HB_GetTailoredCharAttributes(string, length, + scriptItems.constData(), scriptItems.size(), + reinterpret_cast<HB_CharAttributes *>(attributes)); + } } } // namespace QUnicodeTools |
