summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp8
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp7
-rw-r--r--src/gui/painting/qpaintengine_x11.cpp2
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp10
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp1
-rw-r--r--src/gui/text/qfontengine_ft.cpp175
-rw-r--r--src/gui/text/qfontengine_ft_p.h52
-rw-r--r--src/gui/text/qfontengine_x11.cpp16
8 files changed, 166 insertions, 105 deletions
diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
index 6c4d9f1..c202e1f 100644
--- a/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
+++ b/src/3rdparty/harfbuzz/src/harfbuzz-shaper.cpp
@@ -1052,16 +1052,16 @@ HB_Bool HB_SelectScript(HB_ShaperItem *shaper_item, const HB_OpenTypeFeature *fe
{
HB_Script script = shaper_item->item.script;
- if (!shaper_item->face->supported_scripts[script])
- return false;
-
HB_Face face = shaper_item->face;
if (face->current_script == script && face->current_flags == shaper_item->shaperFlags)
- return true;
+ return shaper_item->face->supported_scripts[script] ? true : false;
face->current_script = script;
face->current_flags = shaper_item->shaperFlags;
+ if (!shaper_item->face->supported_scripts[script])
+ return false;
+
assert(script < HB_ScriptCount);
// find script in our list of supported scripts.
unsigned int tag = ot_scripts[script].tag;
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 9242fb6..3af98d6 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -3469,7 +3469,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
}
if (!gset || gset->outline_drawing
- || !fe->loadGlyphs(gset, glyphs.data(), glyphs.size(), neededFormat))
+ || !fe->loadGlyphs(gset, glyphs.data(), glyphs.size(), positions, neededFormat))
{
QPaintEngine::drawTextItem(p, ti);
return;
@@ -3494,12 +3494,13 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
};
for(int i = 0; i < glyphs.size(); i++) {
- QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i]);
+ QFixed spp = fe->subPixelPositionForX(positions[i].x);
+ QFontEngineFT::Glyph *glyph = gset->getGlyph(glyphs[i], spp);
if (!glyph || glyph->format != neededFormat) {
if (!lockedFace)
lockedFace = fe->lockFace();
- glyph = fe->loadGlyph(gset, glyphs[i], neededFormat);
+ glyph = fe->loadGlyph(gset, glyphs[i], spp, neededFormat);
}
if (!glyph || !glyph->data)
diff --git a/src/gui/painting/qpaintengine_x11.cpp b/src/gui/painting/qpaintengine_x11.cpp
index 8b71b83..16ef09b 100644
--- a/src/gui/painting/qpaintengine_x11.cpp
+++ b/src/gui/painting/qpaintengine_x11.cpp
@@ -2385,7 +2385,7 @@ void QX11PaintEngine::drawFreetype(const QPointF &p, const QTextItemInt &ti)
set = ft->loadTransformedGlyphSet(d->matrix);
if (!set || set->outline_drawing
- || !ft->loadGlyphs(set, glyphs.data(), glyphs.size(), QFontEngineFT::Format_Render))
+ || !ft->loadGlyphs(set, glyphs.data(), glyphs.size(), positions, QFontEngineFT::Format_Render))
{
QPaintEngine::drawTextItem(p, ti);
return;
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index e75c0f5..b83dbc0 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -134,9 +134,13 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
if (!supportsSubPixelPositions) {
m_subPixelPositionCount = 1;
} else {
+#if !defined(Q_WS_X11)
int i = 0;
while (m_subPixelPositionCount == 0 && i < numGlyphs)
m_subPixelPositionCount = calculateSubPixelPositionCount(glyphs[i++]);
+#else
+ m_subPixelPositionCount = 4;
+#endif
}
}
@@ -307,9 +311,11 @@ QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g, QFixed subPixelPosition
QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_fontengine);
QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
+ QFontEngineFT::Glyph *glyph = NULL;
+ if (gset)
+ glyph = ft->loadGlyph(gset, g, subPixelPosition, format);
- if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
- QFontEngineFT::Glyph *glyph = gset->getGlyph(g);
+ if (glyph) {
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);
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index 02b0148..0c0c4c8 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -746,6 +746,7 @@ QFontDef qt_FcPatternToQFontDef(FcPattern *pattern, const QFontDef &request)
QFontDef fontDef;
fontDef.styleStrategy = request.styleStrategy;
+ fontDef.hintingPreference = request.hintingPreference;
FcChar8 *value = 0;
if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) == FcResultMatch) {
fontDef.family = QString::fromUtf8(reinterpret_cast<const char *>(value));
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index f5e9e1c..a4211a9 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -174,9 +174,7 @@ int QFreetypeFace::fsType() const
HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
{
- int load_flags = (flags & HB_ShaperFlag_UseDesignMetrics) ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT;
-
- if (HB_Error error = (HB_Error)FT_Load_Glyph(face, glyph, load_flags))
+ if (HB_Error error = (HB_Error)FT_Load_Glyph(face, glyph, flags))
return error;
if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
@@ -760,12 +758,9 @@ void QFontEngineFT::setDefaultHintStyle(HintStyle style)
default_hint_style = style;
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const
+int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
+ bool &hsubpixel, int &vfactor) const
{
- Glyph *g = set->getGlyph(glyph);
- if (g && g->format == format)
- return g;
-
int load_flags = FT_LOAD_DEFAULT | default_load_flags;
int load_target = default_hint_style == HintLight
? FT_LOAD_TARGET_LIGHT
@@ -777,20 +772,35 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph
if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) {
if (default_hint_style == HintFull)
load_target = FT_LOAD_TARGET_LCD;
+ hsubpixel = true;
} else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) {
if (default_hint_style == HintFull)
load_target = FT_LOAD_TARGET_LCD_V;
+ vfactor = 3;
}
}
- if (set->outline_drawing)
+ if (set && set->outline_drawing)
load_flags = FT_LOAD_NO_BITMAP;
- if (default_hint_style == HintNone)
+ if (default_hint_style == HintNone || (flags & HB_ShaperFlag_UseDesignMetrics))
load_flags |= FT_LOAD_NO_HINTING;
else
load_flags |= load_target;
+ return load_flags;
+}
+
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const
+{
+ Glyph *g = set->getGlyph(glyph);
+ if (g && g->format == format)
+ return g;
+
+ bool hsubpixel = false;
+ int vfactor = 1;
+ int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
+
// apply our matrix to this, but note that the metrics will not be affected by this.
FT_Face face = lockFace();
FT_Matrix matrix = this->matrix;
@@ -881,7 +891,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph
return g;
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, GlyphFormat format, bool fetchMetricsOnly) const
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
+ QFixed subPixelPosition,
+ GlyphFormat format,
+ bool fetchMetricsOnly) const
{
// Q_ASSERT(freetype->lock == 1);
@@ -896,10 +909,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
}
}
- Glyph *g = set->getGlyph(glyph);
+ Glyph *g = set->getGlyph(glyph, subPixelPosition);
if (g && g->format == format) {
if (uploadToServer && !g->uploadedToServer) {
- set->setGlyph(glyph, 0);
+ set->setGlyph(glyph, subPixelPosition, 0);
delete g;
g = 0;
} else {
@@ -912,33 +925,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
Q_ASSERT(format != Format_None);
bool hsubpixel = false;
int vfactor = 1;
- int load_flags = FT_LOAD_DEFAULT | default_load_flags;
-
- int load_target = default_hint_style == HintLight
- ? FT_LOAD_TARGET_LIGHT
- : FT_LOAD_TARGET_NORMAL;
-
- if (set->outline_drawing)
- load_flags |= FT_LOAD_NO_BITMAP;
-
- if (format == Format_Mono) {
- load_target = FT_LOAD_TARGET_MONO;
- } else if (format == Format_A32) {
- if (subpixelType == QFontEngineFT::Subpixel_RGB || subpixelType == QFontEngineFT::Subpixel_BGR) {
- if (default_hint_style == HintFull)
- load_target = FT_LOAD_TARGET_LCD;
- hsubpixel = true;
- } else if (subpixelType == QFontEngineFT::Subpixel_VRGB || subpixelType == QFontEngineFT::Subpixel_VBGR) {
- if (default_hint_style == HintFull)
- load_target = FT_LOAD_TARGET_LCD_V;
- vfactor = 3;
- }
- }
-
- if (default_hint_style == HintNone)
- load_flags |= FT_LOAD_NO_HINTING;
- else
- load_flags |= load_target;
+ int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
#ifndef Q_WS_QWS
if (format != Format_Mono && !embeddedbitmap)
@@ -955,6 +942,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
load_flags |= FT_LOAD_NO_BITMAP;
FT_Face face = freetype->face;
+
+ FT_Vector v;
+ v.x = FT_Pos((subPixelPosition).toReal() * 64);
+ v.y = 0;
+ FT_Set_Transform(face, &freetype->matrix, &v);
+
FT_Error err = FT_Load_Glyph(face, glyph, load_flags);
if (err && (load_flags & FT_LOAD_NO_BITMAP)) {
load_flags &= ~FT_LOAD_NO_BITMAP;
@@ -1055,6 +1048,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
top = CEIL(top);
int hpixels = TRUNC(right - left);
+ // subpixel position requires one more pixel
+ if (subPixelPosition > 0)
+ hpixels++;
+
if (hsubpixel)
hpixels = hpixels*3 + 8;
info.width = hpixels;
@@ -1197,7 +1194,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, Glyph
uploadGlyphToServer(set, glyph, g, &info, glyph_buffer_size);
}
- set->setGlyph(glyph, g);
+ set->setGlyph(glyph, subPixelPosition, g);
return g;
}
@@ -1430,12 +1427,28 @@ QFontEngineFT::QGlyphSet *QFontEngineFT::loadTransformedGlyphSet(const QTransfor
return gs;
}
-bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format)
+QFixed QFontEngineFT::subPixelPositionForX(QFixed x)
+{
+ int m_subPixelPositionCount = 4;
+
+ QFixed subPixelPosition;
+ if (x != 0) {
+ subPixelPosition = x - x.floor();
+ QFixed fraction = (subPixelPosition / QFixed::fromReal(1.0 / m_subPixelPositionCount)).floor();
+ subPixelPosition = fraction / QFixed(m_subPixelPositionCount);
+ }
+ return subPixelPosition;
+}
+
+bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs,
+ QVarLengthArray<QFixedPoint> &positions,
+ GlyphFormat format)
{
FT_Face face = 0;
for (int i = 0; i < num_glyphs; ++i) {
- Glyph *glyph = gs->getGlyph(glyphs[i]);
+ QFixed spp = subPixelPositionForX(positions[i].x);
+ Glyph *glyph = gs->getGlyph(glyphs[i], spp);
if (glyph == 0 || glyph->format != format) {
if (!face) {
face = lockFace();
@@ -1444,7 +1457,7 @@ bool QFontEngineFT::loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, G
FT_Set_Transform(face, &m, 0);
freetype->matrix = m;
}
- if (!loadGlyph(gs, glyphs[i], format)) {
+ if (!loadGlyph(gs, glyphs[i], spp, format)) {
unlockFace();
return false;
}
@@ -1668,35 +1681,26 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
{
FT_Face face = 0;
- if (flags & QTextEngine::DesignMetrics) {
- for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
- if (g) {
- glyphs->advances_x[i] = QFixed::fromFixed(g->linearAdvance);
- } else {
- if (!face)
- face = lockFace();
- g = loadGlyph(glyphs->glyphs[i], Format_None, true);
- glyphs->advances_x[i] = QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10);
- }
- glyphs->advances_y[i] = 0;
- }
- } else {
- for (int i = 0; i < glyphs->numGlyphs; i++) {
- Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
- if (g) {
- glyphs->advances_x[i] = QFixed(g->advance);
- } else {
- if (!face)
- face = lockFace();
- g = loadGlyph(glyphs->glyphs[i], Format_None, true);
- glyphs->advances_x[i] = QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
- }
- glyphs->advances_y[i] = 0;
+ bool design = (default_hint_style == HintNone ||
+ default_hint_style == HintLight ||
+ (flags & HB_ShaperFlag_UseDesignMetrics));
+ for (int i = 0; i < glyphs->numGlyphs; i++) {
+ Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
+ if (g) {
+ glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
+ } else {
+ if (!face)
+ face = lockFace();
+ g = loadGlyph(glyphs->glyphs[i], 0, Format_None, true);
+ glyphs->advances_x[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
+ : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
+ if (face)
+ unlockFace();
}
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ glyphs->advances_x[i] = glyphs->advances_x[i].round();
+ glyphs->advances_y[i] = 0;
}
- if (face)
- unlockFace();
}
glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
@@ -1716,7 +1720,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs)
if (!g) {
if (!face)
face = lockFace();
- g = loadGlyph(glyphs.glyphs[i], Format_None, true);
+ g = loadGlyph(glyphs.glyphs[i], 0, Format_None, true);
}
if (g) {
QFixed x = overall.xoff + glyphs.offsets[i].x + g->x;
@@ -1757,7 +1761,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
Glyph *g = defaultGlyphSet.getGlyph(glyph);
if (!g) {
face = lockFace();
- g = loadGlyph(glyph, Format_None, true);
+ g = loadGlyph(glyph, 0, Format_None, true);
}
if (g) {
overall.x = g->x;
@@ -1765,6 +1769,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph)
overall.width = g->width;
overall.height = g->height;
overall.xoff = g->advance;
+ if (fontDef.styleStrategy & QFont::ForceIntegerMetrics)
+ overall.xoff = overall.xoff.round();
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
@@ -1866,7 +1872,7 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g)
GlyphFormat glyph_format = antialias ? Format_A8 : Format_Mono;
- Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format);
+ Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, 0, glyph_format);
if (!glyph) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
@@ -1905,7 +1911,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, in
GlyphFormat glyph_format = Format_A32;
- Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format);
+ Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, subPixelPosition, glyph_format);
if (!glyph) {
unlockFace();
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, margin, t);
@@ -1920,7 +1926,7 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, in
void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
{
- defaultGlyphSet.removeGlyphFromCache(glyph);
+ defaultGlyphSet.removeGlyphFromCache(glyph, 0);
}
int QFontEngineFT::glyphCount() const
@@ -2000,9 +2006,9 @@ void QFontEngineFT::QGlyphSet::clear()
glyph_data.clear();
}
-void QFontEngineFT::QGlyphSet::removeGlyphFromCache(int index)
+void QFontEngineFT::QGlyphSet::removeGlyphFromCache(glyph_t index, QFixed subPixelPosition)
{
- if (index < 256) {
+ if (useFastGlyphData(index, subPixelPosition)) {
if (fast_glyph_data[index]) {
delete fast_glyph_data[index];
fast_glyph_data[index] = 0;
@@ -2010,18 +2016,18 @@ void QFontEngineFT::QGlyphSet::removeGlyphFromCache(int index)
--fast_glyph_count;
}
} else {
- delete glyph_data.take(index);
+ delete glyph_data.take(GlyphAndSubPixelPosition(index, subPixelPosition));
}
}
-void QFontEngineFT::QGlyphSet::setGlyph(int index, Glyph *glyph)
+void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, QFixed subPixelPosition, Glyph *glyph)
{
- if (index < 256) {
+ if (useFastGlyphData(index, subPixelPosition)) {
if (!fast_glyph_data[index])
++fast_glyph_count;
fast_glyph_data[index] = glyph;
} else {
- glyph_data.insert(index, glyph);
+ glyph_data.insert(GlyphAndSubPixelPosition(index, subPixelPosition), glyph);
}
}
@@ -2038,7 +2044,10 @@ void QFontEngineFT::freeServerGlyphSet(unsigned long id)
HB_Error QFontEngineFT::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
{
lockFace();
- HB_Error result = freetype->getPointInOutline(glyph, flags, point, xpos, ypos, nPoints);
+ bool hsubpixel = true;
+ int vfactor = 1;
+ int load_flags = loadFlags(0, Format_A8, flags, hsubpixel, vfactor);
+ HB_Error result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints);
unlockFace();
return result;
}
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index abdbd20..63fd9a7 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -166,6 +166,19 @@ public:
};
#endif
+ struct GlyphAndSubPixelPosition
+ {
+ GlyphAndSubPixelPosition(glyph_t g, QFixed spp) : glyph(g), subPixelPosition(spp) {}
+
+ bool operator==(const GlyphAndSubPixelPosition &other) const
+ {
+ return glyph == other.glyph && subPixelPosition == other.subPixelPosition;
+ }
+
+ glyph_t glyph;
+ QFixed subPixelPosition;
+ };
+
struct QGlyphSet
{
QGlyphSet();
@@ -174,18 +187,21 @@ public:
unsigned long id; // server sided id, GlyphSet for X11
bool outline_drawing;
- void removeGlyphFromCache(int index);
+ void removeGlyphFromCache(glyph_t index, QFixed subPixelPosition);
void clear();
- inline Glyph *getGlyph(int index) const
+ inline bool useFastGlyphData(glyph_t index, QFixed subPixelPosition) const {
+ return (index < 256 && subPixelPosition == 0);
+ }
+ inline Glyph *getGlyph(glyph_t index, QFixed subPixelPosition = 0) const
{
- if (index < 256)
+ if (useFastGlyphData(index, subPixelPosition))
return fast_glyph_data[index];
- return glyph_data.value(index);
+ return glyph_data.value(GlyphAndSubPixelPosition(index, subPixelPosition));
}
- void setGlyph(int index, Glyph *glyph);
+ void setGlyph(glyph_t index, QFixed spp, Glyph *glyph);
private:
- mutable QHash<int, Glyph *> glyph_data; // maps from glyph index to glyph data
+ mutable QHash<GlyphAndSubPixelPosition, Glyph *> glyph_data; // maps from glyph index to glyph data
mutable Glyph *fast_glyph_data[256]; // for fast lookup of glyphs < 256
mutable int fast_glyph_count;
};
@@ -193,6 +209,11 @@ private:
virtual QFontEngine::FaceId faceId() const;
virtual QFontEngine::Properties properties() const;
virtual QFixed emSquareSize() const;
+ virtual bool supportsSubPixelPositions() const
+ {
+ return default_hint_style == HintLight ||
+ default_hint_style == HintNone;
+ }
virtual bool getSfntTableData(uint tag, uchar *buffer, uint *length) const;
virtual int synthesized() const;
@@ -254,17 +275,20 @@ private:
inline bool invalid() const { return xsize == 0 && ysize == 0; }
inline bool isBitmapFont() const { return defaultFormat == Format_Mono; }
- inline Glyph *loadGlyph(uint glyph, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
- { return loadGlyph(&defaultGlyphSet, glyph, format, fetchMetricsOnly); }
- Glyph *loadGlyph(QGlyphSet *set, uint glyph, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
+ inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
+ { return loadGlyph(&defaultGlyphSet, glyph, subPixelPosition, format, fetchMetricsOnly); }
+ Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
QGlyphSet *defaultGlyphs() { return &defaultGlyphSet; }
GlyphFormat defaultGlyphFormat() const { return defaultFormat; }
- inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g); }
+ inline Glyph *cachedGlyph(glyph_t g) const { return defaultGlyphSet.getGlyph(g, 0); }
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
- bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs, GlyphFormat format = Format_Render);
+ QFixed subPixelPositionForX(QFixed x);
+ bool loadGlyphs(QGlyphSet *gs, glyph_t *glyphs, int num_glyphs,
+ QVarLengthArray<QFixedPoint> &positions,
+ GlyphFormat format = Format_Render);
#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)
virtual void draw(QPaintEngine * /*p*/, qreal /*x*/, qreal /*y*/, const QTextItemInt & /*si*/) {}
@@ -309,6 +333,7 @@ protected:
private:
QFontEngineFT::Glyph *loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const;
+ int loadFlags(QGlyphSet *set, GlyphFormat format, int flags, bool &hsubpixel, int &vfactor) const;
GlyphFormat defaultFormat;
FT_Matrix matrix;
@@ -330,6 +355,11 @@ private:
mutable bool kerning_pairs_loaded;
};
+inline uint qHash(const QFontEngineFT::GlyphAndSubPixelPosition &g)
+{
+ return (g.glyph << 8) | (g.subPixelPosition * 10).round().toInt();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_FREETYPE
diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp
index d5ec584..e442471 100644
--- a/src/gui/text/qfontengine_x11.cpp
+++ b/src/gui/text/qfontengine_x11.cpp
@@ -1012,8 +1012,22 @@ QFontEngineX11FT::QFontEngineX11FT(FcPattern *pattern, const QFontDef &fd, int s
}
}
+ if (fd.hintingPreference != QFont::PreferDefaultHinting) {
+ switch (fd.hintingPreference) {
+ case QFont::PreferNoHinting:
+ default_hint_style = HintNone;
+ break;
+ case QFont::PreferVerticalHinting:
+ default_hint_style = HintLight;
+ break;
+ case QFont::PreferFullHinting:
+ default:
+ default_hint_style = HintFull;
+ break;
+ }
+ }
#ifdef FC_HINT_STYLE
- {
+ else {
int hint_style = 0;
if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch)
hint_style = X11->fc_hint_style;