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:
Konstantin Ritt 2013-08-10 20:05:36 +03:00 committed by The Qt Project
parent cbb4a88262
commit 227e9a40cf
5 changed files with 42 additions and 61 deletions

View File

@ -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_;
}

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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();