summaryrefslogtreecommitdiffstats
path: root/src/gui/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/text')
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp5
-rw-r--r--src/gui/text/qfontengine.cpp15
-rw-r--r--src/gui/text/qfontengine_p.h3
-rw-r--r--src/gui/text/qfontengine_win.cpp31
-rw-r--r--src/gui/text/qfontengine_win_p.h4
-rw-r--r--src/gui/text/qfontmetrics.cpp21
-rw-r--r--src/gui/text/qstatictext.cpp168
-rw-r--r--src/gui/text/qstatictext.h8
-rw-r--r--src/gui/text/qstatictext_p.h13
-rw-r--r--src/gui/text/qtextlayout.cpp6
10 files changed, 189 insertions, 85 deletions
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 621f666..ef5e0c4 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -332,6 +332,11 @@ bool QFontDatabase::removeApplicationFont(int handle)
return false;
}
+bool QFontDatabase::removeAllApplicationFonts()
+{
+ return false;
+}
+
bool QFontDatabase::supportsThreadedFontRendering()
{
return false;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index e5975d2..194c5f3 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -379,6 +379,15 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
Q_ASSERT(positions.size() == glyphs_out.size());
}
+void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ glyph_metrics_t gi = boundingBox(glyph);
+ bool isValid = gi.isValid();
+ if (leftBearing != 0)
+ *leftBearing = isValid ? gi.x.toReal() : 0.0;
+ if (rightBearing != 0)
+ *rightBearing = isValid ? (gi.xoff - gi.x - gi.width).toReal() : 0.0;
+}
glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)
{
@@ -1389,6 +1398,12 @@ glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs)
return overall;
}
+void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ int which = highByte(glyph);
+ engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing);
+}
+
void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
QPainterPath *path, QTextItem::RenderFlags flags)
{
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 71ab5a5..e645caf 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -206,6 +206,8 @@ public:
virtual qreal minLeftBearing() const { return qreal(); }
virtual qreal minRightBearing() const { return qreal(); }
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+
virtual const char *name() const = 0;
virtual bool canRender(const QChar *string, int len) = 0;
@@ -374,6 +376,7 @@ public:
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags);
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
virtual QFixed ascent() const;
virtual QFixed descent() const;
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index 55e93bd..a805612 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -39,6 +39,11 @@
**
****************************************************************************/
+#if _WIN32_WINNT < 0x0500
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
#include "qfontengine_p.h"
#include "qtextengine_p.h"
#include <qglobal.h>
@@ -649,6 +654,32 @@ static const ushort char_table[] = {
static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
+#ifndef Q_CC_MINGW
+void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ HDC hdc = shared_dc();
+ SelectObject(hdc, hfont);
+
+#ifndef Q_WS_WINCE
+ if (ttf)
+#endif
+
+ {
+ ABC abcWidths;
+ GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths);
+ if (leftBearing)
+ *leftBearing = abcWidths.abcA;
+ if (rightBearing)
+ *rightBearing = abcWidths.abcC;
+ }
+
+#ifndef Q_WS_WINCE
+ else {
+ QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing);
+ }
+#endif
+}
+#endif // Q_CC_MINGW
qreal QFontEngineWin::minLeftBearing() const
{
diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h
index f9d8f8b..68b53b5 100644
--- a/src/gui/text/qfontengine_win_p.h
+++ b/src/gui/text/qfontengine_win_p.h
@@ -106,6 +106,10 @@ public:
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform);
virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform);
+#ifndef Q_CC_MINGW
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+#endif
+
int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const;
void getCMap();
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 7f9ae8b..3a52e8e 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -472,8 +472,9 @@ int QFontMetrics::leftBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return qRound(gi.x);
+ qreal lb;
+ engine->getGlyphBearings(glyphs.glyphs[0], &lb);
+ return qRound(lb);
}
/*!
@@ -506,8 +507,9 @@ int QFontMetrics::rightBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return qRound(gi.xoff - gi.x - gi.width);
+ qreal rb;
+ engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
+ return qRound(rb);
}
/*!
@@ -1317,8 +1319,9 @@ qreal QFontMetricsF::leftBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return gi.x.toReal();
+ qreal lb;
+ engine->getGlyphBearings(glyphs.glyphs[0], &lb);
+ return lb;
}
/*!
@@ -1351,8 +1354,10 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return (gi.xoff - gi.x - gi.width).toReal();
+ qreal rb;
+ engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
+ return rb;
+
}
/*!
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index d685cd9..5f31ef0 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -99,20 +99,27 @@ QT_BEGIN_NAMESPACE
point with no boundaries, and also when QPainter::drawText() is called with a bounding
rectangle.
- If a bounding rectangle is not required, create a QStaticText object without setting a maximum
- size. The text will then occupy a single line.
+ If a bounding rectangle is not required, create a QStaticText object without setting a preferred
+ text width. The text will then occupy a single line.
- If you set a maximum size on the QStaticText object, this will bound the text. The text will
- be formatted so that no line exceeds the given width. When the object is painted, it will
- be clipped at the given size. The position of the text is decided by the argument
- passed to QPainter::drawStaticText() and can change from call to call with a minimal impact
- on performance.
+ If you set a text width on the QStaticText object, this will bound the text. The text will
+ be formatted so that no line exceeds the given width. The text width set for QStaticText will
+ not automatically be used for clipping. To achieve clipping in addition to line breaks, use
+ QPainter::setClipRect(). The position of the text is decided by the argument passed to
+ QPainter::drawStaticText() and can change from call to call with a minimal impact on
+ performance.
QStaticText will attempt to guess the format of the input text using Qt::mightBeRichText().
To force QStaticText to display its contents as either plain text or rich text, use the
function QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and
Qt::RichText.
+ If it's the first time the static text is drawn, or if the static text, or the painter's font
+ or matrix have been altered since the last time it was drawn, the text's layout has to be
+ recalculated. This will impose an overhead on the QPainter::drawStaticText() call where the
+ relayout occurs. To avoid this overhead in the paint event, you can call prepare() ahead of
+ time to ensure that the layout is calculated.
+
\sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument
*/
@@ -143,12 +150,11 @@ QStaticText::QStaticText()
If an invalid size is passed for \a size the text will be unbounded.
*/
-QStaticText::QStaticText(const QString &text, const QSizeF &size)
+QStaticText::QStaticText(const QString &text)
: data(new QStaticTextPrivate)
{
data->text = text;
- data->maximumSize = size;
- data->init();
+ data->invalidate();
}
/*!
@@ -177,17 +183,17 @@ void QStaticText::detach()
}
/*!
- Prepares the QStaticText object for being painted with the given \a matrix and the given
- \a font to avoid overhead when the actual drawStaticText() call is made.
+ Prepares the QStaticText object for being painted with the given \a matrix and the given \a font
+ to avoid overhead when the actual drawStaticText() call is made.
- When drawStaticText() is called, the layout of the QStaticText will be recalculated if the
- painter's font or matrix is different from the one used for the currently cached layout. By
- default, QStaticText will use a default constructed QFont and an identity matrix to create
- its layout.
+ When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part
+ of the QStaticText object has changed since the last time it was drawn. It will also be
+ recalculated if the painter's font or matrix are not the same as when the QStaticText was last
+ drawn.
- To avoid the overhead of creating the layout the first time you draw the QStaticText with
- a painter whose matrix or font are different from the defaults, you can use the prepare()
- function and pass in the matrix and font you expect to use when drawing the text.
+ To avoid the overhead of creating the layout the first time you draw the QStaticText after
+ making changes, you can use the prepare() function and pass in the \a matrix and \a font you
+ expect to use when drawing the text.
\sa QPainter::setFont(), QPainter::setMatrix()
*/
@@ -209,7 +215,7 @@ QStaticText &QStaticText::operator=(const QStaticText &other)
}
/*!
- Compares \a other to this QStaticText. Returns true if the texts, fonts and maximum sizes
+ Compares \a other to this QStaticText. Returns true if the texts, fonts and text widths
are equal.
*/
bool QStaticText::operator==(const QStaticText &other) const
@@ -217,7 +223,7 @@ bool QStaticText::operator==(const QStaticText &other) const
return (data == other.data
|| (data->text == other.data->text
&& data->font == other.data->font
- && data->maximumSize == other.data->maximumSize));
+ && data->textWidth == other.data->textWidth));
}
/*!
@@ -232,7 +238,7 @@ bool QStaticText::operator!=(const QStaticText &other) const
/*!
Sets the text of the QStaticText to \a text.
- \note This function will cause the layout of the text to be recalculated.
+ \note This function will cause the layout of the text to require recalculation.
\sa text()
*/
@@ -240,7 +246,7 @@ void QStaticText::setText(const QString &text)
{
detach();
data->text = text;
- data->init();
+ data->invalidate();
}
/*!
@@ -250,7 +256,7 @@ void QStaticText::setText(const QString &text)
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.
+ \note This function will cause the layout of the text to require recalculation.
\sa textFormat(), setText(), text()
*/
@@ -258,7 +264,7 @@ void QStaticText::setTextFormat(Qt::TextFormat textFormat)
{
detach();
data->textFormat = textFormat;
- data->init();
+ data->invalidate();
}
/*!
@@ -289,7 +295,7 @@ QString QStaticText::text() const
The default is QStaticText::ModerateCaching.
- \note This function will cause the layout of the text to be recalculated.
+ \note This function will cause the layout of the text to require recalculation.
\sa performanceHint()
*/
@@ -301,7 +307,7 @@ void QStaticText::setPerformanceHint(PerformanceHint performanceHint)
}
detach();
data->useBackendOptimizations = (performanceHint == AggressiveCaching);
- data->init();
+ data->invalidate();
}
/*!
@@ -315,48 +321,56 @@ QStaticText::PerformanceHint QStaticText::performanceHint() const
}
/*!
- Sets the maximum size of the QStaticText to \a size.
+ Sets the preferred width for this QStaticText. If the text is wider than the specified width,
+ it will be broken into multiple lines and grow vertically. If the text cannot be split into
+ multiple lines, it will be larger than the specified \a textWidth.
- \note This function will cause the layout of the text to be recalculated.
+ Setting the preferred text width to a negative number will cause the text to be unbounded.
- \sa maximumSize(), size()
+ Use size() to get the actual size of the text.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa textWidth(), size()
*/
-void QStaticText::setMaximumSize(const QSizeF &size)
+void QStaticText::setTextWidth(qreal textWidth)
{
detach();
- data->maximumSize = size;
- data->init();
+ data->textWidth = textWidth;
+ data->invalidate();
}
/*!
- Returns the maximum size of the QStaticText.
+ Returns the preferred width for this QStaticText.
- \sa setMaximumSize()
+ \sa setTextWidth()
*/
-QSizeF QStaticText::maximumSize() const
+qreal QStaticText::textWidth() const
{
- return data->maximumSize;
+ return data->textWidth;
}
/*!
Returns the size of the bounding rect for this QStaticText.
- \sa maximumSize()
+ \sa textWidth()
*/
QSizeF QStaticText::size() const
{
+ if (data->needsRelayout)
+ data->init();
return data->actualSize;
}
QStaticTextPrivate::QStaticTextPrivate()
- : items(0), itemCount(0), glyphPool(0), positionPool(0), needsClipRect(false),
- useBackendOptimizations(false), textFormat(Qt::AutoText)
+ : items(0), itemCount(0), glyphPool(0), positionPool(0), textWidth(-1.0),
+ needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText)
{
}
QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other)
- : text(other.text), font(other.font), maximumSize(other.maximumSize), matrix(other.matrix),
- items(0), itemCount(0), glyphPool(0), positionPool(0), needsClipRect(false),
+ : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix),
+ items(0), itemCount(0), glyphPool(0), positionPool(0), needsRelayout(true),
useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat)
{
}
@@ -388,8 +402,15 @@ namespace {
m_expectedItemCount(expectedItemCount),
m_expectedGlyphCount(expectedGlyphCount),
m_glyphPool(glyphPool),
- m_positionPool(positionPool)
+ m_positionPool(positionPool),
+ m_dirtyPen(false)
+ {
+ }
+
+ virtual void updateState(const QPaintEngineState &newState)
{
+ if (newState.state() & QPaintEngine::DirtyPen)
+ m_dirtyPen = true;
}
virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
@@ -412,7 +433,8 @@ namespace {
currentItem->numGlyphs = ti.glyphs.numGlyphs;
currentItem->glyphs = m_glyphPool;
currentItem->glyphPositions = m_positionPool;
- currentItem->color = state->pen().color();
+ if (m_dirtyPen)
+ currentItem->color = state->pen().color();
QTransform matrix = state->transform();
matrix.translate(position.x(), position.y());
@@ -435,7 +457,6 @@ namespace {
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
{
@@ -461,6 +482,8 @@ namespace {
glyph_t *m_glyphPool;
QFixedPoint *m_positionPool;
+
+ bool m_dirtyPen;
};
class DrawTextItemDevice: public QPaintDevice
@@ -530,43 +553,55 @@ namespace {
};
}
-void QStaticTextPrivate::paintText(const QPointF &pos, QPainter *p)
+void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p)
{
bool preferRichText = textFormat == Qt::RichText
|| (textFormat == Qt::AutoText && Qt::mightBeRichText(text));
if (!preferRichText) {
- if (maximumSize.isValid()) {
- QRectF boundingRect;
- p->drawText(QRectF(pos, maximumSize), Qt::TextWordWrap, text, &boundingRect);
-
- actualSize = boundingRect.size();
- needsClipRect = boundingRect.width() > maximumSize.width()
- || boundingRect.height() > maximumSize.height();
- } else {
- p->drawText(pos, text);
- needsClipRect = false;
-
- QFontMetrics fm(font);
- actualSize = fm.boundingRect(text).size();
+ QTextLayout textLayout;
+ textLayout.setText(text);
+ textLayout.setFont(font);
+
+ qreal leading = QFontMetricsF(font).leading();
+ qreal height = -leading;
+
+ textLayout.beginLayout();
+ while (1) {
+ QTextLine line = textLayout.createLine();
+ if (!line.isValid())
+ break;
+
+ if (textWidth >= 0.0)
+ line.setLineWidth(textWidth);
+ height += leading;
+ line.setPosition(QPointF(0.0, height));
+ height += line.height();
}
+ textLayout.endLayout();
+
+ actualSize = textLayout.boundingRect().size();
+ textLayout.draw(p, topLeftPosition);
} else {
QTextDocument document;
+ QColor color = p->pen().color();
+ document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }")
+ .arg(QString::number(color.red(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.green(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0')));
document.setDefaultFont(font);
document.setDocumentMargin(0.0);
+ if (textWidth >= 0.0)
+ document.setTextWidth(textWidth);
document.setHtml(text);
- QPointF adjustedPos = pos - QPointF(0, QFontMetricsF(font).ascent());
- QRectF rect = maximumSize.isValid() ? QRectF(adjustedPos, maximumSize) : QRectF();
document.adjustSize();
p->save();
- p->translate(adjustedPos);
- document.drawContents(p, rect);
+ p->translate(topLeftPosition);
+ document.drawContents(p);
p->restore();
+
actualSize = document.size();
- needsClipRect = maximumSize.isValid()
- && (actualSize.width() > maximumSize.width()
- || actualSize.height() > maximumSize.height());
}
}
@@ -613,6 +648,7 @@ void QStaticTextPrivate::init()
paintText(QPointF(0, 0), &painter);
}
+ needsRelayout = false;
}
QT_END_NAMESPACE
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
index 00d42e0..f3bef93 100644
--- a/src/gui/text/qstatictext.h
+++ b/src/gui/text/qstatictext.h
@@ -66,7 +66,7 @@ public:
};
QStaticText();
- QStaticText(const QString &text, const QSizeF &maximumSize = QSizeF());
+ QStaticText(const QString &text);
QStaticText(const QStaticText &other);
~QStaticText();
@@ -76,12 +76,12 @@ public:
void setTextFormat(Qt::TextFormat textFormat);
Qt::TextFormat textFormat() const;
- void setMaximumSize(const QSizeF &maximumSize);
- QSizeF maximumSize() const;
+ void setTextWidth(qreal textWidth);
+ qreal textWidth() const;
QSizeF size() const;
- void prepare(const QTransform &matrix, const QFont &font);
+ void prepare(const QTransform &matrix = QTransform(), const QFont &font = QFont());
void setPerformanceHint(PerformanceHint performanceHint);
PerformanceHint performanceHint() const;
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index e758244..f017ed1 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -118,11 +118,16 @@ public:
void init();
void paintText(const QPointF &pos, QPainter *p);
+ void invalidate()
+ {
+ needsRelayout = true;
+ }
+
QAtomicInt ref; // 4 bytes per text
QString text; // 4 bytes per text
QFont font; // 8 bytes per text
- QSizeF maximumSize; // 16 bytes per text
+ qreal textWidth; // 8 bytes per text
QSizeF actualSize; // 16 bytes per text
QPointF position; // 16 bytes per text
@@ -132,11 +137,11 @@ public:
glyph_t *glyphPool; // 4 bytes per text
QFixedPoint *positionPool; // 4 bytes per text
- unsigned char needsClipRect : 1; // 1 byte per text
- unsigned char useBackendOptimizations : 1;
+ unsigned char needsRelayout : 1;
+ unsigned char useBackendOptimizations : 1; // 1 byte per text
unsigned char textFormat : 2;
// ================
- // 171 bytes per text
+ // 163 bytes per text
static QStaticTextPrivate *get(const QStaticText *q);
};
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 2fc5d1a..312d135 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1702,9 +1702,9 @@ namespace {
if (currentPosition <= 0)
return;
- glyph_metrics_t gi = fontEngine->boundingBox(currentGlyph());
- if (gi.isValid())
- rightBearing = qMin(QFixed(), gi.xoff - gi.x - gi.width);
+ qreal rb;
+ fontEngine->getGlyphBearings(currentGlyph(), 0, &rb);
+ rightBearing = qMin(QFixed(), QFixed::fromReal(rb));
}
inline void resetRightBearing()