diff options
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 34 | ||||
-rw-r--r-- | src/gui/painting/qpaintengine_raster_p.h | 6 | ||||
-rw-r--r-- | src/gui/painting/qpaintengineex.cpp | 2 | ||||
-rw-r--r-- | src/gui/painting/qpainter.cpp | 31 | ||||
-rw-r--r-- | src/gui/painting/qtextureglyphcache.cpp | 7 | ||||
-rw-r--r-- | src/gui/painting/qtextureglyphcache_p.h | 5 | ||||
-rw-r--r-- | src/gui/text/qstatictext.cpp | 77 | ||||
-rw-r--r-- | src/gui/text/qstatictext_p.h | 27 |
8 files changed, 129 insertions, 60 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 387d646..87f374c 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -3007,23 +3007,22 @@ void QRasterPaintEngine::alphaPenBlt(const void* src, int bpl, int depth, int rx blend(current, spans, &s->penData); } -void QRasterPaintEngine::drawCachedGlyphs(const QVarLengthArray<glyph_t> &glyphs, - const QVarLengthArray<QFixedPoint> &positions, - QFontEngine *fontEngine, - const QTransform &matrix) +void QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, + const QFixedPoint *positions, QFontEngine *fontEngine) { Q_D(QRasterPaintEngine); + QRasterPaintEngineState *s = state(); QFontEngineGlyphCache::Type glyphType = fontEngine->glyphFormat >= 0 ? QFontEngineGlyphCache::Type(fontEngine->glyphFormat) : d->glyphCacheType; QImageTextureGlyphCache *cache = - static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, matrix)); + static_cast<QImageTextureGlyphCache *>(fontEngine->glyphCache(0, glyphType, s->matrix)); if (!cache) { - cache = new QImageTextureGlyphCache(glyphType, matrix); + cache = new QImageTextureGlyphCache(glyphType, s->matrix); fontEngine->setGlyphCache(0, cache); } - cache->populate(fontEngine, glyphs, positions); + cache->populate(fontEngine, numGlyphs, glyphs, positions); const QImage &image = cache->image(); int bpl = image.bytesPerLine(); @@ -3041,7 +3040,7 @@ void QRasterPaintEngine::drawCachedGlyphs(const QVarLengthArray<glyph_t> &glyphs const QFixed offs = QFixed::fromReal(aliasedCoordinateDelta); const uchar *bits = image.bits(); - for (int i=0; i<glyphs.size(); ++i) { + for (int i=0; i<numGlyphs; ++i) { const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]); int x = qFloor(positions[i].x + offs) + c.baseLineX - margin; int y = qFloor(positions[i].y + offs) - c.baseLineY - margin; @@ -3218,19 +3217,16 @@ void QRasterPaintEngine::drawStaticTextItem(const QPointF &p, QStaticTextItem *t ensurePen(); ensureState(); - QTransform matrix; - matrix.translate(p.x(), p.y()); - // Translate to actual position - QVarLengthArray<QFixedPoint> glyphPositions = textItem->glyphPositions; - QFixed fx = QFixed::fromReal(p.x()); QFixed fy = QFixed::fromReal(p.y()); - for (int i=0; i<glyphPositions.size(); ++i) { - glyphPositions[i].x += fx; - glyphPositions[i].y += fy; + for (int i=0; i<textItem->numGlyphs; ++i) { + textItem->glyphPositions[i].x += fx; + textItem->glyphPositions[i].y += fy; } - drawCachedGlyphs(textItem->glyphs, glyphPositions, textItem->fontEngine, matrix); + + drawCachedGlyphs(textItem->numGlyphs, textItem->glyphs, textItem->glyphPositions, + textItem->fontEngine); } /*! @@ -3285,11 +3281,13 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte QVarLengthArray<QFixedPoint> positions; QVarLengthArray<glyph_t> glyphs; + QTransform matrix = s->matrix; matrix.translate(p.x(), p.y()); + ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - drawCachedGlyphs(glyphs, positions, ti.fontEngine, matrix); + drawCachedGlyphs(glyphs.size(), glyphs.constData(), positions.constData(), ti.fontEngine); return; } diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 0250c3d..0626a48 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -257,10 +257,8 @@ private: void fillRect(const QRectF &rect, QSpanData *data); void drawBitmap(const QPointF &pos, const QImage &image, QSpanData *fill); - void drawCachedGlyphs(const QVarLengthArray<glyph_t> &glyphs, - const QVarLengthArray<QFixedPoint> &positions, - QFontEngine *fontEngine, - const QTransform &matrix); + void drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, const QFixedPoint *positions, + QFontEngine *fontEngine); void drawStaticTextItem(const QPointF &p, QStaticTextItem *textItem); diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index 15085f9..f167b348 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -592,7 +592,7 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) void QPaintEngineEx::drawStaticTextItem(const QPointF &position, QStaticTextItem *item) { - // ### fall back (we need to recalculate the text item and call drawTextItem()) + // ### Make this pure virtual after implementing in all subclasses } void QPaintEngineEx::draw(const QVectorPath &path) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index 1d7f57d..4eace16 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5730,11 +5730,12 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static if (!d->engine || staticText.isEmpty() || pen().style() == Qt::NoPen) return; - const QStaticTextPrivate *staticText_d = QStaticTextPrivate::get(&staticText); + QStaticTextPrivate *staticText_d = + const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText)); // If we don't have an extended paint engine, or if the painter is transformed, // we go through standard code path - if (d->extended == 0 || !d->state->matrix.isIdentity()) { + if (d->extended == 0) { if (staticText_d->size.isValid()) drawText(QRectF(position, staticText_d->size), staticText_d->text); else @@ -5742,14 +5743,33 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static return; } + // Don't recalculate entire layout because of translation, rather add the dx and dy + // into the position to move each text item the correct distance. + QPointF translatedPosition = position; + QTransform matrix = d->state->transform(); + if (matrix.isTranslating()) { + translatedPosition.rx() += matrix.dx(); + translatedPosition.ry() += matrix.dy(); + translate(-matrix.dx(), -matrix.dy()); + } + + // If the transform is not identical to the text transform, + // we have to relayout the text (for other transformations than plain translation) + if (staticText_d->matrix != d->state->transform()) { + staticText_d->matrix = d->state->transform(); + staticText_d->init(); + } + bool restoreWhenFinished = false; if (staticText_d->size.isValid()) { + save(); setClipRect(QRectF(position, staticText_d->size)); - save(); restoreWhenFinished = true; } + // ### Should we pick up the painter's font and recalculate the layout, like we do + // with the matrix? if (font() != staticText_d->font) { setFont(staticText_d->font); @@ -5759,11 +5779,14 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static for (int i=0; i<staticText_d->itemCount; ++i) { QStaticTextItem *item = staticText_d->items + i; - d->extended->drawStaticTextItem(position, item); + d->extended->drawStaticTextItem(translatedPosition, item); } if (restoreWhenFinished) restore(); + + if (matrix.isTranslating()) + setTransform(matrix); } /*! diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp index 46da88e..5a6a0d9 100644 --- a/src/gui/painting/qtextureglyphcache.cpp +++ b/src/gui/painting/qtextureglyphcache.cpp @@ -55,9 +55,8 @@ QT_BEGIN_NAMESPACE // #define CACHE_DEBUG -void QTextureGlyphCache::populate(QFontEngine *fontEngine, - const QVarLengthArray<glyph_t> &glyphs, - const QVarLengthArray<QFixedPoint> &) +void QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, + const QFixedPoint *) { #ifdef CACHE_DEBUG printf("Populating with '%s'\n", QString::fromRawData(ti.chars, ti.num_chars).toLatin1().data()); @@ -71,7 +70,7 @@ void QTextureGlyphCache::populate(QFontEngine *fontEngine, int rowHeight = 0; // check each glyph for its metrics and get the required rowHeight. - for (int i=0; i < glyphs.size(); ++i) { + for (int i=0; i < numGlyphs; ++i) { const glyph_t glyph = glyphs[i]; if (coords.contains(glyph)) continue; diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h index 2f7fc96..b8717b1 100644 --- a/src/gui/painting/qtextureglyphcache_p.h +++ b/src/gui/painting/qtextureglyphcache_p.h @@ -91,9 +91,8 @@ public: int baseLineY; }; - void populate(QFontEngine *fontEngine, - const QVarLengthArray<glyph_t> &glyphs, - const QVarLengthArray<QFixedPoint> &positions); + void populate(QFontEngine *fontEngine, int numGlyphs, const glyph_t *glyphs, + const QFixedPoint *positions); virtual void createTextureData(int width, int height) = 0; virtual void resizeTextureData(int width, int height) = 0; diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp index c43eeb0..e6f2cc6 100644 --- a/src/gui/text/qstatictext.cpp +++ b/src/gui/text/qstatictext.cpp @@ -262,7 +262,7 @@ bool QStaticText::isEmpty() const } QStaticTextPrivate::QStaticTextPrivate() - : items(0), itemCount(0) + : items(0), itemCount(0), glyphPool(0), positionPool(0) { ref = 1; } @@ -279,6 +279,8 @@ QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other) QStaticTextPrivate::~QStaticTextPrivate() { delete[] items; + delete[] glyphPool; + delete[] positionPool; } QStaticTextPrivate *QStaticTextPrivate::get(const QStaticText *q) @@ -295,37 +297,58 @@ namespace { class DrawTextItemRecorder: public QPaintEngine { public: - DrawTextItemRecorder(int expectedItemCount, QStaticTextItem *items) + DrawTextItemRecorder(int expectedItemCount, QStaticTextItem *items, + int expectedGlyphCount, QFixedPoint *positionPool, glyph_t *glyphPool) : m_items(items), m_expectedItemCount(expectedItemCount), - m_itemCount(0) + m_expectedGlyphCount(expectedGlyphCount), + m_itemCount(0), m_glyphCount(0), + m_positionPool(positionPool), + m_glyphPool(glyphPool) { } virtual void drawTextItem(const QPointF &p, const QTextItem &textItem) { const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); - - Q_ASSERT(m_expectedItemCount < 0 || m_itemCount < m_expectedItemCount); - m_itemCount++; + m_itemCount++; + m_glyphCount += ti.glyphs.numGlyphs; if (m_items == 0) return; + Q_ASSERT(m_itemCount <= m_expectedItemCount); + Q_ASSERT(m_glyphCount <= m_expectedGlyphCount); + QStaticTextItem *currentItem = (m_items + (m_itemCount - 1)); currentItem->fontEngine = ti.fontEngine; currentItem->chars = ti.chars; currentItem->numChars = ti.num_chars; - ti.fontEngine->getGlyphPositions(ti.glyphs, QTransform(), ti.flags, currentItem->glyphs, - currentItem->glyphPositions); + currentItem->numGlyphs = ti.glyphs.numGlyphs; + currentItem->glyphs = m_glyphPool; + currentItem->glyphPositions = m_positionPool; + + QVarLengthArray<glyph_t> glyphs; + QVarLengthArray<QFixedPoint> positions; + ti.fontEngine->getGlyphPositions(ti.glyphs, state->transform(), ti.flags, + glyphs, positions); + + int size = glyphs.size(); + Q_ASSERT(size == ti.glyphs.numGlyphs); + Q_ASSERT(size == positions.size()); + + memmove(currentItem->glyphs, glyphs.constData(), sizeof(glyph_t) * size); + memmove(currentItem->glyphPositions, positions.constData(), sizeof(QFixedPoint) * size); QFixed fx = QFixed::fromReal(p.x()); QFixed fy = QFixed::fromReal(p.y()); - - for (int i=0; i<currentItem->glyphPositions.size(); ++i) { + for (int i=0; i<size; ++i) { currentItem->glyphPositions[i].x += fx; currentItem->glyphPositions[i].y += fy; } + + m_glyphPool += size; + m_positionPool += size; } @@ -343,18 +366,31 @@ namespace { return m_itemCount; } + int glyphCount() const + { + return m_glyphCount; + } + private: QStaticTextItem *m_items; int m_itemCount; + int m_glyphCount; int m_expectedItemCount; + int m_expectedGlyphCount; + + glyph_t *m_glyphPool; + QFixedPoint *m_positionPool; }; class DrawTextItemDevice: public QPaintDevice { public: - DrawTextItemDevice(int expectedItemCount = -1, QStaticTextItem *items = 0) + DrawTextItemDevice(int expectedItemCount = -1, QStaticTextItem *items = 0, + int expectedGlyphCount = -1, QFixedPoint *positionPool = 0, + glyph_t *glyphPool = 0) { - m_paintEngine = new DrawTextItemRecorder(expectedItemCount, items); + m_paintEngine = new DrawTextItemRecorder(expectedItemCount, items, + expectedGlyphCount, positionPool, glyphPool); } ~DrawTextItemDevice() @@ -403,7 +439,10 @@ namespace { return m_paintEngine->itemCount(); } - + int glyphCount() const + { + return m_paintEngine->glyphCount(); + } private: DrawTextItemRecorder *m_paintEngine; @@ -414,6 +453,8 @@ namespace { void QStaticTextPrivate::init() { delete[] items; + delete[] glyphPool; + delete[] positionPool; // Draw once to count number of items and glyphs, so that we can use as little memory // as possible to store the data @@ -421,6 +462,7 @@ void QStaticTextPrivate::init() { QPainter painter(&counterDevice); painter.setFont(font); + painter.setTransform(matrix); if (size.isValid()) painter.drawText(QRectF(QPointF(0, 0), size), text); @@ -428,14 +470,19 @@ void QStaticTextPrivate::init() painter.drawText(0, 0, text); } - itemCount = counterDevice.itemCount(); + itemCount = counterDevice.itemCount(); items = new QStaticTextItem[itemCount]; + int glyphCount = counterDevice.glyphCount(); + glyphPool = new glyph_t[glyphCount]; + positionPool = new QFixedPoint[glyphCount]; + // Draw again to actually record the items and glyphs - DrawTextItemDevice recorderDevice(itemCount, items); + DrawTextItemDevice recorderDevice(itemCount, items, glyphCount, positionPool, glyphPool); { QPainter painter(&recorderDevice); painter.setFont(font); + painter.setTransform(matrix); if (size.isValid()) painter.drawText(QRectF(QPointF(0, 0), size), text); diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h index 2a8d23a..e1ae80d 100644 --- a/src/gui/text/qstatictext_p.h +++ b/src/gui/text/qstatictext_p.h @@ -63,16 +63,18 @@ class QStaticTextItem public: QStaticTextItem() : chars(0), numChars(0), fontEngine(0) {} - QVarLengthArray<QFixedPoint> glyphPositions; // 8 bytes per glyph - QVarLengthArray<glyph_t> glyphs; // 4 bytes per glyph + // ### Use constant length arrays here to minimize memory consumption + QFixedPoint *glyphPositions; // 8 bytes per glyph + glyph_t *glyphs; // 4 bytes per glyph const QChar *chars; // 2 bytes per glyph // ================= // 14 bytes per glyph + int numGlyphs; // 4 bytes per item int numChars; // 4 bytes per item QFontEngine *fontEngine; // 4 bytes per item // ================ - // 8 bytes per item + // 12 bytes per item }; class QStaticText; @@ -85,16 +87,19 @@ public: void init(); - QAtomicInt ref; // 4 bytes per text + QAtomicInt ref; // 4 bytes per text - QString text; // 4 bytes per text - QFont font; // 8 bytes per text - QSizeF size; // 16 bytes per text + QString text; // 4 bytes per text + QFont font; // 8 bytes per text + QSizeF size; // 16 bytes per text - QStaticTextItem *items; // 4 bytes per text - int itemCount; // 4 bytes per text - // ================ - // 40 bytes per text + QTransform matrix; // 80 bytes per text + QStaticTextItem *items; // 4 bytes per text + int itemCount; // 4 bytes per text + glyph_t *glyphPool; // 4 bytes per text + QFixedPoint *positionPool; // 4 bytes per text + // ================ + // 128 bytes per text static QStaticTextPrivate *get(const QStaticText *q); }; |