src/gui/painting/qtextureglyphcache.cpp
changeset 30 5dc02b23752f
parent 29 b72c6db6890b
--- a/src/gui/painting/qtextureglyphcache.cpp	Wed Jun 23 19:07:03 2010 +0300
+++ b/src/gui/painting/qtextureglyphcache.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -55,16 +55,29 @@
 
 // #define CACHE_DEBUG
 
-void QTextureGlyphCache::populate(const QTextItemInt &ti,
-                                  const QVarLengthArray<glyph_t> &glyphs,
-                                  const QVarLengthArray<QFixedPoint> &)
+// returns the highest number closest to v, which is a power of 2
+// NB! assumes 32 bit ints
+static inline int qt_next_power_of_two(int v)
+{
+    v--;
+    v |= v >> 1;
+    v |= v >> 2;
+    v |= v >> 4;
+    v |= v >> 8;
+    v |= v >> 16;
+    ++v;
+    return v;
+}
+
+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());
+    printf("Populating with %d glyphs\n", numGlyphs);
     qDebug() << " -> current transformation: " << m_transform;
 #endif
 
-    m_current_textitem = &ti;
+    m_current_fontengine = fontEngine;
     const int margin = glyphMargin();
     const int paddingDoubled = glyphPadding() * 2;
 
@@ -72,26 +85,23 @@
     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;
         if (listItemCoordinates.contains(glyph))
             continue;
-        glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyph, m_transform);
+        glyph_metrics_t metrics = fontEngine->boundingBox(glyph, m_transform);
 
 #ifdef CACHE_DEBUG
-        printf("'%c' (%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f, ti.ascent=%.2f, ti.descent=%.2f\n",
-               ti.chars[i].toLatin1(),
+        printf("(%4x): w=%.2f, h=%.2f, xoff=%.2f, yoff=%.2f, x=%.2f, y=%.2f\n",
                glyph,
                metrics.width.toReal(),
                metrics.height.toReal(),
                metrics.xoff.toReal(),
                metrics.yoff.toReal(),
                metrics.x.toReal(),
-               metrics.y.toReal(),
-               ti.ascent.toReal(),
-               ti.descent.toReal());
+               metrics.y.toReal());
 #endif
         int glyph_width = metrics.width.ceil().toInt();
         int glyph_height = metrics.height.ceil().toInt();
@@ -117,26 +127,25 @@
 
     rowHeight += margin * 2 + paddingDoubled;
     if (isNull())
-        createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, rowHeight);
+        createCache(QT_DEFAULT_TEXTURE_GLYPH_CACHE_WIDTH, qt_next_power_of_two(rowHeight));
 
     // now actually use the coords and paint the wanted glyps into cache.
     QHash<glyph_t, Coord>::iterator iter = listItemCoordinates.begin();
     while (iter != listItemCoordinates.end()) {
         Coord c = iter.value();
 
+        m_currentRowHeight = qMax(m_currentRowHeight, c.h + margin * 2);
+
         if (m_cx + c.w > m_w) {
             // no room on the current line, start new glyph strip
             m_cx = 0;
-            m_cy = m_h + paddingDoubled;
+            m_cy += m_currentRowHeight + paddingDoubled;
+            m_currentRowHeight = 0; // New row
         }
         if (m_cy + c.h > m_h) {
-            int new_height;
-            if (m_cx == 0) { // add a whole row
-                new_height = m_h + rowHeight;
-                m_cy = m_h;
-            } else { // just extend row
-                new_height = m_cy + rowHeight;
-            }
+            int new_height = m_h*2;
+            while (new_height < m_cy + c.h)
+                new_height *= 2;
             // if no room in the current texture - realloc a larger texture
             resizeTextureData(m_w, new_height);
             m_h = new_height;
@@ -148,14 +157,7 @@
         fillTexture(c, iter.key());
         coords.insert(iter.key(), c);
 
-        if (m_cx + c.w > m_w) {
-            m_cx = 0;
-            m_cy += rowHeight;
-        } else {
-            // for the Mono case, glyph_width is 8-bit aligned,
-            // and therefore so will m_cx
-            m_cx += c.w + paddingDoubled;
-        }
+        m_cx += c.w + paddingDoubled;
         ++iter;
     }
 
@@ -183,11 +185,11 @@
             break;
         };
 
-        QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine);
+        QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_fontengine);
         QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
 
         if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
-            QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g);
+            QFontEngineFT::Glyph *glyph = gset->getGlyph(g);
             const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3
                                : (glyph->width + 3) & ~3);
             return QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, imageFormat);
@@ -195,9 +197,9 @@
     } else
 #endif
     if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
-        return m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
+        return m_current_fontengine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
     else
-        return m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform);
+        return m_current_fontengine->alphaMapForGlyph(g, m_transform);
 
     return QImage();
 }
@@ -325,10 +327,7 @@
     QPoint base(c.x + glyphMargin(), c.y + glyphMargin() + c.baseLineY-1);
     if (m_image.rect().contains(base))
         m_image.setPixel(base, 255);
-    m_image.save(QString::fromLatin1("cache-%1-%2-%3.png")
-                 .arg(m_current_textitem->font().family())
-                 .arg(m_current_textitem->font().pointSize())
-                 .arg(m_transform.type()));
+    m_image.save(QString::fromLatin1("cache-%1.png").arg(int(this)));
 #endif
 }