diff options
Diffstat (limited to 'src/gui/text/qtextlayout.cpp')
-rw-r--r-- | src/gui/text/qtextlayout.cpp | 219 |
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(); |