From 88e735c9c92487f7ff51a06cfd66746afa655b2d Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Wed, 6 Jun 2012 18:00:21 +0300 Subject: [PATCH] Shift positions for lineBreakType to keep them consistent with positions for all other flags. This changes the internal behavior so that attributes[0].lineBreakType now means "break opportunity at start of the text (before the first character in the string)" and is always assigned with HB_NoBreak to conform rule LB2 (see http://www.unicode.org/reports/tr14/#LB2). The current implementation is based on the sample implementation from tr14 that aimed to be as simple as possible rather than to be optimal. From now, we can use pieces of the attributes array "as is" without having to adjust some positions. Or we can analize some long text by chunks (e.g. paragraph by paragraph) and consume less memory. This introduces a minor overhead that will be eliminated shortly. Change-Id: Ic873a05a9d5203b1c3d5aff2e4445a3f034c4bd2 Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c | 3 +-- src/3rdparty/harfbuzz/src/harfbuzz-thai.c | 3 +-- src/corelib/tools/qtextboundaryfinder.cpp | 9 ++++----- src/corelib/tools/qunicodetools.cpp | 5 ++++- src/gui/text/qtextlayout.cpp | 5 +++-- tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp | 8 ++++---- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c b/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c index 4b68e64..1327b18 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-myanmar.c @@ -521,8 +521,7 @@ void HB_MyanmarAttributes(HB_Script script, const HB_UChar16 *text, hb_uint32 fr hb_uint32 boundary = myanmar_nextSyllableBoundary(text, from+i, end, &invalid) - from; attributes[i].charStop = TRUE; - if (i) - attributes[i-1].lineBreakType = HB_Break; + attributes[i].lineBreakType = HB_Break; if (boundary > len-1) boundary = len; diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c index 039394a..54fb953 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c @@ -414,8 +414,7 @@ static void HB_ThaiAssignAttributes(const HB_UChar16 *string, hb_uint32 len, HB_ numbreaks = th_brk((const unsigned char *)cstr, break_positions, brp_size); for (i = 0; i < numbreaks; ++i) { attributes[break_positions[i]].wordBoundary = TRUE; - if (break_positions[i] > 0) - attributes[break_positions[i]-1].lineBreakType = HB_Break; + attributes[break_positions[i]].lineBreakType = HB_Break; } if (break_positions != brp) diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp index 1e12d6e..042f92f 100644 --- a/src/corelib/tools/qtextboundaryfinder.cpp +++ b/src/corelib/tools/qtextboundaryfinder.cpp @@ -374,8 +374,7 @@ int QTextBoundaryFinder::toNextBoundary() ++pos; break; case Line: - Q_ASSERT(pos); - while (pos < length && d->attributes[pos-1].lineBreakType == HB_NoBreak) + while (pos < length && d->attributes[pos].lineBreakType == HB_NoBreak) ++pos; break; } @@ -417,7 +416,7 @@ int QTextBoundaryFinder::toPreviousBoundary() --pos; break; case Line: - while (pos > 0 && d->attributes[pos-1].lineBreakType == HB_NoBreak) + while (pos > 0 && d->attributes[pos].lineBreakType == HB_NoBreak) --pos; break; } @@ -442,7 +441,7 @@ bool QTextBoundaryFinder::isAtBoundary() const case Word: return d->attributes[pos].wordBoundary; case Line: - return (pos > 0) ? d->attributes[pos-1].lineBreakType != HB_NoBreak : true; + return pos == 0 || d->attributes[pos].lineBreakType != HB_NoBreak; case Sentence: return d->attributes[pos].sentenceBoundary; } @@ -458,7 +457,7 @@ QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() cons return NotAtBoundary; if (! isAtBoundary()) return NotAtBoundary; - if (t == Line && pos < length && d->attributes[pos-1].lineBreakType == HB_SoftHyphen) + if (t == Line && pos < length && d->attributes[pos].lineBreakType == HB_SoftHyphen) return SoftHyphen; if (pos == 0) { if (d->attributes[pos].whiteSpace) diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/tools/qunicodetools.cpp index a311213..5845765 100644 --- a/src/corelib/tools/qunicodetools.cpp +++ b/src/corelib/tools/qunicodetools.cpp @@ -239,7 +239,10 @@ static void calcGraphemeAndLineBreaks(const ushort *string, quint32 len, HB_Char grapheme = ngrapheme; attributes[i-1].lineBreakType = lineBreakType; } - attributes[len-1].lineBreakType = HB_ForcedBreak; + + for (quint32 i = len - 1; i > 0; --i) + attributes[i].lineBreakType = attributes[i - 1].lineBreakType; + attributes[0].lineBreakType = HB_NoBreak; // LB2 } diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 3cdd546..3250e28 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1867,7 +1867,7 @@ void QTextLine::layout_helper(int maxGlyphs) if (lbh.currentPosition >= eng->layoutData->string.length() || attributes[lbh.currentPosition].whiteSpace - || attributes[lbh.currentPosition-1].lineBreakType != HB_NoBreak) { + || attributes[lbh.currentPosition].lineBreakType != HB_NoBreak) { sb_or_ws = true; break; } else if (breakany && attributes[lbh.currentPosition].charStop) { @@ -1876,7 +1876,8 @@ void QTextLine::layout_helper(int maxGlyphs) } while (lbh.currentPosition < end); lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw); - if (lbh.currentPosition && attributes[lbh.currentPosition - 1].lineBreakType == HB_SoftHyphen) { + if (lbh.currentPosition > 0 && lbh.currentPosition < end + && attributes[lbh.currentPosition].lineBreakType == HB_SoftHyphen) { // if we are splitting up a word because of // a soft hyphen then we ... // diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp index d20fe83..62cbc1f 100644 --- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp +++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp @@ -274,15 +274,15 @@ void tst_QTextLayout::lineBreaking() QString str = QString::fromUtf8(b->utf8); QTextEngine engine(str, QFont()); const HB_CharAttributes *attrs = engine.attributes(); + QVERIFY(attrs[0].lineBreakType == HB_NoBreak); int i; for (i = 0; i < (int)str.length() - 1; ++i) { QVERIFY(b->breaks[i] != 0xff); - if ( (attrs[i].lineBreakType != HB_NoBreak) != (bool)b->breaks[i] ) { - qDebug("test case \"%s\" failed at char %d; break type: %d", b->utf8, i, attrs[i].lineBreakType); - QCOMPARE( (attrs[i].lineBreakType != HB_NoBreak), (bool)b->breaks[i] ); + if ( (attrs[i + 1].lineBreakType != HB_NoBreak) != (bool)b->breaks[i] ) { + qDebug("test case \"%s\" failed at char %d; break type: %d", b->utf8, i, attrs[i + 1].lineBreakType); + QCOMPARE( (attrs[i + 1].lineBreakType != HB_NoBreak), (bool)b->breaks[i] ); } } - QVERIFY(attrs[i].lineBreakType == HB_ForcedBreak); QCOMPARE(b->breaks[i], (uchar)0xff); ++b; } -- 2.7.4