diff options
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem.cpp | 6 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 23 | ||||
-rw-r--r-- | src/gui/text/qstatictext.cpp | 37 | ||||
-rw-r--r-- | src/gui/text/qstatictext_p.h | 7 | ||||
-rw-r--r-- | src/gui/text/qtextcursor.cpp | 87 | ||||
-rw-r--r-- | src/gui/text/qtextcursor.h | 6 | ||||
-rw-r--r-- | src/gui/text/qtextcursor_p.h | 3 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 33 | ||||
-rw-r--r-- | src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h | 3 | ||||
-rw-r--r-- | tests/auto/qstatictext/tst_qstatictext.cpp | 7 | ||||
-rw-r--r-- | tests/auto/qtextcursor/tst_qtextcursor.cpp | 8 |
11 files changed, 159 insertions, 61 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 9d7354a..b3e1701 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5687,18 +5687,20 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect) return; } - // Find pixmap in cache, then remove to avoid deep copy when modifying.s + // Find pixmap in cache. QPixmap cachedPixmap; if (!QPixmapCache::find(cache->key, &cachedPixmap)) { update(rect); return; } - QPixmapCache::remove(cache->key); QRect scrollRect = (rect.isNull() ? boundingRect() : rect).toAlignedRect(); if (!scrollRect.intersects(cache->boundingRect)) return; // Nothing to scroll. + // Remove from cache to avoid deep copy when modifying. + QPixmapCache::remove(cache->key); + QRegion exposed; cachedPixmap.scroll(dx, dy, scrollRect.translated(-cache->boundingRect.topLeft()), &exposed); diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 54e0aa3..e460b7b 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5855,14 +5855,24 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText return; } + if (d->extended->type() == QPaintEngine::OpenGL2 && !staticText_d->untransformedCoordinates) { + staticText_d->untransformedCoordinates = true; + staticText_d->needsRelayout = true; + } else if (d->extended->type() != QPaintEngine::OpenGL2 && staticText_d->untransformedCoordinates) { + staticText_d->untransformedCoordinates = false; + staticText_d->needsRelayout = true; + } + // Don't recalculate entire layout because of translation, rather add the dx and dy // into the position to move each text item the correct distance. - QPointF transformedPosition = topLeftPosition * d->state->matrix; - QTransform matrix = d->state->matrix; + QPointF transformedPosition = topLeftPosition; + if (!staticText_d->untransformedCoordinates) + transformedPosition = transformedPosition * d->state->matrix; + QTransform oldMatrix; // The translation has been applied to transformedPosition. Remove translation // component from matrix. - if (d->state->matrix.isTranslating()) { + if (d->state->matrix.isTranslating() && !staticText_d->untransformedCoordinates) { qreal m11 = d->state->matrix.m11(); qreal m12 = d->state->matrix.m12(); qreal m13 = d->state->matrix.m13(); @@ -5871,6 +5881,7 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText qreal m23 = d->state->matrix.m23(); qreal m33 = d->state->matrix.m33(); + oldMatrix = d->state->matrix; d->state->matrix.setMatrix(m11, m12, m13, m21, m22, m23, 0.0, 0.0, m33); @@ -5879,7 +5890,7 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText // If the transform is not identical to the text transform, // we have to relayout the text (for other transformations than plain translation) bool staticTextNeedsReinit = staticText_d->needsRelayout; - if (staticText_d->matrix != d->state->matrix) { + if (!staticText_d->untransformedCoordinates && staticText_d->matrix != d->state->matrix) { staticText_d->matrix = d->state->matrix; staticTextNeedsReinit = true; } @@ -5918,8 +5929,8 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText if (currentColor != oldPen.color()) setPen(oldPen); - if (matrix.isTranslating()) - d->state->matrix = matrix; + if (!staticText_d->untransformedCoordinates && oldMatrix.isTranslating()) + d->state->matrix = oldMatrix; } /*! diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index 84c1d96..10870aa 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -115,10 +115,12 @@ QT_BEGIN_NAMESPACE Qt::RichText. If it's the first time the static text is drawn, or if the static text, or the painter's font - or matrix have been altered since the last time it was drawn, the text's layout has to be - recalculated. This will impose an overhead on the QPainter::drawStaticText() call where the - relayout occurs. To avoid this overhead in the paint event, you can call prepare() ahead of - time to ensure that the layout is calculated. + has been altered since the last time it was drawn, the text's layout has to be + recalculated. On some paint engines, changing the matrix of the painter will also cause the + layout to be recalculated. In particular, this will happen for any engine except for the + OpenGL2 paint engine. Recalculating the layout will impose an overhead on the + QPainter::drawStaticText() call where it occurs. To avoid this overhead in the paint event, you + can call prepare() ahead of time to ensure that the layout is calculated. \sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument */ @@ -188,8 +190,9 @@ void QStaticText::detach() When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part of the QStaticText object has changed since the last time it was drawn. It will also be - recalculated if the painter's font or matrix are not the same as when the QStaticText was last - drawn. + recalculated if the painter's font is not the same as when the QStaticText was last drawn, or, + on any other paint engine than the OpenGL2 engine, if the painter's matrix has been altered + since the static text was last drawn. To avoid the overhead of creating the layout the first time you draw the QStaticText after making changes, you can use the prepare() function and pass in the \a matrix and \a font you @@ -364,14 +367,16 @@ QSizeF QStaticText::size() const QStaticTextPrivate::QStaticTextPrivate() : textWidth(-1.0), items(0), itemCount(0), glyphPool(0), positionPool(0), charPool(0), - needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText) + needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText), + untransformedCoordinates(false) { } QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other) : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix), items(0), itemCount(0), glyphPool(0), positionPool(0), charPool(0), needsRelayout(true), - useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat) + useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat), + untransformedCoordinates(other.untransformedCoordinates) { } @@ -396,8 +401,9 @@ namespace { class DrawTextItemRecorder: public QPaintEngine { public: - DrawTextItemRecorder(bool useBackendOptimizations, int numChars) - : m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations) + DrawTextItemRecorder(bool untransformedCoordinates, bool useBackendOptimizations, int numChars) + : m_dirtyPen(false), m_useBackendOptimizations(useBackendOptimizations), + m_untransformedCoordinates(untransformedCoordinates) { } @@ -423,7 +429,7 @@ namespace { if (m_dirtyPen) currentItem.color = state->pen().color(); - QTransform matrix = state->transform(); + QTransform matrix = m_untransformedCoordinates ? QTransform() : state->transform(); matrix.translate(position.x(), position.y()); QVarLengthArray<glyph_t> glyphs; @@ -486,14 +492,17 @@ namespace { bool m_dirtyPen; bool m_useBackendOptimizations; + bool m_untransformedCoordinates; }; class DrawTextItemDevice: public QPaintDevice { public: - DrawTextItemDevice(bool useBackendOptimizations, int numChars) + DrawTextItemDevice(bool untransformedCoordinates, bool useBackendOptimizations, + int numChars) { - m_paintEngine = new DrawTextItemRecorder(useBackendOptimizations, numChars); + m_paintEngine = new DrawTextItemRecorder(untransformedCoordinates, + useBackendOptimizations, numChars); } ~DrawTextItemDevice() @@ -629,7 +638,7 @@ void QStaticTextPrivate::init() position = QPointF(0, 0); - DrawTextItemDevice device(useBackendOptimizations, text.size()); + DrawTextItemDevice device(untransformedCoordinates, useBackendOptimizations, text.size()); { QPainter painter(&device); painter.setFont(font); diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h index 2ab5579..1a96291 100644 --- a/src/gui/text/qstatictext_p.h +++ b/src/gui/text/qstatictext_p.h @@ -148,9 +148,10 @@ public: QFixedPoint *positionPool; // 4 bytes per text QChar *charPool; // 4 bytes per text - unsigned char needsRelayout : 1; - unsigned char useBackendOptimizations : 1; // 1 byte per text - unsigned char textFormat : 2; + unsigned char needsRelayout : 1; // 1 byte per text + unsigned char useBackendOptimizations : 1; + unsigned char textFormat : 2; + unsigned char untransformedCoordinates : 1; // ================ // 167 bytes per text diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp index c91df3c..d6ac3aa 100644 --- a/src/gui/text/qtextcursor.cpp +++ b/src/gui/text/qtextcursor.cpp @@ -64,7 +64,7 @@ enum { QTextCursorPrivate::QTextCursorPrivate(QTextDocumentPrivate *p) : priv(p), x(0), position(0), anchor(0), adjusted_anchor(0), - currentCharFormat(-1), visualNavigation(false) + currentCharFormat(-1), visualNavigation(false), keepPositionOnInsert(false) { priv->addCursor(this); } @@ -79,6 +79,7 @@ QTextCursorPrivate::QTextCursorPrivate(const QTextCursorPrivate &rhs) x = rhs.x; currentCharFormat = rhs.currentCharFormat; visualNavigation = rhs.visualNavigation; + keepPositionOnInsert = rhs.keepPositionOnInsert; priv->addCursor(this); } @@ -95,7 +96,7 @@ QTextCursorPrivate::AdjustResult QTextCursorPrivate::adjustPosition(int position if (position < positionOfChange || (position == positionOfChange && (op == QTextUndoCommand::KeepCursor - || anchor < position) + || keepPositionOnInsert) ) ) { result = CursorUnchanged; @@ -1276,6 +1277,80 @@ void QTextCursor::setVisualNavigation(bool b) d->visualNavigation = b; } + +/*! + \since 4.7 + + Sets the visual x position for vertical cursor movements. + + The vertical movement x position is cleared automatically when the cursor moves horizontally, and kept + unchanged when the cursor moves vertically. The mechanism allows the cursor to move up and down on a + visually straight line with proportional fonts, and to gently "jump" over short lines. + + A value of -1 indicates no predefined x position. It will then be set automatically the next time the + cursor moves up or down. + + \sa verticalMovementX() + */ +void QTextCursor::setVerticalMovementX(int x) +{ + if (d) + d->x = x; +} + +/*! \since 4.7 + + Returns the visual x position for vertical cursor movements. + + A value of -1 indicates no predefined x position. It will then be set automatically the next time the + cursor moves up or down. + + \sa setVerticalMovementX() + */ +int QTextCursor::verticalMovementX() const +{ + return d ? d->x : -1; +} + +/*! + \since 4.7 + + Returns whether the cursor should keep its current position when text gets inserted at the position of the + cursor. + + The default is false; + + \sa setKeepPositionOnInsert() + */ +bool QTextCursor::keepPositionOnInsert() const +{ + return d ? d->keepPositionOnInsert : false; +} + +/*! + \since 4.7 + + Defines whether the cursor should keep its current position when text gets inserted at the current position of the + cursor. + + If \b is true, the cursor keeps its current position when text gets inserted at the positing of the cursor. + If \b is false, the cursor moves along with the inserted text. + + The default is false. + + Note that a cursor always moves when text is inserted before the current position of the cursor, and it + always keeps its position when text is inserted after the current position of the cursor. + + \sa keepPositionOnInsert() + */ +void QTextCursor::setKeepPositionOnInsert(bool b) +{ + if (d) + d->keepPositionOnInsert = b; +} + + + /*! Inserts \a text at the current position, using the current character format. @@ -1408,16 +1483,16 @@ void QTextCursor::deletePreviousChar() { if (!d || !d->priv) return; - + if (d->position != d->anchor) { removeSelectedText(); return; } - + if (d->anchor < 1 || !d->canDelete(d->anchor-1)) return; d->anchor--; - + QTextDocumentPrivate::FragmentIterator fragIt = d->priv->find(d->anchor); const QTextFragmentData * const frag = fragIt.value(); int fpos = fragIt.position(); @@ -1429,7 +1504,7 @@ void QTextCursor::deletePreviousChar() if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00) --d->anchor; } - + d->adjusted_anchor = d->anchor; d->remove(); d->setX(); diff --git a/src/gui/text/qtextcursor.h b/src/gui/text/qtextcursor.h index 3e968a3..251cb33 100644 --- a/src/gui/text/qtextcursor.h +++ b/src/gui/text/qtextcursor.h @@ -132,6 +132,12 @@ public: bool visualNavigation() const; void setVisualNavigation(bool b); + void setVerticalMovementX(int x); + int verticalMovementX() const; + + void setKeepPositionOnInsert(bool b); + bool keepPositionOnInsert() const; + void deleteChar(); void deletePreviousChar(); diff --git a/src/gui/text/qtextcursor_p.h b/src/gui/text/qtextcursor_p.h index 1bdfa78..4e36b95 100644 --- a/src/gui/text/qtextcursor_p.h +++ b/src/gui/text/qtextcursor_p.h @@ -112,7 +112,8 @@ public: int anchor; int adjusted_anchor; int currentCharFormat; - bool visualNavigation; + uint visualNavigation : 1; + uint keepPositionOnInsert : 1; }; QT_END_NAMESPACE diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 5758b25..ee49a3d 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1333,8 +1333,16 @@ void QGL2PaintEngineEx::drawStaticTextItem(QStaticTextItem *textItem) QFontEngineGlyphCache::Type glyphType = textItem->fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(textItem->fontEngine->glyphFormat) : d->glyphCacheType; + if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { + if (d->device->alphaRequested() || state()->matrix.type() > QTransform::TxTranslate + || (state()->composition_mode != QPainter::CompositionMode_Source + && state()->composition_mode != QPainter::CompositionMode_SourceOver)) + { + glyphType = QFontEngineGlyphCache::Raster_A8; + } + } - d->drawCachedGlyphs(glyphType, textItem, true); + d->drawCachedGlyphs(glyphType, textItem); } bool QGL2PaintEngineEx::drawTexture(const QRectF &dest, GLuint textureId, const QSize &size, const QRectF &src) @@ -1408,7 +1416,7 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem staticTextItem.numGlyphs = glyphs.size(); staticTextItem.glyphPositions = positions.data(); - d->drawCachedGlyphs(glyphType, &staticTextItem, false); + d->drawCachedGlyphs(glyphType, &staticTextItem); } return; } @@ -1439,21 +1447,16 @@ namespace { // #define QT_OPENGL_DRAWCACHEDGLYPHS_INDEX_ARRAY_VBO void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, - QStaticTextItem *staticTextItem, - bool includeMatrixInCache) + QStaticTextItem *staticTextItem) { Q_Q(QGL2PaintEngineEx); QOpenGL2PaintEngineState *s = q->state(); QGLTextureGlyphCache *cache = - (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType, - includeMatrixInCache - ? s->matrix - : QTransform()); + (QGLTextureGlyphCache *) staticTextItem->fontEngine->glyphCache(ctx, glyphType, QTransform()); if (!cache || cache->cacheType() != glyphType) { - cache = new QGLTextureGlyphCache(ctx, glyphType, - includeMatrixInCache ? s->matrix : QTransform()); + cache = new QGLTextureGlyphCache(ctx, glyphType, QTransform()); staticTextItem->fontEngine->setGlyphCache(ctx, cache); } @@ -1561,13 +1564,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp QBrush pensBrush = q->state()->pen.brush(); setBrush(pensBrush); - // When painting a QStaticTextItem, the glyph positions are already in device coordinates, - // therefore we temporarily set an identity matrix on the painter for the draw call to - // avoid transforming the positions twice. - QTransform old = s->matrix; - if (includeMatrixInCache) - s->matrix = QTransform(); - if (glyphType == QFontEngineGlyphCache::Raster_RGBMask) { // Subpixel antialiasing without gamma correction @@ -1664,9 +1660,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngineGlyphCache::Type glyp #else glDrawElements(GL_TRIANGLE_STRIP, 6 * staticTextItem->numGlyphs, GL_UNSIGNED_SHORT, elementIndices.data()); #endif - - if (includeMatrixInCache) - s->matrix = old; } void QGL2PaintEngineEx::drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h index 0a046dc..59b90d8 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h @@ -202,8 +202,7 @@ public: void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false); void drawPixmapFragments(const QPainter::PixmapFragment *fragments, int fragmentCount, const QPixmap &pixmap, QPainter::PixmapFragmentHints hints); - void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem, - bool includeMatrixInCache); + void drawCachedGlyphs(QFontEngineGlyphCache::Type glyphType, QStaticTextItem *staticTextItem); // Calls glVertexAttributePointer if the pointer has changed inline void setVertexAttributePointer(unsigned int arrayIndex, const GLfloat *pointer); diff --git a/tests/auto/qstatictext/tst_qstatictext.cpp b/tests/auto/qstatictext/tst_qstatictext.cpp index c7801ac..1d166f4 100644 --- a/tests/auto/qstatictext/tst_qstatictext.cpp +++ b/tests/auto/qstatictext/tst_qstatictext.cpp @@ -324,8 +324,7 @@ bool tst_QStaticText::supportsTransformations() const QPaintEngine::Type type = engine->type(); - if (type == QPaintEngine::OpenGL2 - || type == QPaintEngine::OpenGL + if (type == QPaintEngine::OpenGL #if !defined Q_WS_WIN || type == QPaintEngine::Raster #endif @@ -471,7 +470,7 @@ void tst_QStaticText::transformationChanged() p.drawText(QRectF(0, 0, 1000, 1000), 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit."); - p.scale(7.0, 5.0); + p.scale(2.0, 2.5); p.drawText(QRectF(0, 0, 1000, 1000), 0, "Lorem ipsum dolor sit amet, consectetur adipiscing elit."); } @@ -487,7 +486,7 @@ void tst_QStaticText::transformationChanged() p.drawStaticText(QPointF(0, 0), text); - p.scale(7.0, 5.0); + p.scale(2.0, 2.5); p.drawStaticText(QPointF(0, 0), text); } diff --git a/tests/auto/qtextcursor/tst_qtextcursor.cpp b/tests/auto/qtextcursor/tst_qtextcursor.cpp index d44ce72..99babac 100644 --- a/tests/auto/qtextcursor/tst_qtextcursor.cpp +++ b/tests/auto/qtextcursor/tst_qtextcursor.cpp @@ -226,9 +226,9 @@ void tst_QTextCursor::navigation1() cursor.movePosition(QTextCursor::End); cursor.insertBlock(); { - int oldPos = cursor.position(); - cursor.movePosition(QTextCursor::End); - QVERIFY(cursor.position() == oldPos); + int oldPos = cursor.position(); + cursor.movePosition(QTextCursor::End); + QVERIFY(cursor.position() == oldPos); } QVERIFY(cursor.atBlockStart()); QVERIFY(cursor.position() == 9); @@ -1699,8 +1699,10 @@ void tst_QTextCursor::adjustCursorsOnInsert() QCOMPARE(selection.position(), posAfter+1); doc->undo(); + selection.setKeepPositionOnInsert(true); cursor.setPosition(posAfter); cursor.insertText(QLatin1String("x")); + selection.setKeepPositionOnInsert(false); QCOMPARE(selection.anchor(), posBefore); QCOMPARE(selection.position(), posAfter); doc->undo(); |