From 9f387357a7e171636c97a7ef13afca60c01a9e3b Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Sun, 14 Feb 2010 19:50:51 +0100 Subject: Add API for rich text and getting actual size of QStaticText Required for several use cases, support for some html tags to change font, color and do advanced text layouts, as well as getting the bounds of the text when drawn. --- src/gui/painting/qpainter.cpp | 15 +++++--- src/gui/text/qstatictext.cpp | 80 +++++++++++++++++++++++++++++++------------ src/gui/text/qstatictext.h | 4 ++- src/gui/text/qstatictext_p.h | 10 ++++-- 4 files changed, 78 insertions(+), 31 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 8ab813d..2b5a0c5 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5745,10 +5745,7 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static // If we don't have an extended paint engine, or if the painter is projected, // we go through standard code path if (d->extended == 0 || !d->state->matrix.isAffine()) { - if (staticText_d->size.isValid()) - drawText(QRectF(position, staticText_d->size), staticText_d->text); - else - drawText(position, staticText_d->text); + staticText_d->paintText(this); return; } @@ -5784,7 +5781,7 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static bool restoreWhenFinished = false; if (staticText_d->needsClipRect) { save(); - setClipRect(QRectF(position, staticText_d->size)); + setClipRect(QRectF(position, staticText_d->maximumSize)); restoreWhenFinished = true; } @@ -5815,10 +5812,18 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static staticText_d->position = transformedPosition; } + QPen oldPen = d->state->pen; + QColor currentColor = oldPen.color(); for (int i=0; iitemCount; ++i) { QStaticTextItem *item = staticText_d->items + i; + if (currentColor != item->color) { + setPen(item->color); + currentColor = item->color; + } d->extended->drawStaticTextItem(item); } + if (currentColor != oldPen.color()) + setPen(oldPen); if (restoreWhenFinished) restore(); diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index 74c5958..2fe23e5 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -129,7 +129,7 @@ QStaticText::QStaticText(const QString &text, const QSizeF &size) : data(new QStaticTextPrivate) { data->text = text; - data->size = size; + data->maximumSize = size; data->init(); } @@ -199,7 +199,7 @@ bool QStaticText::operator==(const QStaticText &other) const return (data == other.data || (data->text == other.data->text && data->font == other.data->font - && data->size == other.data->size)); + && data->maximumSize == other.data->maximumSize)); } /*! @@ -212,16 +212,22 @@ bool QStaticText::operator!=(const QStaticText &other) const } /*! - Sets the text of the QStaticText to \a text. + Sets the text of the QStaticText to \a text. If \a textFormat is set to Qt::AutoText + (the default), the format of the text will try to be determined using the function + Qt::mightBeRichText(). If the text format is Qt::PlainText, then the text will be displayed + as is, whereas it will be interpreted as HTML if the format is Qt::RichText. HTML tags + that alter the font of the text, its color, or its layout are supported by QStaticText. \note This function will cause the layout of the text to be recalculated. \sa text() */ -void QStaticText::setText(const QString &text) +void QStaticText::setText(const QString &text, Qt::TextFormat textFormat) { detach(); data->text = text; + data->preferRichText = (textFormat == Qt::RichText + || (textFormat == Qt::AutoText && Qt::mightBeRichText(text))); data->init(); } @@ -283,7 +289,7 @@ bool QStaticText::useBackendOptimizations() const void QStaticText::setMaximumSize(const QSizeF &size) { detach(); - data->size = size; + data->maximumSize = size; data->init(); } @@ -294,7 +300,17 @@ void QStaticText::setMaximumSize(const QSizeF &size) */ QSizeF QStaticText::maximumSize() const { - return data->size; + return data->maximumSize; +} + +/*! + Returns the size of the bounding rect for this QStaticText. + + \sa maximumSize() +*/ +QSizeF QStaticText::size() const +{ + return data->actualSize; } /*! @@ -315,7 +331,7 @@ QStaticTextPrivate::QStaticTextPrivate() } QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other) - : text(other.text), font(other.font), size(other.size), matrix(other.matrix), + : text(other.text), font(other.font), maximumSize(other.maximumSize), matrix(other.matrix), items(0), itemCount(0), glyphPool(0), positionPool(0), needsClipRect(false), useBackendOptimizations(false) { @@ -373,6 +389,7 @@ namespace { currentItem->numGlyphs = ti.glyphs.numGlyphs; currentItem->glyphs = m_glyphPool; currentItem->glyphPositions = m_positionPool; + currentItem->color = state->pen().color(); QTransform matrix = state->transform(); matrix.translate(position.x(), position.y()); @@ -488,7 +505,38 @@ namespace { private: DrawTextItemRecorder *m_paintEngine; }; +} + +void QStaticTextPrivate::paintText(QPainter *p) +{ + if (!preferRichText) { + if (maximumSize.isValid()) { + QRectF boundingRect; + p->drawText(QRectF(QPointF(0, 0), maximumSize), Qt::TextWordWrap, text, &boundingRect); + + actualSize = boundingRect.size(); + needsClipRect = boundingRect.width() > maximumSize.width() + || boundingRect.height() > maximumSize.height(); + } else { + p->drawText(0, 0, text); + needsClipRect = false; + QFontMetrics fm(font); + actualSize = fm.boundingRect(text).size(); + } + } else { + QTextDocument document; + document.setDefaultFont(font); + document.setHtml(text); + + QRectF rect = maximumSize.isValid() ? QRectF(QPointF(0, 0), maximumSize) : QRectF(); + document.adjustSize(); + document.drawContents(p, rect); + actualSize = document.size(); + needsClipRect = maximumSize.isValid() + && (actualSize.width() > maximumSize.width() + || actualSize.height() > maximumSize.height()); + } } void QStaticTextPrivate::init() @@ -507,10 +555,8 @@ void QStaticTextPrivate::init() painter.setFont(font); painter.setTransform(matrix); - if (size.isValid()) - painter.drawText(QRectF(QPointF(0, 0), size), text); - else - painter.drawText(0, 0, text); + paintText(&painter); + } itemCount = counterDevice.itemCount(); @@ -533,17 +579,7 @@ void QStaticTextPrivate::init() painter.setFont(font); painter.setTransform(matrix); - if (size.isValid()) { - QRectF boundingRect; - painter.drawText(QRectF(QPointF(0, 0), size), Qt::TextWordWrap, text, &boundingRect); - - needsClipRect = boundingRect.width() > size.width() - || boundingRect.height() > size.height(); - - } else { - painter.drawText(0, 0, text); - needsClipRect = false; - } + paintText(&painter); } } diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h index 11a4249..7498ad4 100644 --- a/src/gui/text/qstatictext.h +++ b/src/gui/text/qstatictext.h @@ -65,12 +65,14 @@ public: QStaticText(const QStaticText &other); ~QStaticText(); - void setText(const QString &text); + void setText(const QString &text, Qt::TextFormat textFormat = Qt::AutoText); QString text() const; void setMaximumSize(const QSizeF &maximumSize); QSizeF maximumSize() const; + QSizeF size() const; + void prepare(const QTransform &matrix, const QFont &font); void setUseBackendOptimizations(bool on); diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h index 72c8439..7aee5c4 100644 --- a/src/gui/text/qstatictext_p.h +++ b/src/gui/text/qstatictext_p.h @@ -98,11 +98,12 @@ public: int numChars; // 4 bytes per item QFontEngine *fontEngine; // 4 bytes per item QFont font; // 8 bytes per item + QColor color; // 10 bytes per item QStaticTextUserData *userData; // 8 bytes per item char useBackendOptimizations : 1; // 1 byte per item char userDataNeedsUpdate : 1; // // ================ - // 41 bytes per item + // 51 bytes per item }; class QStaticText; @@ -114,12 +115,14 @@ public: ~QStaticTextPrivate(); void init(); + void paintText(QPainter *p); QAtomicInt ref; // 4 bytes per text QString text; // 4 bytes per text QFont font; // 8 bytes per text - QSizeF size; // 16 bytes per text + QSizeF maximumSize; // 16 bytes per text + QSizeF actualSize; // 16 bytes per text QPointF position; // 16 bytes per text QTransform matrix; // 80 bytes per text @@ -130,8 +133,9 @@ public: char needsClipRect : 1; // 1 byte per text char useBackendOptimizations : 1; + char preferRichText : 1; // ================ - // 145 bytes per text + // 171 bytes per text static QStaticTextPrivate *get(const QStaticText *q); }; -- cgit v0.12