diff options
author | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2014-02-19 10:06:25 +0100 |
---|---|---|
committer | Oswald Buddenhagen <oswald.buddenhagen@digia.com> | 2014-02-19 10:06:25 +0100 |
commit | 30fd22b9574def54726e7b193127cc0c901c1b4c (patch) | |
tree | 96dfc923044db0515064ba39d052d9ed577e3e40 /src/platformsupport/fontdatabases | |
parent | d7b0581c1c2ef60c08d238dae39298af6904918f (diff) | |
parent | 6aa09bbce59828d028f6d1e81d2bfc6ba537aae1 (diff) |
Merge remote-tracking branch 'origin/dev' into stable
Change-Id: Ice524edcc51373509f0023ae7f7c2963f4602f88
Diffstat (limited to 'src/platformsupport/fontdatabases')
7 files changed, 318 insertions, 262 deletions
diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp index 33f3601b97..1ed5ede3e8 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase.cpp @@ -113,27 +113,18 @@ void QBasicFontDatabase::populateFontDatabase() } } -QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, QChar::Script script, void *usrPtr) +QFontEngine *QBasicFontDatabase::fontEngine(const QFontDef &fontDef, void *usrPtr) { - QFontEngineFT *engine; FontFile *fontfile = static_cast<FontFile *> (usrPtr); QFontEngine::FaceId fid; fid.filename = QFile::encodeName(fontfile->fileName); fid.index = fontfile->indexValue; - engine = new QFontEngineFT(fontDef); bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; - if (!engine->init(fid,antialias,format)) { - delete engine; - engine = 0; - return engine; - } - if (engine->invalid()) { - delete engine; - engine = 0; - } else if (!engine->supportsScript(script)) { - qWarning(" OpenType support missing for script %d", int(script)); + + QFontEngineFT *engine = new QFontEngineFT(fontDef); + if (!engine->init(fid, antialias, format) || engine->invalid()) { delete engine; engine = 0; } diff --git a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h index 4d6fd2ceeb..45d7218ece 100644 --- a/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/basic/qbasicfontdatabase_p.h @@ -58,7 +58,7 @@ class QBasicFontDatabase : public QPlatformFontDatabase { public: void populateFontDatabase(); - QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle); + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 8c3ca2d229..8b16e7520a 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -69,21 +69,52 @@ static inline bool requiresOpenType(int writingSystem) || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); } -static int getFCWeight(int fc_weight) +static inline int weightFromFcWeight(int fcweight) { - int qtweight = QFont::Black; - if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_REGULAR) / 2) - qtweight = QFont::Light; - else if (fc_weight <= (FC_WEIGHT_REGULAR + FC_WEIGHT_MEDIUM) / 2) - qtweight = QFont::Normal; - else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_BOLD) / 2) - qtweight = QFont::DemiBold; - else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2) - qtweight = QFont::Bold; + // Font Config uses weights from 0 to 215 (the highest enum value) while QFont ranges from + // 0 to 99. The spacing between the values for the enums are uneven so a linear mapping from + // Font Config values to Qt would give surprising results. So, we do a piecewise linear + // mapping. This ensures that where there is a corresponding enum on both sides (for example + // FC_WEIGHT_DEMIBOLD and QFont::DemiBold) we map one to the other but other values map + // to intermediate Qt weights. + const int maxWeight = 99; + int qtweight; + if (fcweight < 0) + qtweight = 0; + else if (fcweight <= FC_WEIGHT_LIGHT) + qtweight = (fcweight * QFont::Light) / FC_WEIGHT_LIGHT; + else if (fcweight <= FC_WEIGHT_NORMAL) + qtweight = QFont::Light + ((fcweight - FC_WEIGHT_LIGHT) * (QFont::Normal - QFont::Light)) / (FC_WEIGHT_NORMAL - FC_WEIGHT_LIGHT); + else if (fcweight <= FC_WEIGHT_DEMIBOLD) + qtweight = QFont::Normal + ((fcweight - FC_WEIGHT_NORMAL) * (QFont::DemiBold - QFont::Normal)) / (FC_WEIGHT_DEMIBOLD - FC_WEIGHT_NORMAL); + else if (fcweight <= FC_WEIGHT_BOLD) + qtweight = QFont::DemiBold + ((fcweight - FC_WEIGHT_DEMIBOLD) * (QFont::Bold - QFont::DemiBold)) / (FC_WEIGHT_BOLD - FC_WEIGHT_DEMIBOLD); + else if (fcweight <= FC_WEIGHT_BLACK) + qtweight = QFont::Bold + ((fcweight - FC_WEIGHT_BOLD) * (QFont::Black - QFont::Bold)) / (FC_WEIGHT_BLACK - FC_WEIGHT_BOLD); + else if (fcweight <= FC_WEIGHT_ULTRABLACK) + qtweight = QFont::Black + ((fcweight - FC_WEIGHT_BLACK) * (maxWeight - QFont::Black)) / (FC_WEIGHT_ULTRABLACK - FC_WEIGHT_BLACK); + else + qtweight = maxWeight; return qtweight; } +static inline int stretchFromFcWidth(int fcwidth) +{ + // Font Config enums for width match pretty closely with those used by Qt so just use + // Font Config values directly while enforcing the same limits imposed by QFont. + const int maxStretch = 4000; + int qtstretch; + if (fcwidth < 1) + qtstretch = 1; + else if (fcwidth > maxStretch) + qtstretch = maxStretch; + else + qtstretch = fcwidth; + + return qtstretch; +} + static const char *specialLanguages[] = { "", // Unknown "", // Inherited @@ -300,15 +331,14 @@ static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) return stylehint; } -void QFontconfigDatabase::populateFontDatabase() +static void populateFromPattern(FcPattern *pattern) { - FcFontSet *fonts; - QString familyName; FcChar8 *value = 0; int weight_value; int slant_value; int spacing_value; + int width_value; FcChar8 *file_value; int indexValue; FcChar8 *foundry_value; @@ -316,13 +346,117 @@ void QFontconfigDatabase::populateFontDatabase() FcBool scalable; FcBool antialias; + if (FcPatternGetString(pattern, FC_FAMILY, 0, &value) != FcResultMatch) + return; + + familyName = QString::fromUtf8((const char *)value); + + slant_value = FC_SLANT_ROMAN; + weight_value = FC_WEIGHT_REGULAR; + spacing_value = FC_PROPORTIONAL; + file_value = 0; + indexValue = 0; + scalable = FcTrue; + + + if (FcPatternGetInteger(pattern, FC_SLANT, 0, &slant_value) != FcResultMatch) + slant_value = FC_SLANT_ROMAN; + if (FcPatternGetInteger(pattern, FC_WEIGHT, 0, &weight_value) != FcResultMatch) + weight_value = FC_WEIGHT_REGULAR; + if (FcPatternGetInteger(pattern, FC_WIDTH, 0, &width_value) != FcResultMatch) + width_value = FC_WIDTH_NORMAL; + if (FcPatternGetInteger(pattern, FC_SPACING, 0, &spacing_value) != FcResultMatch) + spacing_value = FC_PROPORTIONAL; + if (FcPatternGetString(pattern, FC_FILE, 0, &file_value) != FcResultMatch) + file_value = 0; + if (FcPatternGetInteger(pattern, FC_INDEX, 0, &indexValue) != FcResultMatch) + indexValue = 0; + if (FcPatternGetBool(pattern, FC_SCALABLE, 0, &scalable) != FcResultMatch) + scalable = FcTrue; + if (FcPatternGetString(pattern, FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) + foundry_value = 0; + if (FcPatternGetString(pattern, FC_STYLE, 0, &style_value) != FcResultMatch) + style_value = 0; + if (FcPatternGetBool(pattern,FC_ANTIALIAS,0,&antialias) != FcResultMatch) + antialias = true; + + QSupportedWritingSystems writingSystems; + FcLangSet *langset = 0; + FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset); + if (res == FcResultMatch) { + bool hasLang = false; + for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { + const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; + if (lang) { + FcLangResult langRes = FcLangSetHasLang(langset, lang); + if (langRes != FcLangDifferentLang) { + writingSystems.setSupported(QFontDatabase::WritingSystem(j)); + hasLang = true; + } + } + } + if (!hasLang) + // none of our known languages, add it to the other set + writingSystems.setSupported(QFontDatabase::Other); + } else { + // we set Other to supported for symbol fonts. It makes no + // sense to merge these with other ones, as they are + // special in a way. + writingSystems.setSupported(QFontDatabase::Other); + } + +#if FC_VERSION >= 20297 + for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { + if (writingSystems.supported(QFontDatabase::WritingSystem(j)) + && requiresOpenType(j) && openType[j]) { + FcChar8 *cap; + res = FcPatternGetString (pattern, FC_CAPABILITY, 0, &cap); + if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) + writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); + } + } +#endif + + FontFile *fontFile = new FontFile; + fontFile->fileName = QLatin1String((const char *)file_value); + fontFile->indexValue = indexValue; + + QFont::Style style = (slant_value == FC_SLANT_ITALIC) + ? QFont::StyleItalic + : ((slant_value == FC_SLANT_OBLIQUE) + ? QFont::StyleOblique + : QFont::StyleNormal); + // Note: weight should really be an int but registerFont incorrectly uses an enum + QFont::Weight weight = QFont::Weight(weightFromFcWeight(weight_value)); + + double pixel_size = 0; + if (!scalable) + FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &pixel_size); + + bool fixedPitch = spacing_value >= FC_MONO; + // Note: stretch should really be an int but registerFont incorrectly uses an enum + QFont::Stretch stretch = QFont::Stretch(stretchFromFcWidth(width_value)); + QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); + QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); +// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; + + for (int k = 1; FcPatternGetString(pattern, FC_FAMILY, k, &value) == FcResultMatch; ++k) + QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value)); + +} + +void QFontconfigDatabase::populateFontDatabase() +{ + FcInitReinitialize(); + FcFontSet *fonts; + { FcObjectSet *os = FcObjectSetCreate(); FcPattern *pattern = FcPatternCreate(); const char *properties [] = { FC_FAMILY, FC_STYLE, FC_WEIGHT, FC_SLANT, FC_SPACING, FC_FILE, FC_INDEX, - FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, + FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WIDTH, #if FC_VERSION >= 20297 FC_CAPABILITY, @@ -339,102 +473,8 @@ void QFontconfigDatabase::populateFontDatabase() FcPatternDestroy(pattern); } - for (int i = 0; i < fonts->nfont; i++) { - if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) - continue; - // capitalize(value); - familyName = QString::fromUtf8((const char *)value); - slant_value = FC_SLANT_ROMAN; - weight_value = FC_WEIGHT_REGULAR; - spacing_value = FC_PROPORTIONAL; - file_value = 0; - indexValue = 0; - scalable = FcTrue; - - - if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch) - slant_value = FC_SLANT_ROMAN; - if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) - weight_value = FC_WEIGHT_REGULAR; - if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) - spacing_value = FC_PROPORTIONAL; - if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) - file_value = 0; - if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch) - indexValue = 0; - if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch) - scalable = FcTrue; - if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) - foundry_value = 0; - if (FcPatternGetString(fonts->fonts[i], FC_STYLE, 0, &style_value) != FcResultMatch) - style_value = 0; - if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch) - antialias = true; - - QSupportedWritingSystems writingSystems; - FcLangSet *langset = 0; - FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); - if (res == FcResultMatch) { - bool hasLang = false; - for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { - const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; - if (lang) { - FcLangResult langRes = FcLangSetHasLang(langset, lang); - if (langRes != FcLangDifferentLang) { - writingSystems.setSupported(QFontDatabase::WritingSystem(j)); - hasLang = true; - } - } - } - if (!hasLang) - // none of our known languages, add it to the other set - writingSystems.setSupported(QFontDatabase::Other); - } else { - // we set Other to supported for symbol fonts. It makes no - // sense to merge these with other ones, as they are - // special in a way. - writingSystems.setSupported(QFontDatabase::Other); - } - -#if FC_VERSION >= 20297 - for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { - if (writingSystems.supported(QFontDatabase::WritingSystem(j)) - && requiresOpenType(j) && openType[j]) { - FcChar8 *cap; - res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); - if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) - writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); - } - } -#endif - - FontFile *fontFile = new FontFile; - fontFile->fileName = QLatin1String((const char *)file_value); - fontFile->indexValue = indexValue; - - QFont::Style style = (slant_value == FC_SLANT_ITALIC) - ? QFont::StyleItalic - : ((slant_value == FC_SLANT_OBLIQUE) - ? QFont::StyleOblique - : QFont::StyleNormal); - QFont::Weight weight = QFont::Weight(getFCWeight(weight_value)); - - double pixel_size = 0; - if (!scalable) { - int width = 100; - FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width); - FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); - } - - bool fixedPitch = spacing_value >= FC_MONO; - QFont::Stretch stretch = QFont::Unstretched; - QString styleName = style_value ? QString::fromUtf8((const char *) style_value) : QString(); - QPlatformFontDatabase::registerFont(familyName,styleName,QLatin1String((const char *)foundry_value),weight,style,stretch,antialias,scalable,pixel_size,fixedPitch,writingSystems,fontFile); -// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; - - for (int k = 1; FcPatternGetString(fonts->fonts[i], FC_FAMILY, k, &value) == FcResultMatch; ++k) - QPlatformFontDatabase::registerAliasToFontFamily(familyName, QString::fromUtf8((const char *)value)); - } + for (int i = 0; i < fonts->nfont; i++) + populateFromPattern(fonts->fonts[i]); FcFontSetDestroy (fonts); @@ -476,20 +516,18 @@ QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine, return new QFontEngineMultiFontConfig(fontEngine, script); } -QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr) +QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr) { if (!usrPtr) return 0; QFontDef fontDef = f; - QFontEngineFT *engine; FontFile *fontfile = static_cast<FontFile *> (usrPtr); QFontEngine::FaceId fid; fid.filename = QFile::encodeName(fontfile->fileName); fid.index = fontfile->indexValue; bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - engine = new QFontEngineFT(fontDef); QFontEngineFT::GlyphFormat format; // try and get the pattern @@ -509,8 +547,24 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script sc FcPatternAdd(pattern,FC_INDEX,value,true); FcResult result; + + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + FcPattern *match = FcFontMatch(0, pattern, &result); + + QFontEngineFT *engine = new QFontEngineFT(fontDef); + if (match) { + //Respect the file and index of the font config match + FcChar8 *file_value; + int indexValue; + + if (FcPatternGetString(match, FC_FILE, 0, &file_value) == FcResultMatch) + fid.filename = (const char *)file_value; + if (FcPatternGetInteger(match, FC_INDEX, 0, &indexValue) == FcResultMatch) + fid.index = indexValue; + QFontEngineFT::HintStyle default_hint_style; if (f.hintingPreference != QFont::PreferDefaultHinting) { switch (f.hintingPreference) { @@ -587,25 +641,18 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QChar::Script sc format = subpixelType == QFontEngineFT::Subpixel_None ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_A32; engine->subpixelType = subpixelType; - } else + } else { format = QFontEngineFT::Format_Mono; + } FcPatternDestroy(match); - } else + } else { format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + } FcPatternDestroy(pattern); - if (!engine->init(fid,antialias,format)) { - delete engine; - engine = 0; - return engine; - } - if (engine->invalid()) { - delete engine; - engine = 0; - } else if (!engine->supportsScript(script)) { - qWarning(" OpenType support missing for script %d", int(script)); + if (!engine->init(fid, antialias, format) || engine->invalid()) { delete engine; engine = 0; } @@ -715,6 +762,7 @@ static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) { QStringList families; + FcFontSet *set = FcConfigGetFonts(0, FcSetApplication); if (!set) { FcConfigAppFontAddFile(0, (const FcChar8 *)":/non-existent"); @@ -727,28 +775,24 @@ QStringList QFontconfigDatabase::addApplicationFont(const QByteArray &fontData, FcBlanks *blanks = FcConfigGetBlanks(0); int count = 0; - FcPattern *pattern = 0; + FcPattern *pattern; do { pattern = queryFont((const FcChar8 *)QFile::encodeName(fileName).constData(), fontData, id, blanks, &count); if (!pattern) return families; - FcPatternDel(pattern, FC_FILE); - QByteArray cs = fileName.toUtf8(); - FcPatternAddString(pattern, FC_FILE, (const FcChar8 *) cs.constData()); - FcChar8 *fam = 0; if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) { QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam)); families << family; } + populateFromPattern(pattern); - if (!FcFontSetAdd(set, pattern)) - return families; + FcFontSetAdd(set, pattern); ++id; - } while (pattern && id < count); + } while (id < count); return families; } diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h index 6d6dae680e..9f1fd28144 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h @@ -52,7 +52,7 @@ class QFontconfigDatabase : public QBasicFontDatabase public: void populateFontDatabase(); QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script); - QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle); + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); QString resolveFontFamilyAlias(const QString &family) const; diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 38c44e3f35..ab2e9c1f1a 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -278,10 +278,8 @@ void QCoreTextFontDatabase::releaseHandle(void *handle) CFRelease(CTFontDescriptorRef(handle)); } -QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, QChar::Script script, void *usrPtr) +QFontEngine *QCoreTextFontDatabase::fontEngine(const QFontDef &f, void *usrPtr) { - Q_UNUSED(script); - qreal scaledPointSize = f.pixelSize; // When 96 DPI is forced, the Mac plugin will use DPI 72 for some @@ -474,104 +472,120 @@ QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFo return fallbackLists[styleLookupKey.arg(styleHint)]; } -#ifdef Q_OS_MACX +#if HAVE_CORETEXT +static CFArrayRef createDescriptorArrayForFont(CTFontRef font) +{ + CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); + CFArrayAppendValue(array, QCFType<CTFontDescriptorRef>(CTFontCopyFontDescriptor(font))); + return array; +} +#endif + QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) { -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { - CTFontRef font = NULL; + QCFType<CFArrayRef> fonts; + QStringList families; +#if HAVE_CORETEXT + if (&CTFontManagerRegisterGraphicsFont) { + CFErrorRef error = 0; if (!fontData.isEmpty()) { QByteArray* fontDataCopy = new QByteArray(fontData); QCFType<CGDataProviderRef> dataProvider = CGDataProviderCreateWithData(fontDataCopy, fontDataCopy->constData(), fontDataCopy->size(), releaseFontData); - CGFontRef cgFont = CGFontCreateWithDataProvider(dataProvider); + QCFType<CGFontRef> cgFont = CGFontCreateWithDataProvider(dataProvider); if (cgFont) { - CFErrorRef error; - bool success = CTFontManagerRegisterGraphicsFont(cgFont, &error); - if (success) { - font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL); - m_applicationGraphicsFonts.append(QCFType<CGFontRef>::constructFromGet(cgFont)); - } else { - NSLog(@"Unable to register font: %@", error); - CFRelease(error); + if (CTFontManagerRegisterGraphicsFont(cgFont, &error)) { + QCFType<CTFontRef> font = CTFontCreateWithGraphicsFont(cgFont, 0.0, NULL, NULL); + fonts = createDescriptorArrayForFont(font); + m_applicationFonts.append(QVariant::fromValue(QCFType<CGFontRef>::constructFromGet(cgFont))); } - CGFontRelease(cgFont); } } else { - CFErrorRef error; QCFType<CFURLRef> fontURL = CFURLCreateWithFileSystemPath(NULL, QCFString(fileName), kCFURLPOSIXPathStyle, false); - bool success = CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error); - if (success) { - const void *keys[] = { kCTFontURLAttribute }; - const void *values[] = { fontURL }; - QCFType<CFDictionaryRef> attributes = CFDictionaryCreate(NULL, keys, values, 1, - &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes); - font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL); - m_applicationURLFonts.append(QCFType<CFURLRef>::constructFromGet(fontURL)); - } else { - NSLog(@"Unable to register font: %@", error); - CFRelease(error); + if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error)) { +#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_6, __IPHONE_7_0) + if (&CTFontManagerCreateFontDescriptorsFromURL) + fonts = CTFontManagerCreateFontDescriptorsFromURL(fontURL); + else +#endif + { + // We're limited to a single font per file, unless we dive into the font tables + QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, + &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + CFDictionaryAddValue(attributes, kCTFontURLAttribute, fontURL); + QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithAttributes(attributes); + QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, NULL); + fonts = createDescriptorArrayForFont(font); + } + + m_applicationFonts.append(QVariant::fromValue(QCFType<CFURLRef>::constructFromGet(fontURL))); } } - if (font) { - QStringList families; - families.append(QCFString(CTFontCopyFamilyName(font))); - - QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font); - populateFromDescriptor(descriptor); - - CFRelease(font); - return families; + if (error) { + NSLog(@"Unable to register font: %@", error); + CFRelease(error); } - } else + } +#endif +#if HAVE_CORETEXT && HAVE_ATS + else #endif +#if HAVE_ATS { - ATSFontContainerRef fontContainer; - OSStatus e; + ATSFontContainerRef fontContainer; + OSStatus e; - if (!fontData.isEmpty()) { - e = ATSFontActivateFromMemory((void *) fontData.constData(), fontData.size(), - kATSFontContextLocal, kATSFontFormatUnspecified, NULL, - kATSOptionFlagsDefault, &fontContainer); - } else { - FSRef ref; - OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref); - if (qt_mac_create_fsref(fileName, &ref) != noErr) - return QStringList(); - e = ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0, - kATSOptionFlagsDefault, &fontContainer); - } - - if (e == noErr) { - ItemCount fontCount = 0; - e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, 0, 0, &fontCount); - if (e != noErr) - return QStringList(); - - QVarLengthArray<ATSFontRef> containedFonts(fontCount); - e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount); - if (e != noErr) - return QStringList(); - - QStringList families; - for (int i = 0; i < containedFonts.size(); ++i) { - QCFType<CTFontRef> font = CTFontCreateWithPlatformFont(containedFonts[i], 12.0, NULL, NULL); - QCFType<CTFontDescriptorRef> descriptor = CTFontCopyFontDescriptor(font); - populateFromDescriptor(descriptor); - families.append(QCFString(CTFontCopyFamilyName(font))); + if (!fontData.isEmpty()) { + e = ATSFontActivateFromMemory((void *) fontData.constData(), fontData.size(), + kATSFontContextLocal, kATSFontFormatUnspecified, NULL, + kATSOptionFlagsDefault, &fontContainer); + } else { + FSRef ref; + OSErr qt_mac_create_fsref(const QString &file, FSRef *fsref); + if (qt_mac_create_fsref(fileName, &ref) != noErr) + return QStringList(); + e = ATSFontActivateFromFileReference(&ref, kATSFontContextLocal, kATSFontFormatUnspecified, 0, + kATSOptionFlagsDefault, &fontContainer); } - m_applicationFonts.append(fontContainer); - return families; + if (e == noErr) { + ItemCount fontCount = 0; + e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, 0, 0, &fontCount); + if (e != noErr) + return QStringList(); + + QVarLengthArray<ATSFontRef> containedFonts(fontCount); + e = ATSFontFindFromContainer(fontContainer, kATSOptionFlagsDefault, fontCount, containedFonts.data(), &fontCount); + if (e != noErr) + return QStringList(); + + CFMutableArrayRef fontsArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); + for (int i = 0; i < containedFonts.size(); ++i) { + QCFType<CTFontRef> font = CTFontCreateWithPlatformFont(containedFonts[i], 12.0, NULL, NULL); + CFArrayAppendValue(fontsArray, QCFType<CTFontDescriptorRef>(CTFontCopyFontDescriptor(font))); + } + + fonts = fontsArray; + + m_applicationFonts.append(QVariant::fromValue(fontContainer)); + } } +#endif + + if (fonts) { + const int numFonts = CFArrayGetCount(fonts); + for (int i = 0; i < numFonts; ++i) { + CTFontDescriptorRef fontDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fonts, i)); + populateFromDescriptor(fontDescriptor); + QCFType<CFStringRef> familyName = CFStringRef(CTFontDescriptorCopyLocalizedAttribute(fontDescriptor, kCTFontFamilyNameAttribute, NULL)); + families.append(QCFString(familyName)); + } } - return QStringList(); + return families; } -#endif QFont QCoreTextFontDatabase::defaultFont() const { @@ -596,25 +610,31 @@ QList<int> QCoreTextFontDatabase::standardSizes() const void QCoreTextFontDatabase::removeApplicationFonts() { -#ifdef Q_OS_MACX -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 - if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { - CFErrorRef error; - for (int i = 0; i < m_applicationGraphicsFonts.count(); ++i) - CTFontManagerUnregisterGraphicsFont(m_applicationGraphicsFonts[i], &error); - m_applicationGraphicsFonts.clear(); - - for (int i = 0; i < m_applicationURLFonts.count(); ++i) - CTFontManagerUnregisterFontsForURL(m_applicationURLFonts[i], kCTFontManagerScopeProcess, &error); - m_applicationURLFonts.clear(); - } else + foreach (const QVariant &font, m_applicationFonts) { +#if HAVE_CORETEXT + if (&CTFontManagerUnregisterGraphicsFont && &CTFontManagerUnregisterFontsForURL) { + CFErrorRef error; + if (font.canConvert(qMetaTypeId<QCFType<CGFontRef> >())) { + CTFontManagerUnregisterGraphicsFont(font.value<QCFType<CGFontRef> >(), &error); + } else if (font.canConvert(qMetaTypeId<QCFType<CFURLRef> >())) { + CTFontManagerUnregisterFontsForURL(font.value<QCFType<CFURLRef> >(), kCTFontManagerScopeProcess, &error); + } + } #endif - { - for (int i = 0; i < m_applicationFonts.count(); ++i) - ATSFontDeactivate(m_applicationFonts[i], 0, kATSOptionFlagsDoNotNotify); +#if HAVE_CORETEXT && HAVE_ATS + else +#endif +#if HAVE_ATS + if (font.canConvert(qMetaTypeId<ATSFontContainerRef>())) { + ATSFontDeactivate(font.value<ATSFontContainerRef>(), 0, kATSOptionFlagsDoNotNotify); + } +#endif + } + m_applicationFonts.clear(); + +#if HAVE_ATS ATSFontNotify(kATSFontNotifyActionFontsChanged, 0); - } #endif } diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index ee1016509b..1560d36644 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -42,6 +42,10 @@ #ifndef QCORETEXTFONTDATABASE_H #define QCORETEXTFONTDATABASE_H +#include <qglobal.h> +#define HAVE_CORETEXT QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_4_1) +#define HAVE_ATS QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_5, __IPHONE_NA) + #include <qpa/qplatformfontdatabase.h> #include <private/qcore_mac_p.h> @@ -52,6 +56,14 @@ #include <CoreGraphics/CoreGraphics.h> #endif +#if HAVE_CORETEXT +Q_DECLARE_METATYPE(QCFType<CGFontRef>); +Q_DECLARE_METATYPE(QCFType<CFURLRef>); +#endif +#if HAVE_ATS +Q_DECLARE_METATYPE(ATSFontContainerRef); +#endif + QT_BEGIN_NAMESPACE class QCoreTextFontDatabase : public QPlatformFontDatabase @@ -60,12 +72,10 @@ public: QCoreTextFontDatabase(); ~QCoreTextFontDatabase(); void populateFontDatabase(); - QFontEngine *fontEngine(const QFontDef &fontDef, QChar::Script script, void *handle); + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; -#ifdef Q_OS_MACX QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); -#endif void releaseHandle(void *handle); QFont defaultFont() const; QList<int> standardSizes() const; @@ -78,13 +88,8 @@ private: mutable QHash<QString, QString> familyNameToPsName; void removeApplicationFonts(); -#ifdef Q_OS_MACX -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 - QVector<QCFType<CGFontRef> > m_applicationGraphicsFonts; - QVector<QCFType<CFURLRef> > m_applicationURLFonts; -#endif - QVector<ATSFontContainerRef> m_applicationFonts; -#endif + + QVector<QVariant> m_applicationFonts; }; QT_END_NAMESPACE diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 9b8f10f588..31a015ae9f 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -63,15 +63,12 @@ static void loadAdvancesForGlyphs(CTFontRef ctfont, for (int i = 0; i < len; ++i) { if (glyphs->glyphs[i] & 0xff000000) continue; - glyphs->advances_x[i] = QFixed::fromReal(advances[i].width); - glyphs->advances_y[i] = QFixed::fromReal(advances[i].height); + glyphs->advances[i] = QFixed::fromReal(advances[i].width); } if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (int i = 0; i < len; ++i) { - glyphs->advances_x[i] = glyphs->advances_x[i].round(); - glyphs->advances_y[i] = glyphs->advances_y[i].round(); - } + for (int i = 0; i < len; ++i) + glyphs->advances[i] = glyphs->advances[i].round(); } } @@ -191,6 +188,8 @@ void QCoreTextFontEngine::init() avgCharWidth = QFontEngine::averageCharWidth(); cache_cost = (CTFontGetAscent(ctfont) + CTFontGetDescent(ctfont)) * avgCharWidth.toInt() * 2000; + + setUserData(QVariant::fromValue((void *)cgFont)); } bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, @@ -228,15 +227,12 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout * for (int i = 0; i < glyph_pos; ++i) { if (glyphs->glyphs[i] & 0xff000000) continue; - glyphs->advances_x[i] = QFixed::fromReal(advances[i].width); - glyphs->advances_y[i] = QFixed::fromReal(advances[i].height); + glyphs->advances[i] = QFixed::fromReal(advances[i].width); } if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - for (int i = 0; i < glyph_pos; ++i) { - glyphs->advances_x[i] = glyphs->advances_x[i].round(); - glyphs->advances_y[i] = glyphs->advances_y[i].round(); - } + for (int i = 0; i < glyph_pos; ++i) + glyphs->advances[i] = glyphs->advances[i].round(); } return true; } |