summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gui/text/qfontengine_ft.cpp75
-rw-r--r--src/gui/text/qfontengine_ft_p.h3
2 files changed, 67 insertions, 11 deletions
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index b0cfa49b36..83d9edab94 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1459,10 +1459,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me
bool QFontEngineFT::supportsTransformation(const QTransform &transform) const
{
- // The freetype engine falls back to QFontEngine for tranformed glyphs,
- // which uses fast-tranform and produces very ugly results, so we claim
- // to support just translations.
- return transform.type() <= QTransform::TxTranslate;
+ return transform.type() <= QTransform::TxRotate;
}
void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
@@ -1943,17 +1940,75 @@ void QFontEngineFT::unlockAlphaMapForGlyph()
currentlyLockedAlphaMap = QImage();
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format)
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
+ QFixed subPixelPosition,
+ GlyphFormat format,
+ const QTransform &t)
{
- return defaultGlyphSet.outline_drawing ? 0 :
- loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, g, subPixelPosition, format);
+ FT_Face face = 0;
+ QGlyphSet *glyphSet = 0;
+ FT_Matrix ftMatrix = QTransformToFTMatrix(t);
+ if (cacheEnabled) {
+ if (t.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) {
+ for (int i = 0; i < transformedGlyphSets.count(); ++i) {
+ const QGlyphSet &g = transformedGlyphSets.at(i);
+ if (g.transformationMatrix.xx == ftMatrix.xx
+ && g.transformationMatrix.xy == ftMatrix.xy
+ && g.transformationMatrix.yx == ftMatrix.yx
+ && g.transformationMatrix.yy == ftMatrix.yy) {
+
+ // found a match, move it to the front
+ transformedGlyphSets.move(i, 0);
+ glyphSet = &transformedGlyphSets[0];
+ break;
+ }
+ }
+
+ if (!glyphSet) {
+ // don't cache more than 10 transformations
+ if (transformedGlyphSets.count() >= 10) {
+ transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
+ } else {
+ transformedGlyphSets.prepend(QGlyphSet());
+ }
+ glyphSet = &transformedGlyphSets[0];
+ glyphSet->clear();
+ glyphSet->transformationMatrix = ftMatrix;
+ }
+ } else {
+ glyphSet = &defaultGlyphSet;
+ }
+ Q_ASSERT(glyphSet != 0);
+ }
+
+ if (glyphSet != 0 && glyphSet->outline_drawing)
+ return 0;
+
+ Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0;
+ if (!glyph || glyph->format != format) {
+ face = lockFace();
+ FT_Matrix m = this->matrix;
+ FT_Matrix_Multiply(&ftMatrix, &m);
+ freetype->matrix = m;
+ glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false);
+ }
+
+ if (face)
+ unlockFace();
+
+ return glyph;
}
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
{
+ return alphaMapForGlyph(g, subPixelPosition, QTransform());
+}
+
+QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
+{
lockFace();
- QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono));
+ QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
@@ -1987,12 +2042,12 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
{
- if (t.type() > QTransform::TxTranslate)
+ if (t.type() > QTransform::TxRotate)
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
lockFace();
- QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32));
+ QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index a73c281f1d..1894d25d70 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -233,6 +233,7 @@ private:
virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const;
virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); }
virtual QImage alphaMapForGlyph(glyph_t, QFixed);
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
QFixed subPixelPosition,
@@ -265,7 +266,7 @@ private:
inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
{ return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); }
Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
- Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format);
+ Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t);
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,