summaryrefslogtreecommitdiffstats
path: root/src/gui/text/qtextlayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text/qtextlayout.cpp')
-rw-r--r--src/gui/text/qtextlayout.cpp219
1 files changed, 63 insertions, 156 deletions
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 8e605e4ae1..eafd98d234 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1,40 +1,32 @@
/****************************************************************************
**
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL$
+** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
+** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
-** 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.
-**
-**
** $QT_END_LICENSE$
**
****************************************************************************/
@@ -100,14 +92,11 @@ QT_BEGIN_NAMESPACE
\reentrant
\brief The QTextInlineObject class represents an inline object in
- a QTextLayout.
+ a QAbstractTextDocumentLayout and its implementations.
\inmodule QtGui
\ingroup richtext-processing
- This class is only used if the text layout is used to lay out
- parts of a QTextDocument.
-
Normally, you do not need to create a QTextInlineObject. It is
used by QAbstractTextDocumentLayout to handle inline objects when
implementing a custom layout.
@@ -115,8 +104,8 @@ QT_BEGIN_NAMESPACE
The inline object has various attributes that can be set, for
example using, setWidth(), setAscent(), and setDescent(). The
rectangle it occupies is given by rect(), and its direction by
- isRightToLeft(). Its position in the text layout is given by at(),
- and its format is given by format().
+ textDirection(). Its position in the text layout is given by
+ textPosition(), and its format is given by format().
*/
/*!
@@ -505,7 +494,7 @@ QString QTextLayout::preeditAreaText() const
*/
void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
{
- d->setAdditionalFormats(formatList);
+ d->setFormats(formatList);
if (d->block.docHandle())
d->block.docHandle()->documentChange(d->block.position(), d->block.length());
@@ -518,7 +507,7 @@ void QTextLayout::setAdditionalFormats(const QList<FormatRange> &formatList)
*/
QList<QTextLayout::FormatRange> QTextLayout::additionalFormats() const
{
- return d->additionalFormats();
+ return d->formats();
}
/*!
@@ -567,7 +556,7 @@ bool QTextLayout::cacheEnabled() const
*/
void QTextLayout::setCursorMoveStyle(Qt::CursorMoveStyle style)
{
- d->visualMovement = style == Qt::VisualMoveStyle ? true : false;
+ d->visualMovement = style == Qt::VisualMoveStyle;
}
/*!
@@ -1735,6 +1724,7 @@ void QTextLine::layout_helper(int maxGlyphs)
int item = -1;
int newItem = eng->findItem(line.from);
+ Q_ASSERT(newItem >= 0);
LB_DEBUG("from: %d: item=%d, total %d, width available %f", line.from, newItem, eng->layoutData->items.size(), line.width.toReal());
@@ -2020,79 +2010,6 @@ int QTextLine::textLength() const
return eng->lines[index].length + eng->lines[index].trailingSpaces;
}
-static void drawMenuText(QPainter *p, QFixed x, QFixed y, const QScriptItem &si, QTextItemInt &gf, QTextEngine *eng,
- int start, int glyph_start)
-{
- int ge = glyph_start + gf.glyphs.numGlyphs;
- int gs = glyph_start;
- int end = start + gf.num_chars;
- unsigned short *logClusters = eng->logClusters(&si);
- QGlyphLayout glyphs = eng->shapedGlyphs(&si);
- QFixed orig_width = gf.width;
-
- int *ul = eng->underlinePositions;
- if (ul)
- while (*ul != -1 && *ul < start)
- ++ul;
- bool rtl = si.analysis.bidiLevel % 2;
- if (rtl)
- x += si.width;
-
- do {
- int gtmp = ge;
- int stmp = end;
- if (ul && *ul != -1 && *ul < end) {
- stmp = *ul;
- gtmp = logClusters[*ul-si.position];
- }
-
- gf.glyphs = glyphs.mid(gs, gtmp - gs);
- gf.num_chars = stmp - start;
- gf.chars = eng->layoutData->string.unicode() + start;
- QFixed w = 0;
- while (gs < gtmp) {
- w += glyphs.effectiveAdvance(gs);
- ++gs;
- }
- start = stmp;
- gf.width = w;
- if (rtl)
- x -= w;
- if (gf.num_chars)
- QPainterPrivate::get(p)->drawTextItem(QPointF(x.toReal(), y.toReal()), gf, eng);
- if (!rtl)
- x += w;
- if (ul && *ul != -1 && *ul < end) {
- // draw underline
- gtmp = (*ul == end-1) ? ge : logClusters[*ul+1-si.position];
- ++stmp;
- gf.glyphs = glyphs.mid(gs, gtmp - gs);
- gf.num_chars = stmp - start;
- gf.chars = eng->layoutData->string.unicode() + start;
- gf.logClusters = logClusters + start - si.position;
- w = 0;
- while (gs < gtmp) {
- w += glyphs.effectiveAdvance(gs);
- ++gs;
- }
- ++start;
- gf.width = w;
- gf.underlineStyle = QTextCharFormat::SingleUnderline;
- if (rtl)
- x -= w;
- QPainterPrivate::get(p)->drawTextItem(QPointF(x.toReal(), y.toReal()), gf, eng);
- if (!rtl)
- x += w;
- gf.underlineStyle = QTextCharFormat::NoUnderline;
- ++gf.chars;
- ++ul;
- }
- } while (gs < ge);
-
- gf.width = orig_width;
-}
-
-
static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r)
{
QBrush c = chf.foreground();
@@ -2212,14 +2129,10 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
if (si.analysis.flags >= QScriptAnalysis::TabOrObject)
continue;
- QPointF pos(iterator.x.toReal(), y);
- if (from >= 0 && length >= 0 &&
- (from >= si.position + eng->length(&si)
- || from + length <= si.position
- || from + length <= iterator.itemStart
- || from >= iterator.itemEnd)) {
+ if (from >= 0 && length >= 0 && (from >= iterator.itemEnd || from + length <= iterator.itemStart))
continue;
- }
+
+ QPointF pos(iterator.x.toReal(), y);
QFont font;
QGlyphRun::GlyphRunFlags flags;
@@ -2240,15 +2153,13 @@ QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
}
int relativeFrom = qMax(iterator.itemStart, from) - si.position;
- int relativeTo = qMin(iterator.itemEnd - 1, from + length - 1) - si.position;
+ int relativeTo = qMin(iterator.itemEnd, 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];
+ int glyphsEnd = (relativeTo == iterator.itemLength) ? si.num_glyphs - 1 : logClusters[relativeTo];
// the glyph index right next to the requested range
- int nextGlyphIndex = relativeTo < eng->length(&si) - 1 ? logClusters[relativeTo + 1] : si.num_glyphs;
+ int nextGlyphIndex = (relativeTo < iterator.itemLength - 1) ? logClusters[relativeTo + 1] : si.num_glyphs;
if (nextGlyphIndex - 1 > glyphsEnd)
glyphsEnd = nextGlyphIndex - 1;
bool startsInsideLigature = relativeFrom > 0 && logClusters[relativeFrom - 1] == glyphsStart;
@@ -2488,52 +2399,48 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR
Q_ASSERT(gf.fontEngine);
- if (eng->underlinePositions) {
- // can't have selections in this case
- drawMenuText(p, iterator.x, itemBaseLine, si, gf, eng, iterator.itemStart, iterator.glyphsStart);
- } else {
- QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());
- if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {
- QPainterPath path;
- path.setFillRule(Qt::WindingFill);
-
- if (gf.glyphs.numGlyphs)
- gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);
- if (gf.flags) {
- const QFontEngine *fe = gf.fontEngine;
- const qreal lw = fe->lineThickness().toReal();
- if (gf.flags & QTextItem::Underline) {
- qreal offs = fe->underlinePosition().toReal();
- path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);
- }
- if (gf.flags & QTextItem::Overline) {
- qreal offs = fe->ascent().toReal() + 1;
- path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
- }
- if (gf.flags & QTextItem::StrikeOut) {
- qreal offs = fe->ascent().toReal() / 3;
- path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
- }
+ QPointF pos(iterator.x.toReal(), itemBaseLine.toReal());
+ if (format.penProperty(QTextFormat::TextOutline).style() != Qt::NoPen) {
+ QPainterPath path;
+ path.setFillRule(Qt::WindingFill);
+
+ if (gf.glyphs.numGlyphs)
+ gf.fontEngine->addOutlineToPath(pos.x(), pos.y(), gf.glyphs, &path, gf.flags);
+ if (gf.flags) {
+ const QFontEngine *fe = gf.fontEngine;
+ const qreal lw = fe->lineThickness().toReal();
+ if (gf.flags & QTextItem::Underline) {
+ qreal offs = fe->underlinePosition().toReal();
+ path.addRect(pos.x(), pos.y() + offs, gf.width.toReal(), lw);
+ }
+ if (gf.flags & QTextItem::Overline) {
+ qreal offs = fe->ascent().toReal() + 1;
+ path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
+ }
+ if (gf.flags & QTextItem::StrikeOut) {
+ qreal offs = fe->ascent().toReal() / 3;
+ path.addRect(pos.x(), pos.y() - offs, gf.width.toReal(), lw);
}
-
- p->save();
- p->setRenderHint(QPainter::Antialiasing);
- //Currently QPen with a Qt::NoPen style still returns a default
- //QBrush which != Qt::NoBrush so we need this specialcase to reset it
- if (p->pen().style() == Qt::NoPen)
- p->setBrush(Qt::NoBrush);
- else
- p->setBrush(p->pen().brush());
-
- p->setPen(format.textOutline());
- p->drawPath(path);
- p->restore();
- } else {
- if (noText)
- gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be
- QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);
}
+
+ p->save();
+ p->setRenderHint(QPainter::Antialiasing);
+ //Currently QPen with a Qt::NoPen style still returns a default
+ //QBrush which != Qt::NoBrush so we need this specialcase to reset it
+ if (p->pen().style() == Qt::NoPen)
+ p->setBrush(Qt::NoBrush);
+ else
+ p->setBrush(p->pen().brush());
+
+ p->setPen(format.textOutline());
+ p->drawPath(path);
+ p->restore();
+ } else {
+ if (noText)
+ gf.glyphs.numGlyphs = 0; // slightly less elegant than it should be
+ QPainterPrivate::get(p)->drawTextItem(pos, gf, eng);
}
+
if (si.analysis.flags == QScriptAnalysis::Space
&& (eng->option.flags() & QTextOption::ShowTabsAndSpaces)) {
QBrush c = format.foreground();