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 <eskil.abrahamsen-blomfeldt@digia.com>
This commit is contained in:
parent
cbb4a88262
commit
227e9a40cf
@ -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<QFontEngine *>(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_;
|
||||
}
|
||||
|
@ -46,8 +46,6 @@
|
||||
#include "qfontengine_ft_p.h"
|
||||
#include "private/qimage_p.h"
|
||||
|
||||
#include <private/qharfbuzz_p.h>
|
||||
|
||||
#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();
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -50,7 +50,6 @@
|
||||
#include <QtCore/qbuffer.h>
|
||||
#if !defined(QT_NO_FREETYPE)
|
||||
#include "private/qfontengine_ft_p.h"
|
||||
#include <private/qharfbuzz_p.h>
|
||||
#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();
|
||||
|
Loading…
Reference in New Issue
Block a user