summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp4
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-khmer.c4
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c6
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.h19
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-thai.c20
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-tibetan.c4
-rw-r--r--src/corelib/tools/qharfbuzz_p.h3
-rw-r--r--src/corelib/tools/qtextboundaryfinder.cpp62
-rw-r--r--src/corelib/tools/qunicodetools.cpp76
-rw-r--r--src/corelib/tools/qunicodetools_p.h24
-rw-r--r--src/gui/text/qharfbuzz_copy_p.h18
-rw-r--r--src/gui/text/qtextengine.cpp60
-rw-r--r--src/gui/text/qtextengine_p.h6
-rw-r--r--src/gui/text/qtextlayout.cpp25
14 files changed, 171 insertions, 160 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
index bbf479e774..0dcddc4f7d 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-indic.cpp
@@ -1880,12 +1880,12 @@ void HB_IndicAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from
while (i < len) {
bool invalid;
hb_uint32 boundary = indic_nextSyllableBoundary(script, text, from+i, end, &invalid) - from;
- attributes[i].charStop = true;
+ attributes[i].graphemeBoundary = true;
if (boundary > len-1) boundary = len;
i++;
while (i < boundary) {
- attributes[i].charStop = false;
+ attributes[i].graphemeBoundary = false;
++uc;
++i;
}
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-khmer.c b/src/3rdparty/harfbuzz/src/harfbuzz-khmer.c
index 958069e866..1f3c7e2bce 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-khmer.c
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-khmer.c
@@ -652,12 +652,12 @@ void HB_KhmerAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 from
HB_Bool invalid;
hb_uint32 boundary = khmer_nextSyllableBoundary( text, from+i, end, &invalid ) - from;
- attributes[i].charStop = TRUE;
+ attributes[i].graphemeBoundary = TRUE;
if ( boundary > len-1 ) boundary = len;
i++;
while ( i < boundary ) {
- attributes[i].charStop = FALSE;
+ attributes[i].graphemeBoundary = FALSE;
++uc;
++i;
}
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c b/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c
index 1327b185b0..b18b83054d 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c
@@ -520,14 +520,14 @@ void HB_MyanmarAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 fr
HB_Bool invalid;
hb_uint32 boundary = myanmar_nextSyllableBoundary(text, from+i, end, &invalid) - from;
- attributes[i].charStop = TRUE;
- attributes[i].lineBreakType = HB_Break;
+ attributes[i].graphemeBoundary = TRUE;
+ attributes[i].lineBreak = TRUE;
if (boundary > len-1)
boundary = len;
i++;
while (i < boundary) {
- attributes[i].charStop = FALSE;
+ attributes[i].graphemeBoundary = FALSE;
++uc;
++i;
}
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h
index 6dfcdd20a7..2ff52eaf30 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h
@@ -126,21 +126,14 @@ typedef struct
hb_uint8 bidiLevel;
} HB_ScriptItem;
-typedef enum {
- HB_NoBreak,
- HB_SoftHyphen,
- HB_Break,
- HB_ForcedBreak
-} HB_LineBreakType;
-
typedef struct {
- /*HB_LineBreakType*/ hb_bitfield lineBreakType :2;
- /*HB_Bool*/ hb_bitfield whiteSpace :1; /* A unicode whitespace character, except NBSP, ZWNBSP */
- /*HB_Bool*/ hb_bitfield charStop :1; /* Valid cursor position (for left/right arrow) */
- /*HB_Bool*/ hb_bitfield wordBoundary :1;
- /*HB_Bool*/ hb_bitfield sentenceBoundary :1;
- hb_bitfield unused :2;
+ hb_bitfield graphemeBoundary : 1; /* Valid cursor position (for left/right arrow) */
+ hb_bitfield wordBreak : 1;
+ hb_bitfield sentenceBoundary : 1;
+ hb_bitfield lineBreak : 1;
+ hb_bitfield whiteSpace : 1; /* A unicode whitespace character */
+ hb_bitfield unused : 3;
} HB_CharAttributes;
void HB_GetTailoredCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength,
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c
index ecb722d984..70c1d57ff1 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c
@@ -395,8 +395,8 @@ static void HB_ThaiAssignAttributes(const HB_UChar16 *string, hb_uint32 len, HB_
to_tis620(string, len, cstr);
for (i = 0; i < len; ++i) {
- attributes[i].lineBreakType = HB_NoBreak;
- attributes[i].wordBoundary = FALSE;
+ attributes[i].lineBreak = FALSE;
+ attributes[i].wordBreak = FALSE;
}
if (len > 128) {
@@ -410,29 +410,29 @@ static void HB_ThaiAssignAttributes(const HB_UChar16 *string, hb_uint32 len, HB_
}
if (break_positions) {
- attributes[0].wordBoundary = TRUE;
+ attributes[0].wordBreak = TRUE;
numbreaks = th_brk((const unsigned char *)cstr, break_positions, brp_size);
for (i = 0; i < numbreaks; ++i) {
- attributes[break_positions[i]].wordBoundary = TRUE;
- attributes[break_positions[i]].lineBreakType = HB_Break;
+ attributes[break_positions[i]].wordBreak = TRUE;
+ attributes[break_positions[i]].lineBreak = TRUE;
}
if (break_positions != brp)
free(break_positions);
}
- /* manage charStop */
+ /* manage grapheme boundaries */
i = 0;
while (i < len) {
cell_length = th_next_cell((const unsigned char *)cstr + i, len - i, &tis_cell, true);
- attributes[i].charStop = true;
+ attributes[i].graphemeBoundary = true;
for (j = 1; j < cell_length; j++)
- attributes[i + j].charStop = false;
+ attributes[i + j].graphemeBoundary = false;
- /* Set charStop for SARA AM */
+ /* Set graphemeBoundary for SARA AM */
if (cstr[i + cell_length - 1] == (char)0xd3)
- attributes[i + cell_length - 1].charStop = true;
+ attributes[i + cell_length - 1].graphemeBoundary = true;
i += cell_length;
}
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-tibetan.c b/src/3rdparty/harfbuzz/src/harfbuzz-tibetan.c
index e0c263d426..c3570974b3 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-tibetan.c
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-tibetan.c
@@ -260,12 +260,12 @@ void HB_TibetanAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 fr
HB_Bool invalid;
hb_uint32 boundary = tibetan_nextSyllableBoundary(text, from+i, end, &invalid) - from;
- attributes[i].charStop = TRUE;
+ attributes[i].graphemeBoundary = TRUE;
if (boundary > len-1) boundary = len;
i++;
while (i < boundary) {
- attributes[i].charStop = FALSE;
+ attributes[i].graphemeBoundary = FALSE;
++uc;
++i;
}
diff --git a/src/corelib/tools/qharfbuzz_p.h b/src/corelib/tools/qharfbuzz_p.h
index 23de3efa16..72d5bda77f 100644
--- a/src/corelib/tools/qharfbuzz_p.h
+++ b/src/corelib/tools/qharfbuzz_p.h
@@ -65,9 +65,6 @@ Q_CORE_EXPORT HB_Face qHBNewFace(void *font, HB_GetFontTableFunc tableFunc);
Q_CORE_EXPORT void qHBFreeFace(HB_Face);
Q_CORE_EXPORT HB_Face qHBLoadFace(HB_Face face);
-Q_DECLARE_TYPEINFO(HB_CharAttributes, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(HB_ScriptItem, Q_PRIMITIVE_TYPE);
-
Q_DECLARE_TYPEINFO(HB_GlyphAttributes, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(HB_FixedPoint, Q_PRIMITIVE_TYPE);
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp
index c3d44da042..f928932548 100644
--- a/src/corelib/tools/qtextboundaryfinder.cpp
+++ b/src/corelib/tools/qtextboundaryfinder.cpp
@@ -49,12 +49,12 @@ QT_BEGIN_NAMESPACE
class QTextBoundaryFinderPrivate
{
public:
- HB_CharAttributes attributes[1];
+ QCharAttributes attributes[1];
};
-static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int length, HB_CharAttributes *attributes)
+static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int length, QCharAttributes *attributes)
{
- QVarLengthArray<HB_ScriptItem> scriptItems;
+ QVarLengthArray<QUnicodeTools::ScriptItem> scriptItems;
const ushort *string = reinterpret_cast<const ushort *>(chars);
const ushort *unicode = string;
@@ -72,11 +72,9 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
script = QUnicodeTables::Common;
if (script != lastScript) {
if (uc != start) {
- HB_ScriptItem item;
- item.pos = start - string;
- item.length = uc - start;
- item.script = (HB_Script)lastScript;
- item.bidiLevel = 0; // ### what's the proper value?
+ QUnicodeTools::ScriptItem item;
+ item.position = start - string;
+ item.script = lastScript;
scriptItems.append(item);
start = uc;
}
@@ -85,11 +83,9 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int
++uc;
}
if (uc != start) {
- HB_ScriptItem item;
- item.pos = start - string;
- item.length = uc - start;
- item.script = (HB_Script)lastScript;
- item.bidiLevel = 0; // ### what's the proper value?
+ QUnicodeTools::ScriptItem item;
+ item.position = start - string;
+ item.script = lastScript;
scriptItems.append(item);
}
@@ -193,9 +189,9 @@ QTextBoundaryFinder::QTextBoundaryFinder(const QTextBoundaryFinder &other)
, pos(other.pos)
, freePrivate(true)
{
- d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(QCharAttributes));
Q_CHECK_PTR(d);
- memcpy(d, other.d, length*sizeof(HB_CharAttributes));
+ memcpy(d, other.d, length*sizeof(QCharAttributes));
}
/*!
@@ -213,11 +209,11 @@ QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &o
pos = other.pos;
QTextBoundaryFinderPrivate *newD = (QTextBoundaryFinderPrivate *)
- realloc(freePrivate ? d : 0, length*sizeof(HB_CharAttributes));
+ realloc(freePrivate ? d : 0, length*sizeof(QCharAttributes));
Q_CHECK_PTR(newD);
freePrivate = true;
d = newD;
- memcpy(d, other.d, length*sizeof(HB_CharAttributes));
+ memcpy(d, other.d, length*sizeof(QCharAttributes));
return *this;
}
@@ -242,7 +238,7 @@ QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QString &strin
, pos(0)
, freePrivate(true)
{
- d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(QCharAttributes));
Q_CHECK_PTR(d);
init(t, chars, length, d->attributes);
}
@@ -266,11 +262,11 @@ QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QChar *chars,
, length(length)
, pos(0)
{
- if (buffer && (uint)bufferSize >= length*sizeof(HB_CharAttributes)) {
+ if (buffer && (uint)bufferSize >= length*sizeof(QCharAttributes)) {
d = (QTextBoundaryFinderPrivate *)buffer;
freePrivate = false;
} else {
- d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(HB_CharAttributes));
+ d = (QTextBoundaryFinderPrivate *) malloc(length*sizeof(QCharAttributes));
Q_CHECK_PTR(d);
freePrivate = true;
}
@@ -368,11 +364,11 @@ int QTextBoundaryFinder::toNextBoundary()
switch(t) {
case Grapheme:
- while (pos < length && !d->attributes[pos].charStop)
+ while (pos < length && !d->attributes[pos].graphemeBoundary)
++pos;
break;
case Word:
- while (pos < length && !d->attributes[pos].wordBoundary)
+ while (pos < length && !d->attributes[pos].wordBreak)
++pos;
break;
case Sentence:
@@ -380,7 +376,7 @@ int QTextBoundaryFinder::toNextBoundary()
++pos;
break;
case Line:
- while (pos < length && d->attributes[pos].lineBreakType == HB_NoBreak)
+ while (pos < length && !d->attributes[pos].lineBreak)
++pos;
break;
}
@@ -410,11 +406,11 @@ int QTextBoundaryFinder::toPreviousBoundary()
switch(t) {
case Grapheme:
- while (pos > 0 && !d->attributes[pos].charStop)
+ while (pos > 0 && !d->attributes[pos].graphemeBoundary)
--pos;
break;
case Word:
- while (pos > 0 && !d->attributes[pos].wordBoundary)
+ while (pos > 0 && !d->attributes[pos].wordBreak)
--pos;
break;
case Sentence:
@@ -422,7 +418,7 @@ int QTextBoundaryFinder::toPreviousBoundary()
--pos;
break;
case Line:
- while (pos > 0 && d->attributes[pos].lineBreakType == HB_NoBreak)
+ while (pos > 0 && !d->attributes[pos].lineBreak)
--pos;
break;
}
@@ -443,11 +439,11 @@ bool QTextBoundaryFinder::isAtBoundary() const
switch(t) {
case Grapheme:
- return d->attributes[pos].charStop;
+ return d->attributes[pos].graphemeBoundary;
case Word:
- return d->attributes[pos].wordBoundary;
+ return d->attributes[pos].wordBreak;
case Line:
- return pos == 0 || d->attributes[pos].lineBreakType != HB_NoBreak;
+ return pos == 0 || d->attributes[pos].lineBreak;
case Sentence:
return d->attributes[pos].sentenceBoundary;
}
@@ -463,8 +459,6 @@ QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() cons
return NotAtBoundary;
if (! isAtBoundary())
return NotAtBoundary;
- if (t == Line && pos < length && d->attributes[pos].lineBreakType == HB_SoftHyphen)
- return SoftHyphen;
if (pos == 0) {
if (d->attributes[pos].whiteSpace)
return NotAtBoundary;
@@ -476,6 +470,12 @@ QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() cons
return EndWord;
}
+ if (t == Line && chars[pos - 1].unicode() == QChar::SoftHyphen)
+ return SoftHyphen;
+
+ if (t != Word)
+ return BoundaryReasons(StartWord | EndWord);
+
const bool nextIsSpace = d->attributes[pos].whiteSpace;
const bool prevIsSpace = d->attributes[pos - 1].whiteSpace;
diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/tools/qunicodetools.cpp
index f8db6cbac3..ffb9512229 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
diff --git a/src/corelib/tools/qunicodetools_p.h b/src/corelib/tools/qunicodetools_p.h
index ea407e7ddc..3396c33230 100644
--- a/src/corelib/tools/qunicodetools_p.h
+++ b/src/corelib/tools/qunicodetools_p.h
@@ -53,12 +53,30 @@
// We mean it.
//
-#include <private/qharfbuzz_p.h>
+#include <QtCore/qchar.h>
QT_BEGIN_NAMESPACE
+struct Q_PACKED QCharAttributes
+{
+ uchar graphemeBoundary : 1;
+ uchar wordBreak : 1;
+ uchar sentenceBoundary : 1;
+ uchar lineBreak : 1;
+ uchar whiteSpace : 1;
+ uchar unused : 3;
+};
+Q_DECLARE_TYPEINFO(QCharAttributes, Q_PRIMITIVE_TYPE);
+
namespace QUnicodeTools {
+// ### temporary
+struct ScriptItem
+{
+ int position;
+ int script;
+};
+
enum CharAttributeOption {
GraphemeBreaks = 0x01,
WordBreaks = 0x02,
@@ -72,8 +90,8 @@ enum CharAttributeOption {
Q_DECLARE_FLAGS(CharAttributeOptions, CharAttributeOption)
Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
- const HB_ScriptItem *items, int numItems,
- HB_CharAttributes *attributes, CharAttributeOptions options = DefaultOptionsCompat);
+ const ScriptItem *items, int numItems,
+ QCharAttributes *attributes, CharAttributeOptions options = DefaultOptionsCompat);
} // namespace QUnicodeTools
diff --git a/src/gui/text/qharfbuzz_copy_p.h b/src/gui/text/qharfbuzz_copy_p.h
index aa48667e2e..75b1240c3d 100644
--- a/src/gui/text/qharfbuzz_copy_p.h
+++ b/src/gui/text/qharfbuzz_copy_p.h
@@ -66,13 +66,6 @@ typedef enum {
HB_Err_Out_Of_Memory = 0xDEAD
} HB_Error;
-typedef enum {
- HB_NoBreak,
- HB_SoftHyphen,
- HB_Break,
- HB_ForcedBreak
-} HB_LineBreakType;
-
typedef QT_PREPEND_NAMESPACE(quint32) HB_Glyph;
typedef void * HB_Font;
typedef void * HB_Face;
@@ -95,17 +88,6 @@ typedef struct {
hb_bitfield combiningClass :8;
} HB_GlyphAttributes;
-// This struct is strictly not needed, but we replicate it completely in
-// case the compiler tries to get clever with padding.
-typedef struct {
- /*HB_LineBreakType*/ hb_bitfield lineBreakType :2;
- /*HB_Bool*/ hb_bitfield whiteSpace :1; /* A unicode whitespace character, except NBSP, ZWNBSP */
- /*HB_Bool*/ hb_bitfield charStop :1; /* Valid cursor position (for left/right arrow) */
- /*HB_Bool*/ hb_bitfield wordBoundary :1;
- /*HB_Bool*/ hb_bitfield sentenceBoundary :1;
- hb_bitfield unused :2;
-} HB_CharAttributes;
-
}
#endif // ifdef QT_BUILD_GUI_LIB
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index e4572e77a2..b2f760029e 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -52,7 +52,6 @@
#include "qfontengine_p.h"
#include "qstring.h"
#include <private/qunicodetables_p.h>
-#include <private/qunicodetools_p.h>
#include "qtextdocument_p.h"
#include "qrawfont.h"
#include "qrawfont_p.h"
@@ -1198,33 +1197,30 @@ QTextEngine::~QTextEngine()
resetFontEngineCache();
}
-const HB_CharAttributes *QTextEngine::attributes() const
+const QCharAttributes *QTextEngine::attributes() const
{
if (layoutData && layoutData->haveCharAttributes)
- return (HB_CharAttributes *) layoutData->memory;
+ return (QCharAttributes *) layoutData->memory;
itemize();
if (! ensureSpace(layoutData->string.length()))
return NULL;
- QVarLengthArray<HB_ScriptItem> hbScriptItems(layoutData->items.size());
-
+ QVarLengthArray<QUnicodeTools::ScriptItem> scriptItems(layoutData->items.size());
for (int i = 0; i < layoutData->items.size(); ++i) {
const QScriptItem &si = layoutData->items[i];
- hbScriptItems[i].pos = si.position;
- hbScriptItems[i].length = length(i);
- hbScriptItems[i].bidiLevel = si.analysis.bidiLevel;
- hbScriptItems[i].script = (HB_Script)si.analysis.script;
+ scriptItems[i].position = si.position;
+ scriptItems[i].script = si.analysis.script;
}
QUnicodeTools::initCharAttributes(reinterpret_cast<const HB_UChar16 *>(layoutData->string.constData()),
layoutData->string.length(),
- hbScriptItems.data(), hbScriptItems.size(),
- (HB_CharAttributes *)layoutData->memory);
+ scriptItems.data(), scriptItems.size(),
+ (QCharAttributes *)layoutData->memory);
layoutData->haveCharAttributes = true;
- return (HB_CharAttributes *) layoutData->memory;
+ return (QCharAttributes *) layoutData->memory;
}
void QTextEngine::shape(int item) const
@@ -1858,7 +1854,7 @@ void QTextEngine::justify(const QScriptLine &line)
// don't include trailing white spaces when doing justification
int line_length = line.length;
- const HB_CharAttributes *a = attributes();
+ const QCharAttributes *a = attributes();
if (! a)
return;
a += line.from;
@@ -2058,7 +2054,7 @@ QTextEngine::LayoutData::LayoutData(const QString &str, void **stack_memory, int
{
allocated = _allocated;
- int space_charAttributes = sizeof(HB_CharAttributes)*string.length()/sizeof(void*) + 1;
+ int space_charAttributes = sizeof(QCharAttributes)*string.length()/sizeof(void*) + 1;
int space_logClusters = sizeof(unsigned short)*string.length()/sizeof(void*) + 1;
available_glyphs = ((int)allocated - space_charAttributes - space_logClusters)*(int)sizeof(void*)/(int)QGlyphLayout::spaceNeededForGlyphLayout(1);
@@ -2100,7 +2096,7 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs)
return true;
}
- int space_charAttributes = sizeof(HB_CharAttributes)*string.length()/sizeof(void*) + 1;
+ int space_charAttributes = sizeof(QCharAttributes)*string.length()/sizeof(void*) + 1;
int space_logClusters = sizeof(unsigned short)*string.length()/sizeof(void*) + 1;
int space_glyphs = QGlyphLayout::spaceNeededForGlyphLayout(totalGlyphs)/sizeof(void*) + 2;
@@ -2371,7 +2367,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
if (flags & Qt::TextShowMnemonic) {
itemize();
- HB_CharAttributes *attributes = const_cast<HB_CharAttributes *>(this->attributes());
+ QCharAttributes *attributes = const_cast<QCharAttributes *>(this->attributes());
if (!attributes)
return QString();
for (int i = 0; i < layoutData->items.size(); ++i) {
@@ -2387,9 +2383,9 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
if (layoutData->string.at(i) == QLatin1Char('&')) {
const int gp = logClusters[i - si.position];
glyphs.attributes[gp].dontPrint = true;
- attributes[i + 1].charStop = false;
+ attributes[i + 1].graphemeBoundary = false;
+ attributes[i + 1].lineBreak = false;
attributes[i + 1].whiteSpace = false;
- attributes[i + 1].lineBreakType = HB_NoBreak;
if (layoutData->string.at(i + 1) == QLatin1Char('&'))
++i;
}
@@ -2451,7 +2447,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
if (availableWidth < 0)
return QString();
- const HB_CharAttributes *attributes = this->attributes();
+ const QCharAttributes *attributes = this->attributes();
if (!attributes)
return QString();
@@ -2464,7 +2460,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
pos = nextBreak;
++nextBreak;
- while (nextBreak < layoutData->string.length() && !attributes[nextBreak].charStop)
+ while (nextBreak < layoutData->string.length() && !attributes[nextBreak].graphemeBoundary)
++nextBreak;
currentWidth += this->width(pos, nextBreak - pos);
@@ -2487,7 +2483,7 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
pos = nextBreak;
--nextBreak;
- while (nextBreak > 0 && !attributes[nextBreak].charStop)
+ while (nextBreak > 0 && !attributes[nextBreak].graphemeBoundary)
--nextBreak;
currentWidth += this->width(nextBreak, pos - nextBreak);
@@ -2516,11 +2512,11 @@ QString QTextEngine::elidedText(Qt::TextElideMode mode, const QFixed &width, int
rightPos = nextRightBreak;
++nextLeftBreak;
- while (nextLeftBreak < layoutData->string.length() && !attributes[nextLeftBreak].charStop)
+ while (nextLeftBreak < layoutData->string.length() && !attributes[nextLeftBreak].graphemeBoundary)
++nextLeftBreak;
--nextRightBreak;
- while (nextRightBreak > from && !attributes[nextRightBreak].charStop)
+ while (nextRightBreak > from && !attributes[nextRightBreak].graphemeBoundary)
--nextRightBreak;
leftWidth += this->width(leftPos, nextLeftBreak - leftPos);
@@ -2833,12 +2829,12 @@ QFixed QTextEngine::offsetInLigature(const QScriptItem *si, int pos, int max, in
// Scan in logClusters[from..to-1] for glyph_pos
int QTextEngine::getClusterLength(unsigned short *logClusters,
- const HB_CharAttributes *attributes,
+ const QCharAttributes *attributes,
int from, int to, int glyph_pos, int *start)
{
int clusterLength = 0;
for (int i = from; i < to; i++) {
- if (logClusters[i] == glyph_pos && attributes[i].charStop) {
+ if (logClusters[i] == glyph_pos && attributes[i].graphemeBoundary) {
if (*start < 0)
*start = i;
clusterLength++;
@@ -2877,7 +2873,7 @@ int QTextEngine::positionInLigature(const QScriptItem *si, int end,
glyph_pos--;
}
- const HB_CharAttributes *attrs = attributes();
+ const QCharAttributes *attrs = attributes();
logClusters = this->logClusters(si);
clusterLength = getClusterLength(logClusters, attrs, 0, end, glyph_pos, &clusterStart);
@@ -2895,8 +2891,8 @@ int QTextEngine::positionInLigature(const QScriptItem *si, int end,
if (cursorOnCharacter && closestItem > 0)
closestItem--;
int pos = si->position + clusterStart + closestItem;
- // Jump to the next charStop
- while (pos < end && !attrs[pos].charStop)
+ // Jump to the next grapheme boundary
+ while (pos < end && !attrs[pos].graphemeBoundary)
pos++;
return pos;
}
@@ -2905,21 +2901,21 @@ int QTextEngine::positionInLigature(const QScriptItem *si, int end,
int QTextEngine::previousLogicalPosition(int oldPos) const
{
- const HB_CharAttributes *attrs = attributes();
+ const QCharAttributes *attrs = attributes();
if (!attrs || oldPos < 0)
return oldPos;
if (oldPos <= 0)
return 0;
oldPos--;
- while (oldPos && !attrs[oldPos].charStop)
+ while (oldPos && !attrs[oldPos].graphemeBoundary)
oldPos--;
return oldPos;
}
int QTextEngine::nextLogicalPosition(int oldPos) const
{
- const HB_CharAttributes *attrs = attributes();
+ const QCharAttributes *attrs = attributes();
int len = block.isValid() ? block.length() - 1
: layoutData->string.length();
Q_ASSERT(len <= layoutData->string.length());
@@ -2927,7 +2923,7 @@ int QTextEngine::nextLogicalPosition(int oldPos) const
return oldPos;
oldPos++;
- while (oldPos < len && !attrs[oldPos].charStop)
+ while (oldPos < len && !attrs[oldPos].graphemeBoundary)
oldPos++;
return oldPos;
}
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index c2362e6dc5..ac4bc273c0 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -75,6 +75,8 @@
#include "private/qfixed_p.h"
+#include <private/qunicodetools_p.h>
+
#include <stdlib.h>
QT_BEGIN_NAMESPACE
@@ -468,7 +470,7 @@ public:
bool isRightToLeft() const;
static void bidiReorder(int numRuns, const quint8 *levels, int *visualOrder);
- const HB_CharAttributes *attributes() const;
+ const QCharAttributes *attributes() const;
void shape(int item) const;
@@ -672,7 +674,7 @@ private:
void resolveAdditionalFormats() const;
int endOfLine(int lineNum);
int beginningOfLine(int lineNum);
- int getClusterLength(unsigned short *logClusters, const HB_CharAttributes *attributes, int from, int to, int glyph_pos, int *start);
+ int getClusterLength(unsigned short *logClusters, const QCharAttributes *attributes, int from, int to, int glyph_pos, int *start);
};
class Q_GUI_EXPORT QStackTextEngine : public QTextEngine {
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index a49b4112d4..7591b46547 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -683,7 +683,7 @@ void QTextLayout::clearLayout()
*/
int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
{
- const HB_CharAttributes *attributes = d->attributes();
+ const QCharAttributes *attributes = d->attributes();
int len = d->block.isValid() ? d->block.length() - 1
: d->layoutData->string.length();
Q_ASSERT(len <= d->layoutData->string.length());
@@ -692,7 +692,7 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
if (mode == SkipCharacters) {
oldPos++;
- while (oldPos < len && !attributes[oldPos].charStop)
+ while (oldPos < len && !attributes[oldPos].graphemeBoundary)
oldPos++;
} else {
if (oldPos < len && d->atWordSeparator(oldPos)) {
@@ -719,13 +719,13 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
*/
int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
{
- const HB_CharAttributes *attributes = d->attributes();
+ const QCharAttributes *attributes = d->attributes();
if (!attributes || oldPos <= 0 || oldPos > d->layoutData->string.length())
return oldPos;
if (mode == SkipCharacters) {
oldPos--;
- while (oldPos && !attributes[oldPos].charStop)
+ while (oldPos && !attributes[oldPos].graphemeBoundary)
oldPos--;
} else {
while (oldPos && d->atSpace(oldPos-1))
@@ -789,10 +789,10 @@ int QTextLayout::leftCursorPosition(int oldPos) const
*/
bool QTextLayout::isValidCursorPosition(int pos) const
{
- const HB_CharAttributes *attributes = d->attributes();
+ const QCharAttributes *attributes = d->attributes();
if (!attributes || pos < 0 || pos > (int)d->layoutData->string.length())
return false;
- return attributes[pos].charStop;
+ return attributes[pos].graphemeBoundary;
}
/*!
@@ -1770,7 +1770,7 @@ void QTextLine::layout_helper(int maxGlyphs)
Qt::Alignment alignment = eng->option.alignment();
- const HB_CharAttributes *attributes = eng->attributes();
+ const QCharAttributes *attributes = eng->attributes();
if (!attributes)
return;
lbh.currentPosition = line.from;
@@ -1875,17 +1875,18 @@ void QTextLine::layout_helper(int maxGlyphs)
if (lbh.currentPosition >= eng->layoutData->string.length()
|| attributes[lbh.currentPosition].whiteSpace
- || attributes[lbh.currentPosition].lineBreakType != HB_NoBreak) {
+ || attributes[lbh.currentPosition].lineBreak) {
sb_or_ws = true;
break;
- } else if (breakany && attributes[lbh.currentPosition].charStop) {
+ } else if (breakany && attributes[lbh.currentPosition].graphemeBoundary) {
break;
}
} while (lbh.currentPosition < end);
lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);
if (lbh.currentPosition > 0 && lbh.currentPosition < end
- && attributes[lbh.currentPosition].lineBreakType == HB_SoftHyphen) {
+ && attributes[lbh.currentPosition].lineBreak
+ && eng->layoutData->string.at(lbh.currentPosition - 1).unicode() == QChar::SoftHyphen) {
// if we are splitting up a word because of
// a soft hyphen then we ...
//
@@ -2605,12 +2606,12 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const
int lineEnd = line.from + line.length + line.trailingSpaces;
int pos = *cursorPos;
int itm;
- const HB_CharAttributes *attributes = eng->attributes();
+ const QCharAttributes *attributes = eng->attributes();
if (!attributes) {
*cursorPos = 0;
return x.toReal();
}
- while (pos < lineEnd && !attributes[pos].charStop)
+ while (pos < lineEnd && !attributes[pos].graphemeBoundary)
pos++;
if (pos == lineEnd) {
// end of line ensure we have the last item on the line