diff options
author | Eskil Abrahamsen Blomfeldt <eblomfel@trolltech.com> | 2009-08-21 14:29:44 (GMT) |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@nokia.com> | 2010-01-14 13:05:08 (GMT) |
commit | bf919e06127962836a6b566bf119cf248c6a999b (patch) | |
tree | 789ca79fa342cf741513cb21e6d4d3728345a511 /src/opengl/qpaintengine_opengl.cpp | |
parent | 7fbffd29e5904151a3a249004031d0502a16f4fc (diff) | |
download | Qt-bf919e06127962836a6b566bf119cf248c6a999b.zip Qt-bf919e06127962836a6b566bf119cf248c6a999b.tar.gz Qt-bf919e06127962836a6b566bf119cf248c6a999b.tar.bz2 |
Implement drawStaticTextItem() in OpenGL paint engines
The OpenGL and OpenGL2 engines now have support for static text, as
well as the QEmulationPaintEngine.
Also contains an optimization: Instead of passing both the position and
glyph positions to drawStaticTextItem() we add the position into the
glyph position and update it only when it changes. Otherwise we would
have to do this work in all engines for every call. This means we have
to cache the position in QStaticTextPrivate as well, but it seems like
a small price to pay, since it's a per-text overhead and only 16 bytes.
Diffstat (limited to 'src/opengl/qpaintengine_opengl.cpp')
-rw-r--r-- | src/opengl/qpaintengine_opengl.cpp | 96 |
1 files changed, 58 insertions, 38 deletions
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp index 57918d0..d6175e9 100644 --- a/src/opengl/qpaintengine_opengl.cpp +++ b/src/opengl/qpaintengine_opengl.cpp @@ -60,6 +60,7 @@ #include <private/qglpixelbuffer_p.h> #include <private/qbezier_p.h> #include <qglframebufferobject.h> +#include <private/qstatictext_p.h> #include "private/qtessellator_p.h" @@ -4555,7 +4556,7 @@ public: QGLGlyphCache() : QObject(0) { current_cache = 0; } ~QGLGlyphCache(); QGLGlyphCoord *lookup(QFontEngine *, glyph_t); - void cacheGlyphs(QGLContext *, const QTextItemInt &, const QVarLengthArray<glyph_t> &); + void cacheGlyphs(QGLContext *, QFontEngine *, glyph_t *glyphs, int numGlyphs); void cleanCache(); void allocTexture(int width, int height, GLuint texture); @@ -4707,8 +4708,8 @@ static QImage getCurrentTexture(const QColor &color, QGLFontTexture *font_tex) } #endif -void QGLGlyphCache::cacheGlyphs(QGLContext *context, const QTextItemInt &ti, - const QVarLengthArray<glyph_t> &glyphs) +void QGLGlyphCache::cacheGlyphs(QGLContext *context, QFontEngine *fontEngine, + glyph_t *glyphs, int numGlyphs) { QGLContextHash::const_iterator dev_it = qt_context_cache.constFind(context); QGLFontGlyphHash *font_cache = 0; @@ -4744,25 +4745,25 @@ void QGLGlyphCache::cacheGlyphs(QGLContext *context, const QTextItemInt &ti, } Q_ASSERT(font_cache != 0); - QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(ti.fontEngine); + QGLFontGlyphHash::const_iterator cache_it = font_cache->constFind(fontEngine); QGLGlyphHash *cache = 0; if (cache_it == font_cache->constEnd()) { cache = new QGLGlyphHash; - font_cache->insert(ti.fontEngine, cache); - connect(ti.fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*))); + font_cache->insert(fontEngine, cache); + connect(fontEngine, SIGNAL(destroyed(QObject*)), SLOT(fontEngineDestroyed(QObject*))); } else { cache = cache_it.value(); } current_cache = cache; quint64 font_key = (reinterpret_cast<quint64>(context_key ? context_key : context) << 32) - | reinterpret_cast<quint64>(ti.fontEngine); + | reinterpret_cast<quint64>(fontEngine); QGLFontTexHash::const_iterator it = qt_font_textures.constFind(font_key); QGLFontTexture *font_tex; if (it == qt_font_textures.constEnd()) { GLuint font_texture; glGenTextures(1, &font_texture); - GLint tex_height = qt_next_power_of_two(qRound(ti.ascent.toReal() + ti.descent.toReal())+2); + GLint tex_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2); GLint tex_width = qt_next_power_of_two(tex_height*30); // ### GLint max_tex_size; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_tex_size); @@ -4784,16 +4785,16 @@ void QGLGlyphCache::cacheGlyphs(QGLContext *context, const QTextItemInt &ti, glBindTexture(GL_TEXTURE_2D, font_tex->texture); } - for (int i=0; i< glyphs.size(); ++i) { + for (int i=0; i< numGlyphs; ++i) { QGLGlyphHash::const_iterator it = cache->constFind(glyphs[i]); if (it == cache->constEnd()) { // render new glyph and put it in the cache - glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]); + glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]); int glyph_width = qRound(metrics.width.toReal())+2; - int glyph_height = qRound(ti.ascent.toReal() + ti.descent.toReal())+2; + int glyph_height = qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2; if (font_tex->x_offset + glyph_width + x_margin > font_tex->width) { - int strip_height = qt_next_power_of_two(qRound(ti.ascent.toReal() + ti.descent.toReal())+2); + int strip_height = qt_next_power_of_two(qRound(fontEngine->ascent().toReal() + fontEngine->descent().toReal())+2); font_tex->x_offset = x_margin; font_tex->y_offset += strip_height; if (font_tex->y_offset >= font_tex->height) { @@ -4826,8 +4827,8 @@ void QGLGlyphCache::cacheGlyphs(QGLContext *context, const QTextItemInt &ti, } } - QImage glyph_im(ti.fontEngine->alphaMapForGlyph(glyphs[i])); - glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8); + QImage glyph_im(fontEngine->alphaMapForGlyph(glyphs[i])); + glyph_im = glyph_im.convertToFormat(QImage::Format_Indexed8); glyph_width = glyph_im.width(); Q_ASSERT(glyph_width >= 0); // pad the glyph width to an even number @@ -4906,30 +4907,15 @@ void qgl_cleanup_glyph_cache(QGLContext *ctx) qt_glyph_cache()->cleanupContext(ctx); } -void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) +void QOpenGLPaintEngine::drawStaticTextItem(QStaticTextItem *textItem) { Q_D(QOpenGLPaintEngine); - const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); - - // fall back to drawing a polygon if the scale factor is large, or - // we use a gradient pen - if ((d->matrix.det() > 1) || (d->pen_brush_style >= Qt::LinearGradientPattern - && d->pen_brush_style <= Qt::ConicalGradientPattern)) { - QPaintEngine::drawTextItem(p, textItem); - return; - } - d->flushDrawQueue(); - // add the glyphs used to the glyph texture cache - QVarLengthArray<QFixedPoint> positions; - QVarLengthArray<glyph_t> glyphs; - QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y())); - ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); - // make sure the glyphs we want to draw are in the cache - qt_glyph_cache()->cacheGlyphs(d->device->context(), ti, glyphs); + qt_glyph_cache()->cacheGlyphs(d->device.context(), textItem->fontEngine, textItem->glyphs, + textItem->numGlyphs); d->setGradientOps(Qt::SolidPattern, QRectF()); // turns off gradient ops qt_glColor4ubv(d->pen_color); @@ -4951,13 +4937,13 @@ void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bool antialias = !(ti.fontEngine->fontDef.styleStrategy & QFont::NoAntialias) - && (d->matrix.type() > QTransform::TxTranslate); + bool antialias = !(textItem->fontEngine->fontDef.styleStrategy & QFont::NoAntialias) + && (d->matrix.type() > QTransform::TxTranslate); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, antialias ? GL_LINEAR : GL_NEAREST); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, antialias ? GL_LINEAR : GL_NEAREST); - for (int i=0; i< glyphs.size(); ++i) { - QGLGlyphCoord *g = qt_glyph_cache()->lookup(ti.fontEngine, glyphs[i]); + for (int i=0; i< textItem->numGlyphs; ++i) { + QGLGlyphCoord *g = qt_glyph_cache()->lookup(textItem->fontEngine, textItem->glyphs[i]); // we don't cache glyphs with no width/height if (!g) @@ -4969,8 +4955,8 @@ void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte x2 = x1 + g->width; y2 = y1 + g->height; - QPointF logical_pos((positions[i].x - g->x_offset).toReal(), - (positions[i].y + g->y_offset).toReal()); + QPointF logical_pos((textItem->glyphPositions[i].x - g->x_offset).toReal(), + (textItem->glyphPositions[i].y + g->y_offset).toReal()); qt_add_rect_to_array(QRectF(logical_pos, QSizeF(g->log_width, g->log_height)), vertexArray); qt_add_texcoords_to_array(x1, y1, x2, y2, texCoordArray); @@ -4987,6 +4973,40 @@ void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte // XXX: This may not be needed as this behavior does seem to be caused by driver bug glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); #endif + +} + +void QOpenGLPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem) +{ + Q_D(QOpenGLPaintEngine); + + const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); + + // fall back to drawing a polygon if the scale factor is large, or + // we use a gradient pen + if ((d->matrix.det() > 1) || (d->pen_brush_style >= Qt::LinearGradientPattern + && d->pen_brush_style <= Qt::ConicalGradientPattern)) { + QPaintEngine::drawTextItem(p, textItem); + return; + } + + // add the glyphs used to the glyph texture cache + QVarLengthArray<QFixedPoint> positions; + QVarLengthArray<glyph_t> glyphs; + QTransform matrix = QTransform::fromTranslate(qRound(p.x()), qRound(p.y())); + ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); + + { + QStaticTextItem staticTextItem; + staticTextItem.chars = ti.chars; + staticTextItem.fontEngine = ti.fontEngine; + staticTextItem.glyphs = glyphs.data(); + staticTextItem.numChars = ti.num_chars; + staticTextItem.numGlyphs = glyphs.size(); + staticTextItem.glyphPositions = positions.data(); + drawStaticTextItem(&staticTextItem); + } + } |