summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eblomfel@trolltech.com>2009-08-05 13:33:08 (GMT)
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com>2010-01-14 12:49:09 (GMT)
commit135dcf11efe11dacb15f4c384b302d99a0470320 (patch)
tree71f3f18bd34013313bef94856b314d3fb2e69ffe
parent4cfca7cf456722ee8659b595f231f3cc2033b80d (diff)
downloadQt-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.
-rw-r--r--src/gui/painting/qpainter.cpp6
-rw-r--r--src/gui/text/qstatictext.cpp271
-rw-r--r--src/gui/text/qstatictext.h5
-rw-r--r--src/gui/text/qstatictext_p.h11
-rw-r--r--src/gui/text/qtextengine.cpp40
-rw-r--r--src/gui/text/qtextengine_p.h5
6 files changed, 279 insertions, 59 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 50d27ac..1057893 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5729,13 +5729,9 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
return;
const QStaticTextPrivate *staticText_d = QStaticTextPrivate::get(&staticText);
-
- QFixed x = QFixed::fromReal(position.x());
for (int i=0; i<staticText_d->itemCount; ++i) {
const QTextItemInt &gf = staticText_d->items[i];
- if (gf.num_chars != 0)
- drawTextItem(QPointF(x.toReal(), position.y()), gf);
- x += gf.width;
+ d->engine->drawTextItem(staticText_d->itemPositions[i] + position, gf);
}
}
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
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
index 7247bf7..9830b32 100644
--- a/src/gui/text/qstatictext.h
+++ b/src/gui/text/qstatictext.h
@@ -57,7 +57,7 @@ class Q_GUI_EXPORT QStaticText
{
public:
QStaticText();
- QStaticText(const QString &text, const QFont &font = QFont());
+ QStaticText(const QString &text, const QFont &font = QFont(), const QSizeF &maximumSize = QSizeF());
QStaticText(const QStaticText &other);
~QStaticText();
@@ -67,6 +67,9 @@ public:
void setFont(const QFont &font);
QFont font() const;
+ void setMaximumSize(const QSizeF &maximumSize);
+ QSizeF maximumSize() const;
+
QStaticText &operator=(const QStaticText &);
bool operator==(const QStaticText &) const;
bool operator!=(const QStaticText &) const;
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index a0d16d4..f5fd8d3 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -55,7 +55,7 @@
#include <private/qtextengine_p.h>
-QT_BEGIN_NAMESPACE
+QT_BEGIN_NAMESPACE
class QStaticText;
class QStaticTextPrivate
@@ -68,10 +68,15 @@ public:
void init();
QAtomicInt ref;
- QTextItemInt *items;
- int itemCount;
+
QString text;
QFont font;
+ QSizeF size;
+
+ QTextItemInt *items;
+ QPointF *itemPositions;
+ int itemCount;
+
char *glyphLayoutMemory;
unsigned short *logClusterMemory;
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 5343085..b27b0b7 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2640,6 +2640,46 @@ QTextItemInt::QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFo
init(si, font, format);
}
+QTextItemInt::QTextItemInt(const QTextItemInt &other)
+ : descent(other.descent), ascent(other.ascent), width(other.width),
+ flags(other.flags), justified(other.justified), underlineStyle(other.underlineStyle),
+ charFormat(other.charFormat), num_chars(other.num_chars), chars(other.chars),
+ fontEngine(other.fontEngine), f(other.f), glyphs(other.glyphs),
+ logClusters(other.logClusters)
+{
+}
+
+
+QTextItemInt QTextItemInt::clone(char *glyphLayoutMemory, unsigned short *logClusterMemory) const
+{
+ QTextItemInt ti(*this);
+
+ ti.glyphs = glyphs.clone(glyphLayoutMemory);
+ ti.logClusters = logClusterMemory;
+ memmove(logClusterMemory, logClusters, glyphs.numGlyphs * sizeof(unsigned short));
+
+ return ti;
+}
+
+QTextItemInt &QTextItemInt::operator=(const QTextItemInt &other)
+{
+ descent = other.descent;
+ ascent = other.ascent;
+ width = other.width;
+ flags = other.flags;
+ justified = other.justified;
+ underlineStyle = other.underlineStyle;
+ const_cast<QTextCharFormat &>(charFormat) = other.charFormat;
+ num_chars = other.num_chars;
+ chars = other.chars;
+ fontEngine = other.fontEngine;
+ f = other.f;
+ glyphs = other.glyphs;
+ logClusters = other.logClusters;
+
+ return *this;
+}
+
void QTextItemInt::init(const QScriptItem &si, QFont *font, const QTextCharFormat &format)
{
// explicitly initialize flags so that initFontAttributes can be called
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 0491d87..3ce744e 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -313,13 +313,18 @@ public:
logClusters(0), f(0), fontEngine(0)
{}
+ QTextItemInt(const QTextItemInt &other);
QTextItemInt(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat());
void init(const QScriptItem &si, QFont *font, const QTextCharFormat &format = QTextCharFormat());
+ QTextItemInt clone(char *glyphLayoutMemory, unsigned short *logClusterMemory) const;
+
/// copy the structure items, adjusting the glyphs arrays to the right subarrays.
/// the width of the returned QTextItemInt is not adjusted, for speed reasons
QTextItemInt midItem(QFontEngine *fontEngine, int firstGlyphIndex, int numGlyphs) const;
+ QTextItemInt &operator=(const QTextItemInt &other);
+
QFixed descent;
QFixed ascent;
QFixed width;