diff options
Diffstat (limited to 'src/gui/painting/qpainter.cpp')
-rw-r--r-- | src/gui/painting/qpainter.cpp | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 9dadbd5..b694d9c 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -90,6 +90,15 @@ void qt_format_text(const QFont &font, const QRectF &_r, int tf, const QTextOption *option, const QString& str, QRectF *brect, int tabstops, int* tabarray, int tabarraylen, QPainter *painter); +static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, + QTextCharFormat::UnderlineStyle underlineStyle, + const QTextItem::RenderFlags flags, qreal width, + const QTextCharFormat &charFormat); +// Helper function to calculate left most position, width and flags for decoration drawing +static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, + const QFixedPoint *positions, int glyphCount, + QFontEngine *fontEngine, const QFont &font, + const QTextCharFormat &charFormat); static inline QGradient::CoordinateMode coordinateMode(const QBrush &brush) { @@ -5923,6 +5932,10 @@ void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText currentColor = item->color; } d->extended->drawStaticTextItem(item); + + drawDecorationForGlyphs(this, item->glyphs, item->glyphPositions, + item->numGlyphs, item->fontEngine, staticText_d->font, + QTextCharFormat()); } if (currentColor != oldPen.color()) setPen(oldPen); @@ -6290,15 +6303,15 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) return pixmap; } -static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QTextItemInt &ti) +static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const QFontEngine *fe, + QTextCharFormat::UnderlineStyle underlineStyle, + const QTextItem::RenderFlags flags, qreal width, + const QTextCharFormat &charFormat) { - QTextCharFormat::UnderlineStyle underlineStyle = ti.underlineStyle; if (underlineStyle == QTextCharFormat::NoUnderline - && !(ti.flags & (QTextItem::StrikeOut | QTextItem::Overline))) + && !(flags & (QTextItem::StrikeOut | QTextItem::Overline))) return; - QFontEngine *fe = ti.fontEngine; - const QPen oldPen = painter->pen(); const QBrush oldBrush = painter->brush(); painter->setBrush(Qt::NoBrush); @@ -6307,7 +6320,7 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const pen.setWidthF(fe->lineThickness().toReal()); pen.setCapStyle(Qt::FlatCap); - QLineF line(pos.x(), pos.y(), pos.x() + ti.width.toReal(), pos.y()); + QLineF line(pos.x(), pos.y(), pos.x() + width, pos.y()); const qreal underlineOffset = fe->underlinePosition().toReal(); // deliberately ceil the offset to avoid the underline coming too close to @@ -6322,21 +6335,21 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->save(); painter->translate(0, pos.y() + 1); - QColor uc = ti.charFormat.underlineColor(); + QColor uc = charFormat.underlineColor(); if (uc.isValid()) pen.setColor(uc); // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen); - const int descent = (int) ti.descent.toReal(); + const int descent = (int) fe->descent().toReal(); painter->setBrushOrigin(painter->brushOrigin().x(), 0); - painter->fillRect(pos.x(), 0, qCeil(ti.width.toReal()), qMin(wave.height(), descent), wave); + painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave); painter->restore(); } else if (underlineStyle != QTextCharFormat::NoUnderline) { QLineF underLine(line.x1(), underlinePos, line.x2(), underlinePos); - QColor uc = ti.charFormat.underlineColor(); + QColor uc = charFormat.underlineColor(); if (uc.isValid()) pen.setColor(uc); @@ -6348,14 +6361,14 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const pen.setStyle(Qt::SolidLine); pen.setColor(oldPen.color()); - if (ti.flags & QTextItem::StrikeOut) { + if (flags & QTextItem::StrikeOut) { QLineF strikeOutLine = line; strikeOutLine.translate(0., - fe->ascent().toReal() / 3.); painter->setPen(pen); painter->drawLine(strikeOutLine); } - if (ti.flags & QTextItem::Overline) { + if (flags & QTextItem::Overline) { QLineF overLine = line; overLine.translate(0., - fe->ascent().toReal()); painter->setPen(pen); @@ -6366,6 +6379,50 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const painter->setBrush(oldBrush); } +static void drawDecorationForGlyphs(QPainter *painter, const glyph_t *glyphArray, + const QFixedPoint *positions, int glyphCount, + QFontEngine *fontEngine, const QFont &font, + const QTextCharFormat &charFormat) +{ + if (!(font.underline() || font.strikeOut() || font.overline())) + 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 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; + QTextItem::RenderFlags flags = 0; + + if (font.underline()) + flags |= QTextItem::Underline; + if (font.overline()) + flags |= QTextItem::Overline; + if (font.strikeOut()) + flags |= QTextItem::StrikeOut; + + drawTextItemDecoration(painter, QPointF(leftMost.toReal(), baseLine.toReal()), + fontEngine, + font.underline() ? QTextCharFormat::SingleUnderline + : QTextCharFormat::NoUnderline, flags, + width.toReal(), charFormat); +} + void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) { #ifdef QT_DEBUG_DRAW @@ -6496,7 +6553,8 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti) else d->engine->drawTextItem(p, ti); } - drawTextItemDecoration(this, p, ti); + drawTextItemDecoration(this, p, ti.fontEngine, ti.underlineStyle, ti.flags, ti.width.toReal(), + ti.charFormat); if (d->state->renderHints != oldRenderHints) { d->state->renderHints = oldRenderHints; |