diff options
Diffstat (limited to 'src/gui/painting/qpainter.cpp')
-rw-r--r-- | src/gui/painting/qpainter.cpp | 384 |
1 files changed, 75 insertions, 309 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 390147463d..fc93ffa19f 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -96,10 +96,15 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QTextItem::RenderFlags flags, qreal width, const QTextCharFormat &charFormat); // Helper function to calculate left most position, width and flags for decoration drawing -Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, - const QFixedPoint *positions, int glyphCount, - QFontEngine *fontEngine, const QFont &font, - const QTextCharFormat &charFormat); +static void qt_draw_decoration_for_glyphs(QPainter *painter, + const QPointF &decorationPosition, + const glyph_t *glyphArray, + const QFixedPoint *positions, + int glyphCount, + QFontEngine *fontEngine, + bool underline, + bool overline, + bool strikeOut); static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush) { @@ -1924,8 +1929,7 @@ bool QPainter::end() } if (d->states.size() > 1) { - qWarning("QPainter::end: Painter ended with %d saved states", - d->states.size()); + qWarning("QPainter::end: Painter ended with %d saved states", int(d->states.size())); } if (d->engine->autoDestruct()) { @@ -2555,19 +2559,19 @@ QRegion QPainter::clipRegion() const case QPainterClipInfo::PathClip: { QTransform matrix = (info.matrix * d->invMatrix); if (lastWasNothing) { - region = QRegion((info.path * matrix).toFillPolygon(QTransform()).toPolygon(), + region = QRegion((info.path * matrix).toFillPolygon().toPolygon(), info.path.fillRule()); lastWasNothing = false; continue; } if (info.operation == Qt::IntersectClip) { - region &= QRegion((info.path * matrix).toFillPolygon(QTransform()).toPolygon(), + region &= QRegion((info.path * matrix).toFillPolygon().toPolygon(), info.path.fillRule()); } else if (info.operation == Qt::NoClip) { lastWasNothing = true; region = QRegion(); } else { - region = QRegion((info.path * matrix).toFillPolygon(QTransform()).toPolygon(), + region = QRegion((info.path * matrix).toFillPolygon().toPolygon(), info.path.fillRule()); } break; @@ -2891,175 +2895,6 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op) d->updateState(d->state); } -#if QT_DEPRECATED_SINCE(5, 13) -/*! - \since 4.2 - \obsolete - - Sets the transformation matrix to \a matrix and enables transformations. - - \note It is advisable to use setWorldTransform() instead of this function to - preserve the properties of perspective transformations. - - If \a combine is true, then \a matrix is combined with the current - transformation matrix; otherwise \a matrix replaces the current - transformation matrix. - - If \a matrix is the identity matrix and \a combine is false, this - function calls setWorldMatrixEnabled(false). (The identity matrix is the - matrix where QMatrix::m11() and QMatrix::m22() are 1.0 and the - rest are 0.0.) - - The following functions can transform the coordinate system without using - a QMatrix: - \list - \li translate() - \li scale() - \li shear() - \li rotate() - \endlist - - They operate on the painter's worldMatrix() and are implemented like this: - - \snippet code/src_gui_painting_qpainter.cpp 4 - - Note that when using setWorldMatrix() function you should always have - \a combine be true when you are drawing into a QPicture. Otherwise - it may not be possible to replay the picture with additional - transformations; using the translate(), scale(), etc. convenience - functions is safe. - - For more information about the coordinate system, transformations - and window-viewport conversion, see \l {Coordinate System}. - - \sa setWorldTransform(), QTransform -*/ - -void QPainter::setWorldMatrix(const QMatrix &matrix, bool combine) -{ - setWorldTransform(QTransform(matrix), combine); -} - -/*! - \since 4.2 - \obsolete - - Returns the world transformation matrix. - - It is advisable to use worldTransform() because worldMatrix() does not - preserve the properties of perspective transformations. - - \sa {QPainter#Coordinate Transformations}{Coordinate Transformations}, - {Coordinate System} -*/ - -const QMatrix &QPainter::worldMatrix() const -{ - Q_D(const QPainter); - if (!d->engine) { - qWarning("QPainter::worldMatrix: Painter not active"); - return d->fakeState()->transform.toAffine(); - } - return d->state->worldMatrix.toAffine(); -} - -/*! - \obsolete - - Use setWorldTransform() instead. - - \sa setWorldTransform() -*/ - -void QPainter::setMatrix(const QMatrix &matrix, bool combine) -{ - setWorldTransform(QTransform(matrix), combine); -} - -/*! - \obsolete - - Use worldTransform() instead. - - \sa worldTransform() -*/ - -const QMatrix &QPainter::matrix() const -{ -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - return worldMatrix(); -QT_WARNING_POP -} - - -/*! - \since 4.2 - \obsolete - - Returns the transformation matrix combining the current - window/viewport and world transformation. - - It is advisable to use combinedTransform() instead of this - function to preserve the properties of perspective transformations. - - \sa setWorldTransform(), setWindow(), setViewport() -*/ -QMatrix QPainter::combinedMatrix() const -{ - return combinedTransform().toAffine(); -} - - -/*! - \obsolete - - Returns the matrix that transforms from logical coordinates to - device coordinates of the platform dependent paint device. - - \note It is advisable to use deviceTransform() instead of this - function to preserve the properties of perspective transformations. - - This function is \e only needed when using platform painting - commands on the platform dependent handle (Qt::HANDLE), and the - platform does not do transformations nativly. - - The QPaintEngine::PaintEngineFeature enum can be queried to - determine whether the platform performs the transformations or - not. - - \sa worldMatrix(), QPaintEngine::hasFeature(), -*/ -const QMatrix &QPainter::deviceMatrix() const -{ - Q_D(const QPainter); - if (!d->engine) { - qWarning("QPainter::deviceMatrix: Painter not active"); - return d->fakeState()->transform.toAffine(); - } - return d->state->matrix.toAffine(); -} - -/*! - \obsolete - - Resets any transformations that were made using translate(), scale(), - shear(), rotate(), setWorldMatrix(), setViewport() and - setWindow(). - - It is advisable to use resetTransform() instead of this function - to preserve the properties of perspective transformations. - - \sa {QPainter#Coordinate Transformations}{Coordinate - Transformations} -*/ - -void QPainter::resetMatrix() -{ - resetTransform(); -} -#endif - /*! \since 4.2 @@ -3109,34 +2944,6 @@ bool QPainter::worldMatrixEnabled() const return d->state->WxF; } -#if QT_DEPRECATED_SINCE(5, 13) -/*! - \obsolete - - Use setWorldMatrixEnabled() instead. - - \sa setWorldMatrixEnabled() -*/ - -void QPainter::setMatrixEnabled(bool enable) -{ - setWorldMatrixEnabled(enable); -} - -/*! - \obsolete - - Use worldMatrixEnabled() instead - - \sa worldMatrixEnabled() -*/ - -bool QPainter::matrixEnabled() const -{ - return worldMatrixEnabled(); -} -#endif - /*! Scales the coordinate system by (\a{sx}, \a{sy}). @@ -5607,40 +5414,31 @@ void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun) fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition); } - d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, fontD->fontEngine, - glyphRun.overline(), glyphRun.underline(), glyphRun.strikeOut()); + d->drawGlyphs(engineRequiresPretransformedGlyphPositions + ? d->state->transform().map(position) + : position, + glyphIndexes, + fixedPointPositions.data(), + count, + fontD->fontEngine, + glyphRun.overline(), + glyphRun.underline(), + glyphRun.strikeOut()); } -void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions, +void QPainterPrivate::drawGlyphs(const QPointF &decorationPosition, + const quint32 *glyphArray, + QFixedPoint *positions, int glyphCount, - QFontEngine *fontEngine, bool overline, bool underline, + QFontEngine *fontEngine, + bool overline, + bool underline, bool strikeOut) { Q_Q(QPainter); updateState(state); - QFixed leftMost; - QFixed rightMost; - QFixed baseLine; - for (int i=0; i<glyphCount; ++i) { - glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); - if (i == 0 || leftMost > positions[i].x) - leftMost = positions[i].x; - - // We don't support glyphs that do not share a common baseline. If this turns out to - // be a relevant use case, then we need to find clusters of glyphs that share a baseline - // and do a drawTextItemDecorations call per cluster. - if (i == 0 || baseLine < positions[i].y) - baseLine = positions[i].y; - - // We use the advance rather than the actual bounds to match the algorithm in drawText() - if (i == 0 || rightMost < positions[i].x + gm.xoff) - rightMost = positions[i].x + gm.xoff; - } - - QFixed width = rightMost - leftMost; - if (extended != nullptr && state->matrix.isAffine()) { QStaticTextItem staticTextItem; staticTextItem.color = state->pen.color(); @@ -5674,21 +5472,15 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positio engine->drawTextItem(QPointF(0, 0), textItem); } - QTextItemInt::RenderFlags flags; - if (underline) - flags |= QTextItemInt::Underline; - if (overline) - flags |= QTextItemInt::Overline; - if (strikeOut) - flags |= QTextItemInt::StrikeOut; - - drawTextItemDecoration(q, QPointF(leftMost.toReal(), baseLine.toReal()), - fontEngine, - nullptr, // textEngine - (underline - ? QTextCharFormat::SingleUnderline - : QTextCharFormat::NoUnderline), - flags, width.toReal(), QTextCharFormat()); + qt_draw_decoration_for_glyphs(q, + decorationPosition, + glyphArray, + positions, + glyphCount, + fontEngine, + underline, + overline, + strikeOut); } #endif // QT_NO_RAWFONT @@ -5868,9 +5660,15 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText } d->extended->drawStaticTextItem(item); - qt_draw_decoration_for_glyphs(this, item->glyphs, item->glyphPositions, - item->numGlyphs, item->fontEngine(), staticText_d->font, - QTextCharFormat()); + qt_draw_decoration_for_glyphs(this, + topLeftPosition, + item->glyphs, + item->glyphPositions, + item->numGlyphs, + item->fontEngine(), + staticText_d->font.underline(), + staticText_d->font.overline(), + staticText_d->font.strikeOut()); } if (currentColor != oldPen.color()) setPen(oldPen); @@ -6375,49 +6173,44 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->setRenderHint(QPainter::Qt4CompatiblePainting); } -Q_GUI_EXPORT void qt_draw_decoration_for_glyphs(QPainter *painter, const glyph_t *glyphArray, - const QFixedPoint *positions, int glyphCount, - QFontEngine *fontEngine, const QFont &font, - const QTextCharFormat &charFormat) +static void qt_draw_decoration_for_glyphs(QPainter *painter, + const QPointF &decorationPosition, + const glyph_t *glyphArray, + const QFixedPoint *positions, + int glyphCount, + QFontEngine *fontEngine, + bool underline, + bool overline, + bool strikeOut) { - if (!(font.underline() || font.strikeOut() || font.overline())) + if (!underline && !overline && !strikeOut) return; - QFixed leftMost; - QFixed rightMost; - QFixed baseLine; - for (int i=0; i<glyphCount; ++i) { - glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[i]); - if (i == 0 || leftMost > positions[i].x) - leftMost = positions[i].x; - - // We don't support glyphs that do not share a common baseline. If this turns out to - // be a relevant use case, then we need to find clusters of glyphs that share a baseline - // and do a drawTextItemDecoration call per cluster. - if (i == 0 || baseLine < positions[i].y) - baseLine = positions[i].y; - - // We use the advance rather than the actual bounds to match the algorithm in drawText() - if (i == 0 || rightMost < positions[i].x + gm.xoff) - rightMost = positions[i].x + gm.xoff; - } - - QFixed width = rightMost - leftMost; QTextItem::RenderFlags flags; - - if (font.underline()) + if (underline) flags |= QTextItem::Underline; - if (font.overline()) + if (overline) flags |= QTextItem::Overline; - if (font.strikeOut()) + if (strikeOut) flags |= QTextItem::StrikeOut; - drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()), + bool rtl = positions[glyphCount - 1].x < positions[0].x; + QFixed baseline = positions[0].y; + glyph_metrics_t gm = fontEngine->boundingBox(glyphArray[rtl ? 0 : glyphCount - 1]); + + qreal width = rtl + ? (positions[0].x + gm.xoff - positions[glyphCount - 1].x).toReal() + : (positions[glyphCount - 1].x + gm.xoff - positions[0].x).toReal(); + + drawTextItemDecoration(painter, + QPointF(decorationPosition.x(), baseline.toReal()), fontEngine, nullptr, // textEngine - font.underline() ? QTextCharFormat::SingleUnderline - : QTextCharFormat::NoUnderline, flags, - width.toReal(), charFormat); + underline ? QTextCharFormat::SingleUnderline + : QTextCharFormat::NoUnderline, + flags, + width, + QTextCharFormat()); } void QPainter::drawTextItem(const QPointF &p, const QTextItem &ti) @@ -8084,33 +7877,6 @@ QFont QPaintEngineState::font() const return static_cast<const QPainterState *>(this)->font; } -#if QT_DEPRECATED_SINCE(5, 13) -/*! - \since 4.2 - \obsolete - - Use transform() instead. - - Returns the matrix in the current paint engine - state. - - \note It is advisable to use transform() instead of this function to - preserve the properties of perspective transformations. - - This variable should only be used when the state() returns a - combination which includes the QPaintEngine::DirtyTransform flag. - - \sa state(), QPaintEngine::updateState() -*/ - -QMatrix QPaintEngineState::matrix() const -{ - const QPainterState *st = static_cast<const QPainterState *>(this); - - return st->matrix.toAffine(); -} -#endif - /*! \since 4.3 |