diff options
author | Konstantin Ritt <ritt.ks@gmail.com> | 2012-10-12 06:49:27 +0300 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-10-12 07:44:51 +0200 |
commit | da7111be51cab7c7484afd15ec9de7fb852ae305 (patch) | |
tree | 03ffbe7a5cb8e49ada9b521bf5f613d501cbbb3a /src/corelib/tools/qtextboundaryfinder.cpp | |
parent | 8b41f22f5c4bb401182e2b458f61177b92bd48ce (diff) |
QTextBoundaryFinder: Fix handling of break opportunities
Add BoundaryReason::BreakOpportunity flag that will be returned by the
boundaryReasons() when the boundary finder is at the break opportunity
position that might be not an item boundary.
This is the same as (StartWord || EndWord) in Grapheme and Sentence modes;
in Word and Line modes, BreakOpportunity flag might occur between the words
or in between of Line boundaries (e.g. in conjunction with SoftHyphen flag).
In other words, the text boundaries are always break opportunities, but not vice versa.
StartWord and EndWord flags has been deprecated by new StartOfItem and EndOfItem
flags which are not about the word boundaries only. In line breaking,
StartOfItem and EndOfItem are set for the mandatory breaks only.
Change-Id: I79bf297e2b988f5976f30cff0c8ca616385f6552
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
Diffstat (limited to 'src/corelib/tools/qtextboundaryfinder.cpp')
-rw-r--r-- | src/corelib/tools/qtextboundaryfinder.cpp | 142 |
1 files changed, 89 insertions, 53 deletions
diff --git a/src/corelib/tools/qtextboundaryfinder.cpp b/src/corelib/tools/qtextboundaryfinder.cpp index 416a14a35a..259a63335a 100644 --- a/src/corelib/tools/qtextboundaryfinder.cpp +++ b/src/corelib/tools/qtextboundaryfinder.cpp @@ -148,7 +148,7 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int \enum QTextBoundaryFinder::BoundaryType \value Grapheme Finds a grapheme which is the smallest boundary. It - including letters, punctation marks, numerals and more. + including letters, punctuation marks, numerals and more. \value Word Finds a word. \value Line Finds possible positions for breaking the text into multiple lines. @@ -160,12 +160,25 @@ static void init(QTextBoundaryFinder::BoundaryType type, const QChar *chars, int \enum QTextBoundaryFinder::BoundaryReason \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 BreakOpportunity The boundary finder is at a break opportunity position. + Such a break opportunity might also be an item boundary + (either StartOfItem, EndOfItem, or combination of both), + a mandatory line break, or a soft hyphen. + \value StartOfItem Since 5.0. The boundary finder is at the start of + a grapheme, a word, a sentence, or a line. + \value EndOfItem Since 5.0. The boundary finder is at the end of + a grapheme, a word, a sentence, or a line. \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). + + \value StartWord Deprecated since 5.0. Use StartOfItem instead. + The boundary finder is at the start of a word. + (can occur for a Word boundary type only). + \value EndWord Deprecated since 5.0. Use EndOfItem instead. + The boundary finder is at the end of a word. + (can occur for a Word boundary type only). */ /*! @@ -190,10 +203,14 @@ QTextBoundaryFinder::QTextBoundaryFinder(const QTextBoundaryFinder &other) , length(other.length) , pos(other.pos) , freePrivate(true) + , d(0) { - d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes)); - Q_CHECK_PTR(d); - memcpy(d, other.d, (length + 1) * sizeof(QCharAttributes)); + if (other.d) { + Q_ASSERT(length > 0); + d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes)); + Q_CHECK_PTR(d); + memcpy(d, other.d, (length + 1) * sizeof(QCharAttributes)); + } } /*! @@ -205,7 +222,8 @@ QTextBoundaryFinder &QTextBoundaryFinder::operator=(const QTextBoundaryFinder &o return *this; if (other.d) { - uint newCapacity = (length + 1) * sizeof(QCharAttributes); + Q_ASSERT(other.length > 0); + uint newCapacity = (other.length + 1) * sizeof(QCharAttributes); QTextBoundaryFinderPrivate *newD = (QTextBoundaryFinderPrivate *) realloc(freePrivate ? d : 0, newCapacity); Q_CHECK_PTR(newD); freePrivate = true; @@ -248,10 +266,13 @@ QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QString &strin , length(string.length()) , pos(0) , freePrivate(true) + , d(0) { - d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes)); - Q_CHECK_PTR(d); - init(t, chars, length, d->attributes); + if (length > 0) { + d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes)); + Q_CHECK_PTR(d); + init(t, chars, length, d->attributes); + } } /*! @@ -273,16 +294,21 @@ QTextBoundaryFinder::QTextBoundaryFinder(BoundaryType type, const QChar *chars, , chars(chars) , length(length) , pos(0) + , freePrivate(true) + , d(0) { - if (buffer && (uint)bufferSize >= (length + 1) * sizeof(QCharAttributes)) { - d = (QTextBoundaryFinderPrivate *)buffer; - freePrivate = false; - } else { - d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes)); - Q_CHECK_PTR(d); - freePrivate = true; + if (!chars) { + length = 0; + } else if (length > 0) { + if (buffer && (uint)bufferSize >= (length + 1) * sizeof(QCharAttributes)) { + d = (QTextBoundaryFinderPrivate *)buffer; + freePrivate = false; + } else { + d = (QTextBoundaryFinderPrivate *) malloc((length + 1) * sizeof(QCharAttributes)); + Q_CHECK_PTR(d); + } + init(t, chars, length, d->attributes); } - init(t, chars, length, d->attributes); } /*! @@ -361,19 +387,12 @@ QString QTextBoundaryFinder::string() const */ int QTextBoundaryFinder::toNextBoundary() { - if (!d) { + if (!d || pos < 0 || pos >= length) { pos = -1; return pos; } - if (pos < 0 || pos >= length) { - pos = -1; - return pos; - } ++pos; - if (pos == length) - return pos; - switch(t) { case Grapheme: while (pos < length && !d->attributes[pos].graphemeBoundary) @@ -403,19 +422,12 @@ int QTextBoundaryFinder::toNextBoundary() */ int QTextBoundaryFinder::toPreviousBoundary() { - if (!d) { + if (!d || pos <= 0 || pos > length) { pos = -1; return pos; } - if (pos <= 0 || pos > length) { - pos = -1; - return pos; - } --pos; - if (pos == 0) - return pos; - switch(t) { case Grapheme: while (pos > 0 && !d->attributes[pos].graphemeBoundary) @@ -443,21 +455,19 @@ int QTextBoundaryFinder::toPreviousBoundary() */ bool QTextBoundaryFinder::isAtBoundary() const { - if (!d || pos < 0) + if (!d || pos < 0 || pos > length) return false; - if (pos == length) - return true; - switch(t) { case Grapheme: return d->attributes[pos].graphemeBoundary; case Word: return d->attributes[pos].wordBreak; - case Line: - return pos == 0 || d->attributes[pos].lineBreak; case Sentence: return d->attributes[pos].sentenceBoundary; + case Line: + // ### TR#14 LB2 prohibits break at sot + return d->attributes[pos].lineBreak || pos == 0; } return false; } @@ -468,26 +478,52 @@ bool QTextBoundaryFinder::isAtBoundary() const QTextBoundaryFinder::BoundaryReasons QTextBoundaryFinder::boundaryReasons() const { BoundaryReasons reasons = NotAtBoundary; - if (!d || !isAtBoundary()) + if (!d || pos < 0 || pos > length) return reasons; + const QCharAttributes attr = d->attributes[pos]; switch (t) { + case Grapheme: + if (attr.graphemeBoundary) { + reasons |= BreakOpportunity | StartOfItem | EndOfItem; + if (pos == 0) + reasons &= (~EndOfItem); + else if (pos == length) + reasons &= (~StartOfItem); + } + break; case Word: - if (d->attributes[pos].wordStart) - reasons |= StartWord; - if (d->attributes[pos].wordEnd) - reasons |= EndWord; + if (attr.wordBreak) { + reasons |= BreakOpportunity; + if (attr.wordStart) + reasons |= StartOfItem | StartWord; + if (attr.wordEnd) + reasons |= EndOfItem | EndWord; + } + break; + case Sentence: + if (attr.sentenceBoundary) { + reasons |= BreakOpportunity | StartOfItem | EndOfItem; + if (pos == 0) + reasons &= (~EndOfItem); + else if (pos == length) + reasons &= (~StartOfItem); + } break; case Line: // ### 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: - case Sentence: - reasons |= StartWord | EndWord; + if (attr.lineBreak || pos == 0) { + reasons |= BreakOpportunity; + if (attr.mandatoryBreak || pos == 0) { + reasons |= MandatoryBreak | StartOfItem | EndOfItem; + if (pos == 0) + reasons &= (~EndOfItem); + else if (pos == length) + reasons &= (~StartOfItem); + } else if (pos > 0 && chars[pos - 1].unicode() == QChar::SoftHyphen) { + reasons |= SoftHyphen; + } + } break; default: break; |