diff options
author | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2019-06-20 09:55:40 +0200 |
---|---|---|
committer | Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> | 2019-06-20 10:54:54 +0200 |
commit | 8e7db0dd1cdc63c962359b37f882643dd3ed0e1a (patch) | |
tree | db6e95d119b4a556d072fbe57472b1cc61e7d1ad | |
parent | 8e3e12faadd629fb8ae2bd1bd46f3c05e292a10e (diff) | |
download | qttools-8e7db0dd1cdc63c962359b37f882643dd3ed0e1a.tar.gz |
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.cpp | 17 |
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) |