Fix bundled HarfBuzz-NG build outside QtGui
On Mac, hb_coretext requires both CTFont and CGFont. Due to not supporting the 0 tag by CoreText, hb_blob_get_data() always fails causing the hb_coretext_shaper initialization to fail, too. Since HarfBuzz-NG is not a part of QtGui module anymore, there are two possibilities to workaround this: either engineer the font data by querying tables one-by-one and generating the font directory table, or pass CTFont and CGFont refs directly to hb_coretext via the hb_face's user_data. This patch implements the latter. Change-Id: I7d2e2df00818ea811642cb6a6c3b9c9abd5d7b94 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
0d50efeae9
commit
c6b555dac3
46
src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
vendored
46
src/3rdparty/harfbuzz-ng/src/hb-coretext.cc
vendored
@ -32,7 +32,6 @@
|
||||
#include "hb-coretext.h"
|
||||
|
||||
#include "hb-face-private.hh"
|
||||
#include <private/qfontengine_p.h>
|
||||
|
||||
|
||||
#ifndef HB_DEBUG_CORETEXT
|
||||
@ -44,6 +43,19 @@ HB_SHAPER_DATA_ENSURE_DECLARE(coretext, face)
|
||||
HB_SHAPER_DATA_ENSURE_DECLARE(coretext, font)
|
||||
|
||||
|
||||
typedef bool (*qt_get_font_table_func_t) (void *user_data, unsigned int tag, unsigned char *buffer, unsigned int *length);
|
||||
|
||||
struct FontEngineFaceData {
|
||||
void *user_data;
|
||||
qt_get_font_table_func_t get_font_table;
|
||||
};
|
||||
|
||||
struct CoreTextFontEngineData {
|
||||
CTFontRef ctFont;
|
||||
CGFontRef cgFont;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* shaper face data
|
||||
*/
|
||||
@ -83,25 +95,11 @@ _hb_coretext_shaper_face_data_create (hb_face_t *face)
|
||||
if (unlikely (!data))
|
||||
return NULL;
|
||||
|
||||
QFontEngine *fe = (QFontEngine *) ((QFontEngine::FaceData *) face->user_data)->user_data;
|
||||
if (fe->type () == QFontEngine::Mac)
|
||||
{
|
||||
data->cg_font = (CGFontRef) fe->userData ().value<void *> ();
|
||||
if (likely (data->cg_font))
|
||||
CFRetain (data->cg_font);
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_blob_t *blob = hb_face_reference_blob (face);
|
||||
unsigned int blob_length;
|
||||
const char *blob_data = hb_blob_get_data (blob, &blob_length);
|
||||
if (unlikely (!blob_length))
|
||||
DEBUG_MSG (CORETEXT, face, "Face has empty blob");
|
||||
|
||||
CGDataProviderRef provider = CGDataProviderCreateWithData (blob, blob_data, blob_length, &release_data);
|
||||
data->cg_font = CGFontCreateWithDataProvider (provider);
|
||||
CGDataProviderRelease (provider);
|
||||
}
|
||||
FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data;
|
||||
CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data;
|
||||
data->cg_font = coreTextFontEngineData->cgFont;
|
||||
if (likely (data->cg_font))
|
||||
CFRetain (data->cg_font);
|
||||
|
||||
if (unlikely (!data->cg_font)) {
|
||||
DEBUG_MSG (CORETEXT, face, "Face CGFontCreateWithDataProvider() failed");
|
||||
@ -146,9 +144,13 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
|
||||
return NULL;
|
||||
|
||||
hb_face_t *face = font->face;
|
||||
hb_coretext_shaper_face_data_t *face_data = HB_SHAPER_DATA_GET (face);
|
||||
|
||||
data->ct_font = CTFontCreateWithGraphicsFont (face_data->cg_font, font->y_scale / 64, NULL, NULL);
|
||||
FontEngineFaceData *fontEngineFaceData = (FontEngineFaceData *) face->user_data;
|
||||
CoreTextFontEngineData *coreTextFontEngineData = (CoreTextFontEngineData *) fontEngineFaceData->user_data;
|
||||
data->ct_font = coreTextFontEngineData->ctFont;
|
||||
if (likely (data->ct_font))
|
||||
CFRetain (data->ct_font);
|
||||
|
||||
if (unlikely (!data->ct_font)) {
|
||||
DEBUG_MSG (CORETEXT, font, "Font CTFontCreateWithGraphicsFont() failed");
|
||||
free (data);
|
||||
|
@ -50,6 +50,22 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
static float SYNTHETIC_ITALIC_SKEW = tanf(14 * acosf(0) / 90);
|
||||
|
||||
static bool ct_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *length)
|
||||
{
|
||||
CTFontRef ctfont = *(CTFontRef *)user_data;
|
||||
|
||||
QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0);
|
||||
if (!table)
|
||||
return false;
|
||||
|
||||
CFIndex tableLength = CFDataGetLength(table);
|
||||
if (buffer && int(*length) >= tableLength)
|
||||
CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer);
|
||||
*length = tableLength;
|
||||
Q_ASSERT(int(*length) > 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void loadAdvancesForGlyphs(CTFontRef ctfont,
|
||||
QVarLengthArray<CGGlyph> &cgGlyphs,
|
||||
QGlyphLayout *glyphs, int len,
|
||||
@ -191,7 +207,10 @@ void QCoreTextFontEngine::init()
|
||||
|
||||
cache_cost = (CTFontGetAscent(ctfont) + CTFontGetDescent(ctfont)) * avgCharWidth.toInt() * 2000;
|
||||
|
||||
setUserData(QVariant::fromValue((void *)cgFont));
|
||||
// HACK hb_coretext requires both CTFont and CGFont but user_data is only void*
|
||||
Q_ASSERT((void *)(&ctfont + 1) == (void *)&cgFont);
|
||||
faceData.user_data = &ctfont;
|
||||
faceData.get_font_table = ct_getSfntTable;
|
||||
}
|
||||
|
||||
glyph_t QCoreTextFontEngine::glyphIndex(uint ucs4) const
|
||||
@ -683,15 +702,7 @@ bool QCoreTextFontEngine::canRender(const QChar *string, int len) const
|
||||
|
||||
bool QCoreTextFontEngine::getSfntTableData(uint tag, uchar *buffer, uint *length) const
|
||||
{
|
||||
QCFType<CFDataRef> table = CTFontCopyTable(ctfont, tag, 0);
|
||||
if (!table)
|
||||
return false;
|
||||
CFIndex tableLength = CFDataGetLength(table);
|
||||
if (buffer && int(*length) >= tableLength)
|
||||
CFDataGetBytes(table, CFRangeMake(0, tableLength), buffer);
|
||||
*length = tableLength;
|
||||
Q_ASSERT(int(*length) > 0);
|
||||
return true;
|
||||
return ct_getSfntTable((void *)&ctfont, tag, buffer, length);
|
||||
}
|
||||
|
||||
void QCoreTextFontEngine::getUnscaledGlyph(glyph_t, QPainterPath *, glyph_metrics_t *)
|
||||
|
Loading…
Reference in New Issue
Block a user