diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 7c0492bb1a8bc94f0f4552641fe905d54682641d..96f7e06a471d462b95184ee2726f93bc0ec75c63 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -246,8 +246,8 @@ Q_AUTOTEST_EXPORT QList<QFontEngine *> QFontEngine_stopCollectingEngines() QFontEngine::QFontEngine(Type type) : m_type(type), ref(0), - font_(0), font_destroy_func(0), - face_(0), face_destroy_func(0), + font_(), + face_(), m_minLeftBearing(kBearingNotInitialized), m_minRightBearing(kBearingNotInitialized) { @@ -269,17 +269,6 @@ QFontEngine::QFontEngine(Type type) QFontEngine::~QFontEngine() { - m_glyphCaches.clear(); - - if (font_ && font_destroy_func) { - font_destroy_func(font_); - font_ = 0; - } - if (face_ && face_destroy_func) { - face_destroy_func(face_); - face_ = 0; - } - #ifdef QT_BUILD_INTERNAL if (enginesCollector) enginesCollector->removeOne(this); @@ -334,10 +323,9 @@ void *QFontEngine::harfbuzzFont() const 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; + font_ = Holder(hbFont, free); } - return font_; + return font_.get(); } void *QFontEngine::harfbuzzFace() const @@ -357,10 +345,9 @@ void *QFontEngine::harfbuzzFace() const Q_CHECK_PTR(hbFace); hbFace->isSymbolFont = symbol; - face_ = (void *)hbFace; - face_destroy_func = hb_freeFace; + face_ = Holder(hbFace, hb_freeFace); } - return face_; + return face_.get(); } bool QFontEngine::supportsScript(QChar::Script script) const diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 779333351f9002c5a93e8ccde9b257c0a0ab67f7..3207325755969cadf5acb6c2b2942c9ab2a7825a 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -246,9 +246,6 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, } newFreetype->face = face; - newFreetype->hbFace = 0; - newFreetype->hbFace_destroy_func = 0; - newFreetype->ref.store(1); newFreetype->xsize = 0; newFreetype->ysize = 0; @@ -300,10 +297,7 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id, void QFreetypeFace::cleanup() { - if (hbFace && hbFace_destroy_func) { - hbFace_destroy_func(hbFace); - hbFace = 0; - } + hbFace.reset(); FT_Done_Face(face); face = 0; } @@ -686,6 +680,8 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, return init(faceId, antialias, format, QFreetypeFace::getFace(faceId, fontData)); } +static void dont_delete(void*) {} + bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, QFreetypeFace *freetypeFace) { @@ -776,13 +772,13 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format, if (!freetype->hbFace) { faceData.user_data = face; faceData.get_font_table = ft_getSfntTable; - freetype->hbFace = harfbuzzFace(); - freetype->hbFace_destroy_func = face_destroy_func; + (void)harfbuzzFace(); // populates face_ + freetype->hbFace = std::move(face_); } 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 + // we share the HB face in QFreeTypeFace, so do not let ~QFontEngine() destroy it + face_ = Holder(freetype->hbFace.get(), dont_delete); unlockFace(); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 1886fc67bad8325ecba0cd133edc32d356bf7958..f9b37ff0392d2a0e60d43a5b7cbec53d83b960bf 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -121,8 +121,7 @@ private: QMutex _lock; QByteArray fontData; - void *hbFace; - qt_destroy_func_t hbFace_destroy_func; + QFontEngine::Holder hbFace; }; // 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 059b3df88ec0d44a310d3cd48a9ab05b59434eb5..1ef3a360d4c32d14f61b8512a9c2487e74b6131a 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -275,10 +275,45 @@ public: QAtomicInt ref; QFontDef fontDef; - mutable void *font_; - mutable qt_destroy_func_t font_destroy_func; - mutable void *face_; - mutable qt_destroy_func_t face_destroy_func; + class Holder { // replace by std::unique_ptr once available + void *ptr; + qt_destroy_func_t destroy_func; + public: + Holder() : ptr(nullptr), destroy_func(nullptr) {} + explicit Holder(void *p, qt_destroy_func_t d) : ptr(p), destroy_func(d) {} + ~Holder() { if (ptr && destroy_func) destroy_func(ptr); } + Holder(Holder &&other) Q_DECL_NOTHROW + : ptr(other.ptr), + destroy_func(other.destroy_func) + { + other.ptr = nullptr; + other.destroy_func = nullptr; + } + Holder &operator=(Holder &&other) Q_DECL_NOTHROW + { swap(other); return *this; } + + void swap(Holder &other) Q_DECL_NOTHROW + { + qSwap(ptr, other.ptr); + qSwap(destroy_func, other.destroy_func); + } + + void *get() const Q_DECL_NOTHROW { return ptr; } + void *release() Q_DECL_NOTHROW { + void *result = ptr; + ptr = nullptr; + destroy_func = nullptr; + return result; + } + void reset() Q_DECL_NOTHROW { Holder().swap(*this); } + qt_destroy_func_t get_deleter() const Q_DECL_NOTHROW { return destroy_func; } + + bool operator!() const Q_DECL_NOTHROW { return !ptr; } + }; + + mutable Holder font_; // \ NOTE: Declared before m_glyphCaches, so font_, face_ + mutable Holder face_; // / are destroyed _after_ m_glyphCaches is destroyed. + struct FaceData { void *user_data; qt_get_font_table_func_t get_font_table; diff --git a/src/gui/text/qharfbuzzng.cpp b/src/gui/text/qharfbuzzng.cpp index e33b46140170c696614395ffe3c59337247cd56f..55ef9f0d15c076ac242024b5c6763a1a47832872 100644 --- a/src/gui/text/qharfbuzzng.cpp +++ b/src/gui/text/qharfbuzzng.cpp @@ -678,14 +678,10 @@ hb_face_t *hb_qt_face_get_for_engine(QFontEngine *fe) { Q_ASSERT(fe && fe->type() != QFontEngine::Multi); - if (Q_UNLIKELY(!fe->face_)) { - fe->face_ = _hb_qt_face_create(fe); - if (Q_UNLIKELY(!fe->face_)) - return NULL; - fe->face_destroy_func = _hb_qt_face_release; - } + if (Q_UNLIKELY(!fe->face_)) + fe->face_ = QFontEngine::Holder(_hb_qt_face_create(fe), _hb_qt_face_release); - return static_cast<hb_face_t *>(fe->face_); + return static_cast<hb_face_t *>(fe->face_.get()); } @@ -728,14 +724,10 @@ hb_font_t *hb_qt_font_get_for_engine(QFontEngine *fe) { Q_ASSERT(fe && fe->type() != QFontEngine::Multi); - if (Q_UNLIKELY(!fe->font_)) { - fe->font_ = _hb_qt_font_create(fe); - if (Q_UNLIKELY(!fe->font_)) - return NULL; - fe->font_destroy_func = _hb_qt_font_release; - } + if (Q_UNLIKELY(!fe->font_)) + fe->font_ = QFontEngine::Holder(_hb_qt_font_create(fe), _hb_qt_font_release); - return static_cast<hb_font_t *>(fe->font_); + return static_cast<hb_font_t *>(fe->font_.get()); } QT_END_NAMESPACE