diff options
-rw-r--r-- | src/3rdparty/harfbuzz/src/harfbuzz-shaper.h | 2 | ||||
-rw-r--r-- | src/corelib/tools/qtextboundaryfinder.cpp | 7 | ||||
-rw-r--r-- | src/corelib/tools/qtextboundaryfinder.h | 7 | ||||
-rw-r--r-- | src/corelib/tools/qunicodetools.cpp | 6 | ||||
-rw-r--r-- | src/corelib/tools/qunicodetools_p.h | 2 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp | 37 |
6 files changed, 52 insertions, 9 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h index 5a3329dd4b..e2891d047e 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h +++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.h @@ -135,7 +135,7 @@ typedef struct { hb_bitfield whiteSpace : 1; /* A unicode whitespace character */ hb_bitfield wordStart : 1; hb_bitfield wordEnd : 1; - hb_bitfield unused : 1; + hb_bitfield mandatoryBreak : 1; } HB_CharAttributes; void HB_GetTailoredCharAttributes(const HB_UChar16 *string, hb_uint32 stringLength, diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp index 7f120323fe..416a14a35a 100644 --- a/src/corelib/tools/qtextboundaryfinder.cpp +++ b/src/corelib/tools/qtextboundaryfinder.cpp @@ -162,6 +162,8 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int \value NotAtBoundary The boundary finder is not at a boundary position. \value StartWord The boundary finder is at the start of a word. \value EndWord The boundary finder is at the end of a word. + \value MandatoryBreak Since 5.0. The boundary finder is at the end of line + (can occur for a Line boundary type only). \value SoftHyphen The boundary finder is at the soft hyphen (can occur for a Line boundary type only). */ @@ -477,7 +479,10 @@ QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() cons reasons |= EndWord; break; case Line: - if (pos > 0 && chars[pos - 1].unicode() == QChar::SoftHyphen) + // ### TR#14 LB2 prohibits break at sot + if (d->attributes[pos].mandatoryBreak || pos == 0) + reasons |= MandatoryBreak; + else if (pos > 0 && chars[pos - 1].unicode() == QChar::SoftHyphen) reasons |= SoftHyphen; // fall through case Grapheme: diff --git a/src/corelib/tools/qtextboundaryfinder.h b/src/corelib/tools/qtextboundaryfinder.h index 57c2fda3ea..c752623844 100644 --- a/src/corelib/tools/qtextboundaryfinder.h +++ b/src/corelib/tools/qtextboundaryfinder.h @@ -69,9 +69,10 @@ public: enum BoundaryReason { NotAtBoundary = 0, - StartWord = 1, - EndWord = 2, - SoftHyphen = 4 + StartWord = 0x10, + EndWord = 0x20, + MandatoryBreak = 0x40, + SoftHyphen = 0x80 }; Q_DECLARE_FLAGS( BoundaryReasons, BoundaryReason ) diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/tools/qunicodetools.cpp index 1f45575016..3d58f16d19 100644 --- a/src/corelib/tools/qunicodetools.cpp +++ b/src/corelib/tools/qunicodetools.cpp @@ -497,7 +497,7 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at if (Q_UNLIKELY(lcls >= QUnicodeTables::LineBreak_CR)) { // LB4: BK!, LB5: (CRxLF|CR|LF|NL)! if (lcls > QUnicodeTables::LineBreak_CR || ncls != QUnicodeTables::LineBreak_LF) - attributes[pos].lineBreak = true; + attributes[pos].lineBreak = attributes[pos].mandatoryBreak = true; goto next; } @@ -547,8 +547,8 @@ static void getLineBreaks(const ushort *string, quint32 len, QCharAttributes *at attributes[j].lineBreak = false; } - attributes[0].lineBreak = false; // LB2 - attributes[len].lineBreak = true; // LB3 + attributes[0].lineBreak = attributes[0].mandatoryBreak = false; // LB2 + attributes[len].lineBreak = attributes[len].mandatoryBreak = true; // LB3 } diff --git a/src/corelib/tools/qunicodetools_p.h b/src/corelib/tools/qunicodetools_p.h index b1e9127662..143a4fd7be 100644 --- a/src/corelib/tools/qunicodetools_p.h +++ b/src/corelib/tools/qunicodetools_p.h @@ -66,7 +66,7 @@ struct Q_PACKED QCharAttributes uchar whiteSpace : 1; uchar wordStart : 1; uchar wordEnd : 1; - uchar unused : 1; + uchar mandatoryBreak : 1; }; Q_DECLARE_TYPEINFO(QCharAttributes, Q_PRIMITIVE_TYPE); diff --git a/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp b/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp index 22d3465823..a0aab340a3 100644 --- a/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp +++ b/tests/auto/corelib/tools/qtextboundaryfinder/tst_qtextboundaryfinder.cpp @@ -76,6 +76,8 @@ private slots: void wordBoundaries_qtbug6498(); void isAtSoftHyphen_data(); void isAtSoftHyphen(); + void isAtMandatoryBreak_data(); + void isAtMandatoryBreak(); void thaiLineBreak(); }; @@ -659,6 +661,41 @@ void tst_QTextBoundaryFinder::isAtSoftHyphen() } } +void tst_QTextBoundaryFinder::isAtMandatoryBreak_data() +{ + QTest::addColumn<QString>("testString"); + QTest::addColumn<QList<int> >("expectedBreakPositions"); + + { + QChar s[] = { 0x000D, 0x0308, 0x000A, 0x000A }; + QString testString(s, sizeof(s)/sizeof(s[0])); + QList<int> expectedBreakPositions; + expectedBreakPositions << 0 << 1 << 3 << 4; + + QTest::newRow("+CR+FExLF+LF+") << testString << expectedBreakPositions; + } + { + QString testString(QString::fromUtf8("Aaa bbb ccc.\r\nDdd eee fff.")); + QList<int> expectedBreakPositions; + expectedBreakPositions << 0 << 14 << 26; + + QTest::newRow("data1") << testString << expectedBreakPositions; + } +} + +void tst_QTextBoundaryFinder::isAtMandatoryBreak() +{ + QFETCH(QString, testString); + QFETCH(QList<int>, expectedBreakPositions); + + QTextBoundaryFinder boundaryFinder(QTextBoundaryFinder::Line, testString); + for (int i = 0; i <= testString.size(); ++i) { + boundaryFinder.setPosition(i); + if (boundaryFinder.boundaryReasons() & QTextBoundaryFinder::MandatoryBreak) + QVERIFY(expectedBreakPositions.contains(i)); + } +} + #include <qlibrary.h> #define LIBTHAI_MAJOR 0 |