diff options
Diffstat (limited to 'src/gui/text/qfontengine_ft.cpp')
-rw-r--r-- | src/gui/text/qfontengine_ft.cpp | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index f5ca559d62..0a22038bb4 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -132,6 +132,7 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng return result; } +static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0}; // -------------------------- Freetype support ------------------------------ @@ -678,6 +679,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) const QByteArray env = qgetenv("QT_NO_FT_CACHE"); cacheEnabled = env.isEmpty() || env.toInt() == 0; m_subPixelPositionCount = 4; + forceAutoHint = false; } QFontEngineFT::~QFontEngineFT() @@ -813,11 +815,11 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags, 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 (subpixelType == Subpixel_RGB || subpixelType == 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) { + } else if (subpixelType == Subpixel_VRGB || subpixelType == Subpixel_VBGR) { if (default_hint_style == HintFull) load_target = FT_LOAD_TARGET_LCD_V; vfactor = 3; @@ -825,13 +827,16 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags, } if (set && set->outline_drawing) - load_flags = FT_LOAD_NO_BITMAP; + load_flags |= FT_LOAD_NO_BITMAP; if (default_hint_style == HintNone || (flags & DesignMetrics) || (set && set->outline_drawing)) load_flags |= FT_LOAD_NO_HINTING; else load_flags |= load_target; + if (forceAutoHint) + load_flags |= FT_LOAD_FORCE_AUTOHINT; + return load_flags; } @@ -854,6 +859,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, if (g && g->format == format && (fetchMetricsOnly || g->data)) return g; + if (!g && set && set->isGlyphMissing(glyph)) + return &emptyGlyph; + QFontEngineFT::GlyphInfo info; Q_ASSERT(format != Format_None); @@ -890,8 +898,12 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, load_flags |= FT_LOAD_FORCE_AUTOHINT; err = FT_Load_Glyph(face, glyph, load_flags); } - if (err != FT_Err_Ok) + if (err != FT_Err_Ok) { qWarning("load glyph failed err=%x face=%p, glyph=%d", err, face, glyph); + if (set) + set->setGlyphMissing(glyph); + return &emptyGlyph; + } FT_GlyphSlot slot = face->glyph; @@ -977,9 +989,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, glyph_buffer = new uchar[glyph_buffer_size]; if (hsubpixel) - convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, false); + convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB, false); else if (vfactor != 1) - convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, false); + convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB, false); } else #endif { @@ -1091,10 +1103,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch); buffer = convoluted; } - convertRGBToARGB(buffer + 1, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_RGB, useLegacyLcdFilter); + convertRGBToARGB(buffer + 1, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != Subpixel_RGB, useLegacyLcdFilter); delete [] convoluted; } else if (vfactor != 1) { - convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != QFontEngineFT::Subpixel_VRGB, true); + convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch, subpixelType != Subpixel_VRGB, true); } else if (format == Format_A32 && bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) { convertGRAYToARGB(bitmap.buffer, (uint *)glyph_buffer, info.width, info.height, bitmap.pitch); } @@ -1629,9 +1641,12 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlag if (!face) face = lockFace(); g = loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyphs->glyphs[i], 0, Format_None, true); - glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10) - : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round(); - if (!cacheEnabled) + if (g) + glyphs->advances[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance); + else + glyphs->advances[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10) + : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round(); + if (!cacheEnabled && g != &emptyGlyph) delete g; } } @@ -1670,7 +1685,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) xmax = qMax(xmax, x + g->width); ymax = qMax(ymax, y + g->height); overall.xoff += g->advance; - if (!cacheEnabled) + if (!cacheEnabled && g != &emptyGlyph) delete g; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); @@ -1713,7 +1728,7 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) overall.xoff = g->advance; if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) overall.xoff = overall.xoff.round(); - if (!cacheEnabled) + if (!cacheEnabled && g != &emptyGlyph) delete g; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); @@ -1804,7 +1819,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe overall.width = g->width; overall.height = g->height; overall.xoff = g->advance; - if (!glyphSet) + if (!glyphSet && g != &emptyGlyph) delete g; } else { int left = FLOOR(face->glyph->metrics.horiBearingX); |