Don't use a QList on a type that can't be copied
QGlyphSet would not copy correctly, but also didn't have a Q_DISABLE_COPY defined. This can easily lead to undefined behavior, and was visible when trying to do the QList to QVector conversion. As we only have a 10 item large LRU list here, implement it manually. Change-Id: I903085ddeac59224715dca6e8a1ff26c44f5b0b0 Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
6f27bb1352
commit
2c47d53249
@ -1354,6 +1354,53 @@ static inline FT_Matrix QTransformToFTMatrix(const QTransform &matrix)
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QFontEngineFT::QGlyphSet *QFontEngineFT::TransformedGlyphSets::findSet(const QTransform &matrix, const QFontDef &fontDef)
|
||||||
|
{
|
||||||
|
FT_Matrix m = QTransformToFTMatrix(matrix);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < nSets; ++i) {
|
||||||
|
QGlyphSet *g = sets[i];
|
||||||
|
if (!g)
|
||||||
|
break;
|
||||||
|
if (g->transformationMatrix.xx == m.xx
|
||||||
|
&& g->transformationMatrix.xy == m.xy
|
||||||
|
&& g->transformationMatrix.yx == m.yx
|
||||||
|
&& g->transformationMatrix.yy == m.yy) {
|
||||||
|
|
||||||
|
// found a match, move it to the front
|
||||||
|
moveToFront(i);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't cache more than nSets transformations
|
||||||
|
if (i == nSets)
|
||||||
|
// reuse the last set
|
||||||
|
--i;
|
||||||
|
moveToFront(nSets - 1);
|
||||||
|
if (!sets[0])
|
||||||
|
sets[0] = new QGlyphSet;
|
||||||
|
QGlyphSet *gs = sets[0];
|
||||||
|
gs->clear();
|
||||||
|
gs->transformationMatrix = m;
|
||||||
|
gs->outline_drawing = fontDef.pixelSize * fontDef.pixelSize * qAbs(matrix.determinant()) > QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE;
|
||||||
|
Q_ASSERT(gs != 0);
|
||||||
|
|
||||||
|
return gs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QFontEngineFT::TransformedGlyphSets::moveToFront(int i)
|
||||||
|
{
|
||||||
|
QGlyphSet *g = sets[i];
|
||||||
|
while (i > 0) {
|
||||||
|
sets[i] = sets[i - 1];
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
sets[0] = g;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QFontEngineFT::QGlyphSet *QFontEngineFT::loadGlyphSet(const QTransform &matrix)
|
QFontEngineFT::QGlyphSet *QFontEngineFT::loadGlyphSet(const QTransform &matrix)
|
||||||
{
|
{
|
||||||
if (matrix.type() > QTransform::TxShear || !cacheEnabled)
|
if (matrix.type() > QTransform::TxShear || !cacheEnabled)
|
||||||
@ -1363,39 +1410,7 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadGlyphSet(const QTransform &matrix)
|
|||||||
if (!FT_IS_SCALABLE(freetype->face))
|
if (!FT_IS_SCALABLE(freetype->face))
|
||||||
return matrix.type() <= QTransform::TxTranslate ? &defaultGlyphSet : nullptr;
|
return matrix.type() <= QTransform::TxTranslate ? &defaultGlyphSet : nullptr;
|
||||||
|
|
||||||
FT_Matrix m = QTransformToFTMatrix(matrix);
|
return transformedGlyphSets.findSet(matrix, fontDef);
|
||||||
|
|
||||||
QGlyphSet *gs = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < transformedGlyphSets.count(); ++i) {
|
|
||||||
const QGlyphSet &g = transformedGlyphSets.at(i);
|
|
||||||
if (g.transformationMatrix.xx == m.xx
|
|
||||||
&& g.transformationMatrix.xy == m.xy
|
|
||||||
&& g.transformationMatrix.yx == m.yx
|
|
||||||
&& g.transformationMatrix.yy == m.yy) {
|
|
||||||
|
|
||||||
// found a match, move it to the front
|
|
||||||
transformedGlyphSets.move(i, 0);
|
|
||||||
gs = &transformedGlyphSets[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gs) {
|
|
||||||
// don't cache more than 10 transformations
|
|
||||||
if (transformedGlyphSets.count() >= 10) {
|
|
||||||
transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
|
|
||||||
} else {
|
|
||||||
transformedGlyphSets.prepend(QGlyphSet());
|
|
||||||
}
|
|
||||||
gs = &transformedGlyphSets[0];
|
|
||||||
gs->clear();
|
|
||||||
gs->transformationMatrix = m;
|
|
||||||
gs->outline_drawing = fontDef.pixelSize * fontDef.pixelSize * qAbs(matrix.determinant()) > QT_MAX_CACHED_GLYPH_SIZE * QT_MAX_CACHED_GLYPH_SIZE;
|
|
||||||
}
|
|
||||||
Q_ASSERT(gs != 0);
|
|
||||||
|
|
||||||
return gs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
|
void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
|
||||||
|
@ -63,6 +63,8 @@
|
|||||||
|
|
||||||
#include <qmutex.h>
|
#include <qmutex.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QFontEngineFTRawFont;
|
class QFontEngineFTRawFont;
|
||||||
@ -170,6 +172,7 @@ public:
|
|||||||
inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); }
|
inline bool isGlyphMissing(glyph_t index) const { return missing_glyphs.contains(index); }
|
||||||
inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); }
|
inline void setGlyphMissing(glyph_t index) const { missing_glyphs.insert(index); }
|
||||||
private:
|
private:
|
||||||
|
Q_DISABLE_COPY(QGlyphSet);
|
||||||
mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
|
mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
|
||||||
mutable QSet<glyph_t> missing_glyphs;
|
mutable QSet<glyph_t> missing_glyphs;
|
||||||
mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
|
mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
|
||||||
@ -310,7 +313,18 @@ private:
|
|||||||
GlyphFormat defaultFormat;
|
GlyphFormat defaultFormat;
|
||||||
FT_Matrix matrix;
|
FT_Matrix matrix;
|
||||||
|
|
||||||
QList<QGlyphSet> transformedGlyphSets;
|
struct TransformedGlyphSets {
|
||||||
|
enum { nSets = 10 };
|
||||||
|
QGlyphSet *sets[nSets];
|
||||||
|
|
||||||
|
QGlyphSet *findSet(const QTransform &matrix, const QFontDef &fontDef);
|
||||||
|
TransformedGlyphSets() { std::fill(&sets[0], &sets[nSets], nullptr); }
|
||||||
|
~TransformedGlyphSets() { qDeleteAll(&sets[0], &sets[nSets]); }
|
||||||
|
private:
|
||||||
|
void moveToFront(int i);
|
||||||
|
Q_DISABLE_COPY(TransformedGlyphSets);
|
||||||
|
};
|
||||||
|
TransformedGlyphSets transformedGlyphSets;
|
||||||
mutable QGlyphSet defaultGlyphSet;
|
mutable QGlyphSet defaultGlyphSet;
|
||||||
|
|
||||||
QFontEngine::FaceId face_id;
|
QFontEngine::FaceId face_id;
|
||||||
@ -326,6 +340,9 @@ private:
|
|||||||
QFixed scalableBitmapScaleFactor;
|
QFixed scalableBitmapScaleFactor;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_TYPEINFO(QFontEngineFT::QGlyphSet, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
|
|
||||||
inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g)
|
inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g)
|
||||||
{
|
{
|
||||||
return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
|
return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user