** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
**
**
**
}
/*!
- Set the visual cursor movement style. If the QTextLayout is backed by
- a document, you can ignore this and use the option in QTextDocument,
- this option is for widgets like QLineEdit or custom widgets without
- a QTextDocument. Default value is QTextCursor::Logical.
+ Sets the visual cursor movement style to the given \a style. If the
+ QTextLayout is backed by a document, you can ignore this and use the option
+ in QTextDocument, this option is for widgets like QLineEdit or custom
+ widgets without a QTextDocument. Default value is QTextCursor::Logical.
- \sa setCursorMoveStyle()
+ \sa cursorMoveStyle()
*/
-void QTextLayout::setCursorMoveStyle(QTextCursor::MoveStyle style)
+void QTextLayout::setCursorMoveStyle(Qt::CursorMoveStyle style)
{
- d->visualMovement = style == QTextCursor::Visual ? true : false;
+ d->visualMovement = style == Qt::VisualMoveStyle ? true : false;
}
/*!
The cursor movement style of this QTextLayout. The default is
- QTextCursor::Logical.
+ Qt::LogicalMoveStyle.
\sa setCursorMoveStyle()
*/
-QTextCursor::MoveStyle QTextLayout::cursorMoveStyle() const
+Qt::CursorMoveStyle QTextLayout::cursorMoveStyle() const
{
- return d->visualMovement ? QTextCursor::Visual : QTextCursor::Logical;
+ return d->visualMovement ? Qt::VisualMoveStyle : Qt::LogicalMoveStyle;
}
/*!
\sa draw(), QPainter::drawGlyphRun()
*/
#if !defined(QT_NO_RAWFONT)
-QList<QGlyphRun> QTextLayout::glyphRuns() const
-{
+QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const
+{
+ if (from < 0)
+ from = 0;
+ if (length < 0)
+ length = text().length();
+
QList<QGlyphRun> glyphs;
- for (int i=0; i<d->lines.size(); ++i)
- glyphs += QTextLine(i, d).glyphs(-1, -1);
+ for (int i=0; i<d->lines.size(); ++i) {
+ if (d->lines[i].from > from + length)
+ break;
+ else if (d->lines[i].from + d->lines[i].length >= from)
+ glyphs += QTextLine(i, d).glyphRuns(from, length);
+ }
return glyphs;
}
}
/*!
- \internal
+ Returns the glyph indexes and positions for all glyphs in this QTextLine for characters
+ in the range defined by \a from and \a length. The \a from index is relative to the beginning
+ of the text in the containing QTextLayout, and the range must be within the range of QTextLine
+ as given by functions textStart() and textLength().
- Returns the glyph indexes and positions for all glyphs in this QTextLine which reside in
- QScriptItems that overlap with the range defined by \a from and \a length. The arguments
- specify characters, relative to the text in the layout. Note that it is not possible to
- use this function to retrieve a subset of the glyphs in a QScriptItem.
+ If \a from is negative, it will default to textStart(), and if \a length is negative it will
+ default to the return value of textLength().
- \since 4.8
+ \since 5.0
\sa QTextLayout::glyphRuns()
*/
#if !defined(QT_NO_RAWFONT)
-QList<QGlyphRun> QTextLine::glyphs(int from, int length) const
+QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
{
const QScriptLine &line = eng->lines[i];
if (line.length == 0)
return QList<QGlyphRun>();
+ if (from < 0)
+ from = textStart();
+
+ if (length < 0)
+ length = textLength();
+
QHash<QFontEngine *, GlyphInfo> glyphLayoutHash;
QTextLineItemIterator iterator(eng, i);
QPointF pos(iterator.x.toReal(), y);
if (from >= 0 && length >= 0 &&
- (from >= si.position + eng->length(&si) || from + length <= si.position))
+ (from >= si.position + eng->length(&si) || from + length <= si.position)) {
continue;
+ }
QFont font = eng->font(si);
flags |= QTextItem::Underline;
if (font.strikeOut())
flags |= QTextItem::StrikeOut;
- if (si.analysis.bidiLevel % 2)
+
+ bool rtl = false;
+ if (si.analysis.bidiLevel % 2) {
flags |= QTextItem::RightToLeft;
+ rtl = true;
+ }
+
+ int relativeFrom = qMax(iterator.itemStart, from) - si.position;
+ int relativeTo = qMin(iterator.itemEnd - 1, from + length - 1) - si.position;
+
+ unsigned short *logClusters = eng->logClusters(&si);
+ int glyphsStart = logClusters[relativeFrom];
+ int glyphsEnd = (relativeTo == eng->length(&si))
+ ? si.num_glyphs - 1
+ : logClusters[relativeTo];
+
+ QGlyphLayout glyphLayout = eng->shapedGlyphs(&si);
+
+ // Calculate new x position of glyph layout for a subset. This becomes somewhat complex
+ // when we're breaking a RTL script item, since the expected position passed into
+ // getGlyphPositions() is the left-most edge of the left-most glyph in an RTL run.
+ if (relativeFrom != (iterator.itemStart - si.position) && !rtl) {
+ for (int i=0; i<glyphsStart; ++i) {
+ QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
+ pos += QPointF((glyphLayout.advances_x[i] + justification).toReal(),
+ glyphLayout.advances_y[i].toReal());
+ }
+ } else if (relativeTo != (iterator.itemEnd - si.position - 1) && rtl) {
+ for (int i=glyphLayout.numGlyphs - 1; i>glyphsEnd; --i) {
+ QFixed justification = QFixed::fromFixed(glyphLayout.justifications[i].space_18d6);
+ pos += QPointF((glyphLayout.advances_x[i] + justification).toReal(),
+ glyphLayout.advances_y[i].toReal());
+ }
+ }
- QGlyphLayout glyphLayout = eng->shapedGlyphs(&si).mid(iterator.glyphsStart,
- iterator.glyphsEnd - iterator.glyphsStart);
+ glyphLayout = glyphLayout.mid(glyphsStart, glyphsEnd - glyphsStart + 1);
if (glyphLayout.numGlyphs > 0) {
QFontEngine *mainFontEngine = font.d->engineForScript(si.analysis.script);
QGlyphLayout subLayout = glyphLayout.mid(start, end - start);
glyphLayoutHash.insertMulti(multiFontEngine->engine(which),
GlyphInfo(subLayout, pos, flags));
- for (int i = 0; i < subLayout.numGlyphs; i++)
+ for (int i = 0; i < subLayout.numGlyphs; i++) {
pos += QPointF(subLayout.advances_x[i].toReal(),
subLayout.advances_y[i].toReal());
+ }
start = end;
which = e;
glyphIndexes.setRawFont(font);
QPair<QFontEngine *, int> key(fontEngine, int(flags));
- if (!glyphsHash.contains(key))
+ if (!glyphsHash.contains(key)) {
glyphsHash.insert(key, glyphIndexes);
- else
- glyphsHash[key] += glyphIndexes;
+ } else {
+ QGlyphRun &glyphRun = glyphsHash[key];
+
+ QVector<quint32> indexes = glyphRun.glyphIndexes();
+ QVector<QPointF> positions = glyphRun.positions();
+
+ indexes += glyphIndexes.glyphIndexes();
+ positions += glyphIndexes.positions();
+
+ glyphRun.setGlyphIndexes(indexes);
+ glyphRun.setPositions(positions);
+ }
}
}
pos = 0;
int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos];
- if (edge == Trailing) {
+ if (edge == Trailing && glyph_pos < si->num_glyphs) {
// trailing edge is leading edge of next cluster
+ glyph_pos++;
while (glyph_pos < si->num_glyphs && !glyphs.attributes[glyph_pos].clusterStart)
glyph_pos++;
}
} else {
bool rtl = eng->isRightToLeft();
bool visual = eng->visualCursorMovement();
+ int end = qMin(lineEnd, si->position + l) - si->position;
if (reverse) {
- int end = qMin(lineEnd, si->position + l) - si->position;
int glyph_end = end == l ? si->num_glyphs : logClusters[end];
int glyph_start = glyph_pos;
if (visual && !rtl && !(lastLine && itm == (visualOrder[nItems - 1] + firstItem)))
for (int i = glyph_start; i <= glyph_end; i++)
x += glyphs.effectiveAdvance(i);
}
- x += eng->offsetInLigature(si, pos, line.length, glyph_pos);
+ x += eng->offsetInLigature(si, pos, end, glyph_pos);
}
*cursorPos = pos + si->position;
}
int glyph_pos = -1;
+ QFixed edge;
// has to be inside run
if (cpos == QTextLine::CursorOnCharacter) {
if (si.analysis.bidiLevel % 2) {
if (pos < x)
break;
glyph_pos = gs;
+ edge = pos;
break;
}
pos -= glyphs.effectiveAdvance(gs);
if (pos > x)
break;
glyph_pos = gs;
+ edge = pos;
}
pos += glyphs.effectiveAdvance(gs);
++gs;
while (gs <= ge) {
if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
glyph_pos = gs;
+ edge = pos;
dist = qAbs(x-pos);
}
pos -= glyphs.effectiveAdvance(gs);
while (ge >= gs) {
if (glyphs.attributes[ge].clusterStart && qAbs(x-pos) < dist) {
glyph_pos = ge;
+ edge = pos;
dist = qAbs(x-pos);
}
pos += glyphs.effectiveAdvance(ge);
while (gs <= ge) {
if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
glyph_pos = gs;
+ edge = pos;
dist = qAbs(x-pos);
}
pos += glyphs.effectiveAdvance(gs);
pos += glyphs.effectiveAdvance(gs);
if (glyphs.attributes[gs].clusterStart && qAbs(x-pos) < dist) {
glyph_pos = gs;
+ edge = pos;
dist = qAbs(x-pos);
}
++gs;
if (rtl && nchars > 0)
return insertionPoints[lastLine ? nchars : nchars - 1];
}
- return si.position + end;
+ return eng->positionInLigature(&si, end, x, pos, -1,
+ cpos == QTextLine::CursorOnCharacter);
}
}
Q_ASSERT(glyph_pos != -1);
- int j;
- for (j = 0; j < eng->length(item); ++j)
- if (logClusters[j] == glyph_pos)
- break;
-// qDebug("at pos %d (in run: %d)", si.position + j, j);
- return si.position + j;
+ return eng->positionInLigature(&si, end, x, edge, glyph_pos,
+ cpos == QTextLine::CursorOnCharacter);
}
}
// right of last item