summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2019-06-20 09:55:40 +0200
committerEskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>2019-06-20 10:54:54 +0200
commit8e7db0dd1cdc63c962359b37f882643dd3ed0e1a (patch)
treedb6e95d119b4a556d072fbe57472b1cc61e7d1ad
parent8e3e12faadd629fb8ae2bd1bd46f3c05e292a10e (diff)
distancefieldgenerator: Avoid exceeding max texture size
Since we use a single area allocator for all textures, a glyph on the edge between two textures, would end up spanning two textures. It would be assigned to the first, and which in turn would be expanded to account for the additional data. The result was that the texture height exceeded the maximum size set. This is actually an inherited problem from Qt Quick, but it happens more frequently with the distancefieldgenerator because you will typically generate a large number of glyphs, and also the default max size set is quite low to be on the safe side. The bandaid in this patch is to pad the texture height by the size of one glyph, which will for the most part get rid of the problem, except for fonts where a majority of glyphs exceed the em square. [ChangeLog][distancefieldgenerator] Fixed a bug where the generated textures might exceed the maximum height. Task-number: QTBUG-76528 Change-Id: I51487bbf7c46556b022bfd45cefc8776d0272de3 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/distancefieldgenerator/mainwindow.cpp17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/distancefieldgenerator/mainwindow.cpp b/src/distancefieldgenerator/mainwindow.cpp
index 763aeaa6b..a3f48cb0a 100644
--- a/src/distancefieldgenerator/mainwindow.cpp
+++ b/src/distancefieldgenerator/mainwindow.cpp
@@ -417,10 +417,20 @@ QByteArray MainWindow::createSfntTable()
header.minorVersion = 12;
header.pixelSize = qToBigEndian(quint16(qRound(m_model->pixelSize())));
+ const quint8 padding = 2;
+ qreal scaleFactor = qreal(1) / QT_DISTANCEFIELD_SCALE(m_model->doubleGlyphResolution());
+ const int radius = QT_DISTANCEFIELD_RADIUS(m_model->doubleGlyphResolution())
+ / QT_DISTANCEFIELD_SCALE(m_model->doubleGlyphResolution());
+
quint32 textureSize = ui->sbMaximumTextureSize->value();
+
+ // Since we are using a single area allocator that spans all textures, we need
+ // to split the textures one row before the actual maximum size, otherwise
+ // glyphs that fall on the edge between two textures will expand the texture
+ // they are assigned to, and this will end up being larger than the max.
+ textureSize -= quint32(qCeil(m_model->pixelSize() * scaleFactor) + radius * 2 + padding * 2);
header.textureSize = qToBigEndian(textureSize);
- const quint8 padding = 2;
header.padding = padding;
header.flags = m_model->doubleGlyphResolution() ? 1 : 0;
header.numGlyphs = qToBigEndian(quint32(list.size()));
@@ -443,13 +453,9 @@ QByteArray MainWindow::createSfntTable()
int textureCount = 0;
{
- qreal scaleFactor = qreal(1) / QT_DISTANCEFIELD_SCALE(m_model->doubleGlyphResolution());
QTransform scaleDown;
scaleDown.scale(scaleFactor, scaleFactor);
- const int radius = QT_DISTANCEFIELD_RADIUS(m_model->doubleGlyphResolution())
- / QT_DISTANCEFIELD_SCALE(m_model->doubleGlyphResolution());
-
{
bool foundOptimalSize = false;
while (!foundOptimalSize) {
@@ -466,6 +472,7 @@ QByteArray MainWindow::createSfntTable()
glyphData.boundingRect = scaleDown.mapRect(path.boundingRect());
int glyphWidth = qCeil(glyphData.boundingRect.width()) + radius * 2;
int glyphHeight = qCeil(glyphData.boundingRect.height()) + radius * 2;
+
glyphData.glyphSize = QSize(glyphWidth + padding * 2, glyphHeight + padding * 2);
if (glyphData.glyphSize.width() > qint32(textureSize)