diff options
author | Eskil Abrahamsen Blomfeldt <eblomfel@trolltech.com> | 2009-08-05 13:33:08 (GMT) |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2010-01-14 12:49:09 (GMT) |
commit | 135dcf11efe11dacb15f4c384b302d99a0470320 (patch) | |
tree | 71f3f18bd34013313bef94856b314d3fb2e69ffe /src/gui/text/qstatictext.cpp | |
parent | 4cfca7cf456722ee8659b595f231f3cc2033b80d (diff) | |
download | Qt-135dcf11efe11dacb15f4c384b302d99a0470320.zip Qt-135dcf11efe11dacb15f4c384b302d99a0470320.tar.gz Qt-135dcf11efe11dacb15f4c384b302d99a0470320.tar.bz2 |
Support maximumSize for the layout of the text in a QStaticText
Put back maximumSize property in QStaticText to allow matching calls
to drawText with a target rectangle. Implementation is done by
having a dummy paint engine which records the calls to drawTextItem()
and storing these, then replaying them later.
Diffstat (limited to 'src/gui/text/qstatictext.cpp')
-rw-r--r-- | src/gui/text/qstatictext.cpp | 271 |
1 files changed, 221 insertions, 50 deletions
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index d97c0c9..5a8fd9b 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -43,6 +43,8 @@ #include "qstatictext_p.h" #include <private/qtextengine_p.h> +#include <QtGui/qapplication.h> + QT_BEGIN_NAMESPACE /*! @@ -111,11 +113,12 @@ QStaticText::QStaticText() \a font and bounded by the given \a maximumSize. If an invalid size is passed for \a maximumSize the text will be unbounded. */ -QStaticText::QStaticText(const QString &text, const QFont &font) +QStaticText::QStaticText(const QString &text, const QFont &font, const QSizeF &size) : d_ptr(new QStaticTextPrivate) { d_ptr->text = text; d_ptr->font = font; + d_ptr->size = size; d_ptr->init(); } @@ -162,7 +165,9 @@ QStaticText &QStaticText::operator=(const QStaticText &other) bool QStaticText::operator==(const QStaticText &other) const { return (d_ptr == other.d_ptr - || (d_ptr->text == other.d_ptr->text && d_ptr->font == other.d_ptr->font)); + || (d_ptr->text == other.d_ptr->text + && d_ptr->font == other.d_ptr->font + && d_ptr->size == other.d_ptr->size)); } /*! @@ -199,6 +204,30 @@ QString QStaticText::text() const } /*! + Sets the maximum size of the QStaticText to \a maximumSize. + + \note This function will cause the layout of the text to be recalculated. + + \sa maximumSize() +*/ +void QStaticText::setMaximumSize(const QSizeF &size) +{ + detach(); + d_ptr->size = size; + d_ptr->init(); +} + +/*! + Returns the maximum size of the QStaticText. + + \sa setMaximumSize +*/ +QSizeF QStaticText::maximumSize() const +{ + return d_ptr->size; +} + +/*! Sets the font of the QStaticText to \a font. \note This function will cause the layout of the text to be recalculated. @@ -233,7 +262,7 @@ bool QStaticText::isEmpty() const } QStaticTextPrivate::QStaticTextPrivate() - : glyphLayoutMemory(0), logClusterMemory(0), items(0), itemCount(0) + : glyphLayoutMemory(0), logClusterMemory(0), items(0), itemPositions(0), itemCount(0) { ref = 1; } @@ -243,14 +272,16 @@ QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other) ref = 1; text = other.text; font = other.font; + size = other.size; init(); } QStaticTextPrivate::~QStaticTextPrivate() { delete[] glyphLayoutMemory; - delete[] logClusterMemory; + delete[] logClusterMemory; delete[] items; + delete[] itemPositions; } QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q) @@ -258,59 +289,199 @@ QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q) return q->d_ptr; } + +extern int qt_defaultDpiX(); +extern int qt_defaultDpiY(); + +namespace { + + class DrawTextItemRecorder: public QPaintEngine + { + public: + DrawTextItemRecorder(int expectedItemCount, int expectedGlyphCount, + QTextItemInt *items, + QPointF *positions, + char *glyphLayoutMemory, + unsigned short *logClusterMemory) + : m_items(items), + m_positions(positions), + m_glyphLayoutMemory(glyphLayoutMemory), + m_logClusterMemory(logClusterMemory), + m_glyphLayoutMemoryOffset(0), + m_logClusterMemoryOffset(0), + m_expectedItemCount(expectedItemCount), + m_expectedGlyphCount(expectedGlyphCount), + m_glyphCount(0), + m_itemCount(0) + { + } + + virtual void drawTextItem(const QPointF &p, const QTextItem &textItem) + { + const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); + + m_itemCount++; + m_glyphCount += ti.glyphs.numGlyphs; + + Q_ASSERT(m_expectedItemCount < 0 || m_itemCount <= m_expectedItemCount); + Q_ASSERT(m_expectedGlyphCount < 0 || m_glyphCount <= m_expectedGlyphCount); + + if (m_items == 0 || m_glyphLayoutMemory == 0 || m_logClusterMemory == 0 || m_positions == 0) + return; + + m_items[m_itemCount - 1] = ti.clone(m_glyphLayoutMemory + m_glyphLayoutMemoryOffset, + m_logClusterMemory + m_logClusterMemoryOffset); + m_positions[m_itemCount - 1] = p; + + m_glyphLayoutMemoryOffset += QGlyphLayout::spaceNeededForGlyphLayout(ti.glyphs.numGlyphs); + m_logClusterMemoryOffset += ti.glyphs.numGlyphs; + } + + + virtual bool begin(QPaintDevice *) { return true; } + virtual bool end() { return true; } + virtual void updateState(const QPaintEngineState &) {} + virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {} + virtual Type type() const + { + return User; + } + + int glyphCount() const + { + return m_glyphCount; + } + + int itemCount() const + { + return m_itemCount; + } + + private: + QTextItemInt *m_items; + char *m_glyphLayoutMemory; + unsigned short *m_logClusterMemory; + QPointF *m_positions; + + int m_glyphLayoutMemoryOffset; + int m_logClusterMemoryOffset; + int m_expectedGlyphCount; + int m_expectedItemCount; + int m_glyphCount; + int m_itemCount; + }; + + class DrawTextItemDevice: public QPaintDevice + { + public: + DrawTextItemDevice(int expectedItemCount = -1, int expectedGlyphCount = -1, + QTextItemInt *items = 0, QPointF *positions = 0, + char *glyphLayoutMemory = 0, unsigned short *logClusterMemory = 0) + { + m_paintEngine = new DrawTextItemRecorder(expectedItemCount, expectedGlyphCount, + items, positions,glyphLayoutMemory, + logClusterMemory); + } + + ~DrawTextItemDevice() + { + delete m_paintEngine; + } + + int metric(PaintDeviceMetric m) const + { + int val; + switch (m) { + case PdmWidth: + case PdmHeight: + case PdmWidthMM: + case PdmHeightMM: + val = 0; + break; + case PdmDpiX: + case PdmPhysicalDpiX: + val = qt_defaultDpiX(); + break; + case PdmDpiY: + case PdmPhysicalDpiY: + val = qt_defaultDpiY(); + break; + case PdmNumColors: + val = 16777216; + break; + case PdmDepth: + val = 24; + break; + default: + val = 0; + qWarning("DrawTextItemDevice::metric: Invalid metric command"); + } + return val; + } + + virtual QPaintEngine *paintEngine() const + { + return m_paintEngine; + } + + int glyphCount() const + { + return m_paintEngine->glyphCount(); + } + + int itemCount() const + { + return m_paintEngine->itemCount(); + } + + + + private: + DrawTextItemRecorder *m_paintEngine; + QRectF brect; + }; + +} + void QStaticTextPrivate::init() { delete[] glyphLayoutMemory; delete[] logClusterMemory; delete[] items; + delete[] itemPositions; + + // Draw once to count number of items and glyphs, so that we can use as little memory + // as possible to store the data + DrawTextItemDevice counterDevice; + { + QPainter painter(&counterDevice); + + if (size.isValid()) + painter.drawText(QRectF(QPointF(0, 0), size), text); + else + painter.drawText(0, 0, text); + } - QStackTextEngine engine(text, font); - engine.itemize(); - - engine.option.setTextDirection(QApplication::layoutDirection()); - QScriptLine line; - line.length = text.length(); - engine.shapeLine(line); - - int nItems = engine.layoutData->items.size(); - QVarLengthArray<int> visualOrder(nItems); - QVarLengthArray<uchar> levels(nItems); - for (int i = 0; i < nItems; ++i) - levels[i] = engine.layoutData->items[i].analysis.bidiLevel; - QTextEngine::bidiReorder(nItems, levels.data(), visualOrder.data()); - - int numGlyphs = engine.layoutData->used; - glyphLayoutMemory = new char[QGlyphLayout::spaceNeededForGlyphLayout(numGlyphs)]; - logClusterMemory = new unsigned short[numGlyphs]; - items = new QTextItemInt[nItems]; - itemCount = nItems; - - char *currentGlyphLayout = glyphLayoutMemory; - unsigned short *currentLogCluster = logClusterMemory; - for (int i = 0; i < nItems; ++i) { - int item = visualOrder[i]; - const QScriptItem &si = engine.layoutData->items.at(item); - - QFont f = engine.font(si); - if (si.analysis.flags >= QScriptAnalysis::TabOrObject) { - items[i].width = si.width; - continue; - } - - items[i].init(si, &f); - - QGlyphLayout l = engine.shapedGlyphs(&si); - items[i].glyphs = l.clone(currentGlyphLayout); - currentGlyphLayout += QGlyphLayout::spaceNeededForGlyphLayout(l.numGlyphs); - - items[i].chars = text.unicode() + si.position; - items[i].num_chars = engine.length(item); - items[i].width = si.width; - - memmove(currentLogCluster, engine.logClusters(&si), sizeof(unsigned short) * l.numGlyphs); - items[i].logClusters = currentLogCluster; - currentLogCluster += l.numGlyphs; + itemCount = counterDevice.itemCount(); + items = new QTextItemInt[itemCount]; + itemPositions = new QPointF[itemCount]; + + int glyphCount = counterDevice.glyphCount(); + glyphLayoutMemory = new char[QGlyphLayout::spaceNeededForGlyphLayout(glyphCount)]; + logClusterMemory = new unsigned short[glyphCount]; + + // Draw again to actually record the items and glyphs + DrawTextItemDevice recorderDevice(itemCount, glyphCount, items, itemPositions, + glyphLayoutMemory, logClusterMemory); + { + QPainter painter(&recorderDevice); + + if (size.isValid()) + painter.drawText(QRectF(QPointF(0, 0), size), text); + else + painter.drawText(0, 0, text); } + } QT_END_NAMESPACE |