do not share the freetype2 library instance

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2021-12-24 13:47:51 +02:00
parent 56ed1cddd5
commit 6e507c1a74
4 changed files with 112 additions and 206 deletions

View file

@ -1079,8 +1079,8 @@ static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id,
if (data.isEmpty()) if (data.isEmpty())
return FcFreeTypeQuery(file, id, blanks, count); return FcFreeTypeQuery(file, id, blanks, count);
extern FT_Library qt_getFreetype(); FT_Library lib;
FT_Library lib = qt_getFreetype(); FT_Init_FreeType(&lib);
FcPattern *pattern = nullptr; FcPattern *pattern = nullptr;
@ -1092,6 +1092,7 @@ static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id,
FT_Done_Face(face); FT_Done_Face(face);
} }
FT_Done_FreeType(lib);
return pattern; return pattern;
} }

View file

@ -68,32 +68,89 @@ QT_BEGIN_NAMESPACE
// -------------------------- Freetype support ------------------------------ // -------------------------- Freetype support ------------------------------
class QtFreetypeData QFreetypeFace::QFreetypeFace(const QFontEngine::FaceId &face_id)
: face(nullptr),
xsize(0),
ysize(0),
unicode_map(nullptr),
symbol_map(nullptr),
library(nullptr)
{ {
public:
QtFreetypeData()
: library(0)
{ }
FT_Library library; matrix.xx = 0x10000;
QHash<QFontEngine::FaceId, QFreetypeFace *> faces; matrix.yy = 0x10000;
}; matrix.xy = 0;
matrix.yx = 0;
::memset(cmapCache, 0, sizeof(cmapCache));
QTHREADLOCAL(QtFreetypeData, theFreetypeData); FT_Init_FreeType(&library);
QtFreetypeData *qt_getFreetypeData() if (face_id.filename.isEmpty())
{ return;
if (!theFreetypeData)
theFreetypeData = new QtFreetypeData; if (!face_id.filename.isEmpty()) {
return theFreetypeData; QFile file(QString::fromUtf8(face_id.filename));
if (face_id.filename.startsWith(":qmemoryfonts/")) {
// from qfontdatabase.cpp
extern QByteArray qt_fontdata_from_index(int);
QByteArray idx = face_id.filename;
idx.remove(0, 14); // remove ':qmemoryfonts/'
bool ok = false;
fontData = qt_fontdata_from_index(idx.toInt(&ok));
if (!ok)
fontData = QByteArray();
} else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
if (!file.open(QIODevice::ReadOnly)) {
return;
}
fontData = file.readAll();
}
}
if (!fontData.isEmpty()) {
if (FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), face_id.index, &face)) {
return;
}
} else if (FT_New_Face(library, face_id.filename, face_id.index, &face)) {
return;
}
for (int i = 0; i < face->num_charmaps; ++i) {
FT_CharMap cm = face->charmaps[i];
switch(cm->encoding) {
case FT_ENCODING_UNICODE: {
unicode_map = cm;
break;
}
case FT_ENCODING_APPLE_ROMAN:
case FT_ENCODING_ADOBE_LATIN_1: {
if (!unicode_map || unicode_map->encoding != FT_ENCODING_UNICODE)
unicode_map = cm;
break;
}
case FT_ENCODING_ADOBE_CUSTOM:
case FT_ENCODING_MS_SYMBOL: {
if (!symbol_map)
symbol_map = cm;
break;
}
default: {
break;
}
}
}
if (!FT_IS_SCALABLE(face) && face->num_fixed_sizes == 1) {
FT_Set_Char_Size (face, face->available_sizes[0].x_ppem,
face->available_sizes[0].y_ppem, 0, 0);
}
FT_Set_Charmap(face, unicode_map);
} }
FT_Library qt_getFreetype() QFreetypeFace::~QFreetypeFace()
{ {
QtFreetypeData *freetypeData = qt_getFreetypeData(); FT_Done_Face(face);
if (!freetypeData->library) FT_Done_FreeType(library);
FT_Init_FreeType(&freetypeData->library);
return freetypeData->library;
} }
int QFreetypeFace::fsType() const int QFreetypeFace::fsType() const
@ -126,114 +183,6 @@ HB_Error QFreetypeFace::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 p
return HB_Err_Ok; return HB_Err_Ok;
} }
/*
* One font file can contain more than one font (bold/italic for example)
* find the right one and return it.
*
* Returns the freetype face or 0 in case of an empty file or any other problems
* (like not being able to open the file)
*/
QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id)
{
if (face_id.filename.isEmpty())
return 0;
QtFreetypeData *freetypeData = qt_getFreetypeData();
if (!freetypeData->library)
FT_Init_FreeType(&freetypeData->library);
QFreetypeFace *freetype = freetypeData->faces.value(face_id, 0);
if (freetype) {
freetype->ref.ref();
} else {
QScopedPointer<QFreetypeFace> newFreetype(new QFreetypeFace);
FT_Face face;
if (!face_id.filename.isEmpty()) {
QFile file(QString::fromUtf8(face_id.filename));
if (face_id.filename.startsWith(":qmemoryfonts/")) {
// from qfontdatabase.cpp
extern QByteArray qt_fontdata_from_index(int);
QByteArray idx = face_id.filename;
idx.remove(0, 14); // remove ':qmemoryfonts/'
bool ok = false;
newFreetype->fontData = qt_fontdata_from_index(idx.toInt(&ok));
if (!ok)
newFreetype->fontData = QByteArray();
} else if (!(file.fileEngine()->fileFlags(QAbstractFileEngine::FlagsMask) & QAbstractFileEngine::LocalDiskFlag)) {
if (!file.open(QIODevice::ReadOnly)) {
return 0;
}
newFreetype->fontData = file.readAll();
}
}
if (!newFreetype->fontData.isEmpty()) {
if (FT_New_Memory_Face(freetypeData->library, (const FT_Byte *)newFreetype->fontData.constData(), newFreetype->fontData.size(), face_id.index, &face)) {
return 0;
}
} else if (FT_New_Face(freetypeData->library, face_id.filename, face_id.index, &face)) {
return 0;
}
newFreetype->face = face;
newFreetype->ref = 1;
newFreetype->xsize = 0;
newFreetype->ysize = 0;
newFreetype->matrix.xx = 0x10000;
newFreetype->matrix.yy = 0x10000;
newFreetype->matrix.xy = 0;
newFreetype->matrix.yx = 0;
newFreetype->unicode_map = 0;
newFreetype->symbol_map = 0;
memset(newFreetype->cmapCache, 0, sizeof(newFreetype->cmapCache));
for (int i = 0; i < newFreetype->face->num_charmaps; ++i) {
FT_CharMap cm = newFreetype->face->charmaps[i];
switch(cm->encoding) {
case FT_ENCODING_UNICODE:
newFreetype->unicode_map = cm;
break;
case FT_ENCODING_APPLE_ROMAN:
case FT_ENCODING_ADOBE_LATIN_1:
if (!newFreetype->unicode_map || newFreetype->unicode_map->encoding != FT_ENCODING_UNICODE)
newFreetype->unicode_map = cm;
break;
case FT_ENCODING_ADOBE_CUSTOM:
case FT_ENCODING_MS_SYMBOL:
if (!newFreetype->symbol_map)
newFreetype->symbol_map = cm;
break;
default:
break;
}
}
if (!FT_IS_SCALABLE(newFreetype->face) && newFreetype->face->num_fixed_sizes == 1)
FT_Set_Char_Size (face, newFreetype->face->available_sizes[0].x_ppem,
newFreetype->face->available_sizes[0].y_ppem, 0, 0);
FT_Set_Charmap(newFreetype->face, newFreetype->unicode_map);
freetypeData->faces.insert(face_id, newFreetype.data());
freetype = newFreetype.take();
}
return freetype;
}
void QFreetypeFace::release(const QFontEngine::FaceId &face_id)
{
QtFreetypeData *freetypeData = qt_getFreetypeData();
if (!ref.deref()) {
FT_Done_Face(face);
if(freetypeData->faces.contains(face_id))
freetypeData->faces.take(face_id);
delete this;
}
if (freetypeData->faces.isEmpty()) {
FT_Done_FreeType(freetypeData->library);
freetypeData->library = 0;
}
}
void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing) void QFreetypeFace::computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing)
{ {
*ysize = qRound(fontDef.pixelSize * 64); *ysize = qRound(fontDef.pixelSize * 64);
@ -529,14 +478,13 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd)
QFontEngineFT::~QFontEngineFT() QFontEngineFT::~QFontEngineFT()
{ {
if (freetype) delete freetype;
freetype->release(face_id);
} }
bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
{ {
freetype = QFreetypeFace::getFace(faceId); freetype = new QFreetypeFace(faceId);
if (!freetype) { if (!freetype->face) {
xsize = 0; xsize = 0;
ysize = 0; ysize = 0;
return false; return false;
@ -556,7 +504,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
lbearing = rbearing = SHRT_MIN; lbearing = rbearing = SHRT_MIN;
freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing); freetype->computeSize(fontDef, &xsize, &ysize, &defaultGlyphSet.outline_drawing);
FT_Face face = lockFace(); FT_Face face = getFace();
if (FT_IS_SCALABLE(face)) { if (FT_IS_SCALABLE(face)) {
bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC); bool fake_oblique = (fontDef.style != QFont::StyleNormal) && !(face->style_flags & FT_STYLE_FLAG_ITALIC);
@ -593,7 +541,6 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format)
fsType = freetype->fsType(); fsType = freetype->fsType();
unlockFace();
return true; return true;
} }
@ -693,7 +640,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
FT_GlyphSlot slot = face->glyph; FT_GlyphSlot slot = face->glyph;
if (embolden) FT_GlyphSlot_Embolden(slot); if (embolden) FT_GlyphSlot_Embolden(slot);
FT_Library library = qt_getFreetype(); FT_Library library = freetype->library;
info.xOff = TRUNC(ROUND(slot->advance.x)); info.xOff = TRUNC(ROUND(slot->advance.x));
info.yOff = 0; info.yOff = 0;
@ -935,10 +882,10 @@ QFontEngine::Properties QFontEngineFT::properties() const
QFixed QFontEngineFT::emSquareSize() const QFixed QFontEngineFT::emSquareSize() const
{ {
if (FT_IS_SCALABLE(freetype->face)) if (FT_IS_SCALABLE(freetype->face)) {
return freetype->face->units_per_EM; return freetype->face->units_per_EM;
else }
return freetype->face->size->metrics.y_ppem; return freetype->face->size->metrics.y_ppem;
} }
bool QFontEngineFT::getSfntTableData(uint tag, uchar *buffer, uint *length) const bool QFontEngineFT::getSfntTableData(uint tag, uchar *buffer, uint *length) const
@ -986,10 +933,8 @@ QFixed QFontEngineFT::xHeight() const
{ {
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
if (os2 && os2->sxHeight) { if (os2 && os2->sxHeight) {
lockFace(); getFace();
QFixed answer = QFixed(os2->sxHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM; return QFixed(os2->sxHeight*freetype->face->size->metrics.y_ppem)/freetype->face->units_per_EM;
unlockFace();
return answer;
} }
return QFontEngine::xHeight(); return QFontEngine::xHeight();
} }
@ -998,10 +943,8 @@ QFixed QFontEngineFT::averageCharWidth() const
{ {
TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2); TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(freetype->face, ft_sfnt_os2);
if (os2 && os2->xAvgCharWidth) { if (os2 && os2->xAvgCharWidth) {
lockFace(); getFace();
QFixed answer = QFixed(os2->xAvgCharWidth*freetype->face->size->metrics.x_ppem)/freetype->face->units_per_EM; return QFixed(os2->xAvgCharWidth*freetype->face->size->metrics.x_ppem)/freetype->face->units_per_EM;
unlockFace();
return answer;
} }
return QFontEngine::averageCharWidth(); return QFontEngine::averageCharWidth();
} }
@ -1075,19 +1018,18 @@ void QFontEngineFT::doKerning(QGlyphLayout *g, QTextEngine::ShaperFlags flags)
{ {
if (!kerning_pairs_loaded) { if (!kerning_pairs_loaded) {
kerning_pairs_loaded = true; kerning_pairs_loaded = true;
lockFace(); getFace();
if (freetype->face->size->metrics.x_ppem != 0) { if (freetype->face->size->metrics.x_ppem != 0) {
QFixed scalingFactor(freetype->face->units_per_EM/freetype->face->size->metrics.x_ppem); QFixed scalingFactor(freetype->face->units_per_EM/freetype->face->size->metrics.x_ppem);
loadKerningPairs(scalingFactor); loadKerningPairs(scalingFactor);
} }
unlockFace();
} }
QFontEngine::doKerning(g, flags); QFontEngine::doKerning(g, flags);
} }
void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics) void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
{ {
FT_Face face = lockFace(Unscaled); FT_Face face = getFace(Unscaled);
FT_Set_Transform(face, 0, 0); FT_Set_Transform(face, 0, 0);
FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP); FT_Load_Glyph(face, glyph, FT_LOAD_NO_BITMAP);
@ -1112,7 +1054,6 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me
QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6); QFreetypeFace::addGlyphToPath(face, face->glyph, p, path, face->units_per_EM << 6, face->units_per_EM << 6);
FT_Set_Transform(face, &freetype->matrix, 0); FT_Set_Transform(face, &freetype->matrix, 0);
unlockFace();
} }
static inline unsigned int getChar(const QChar *str, int &i, const int len) static inline unsigned int getChar(const QChar *str, int &i, const int len)
@ -1149,20 +1090,19 @@ void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyph
const QTransform matrix = QTransform::fromTranslate(x, y); const QTransform matrix = QTransform::fromTranslate(x, y);
getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions); getGlyphPositions(glyphs, matrix, flags, positioned_glyphs, positions);
FT_Face face = lockFace(Unscaled); FT_Face face = getFace(Unscaled);
for (int gl = 0; gl < glyphs.numGlyphs; gl++) { for (int gl = 0; gl < glyphs.numGlyphs; gl++) {
FT_UInt glyph = positioned_glyphs[gl]; FT_UInt glyph = positioned_glyphs[gl];
FT_Load_Glyph(face, glyph, FT_LOAD_TARGET_MONO); FT_Load_Glyph(face, glyph, FT_LOAD_TARGET_MONO);
freetype->addBitmapToPath(face->glyph, positions[gl], path); freetype->addBitmapToPath(face->glyph, positions[gl], path);
} }
unlockFace();
} }
} }
void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs, void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int numGlyphs,
QPainterPath *path, QTextItem::RenderFlags) QPainterPath *path, QTextItem::RenderFlags)
{ {
FT_Face face = lockFace(Unscaled); FT_Face face = getFace(Unscaled);
for (int gl = 0; gl < numGlyphs; gl++) { for (int gl = 0; gl < numGlyphs; gl++) {
FT_UInt glyph = glyphs[gl]; FT_UInt glyph = glyphs[gl];
@ -1174,7 +1114,6 @@ void QFontEngineFT::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int
continue; continue;
QFreetypeFace::addGlyphToPath(face, g, positions[gl], path, xsize, ysize); QFreetypeFace::addGlyphToPath(face, g, positions[gl], path, xsize, ysize);
} }
unlockFace();
} }
bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
@ -1234,10 +1173,10 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags flags) const
{ {
FT_Face face = 0; FT_Face face = getFace();
bool design = (default_hint_style == HintNone || bool design = (default_hint_style == HintNone ||
default_hint_style == HintLight || default_hint_style == HintLight ||
(flags & HB_ShaperFlag_UseDesignMetrics)) && FT_IS_SCALABLE(freetype->face); (flags & HB_ShaperFlag_UseDesignMetrics)) && FT_IS_SCALABLE(face);
for (int i = 0; i < glyphs->numGlyphs; i++) { for (int i = 0; i < glyphs->numGlyphs; i++) {
Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]); Glyph *g = defaultGlyphSet.getGlyph(glyphs->glyphs[i]);
// Since we are passing Format_None to loadGlyph, use same default format logic as loadGlyph // Since we are passing Format_None to loadGlyph, use same default format logic as loadGlyph
@ -1245,8 +1184,6 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
if (g && g->format == acceptableFormat) { if (g && g->format == acceptableFormat) {
glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance); glyphs->advances_x[i] = design ? QFixed::fromFixed(g->linearAdvance) : QFixed(g->advance);
} else { } else {
if (!face)
face = lockFace();
g = loadGlyph(glyphs->glyphs[i], Format_None, true); g = loadGlyph(glyphs->glyphs[i], Format_None, true);
glyphs->advances_x[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10) glyphs->advances_x[i] = design ? QFixed::fromFixed(face->glyph->linearHoriAdvance >> 10)
: QFixed::fromFixed(face->glyph->metrics.horiAdvance).round(); : QFixed::fromFixed(face->glyph->metrics.horiAdvance).round();
@ -1255,14 +1192,12 @@ void QFontEngineFT::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlag
glyphs->advances_x[i] = glyphs->advances_x[i].round(); glyphs->advances_x[i] = glyphs->advances_x[i].round();
glyphs->advances_y[i] = 0; glyphs->advances_y[i] = 0;
} }
if (face)
unlockFace();
} }
glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) const glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) const
{ {
FT_Face face = 0; FT_Face face = getFace();
glyph_metrics_t overall; glyph_metrics_t overall;
// initialize with line height, we get the same behaviour on all platforms // initialize with line height, we get the same behaviour on all platforms
@ -1274,8 +1209,6 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) const
for (int i = 0; i < glyphs.numGlyphs; i++) { for (int i = 0; i < glyphs.numGlyphs; i++) {
Glyph *g = defaultGlyphSet.getGlyph(glyphs.glyphs[i]); Glyph *g = defaultGlyphSet.getGlyph(glyphs.glyphs[i]);
if (!g) { if (!g) {
if (!face)
face = lockFace();
g = loadGlyph(glyphs.glyphs[i], Format_None, true); g = loadGlyph(glyphs.glyphs[i], Format_None, true);
} }
if (g) { if (g) {
@ -1304,19 +1237,15 @@ glyph_metrics_t QFontEngineFT::boundingBox(const QGlyphLayout &glyphs) const
overall.height = qMax(overall.height, ymax - overall.y); overall.height = qMax(overall.height, ymax - overall.y);
overall.width = xmax - overall.x; overall.width = xmax - overall.x;
if (face)
unlockFace();
return overall; return overall;
} }
glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) const glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) const
{ {
FT_Face face = 0; FT_Face face = getFace();
glyph_metrics_t overall; glyph_metrics_t overall;
Glyph *g = defaultGlyphSet.getGlyph(glyph); Glyph *g = defaultGlyphSet.getGlyph(glyph);
if (!g) { if (!g) {
face = lockFace();
g = loadGlyph(glyph, Format_None, true); g = loadGlyph(glyph, Format_None, true);
} }
if (g) { if (g) {
@ -1339,20 +1268,17 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph) const
overall.y = -TRUNC(top); overall.y = -TRUNC(top);
overall.xoff = TRUNC(ROUND(face->glyph->advance.x)); overall.xoff = TRUNC(ROUND(face->glyph->advance.x));
} }
if (face)
unlockFace();
return overall; return overall;
} }
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g) QImage QFontEngineFT::alphaMapForGlyph(glyph_t g)
{ {
lockFace(); getFace();
GlyphFormat glyph_format = antialias ? Format_A32 : Format_Mono; GlyphFormat glyph_format = antialias ? Format_A32 : Format_Mono;
Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format); Glyph *glyph = defaultGlyphSet.outline_drawing ? 0 : loadGlyph(g, glyph_format);
if (!glyph) { if (!glyph) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g); return QFontEngine::alphaMapForGlyph(g);
} }
@ -1368,7 +1294,6 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g)
for (int y = 0; y < glyph->height; ++y) for (int y = 0; y < glyph->height; ++y)
memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch); memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch);
} }
unlockFace();
return img; return img;
} }
@ -1376,17 +1301,15 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g)
int QFontEngineFT::glyphCount() const int QFontEngineFT::glyphCount() const
{ {
int count = 0; int count = 0;
FT_Face face = lockFace(); FT_Face face = getFace();
if (face) { if (face) {
count = face->num_glyphs; count = face->num_glyphs;
} }
unlockFace();
return count; return count;
} }
FT_Face QFontEngineFT::lockFace(Scaling scale) const FT_Face QFontEngineFT::getFace(Scaling scale) const
{ {
freetype->lock();
FT_Face face = freetype->face; FT_Face face = freetype->face;
if (scale == Unscaled) { if (scale == Unscaled) {
FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0); FT_Set_Char_Size(face, face->units_per_EM << 6, face->units_per_EM << 6, 0, 0);
@ -1408,10 +1331,6 @@ FT_Face QFontEngineFT::lockFace(Scaling scale) const
return face; return face;
} }
void QFontEngineFT::unlockFace() const
{
freetype->unlock();
}
FT_Face QFontEngineFT::non_locked_face() const FT_Face QFontEngineFT::non_locked_face() const
{ {
@ -1459,12 +1378,11 @@ void QFontEngineFT::QGlyphSet::setGlyph(glyph_t index, Glyph *glyph)
HB_Error QFontEngineFT::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints) HB_Error QFontEngineFT::getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints)
{ {
lockFace(); getFace();
bool hsubpixel = true; bool hsubpixel = true;
int vfactor = 1; int vfactor = 1;
int load_flags = loadFlags(0, Format_A32, flags, hsubpixel, vfactor); int load_flags = loadFlags(0, Format_A32, flags, hsubpixel, vfactor);
HB_Error result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints); HB_Error result = freetype->getPointInOutline(glyph, load_flags, point, xpos, ypos, nPoints);
unlockFace();
return result; return result;
} }

View file

@ -58,22 +58,12 @@ QT_BEGIN_NAMESPACE
class QFreetypeFace class QFreetypeFace
{ {
public: public:
QFreetypeFace(const QFontEngine::FaceId &face_id);
~QFreetypeFace();
void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing); void computeSize(const QFontDef &fontDef, int *xsize, int *ysize, bool *outline_drawing);
QFontEngine::Properties properties() const; QFontEngine::Properties properties() const;
static QFreetypeFace *getFace(const QFontEngine::FaceId &face_id);
void release(const QFontEngine::FaceId &face_id);
// locks the struct for usage. Any read/write operations require locking.
void lock()
{
_lock.lock();
}
void unlock()
{
_lock.unlock();
}
FT_Face face; FT_Face face;
int xsize; // 26.6 int xsize; // 26.6
int ysize; // 26.6 int ysize; // 26.6
@ -92,12 +82,12 @@ public:
static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path); static void addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, QPainterPath *path);
private: private:
Q_DISABLE_COPY(QFreetypeFace);
friend class QFontEngineFT; friend class QFontEngineFT;
friend class QScopedPointerDeleter<QFreetypeFace>;
QFreetypeFace() {} FT_Library library;
~QFreetypeFace() {}
QAtomicInt ref;
std::recursive_mutex _lock;
QByteArray fontData; QByteArray fontData;
}; };
@ -209,8 +199,7 @@ private:
Scaled, Scaled,
Unscaled Unscaled
}; };
FT_Face lockFace(Scaling scale = Scaled) const; FT_Face getFace(Scaling scale = Scaled) const;
void unlockFace() const;
FT_Face non_locked_face() const; FT_Face non_locked_face() const;

View file

@ -37,8 +37,6 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QFreetypeFace;
#ifndef QT_NO_FONTCONFIG #ifndef QT_NO_FONTCONFIG
class Q_GUI_EXPORT QFontEngineMultiFT : public QFontEngineMulti class Q_GUI_EXPORT QFontEngineMultiFT : public QFontEngineMulti