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(xpos)
|
||||||
Q_UNUSED(ypos)
|
Q_UNUSED(ypos)
|
||||||
Q_UNUSED(nPoints)
|
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)
|
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;
|
fsType = 0;
|
||||||
symbol = false;
|
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;
|
glyphFormat = -1;
|
||||||
m_subPixelPositionCount = 0;
|
m_subPixelPositionCount = 0;
|
||||||
|
|
||||||
@ -262,8 +251,12 @@ QFixed QFontEngine::underlinePosition() const
|
|||||||
|
|
||||||
void *QFontEngine::harfbuzzFont() const
|
void *QFontEngine::harfbuzzFont() const
|
||||||
{
|
{
|
||||||
HB_FontRec *hbFont = (HB_FontRec *)font_;
|
if (!font_) {
|
||||||
if (!hbFont->x_ppem) {
|
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();
|
qint64 emSquare = emSquareSize().truncate();
|
||||||
Q_ASSERT(emSquare == emSquareSize().toInt()); // ensure no truncation
|
Q_ASSERT(emSquare == emSquareSize().toInt()); // ensure no truncation
|
||||||
if (emSquare == 0)
|
if (emSquare == 0)
|
||||||
@ -273,6 +266,9 @@ void *QFontEngine::harfbuzzFont() const
|
|||||||
// same as QFixed(x)/QFixed(emSquare) but without int32 overflow for x
|
// 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->x_scale = (((qint64)hbFont->x_ppem << 6) * 0x10000L + (emSquare >> 1)) / emSquare;
|
||||||
hbFont->y_scale = (((qint64)hbFont->y_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_;
|
return font_;
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,6 @@
|
|||||||
#include "qfontengine_ft_p.h"
|
#include "qfontengine_ft_p.h"
|
||||||
#include "private/qimage_p.h"
|
#include "private/qimage_p.h"
|
||||||
|
|
||||||
#include <private/qharfbuzz_p.h>
|
|
||||||
|
|
||||||
#ifndef QT_NO_FREETYPE
|
#ifndef QT_NO_FREETYPE
|
||||||
|
|
||||||
#include "qfile.h"
|
#include "qfile.h"
|
||||||
@ -118,24 +116,6 @@ QT_BEGIN_NAMESPACE
|
|||||||
#define TRUNC(x) ((x) >> 6)
|
#define TRUNC(x) ((x) >> 6)
|
||||||
#define ROUND(x) (((x)+32) & -64)
|
#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 ------------------------------
|
// -------------------------- Freetype support ------------------------------
|
||||||
|
|
||||||
class QtFreetypeData
|
class QtFreetypeData
|
||||||
@ -191,19 +171,19 @@ int QFreetypeFace::getPointInOutline(glyph_t glyph, int flags, quint32 point, QF
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||||
return HB_Err_Invalid_SubTable;
|
return Err_Invalid_SubTable;
|
||||||
|
|
||||||
*nPoints = face->glyph->outline.n_points;
|
*nPoints = face->glyph->outline.n_points;
|
||||||
if (!(*nPoints))
|
if (!(*nPoints))
|
||||||
return HB_Err_Ok;
|
return Err_Ok;
|
||||||
|
|
||||||
if (point > *nPoints)
|
if (point > *nPoints)
|
||||||
return HB_Err_Invalid_SubTable;
|
return Err_Invalid_SubTable;
|
||||||
|
|
||||||
*xpos = QFixed::fromFixed(face->glyph->outline.points[point].x);
|
*xpos = QFixed::fromFixed(face->glyph->outline.points[point].x);
|
||||||
*ypos = QFixed::fromFixed(face->glyph->outline.points[point].y);
|
*ypos = QFixed::fromFixed(face->glyph->outline.points[point].y);
|
||||||
|
|
||||||
return HB_Err_Ok;
|
return Err_Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern QByteArray qt_fontdata_from_index(int);
|
extern QByteArray qt_fontdata_from_index(int);
|
||||||
@ -260,11 +240,8 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
|
|||||||
}
|
}
|
||||||
newFreetype->face = face;
|
newFreetype->face = face;
|
||||||
|
|
||||||
HB_Face hbFace = qHBNewFace(face, hb_getSFntTable);
|
newFreetype->hbFace = 0;
|
||||||
Q_CHECK_PTR(hbFace);
|
newFreetype->hbFace_destroy_func = 0;
|
||||||
if (hbFace->font_for_init != 0)
|
|
||||||
hbFace = qHBLoadFace(hbFace);
|
|
||||||
newFreetype->hbFace = (void *)hbFace;
|
|
||||||
|
|
||||||
newFreetype->ref.store(1);
|
newFreetype->ref.store(1);
|
||||||
newFreetype->xsize = 0;
|
newFreetype->xsize = 0;
|
||||||
@ -319,7 +296,10 @@ void QFreetypeFace::release(const QFontEngine::FaceId &face_id)
|
|||||||
{
|
{
|
||||||
QtFreetypeData *freetypeData = qt_getFreetypeData();
|
QtFreetypeData *freetypeData = qt_getFreetypeData();
|
||||||
if (!ref.deref()) {
|
if (!ref.deref()) {
|
||||||
qHBFreeFace((HB_Face)hbFace);
|
if (hbFace && hbFace_destroy_func) {
|
||||||
|
hbFace_destroy_func(hbFace);
|
||||||
|
hbFace = 0;
|
||||||
|
}
|
||||||
FT_Done_Face(face);
|
FT_Done_Face(face);
|
||||||
if(freetypeData->faces.contains(face_id))
|
if(freetypeData->faces.contains(face_id))
|
||||||
freetypeData->faces.take(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) {
|
if (FT_Get_PS_Font_Info(freetype->face, &psrec) == FT_Err_Ok) {
|
||||||
symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive));
|
symbol = bool(fontDef.family.contains(QLatin1String("symbol"), Qt::CaseInsensitive));
|
||||||
}
|
}
|
||||||
// #####
|
|
||||||
((HB_Face)freetype->hbFace)->isSymbolFont = symbol;
|
|
||||||
|
|
||||||
lbearing = rbearing = SHRT_MIN;
|
lbearing = rbearing = SHRT_MIN;
|
||||||
freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing);
|
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)
|
if (line_thickness < 1)
|
||||||
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;
|
metrics = face->size->metrics;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -773,6 +739,15 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format,
|
|||||||
|
|
||||||
fontDef.styleName = QString::fromUtf8(face->style_name);
|
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();
|
unlockFace();
|
||||||
|
|
||||||
fsType = freetype->fsType();
|
fsType = freetype->fsType();
|
||||||
|
@ -99,7 +99,6 @@ struct QFreetypeFace
|
|||||||
}
|
}
|
||||||
|
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
void *hbFace;
|
|
||||||
int xsize; // 26.6
|
int xsize; // 26.6
|
||||||
int ysize; // 26.6
|
int ysize; // 26.6
|
||||||
FT_Matrix matrix;
|
FT_Matrix matrix;
|
||||||
@ -124,6 +123,9 @@ private:
|
|||||||
QAtomicInt ref;
|
QAtomicInt ref;
|
||||||
QMutex _lock;
|
QMutex _lock;
|
||||||
QByteArray fontData;
|
QByteArray fontData;
|
||||||
|
|
||||||
|
void *hbFace;
|
||||||
|
qt_destroy_func_t hbFace_destroy_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
// If this is exported this breaks compilation of the windows
|
// If this is exported this breaks compilation of the windows
|
||||||
|
@ -75,6 +75,15 @@ struct QGlyphLayout;
|
|||||||
((quint32)(ch4)) \
|
((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);
|
typedef void (*qt_destroy_func_t) (void *user_data);
|
||||||
|
|
||||||
class Q_GUI_EXPORT QFontEngine : public QObject
|
class Q_GUI_EXPORT QFontEngine : public QObject
|
||||||
|
@ -50,7 +50,6 @@
|
|||||||
#include <QtCore/qbuffer.h>
|
#include <QtCore/qbuffer.h>
|
||||||
#if !defined(QT_NO_FREETYPE)
|
#if !defined(QT_NO_FREETYPE)
|
||||||
#include "private/qfontengine_ft_p.h"
|
#include "private/qfontengine_ft_p.h"
|
||||||
#include <private/qharfbuzz_p.h>
|
|
||||||
#endif
|
#endif
|
||||||
#include "private/qcore_unix_p.h" // overrides QT_OPEN
|
#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)
|
int QFontEngineQPF::getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints)
|
||||||
{
|
{
|
||||||
if (!freetype)
|
if (!freetype)
|
||||||
return HB_Err_Not_Covered;
|
return Err_Not_Covered;
|
||||||
lockFace();
|
lockFace();
|
||||||
int result = freetype->getPointInOutline(glyph, flags, point, xpos, ypos, nPoints);
|
int result = freetype->getPointInOutline(glyph, flags, point, xpos, ypos, nPoints);
|
||||||
unlockFace();
|
unlockFace();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user