From 227e9a40cfeb7e00658cd343266e9d4140a4ebcf Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 10 Aug 2013 20:05:36 +0300 Subject: [PATCH] Get rid of HB dependency in FT font engine Instead of loading HB face in QFreetypeFace::getFace(), defer allocation until the first FT font engine for that face gets initialized; then, QFreetypeFace "reparents" and manages the loaded HB face. Change-Id: I2ac8ead4c6ed25d341af9c9cf0c34dfb979f8390 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontengine.cpp | 24 +++++------- src/gui/text/qfontengine_ft.cpp | 63 ++++++++++---------------------- src/gui/text/qfontengine_ft_p.h | 4 +- src/gui/text/qfontengine_p.h | 9 +++++ src/gui/text/qfontengine_qpf.cpp | 3 +- 5 files changed, 42 insertions(+), 61 deletions(-) diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 6a6e67abb0..d8a8e34b0b 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -143,7 +143,7 @@ int QFontEngine::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFix Q_UNUSED(xpos) Q_UNUSED(ypos) Q_UNUSED(nPoints) - return HB_Err_Not_Covered; + return Err_Not_Covered; } static HB_Error hb_getPointInOutline(HB_Font font, HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints) @@ -203,17 +203,6 @@ QFontEngine::QFontEngine() fsType = 0; symbol = false; - { - HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec)); - Q_CHECK_PTR(hbFont); - memset(hbFont, 0, sizeof(HB_FontRec)); - hbFont->klass = &hb_fontClass; - hbFont->userData = this; - - font_ = (void *)hbFont; - font_destroy_func = free; - } - glyphFormat = -1; m_subPixelPositionCount = 0; @@ -262,8 +251,12 @@ QFixed QFontEngine::underlinePosition() const void *QFontEngine::harfbuzzFont() const { - HB_FontRec *hbFont = (HB_FontRec *)font_; - if (!hbFont->x_ppem) { + if (!font_) { + HB_FontRec *hbFont = (HB_FontRec *) malloc(sizeof(HB_FontRec)); + Q_CHECK_PTR(hbFont); + hbFont->klass = &hb_fontClass; + hbFont->userData = const_cast(this); + qint64 emSquare = emSquareSize().truncate(); Q_ASSERT(emSquare == emSquareSize().toInt()); // ensure no truncation if (emSquare == 0) @@ -273,6 +266,9 @@ void *QFontEngine::harfbuzzFont() const // same as QFixed(x)/QFixed(emSquare) but without int32 overflow for x hbFont->x_scale = (((qint64)hbFont->x_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare; hbFont->y_scale = (((qint64)hbFont->y_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare; + + font_ = (void *)hbFont; + font_destroy_func = free; } return font_; } diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 7b4925a9c8..cad9b02f41 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -46,8 +46,6 @@ #include "qfontengine_ft_p.h" #include "private/qimage_p.h" -#include - #ifndef QT_NO_FREETYPE #include "qfile.h" @@ -118,24 +116,6 @@ QT_BEGIN_NAMESPACE #define TRUNC(x) ((x) >> 6) #define ROUND(x) (((x)+32) & -64) -static HB_Error hb_getSFntTable(void *font, HB_Tag tableTag, HB_Byte *buffer, HB_UInt *length) -{ -#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) > 20103 - FT_Face face = (FT_Face)font; - FT_ULong ftlen = *length; - FT_Error error = 0; - - if ( !FT_IS_SFNT(face) ) - return HB_Err_Invalid_Argument; - - error = FT_Load_Sfnt_Table(face, tableTag, 0, buffer, &ftlen); - *length = ftlen; - return (HB_Error)error; -#else - return HB_Err_Invalid_Argument; -#endif -} - // -------------------------- Freetype support ------------------------------ class QtFreetypeData @@ -191,19 +171,19 @@ int QFreetypeFace::getPointInOutline(glyph_t glyph, int flags, quint32 point, QF return error; if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) - return HB_Err_Invalid_SubTable; + return Err_Invalid_SubTable; *nPoints = face->glyph->outline.n_points; if (!(*nPoints)) - return HB_Err_Ok; + return Err_Ok; if (point > *nPoints) - return HB_Err_Invalid_SubTable; + return Err_Invalid_SubTable; *xpos = QFixed::fromFixed(face->glyph->outline.points[point].x); *ypos = QFixed::fromFixed(face->glyph->outline.points[point].y); - return HB_Err_Ok; + return Err_Ok; } extern QByteArray qt_fontdata_from_index(int); @@ -260,11 +240,8 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, } newFreetype->face = face; - HB_Face hbFace = qHBNewFace(face, hb_getSFntTable); - Q_CHECK_PTR(hbFace); - if (hbFace->font_for_init != 0) - hbFace = qHBLoadFace(hbFace); - newFreetype->hbFace = (void *)hbFace; + newFreetype->hbFace = 0; + newFreetype->hbFace_destroy_func = 0; newFreetype->ref.store(1); newFreetype->xsize = 0; @@ -319,7 +296,10 @@ void QFreetypeFace::release(const QFontEngine::FaceId &face_id) { QtFreetypeData *freetypeData = qt_getFreetypeData(); if (!ref.deref()) { - qHBFreeFace((HB_Face)hbFace); + if (hbFace && hbFace_destroy_func) { + hbFace_destroy_func(hbFace); + hbFace = 0; + } FT_Done_Face(face); if(freetypeData->faces.contains(face_id)) freetypeData->faces.take(face_id); @@ -695,8 +675,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, if (FT_Get_PS_Font_Info(freetype->face, &psrec) == FT_Err_Ok) { symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive)); } - // ##### - ((HB_Face)freetype->hbFace)->isSymbolFont = symbol; lbearing = rbearing = SHRT_MIN; freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing); @@ -734,18 +712,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, if (line_thickness < 1) line_thickness = 1; - HB_FontRec *hbFont = (HB_FontRec *)font_; - hbFont->x_ppem = face->size->metrics.x_ppem; - hbFont->y_ppem = face->size->metrics.y_ppem; - hbFont->x_scale = face->size->metrics.x_scale; - hbFont->y_scale = face->size->metrics.y_scale; - - // ### - if (face_ && face_destroy_func) - face_destroy_func(face_); - face_ = freetype->hbFace; - face_destroy_func = 0; // we share the face in QFreeTypeFace, don't let ~QFontEngine delete it - metrics = face->size->metrics; /* @@ -773,6 +739,15 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, fontDef.styleName = QString::fromUtf8(face->style_name); + if (!freetype->hbFace) { + freetype->hbFace = harfbuzzFace(); + freetype->hbFace_destroy_func = face_destroy_func; + } else { + Q_ASSERT(!face_); + face_ = freetype->hbFace; + } + face_destroy_func = 0; // we share the HB face in QFreeTypeFace, so do not let ~QFontEngine() destroy it + unlockFace(); fsType = freetype->fsType(); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index bd4c855b91..e2e99893c8 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -99,7 +99,6 @@ struct QFreetypeFace } FT_Face face; - void *hbFace; int xsize; // 26.6 int ysize; // 26.6 FT_Matrix matrix; @@ -124,6 +123,9 @@ private: QAtomicInt ref; QMutex _lock; QByteArray fontData; + + void *hbFace; + qt_destroy_func_t hbFace_destroy_func; }; // If this is exported this breaks compilation of the windows diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 855f0099ff..4427000d03 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -75,6 +75,15 @@ struct QGlyphLayout; ((quint32)(ch4)) \ ) +// ### this only used in getPointInOutline(), refactor it and then remove these magic numbers +enum HB_Compat_Error { + Err_Ok = 0x0000, + Err_Not_Covered = 0xFFFF, + Err_Invalid_Argument = 0x1A66, + Err_Invalid_SubTable_Format = 0x157F, + Err_Invalid_SubTable = 0x1570 +}; + typedef void (*qt_destroy_func_t) (void *user_data); class Q_GUI_EXPORT QFontEngine : public QObject diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp index def671c62f..78bc3f871a 100644 --- a/src/gui/text/qfontengine_qpf.cpp +++ b/src/gui/text/qfontengine_qpf.cpp @@ -50,7 +50,6 @@ #include #if !defined(QT_NO_FREETYPE) #include "private/qfontengine_ft_p.h" -#include #endif #include "private/qcore_unix_p.h" // overrides QT_OPEN @@ -858,7 +857,7 @@ void QFontEngineQPF::doKerning(QGlyphLayout *g, QFontEngine::ShaperFlags flags) int QFontEngineQPF::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints) { if (!freetype) - return HB_Err_Not_Covered; + return Err_Not_Covered; lockFace(); int result = freetype->getPointInOutline(glyph, flags, point, xpos, ypos, nPoints); unlockFace();