From c6b555dac389f9a599a9ad342de56dea329fff60 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 15 Mar 2014 15:55:36 +0200 Subject: 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 --- src/3rdparty/harfbuzz-ng/src/hb-coretext.cc | 46 +++++++++++----------- .../fontdatabases/mac/qfontengine_coretext.mm | 31 ++++++++++----- 2 files changed, 45 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc index 5a34eddecc..40c06371bd 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-coretext.cc @@ -32,7 +32,6 @@ #include "hb-coretext.h" #include "hb-face-private.hh" -#include #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 (); - 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); diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 3c30df6efb..0460f11139 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -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 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 &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 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 *) -- cgit v1.2.3