📄 qfontdatabase_x11.cpp
字号:
0xd9a, // Sinhala 0, // Thai 0, // Lao 0, // Tibetan 0x1000, // Myanmar 0, // Korean 0 // Khmer};enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) };// Newer FontConfig let's us sort out fonts that contain certain glyphs, but no// open type tables for is directly. Do this so we don't pick some strange// pseudo unicode fontstatic const char *openType[] = { 0, // Any 0, // Latin 0, // Greek 0, // Cyrillic 0, // Armenian 0, // Hebrew 0, // Arabic "syrc", // Syriac "thaa", // Thaana "deva", // Devanagari "beng", // Bengali "guru", // Gurmukhi "gurj", // Gujarati "orya", // Oriya "taml", // Tamil "telu", // Telugu "knda", // Kannada "mlym", // Malayalam "sinh", // Sinhala 0, // Thai 0, // Lao "tibt", // Tibetan "mymr", // Myanmar 0, // Georgian "khmr", // Khmer 0, // SimplifiedChinese 0, // TraditionalChinese 0, // Japanese 0, // Korean 0 // Vietnamese};enum { OpenTypeCount = sizeof(openType) / sizeof(const char *) };static void loadFontConfig(){ Q_ASSERT_X(X11, "QFontDatabase", "A QApplication object needs to be constructed before FontConfig is used."); if (!X11->has_fontconfig) return; Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialLanguageCount, "QFontDatabase", "New scripts have been added."); Q_ASSERT_X(int(QUnicodeTables::ScriptCount) == SpecialCharCount, "QFontDatabase", "New scripts have been added."); Q_ASSERT_X((QFontDatabase::WritingSystemsCount - 1) == LanguageCount, "QFontDatabase", "New writing systems have been added."); Q_ASSERT_X((QFontDatabase::WritingSystemsCount - 1) == SampleCharCount, "QFontDatabase", "New writing systems have been added."); Q_ASSERT_X((QFontDatabase::WritingSystemsCount - 1) == OpenTypeCount, "QFontDatabase", "New writing systems have been added."); QFontDatabasePrivate *db = privateDb(); FcFontSet *fonts; QString familyName; QString rawName; FcChar8 *value = 0; int weight_value; int slant_value; int spacing_value; FcChar8 *file_value; int index_value; FcChar8 *foundry_value; FcBool scalable; { FcObjectSet *os = FcObjectSetCreate(); FcPattern *pattern = FcPatternCreate(); const char *properties [] = { FC_FAMILY, FC_WEIGHT, FC_SLANT, FC_SPACING, FC_FILE, FC_INDEX, FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, FC_WIDTH,#if FC_VERSION >= 20297 FC_CAPABILITY,#endif (const char *)0 }; const char **p = properties; while (*p) { FcObjectSetAdd(os, *p); ++p; } fonts = FcFontList(0, pattern, os); FcObjectSetDestroy(os); FcPatternDestroy(pattern); } for (int i = 0; i < fonts->nfont; i++) { if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) continue; // capitalize(value); rawName = familyName = QString::fromUtf8((const char *)value); familyName.replace('-', ' '); familyName.replace("/", ""); slant_value = FC_SLANT_ROMAN; weight_value = FC_WEIGHT_MEDIUM; spacing_value = FC_PROPORTIONAL; file_value = 0; index_value = 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_MEDIUM; 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, &index_value) != FcResultMatch) index_value = 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; QtFontFamily *family = db->family(familyName, true); family->rawName = rawName; family->hasFT = true; FcLangSet *langset = 0; FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); if (res == FcResultMatch) { for (int i = 1; i < LanguageCount; ++i) { const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i]; if (!lang) { family->writingSystems[i] |= QtFontFamily::UnsupportedFT; } else { FcLangResult langRes = FcLangSetHasLang(langset, lang); if (langRes != FcLangDifferentLang) family->writingSystems[i] = QtFontFamily::Supported; else family->writingSystems[i] |= QtFontFamily::UnsupportedFT; } } family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT; family->ftWritingSystemCheck = true; } 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. for (int i = 1; i < LanguageCount; ++i) family->writingSystems[i] |= QtFontFamily::UnsupportedFT; family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported; } FcCharSet *cs = 0; res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs); if (res == FcResultMatch) { // some languages are not supported by FontConfig, we rather check the // charset to detect these for (int i = 1; i < SampleCharCount; ++i) { if (!sampleCharForWritingSystem[i]) continue; if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i])) family->writingSystems[i] = QtFontFamily::Supported; } }#if FC_VERSION >= 20297 for (int j = 1; j < LanguageCount; ++j) { if (family->writingSystems[j] == QtFontFamily::Supported && requiresOpenType(j) && openType[j]) { FcChar8 *cap; res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) family->writingSystems[j] = QtFontFamily::UnsupportedFT; } }#endif QByteArray file((const char *)file_value); family->fontFilename = file; family->fontFileIndex = index_value; QtFontStyle::Key styleKey; styleKey.style = (slant_value == FC_SLANT_ITALIC) ? QFont::StyleItalic : ((slant_value == FC_SLANT_OBLIQUE) ? QFont::StyleOblique : QFont::StyleNormal); styleKey.weight = getFCWeight(weight_value); if (!scalable) { int width = 100; FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width); styleKey.stretch = width; } QtFontFoundry *foundry = family->foundry(foundry_value ? QString::fromUtf8((const char *)foundry_value) : QString(), true); QtFontStyle *style = foundry->style(styleKey, true); if (spacing_value < FC_MONO) family->fixedPitch = false; QtFontSize *size; if (scalable) { style->smoothScalable = true; size = style->pixelSize(SMOOTH_SCALABLE, true); } else { double pixel_size = 0; FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); size = style->pixelSize((int)pixel_size, true); } QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); enc->pitch = (spacing_value >= FC_CHARCELL ? 'c' : (spacing_value >= FC_MONO ? 'm' : 'p')); } FcFontSetDestroy (fonts); struct FcDefaultFont { const char *qtname; const char *rawname; bool fixed; }; const FcDefaultFont defaults[] = { { "Serif", "serif", false }, { "Sans Serif", "sans-serif", false }, { "Monospace", "monospace", true }, { 0, 0, false } }; const FcDefaultFont *f = defaults; while (f->qtname) { QtFontFamily *family = db->family(f->qtname, true); family->fixedPitch = f->fixed; family->rawName = f->rawname; family->hasFT = true; family->synthetic = true; QtFontFoundry *foundry = family->foundry(QString(), true); // aliases only make sense for 'common', not for any of the specials for (int i = 1; i < LanguageCount; ++i) { if (requiresOpenType(i)) family->writingSystems[i] = QtFontFamily::UnsupportedFT; else family->writingSystems[i] = QtFontFamily::Supported; } family->writingSystems[QFontDatabase::Other] = QtFontFamily::UnsupportedFT; QtFontStyle::Key styleKey; for (int i = 0; i < 4; ++i) { styleKey.style = (i%2) ? QFont::StyleNormal : QFont::StyleItalic; styleKey.weight = (i > 1) ? QFont::Bold : QFont::Normal; QtFontStyle *style = foundry->style(styleKey, true); style->smoothScalable = true; QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE, true); QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); enc->pitch = (f->fixed ? 'm' : 'p'); } ++f; }}#endif // QT_NO_FONTCONFIGstatic void load(const QString &family = QString(), int script = -1){ if (X11->has_fontconfig) return;#ifdef QFONTDATABASE_DEBUG QTime t; t.start();#endif if (family.isNull() && script == -1) { loadXlfds(0, -1); } else { if (family.isNull()) { // load all families in all writing systems that match \a script for (int ws = 1; ws < QFontDatabase::WritingSystemsCount; ++ws) { if (scriptForWritingSystem[ws] != script) continue; for (int i = 0; i < numEncodings; ++i) { if (writingSystems_for_xlfd_encoding[i][ws]) loadXlfds(0, i); } } } else { QtFontFamily *f = privateDb()->family(family); // could reduce this further with some more magic: // would need to remember the encodings loaded for the family. if (!f || !f->xlfdLoaded) loadXlfds(family.toLatin1(), -1); } }#ifdef QFONTDATABASE_DEBUG FD_DEBUG("QFontDatabase: load(%s, %d) took %d ms", family.toLatin1().constData(), script, t.elapsed());#endif}static void initializeDb(){ QFontDatabasePrivate *db = privateDb(); if (!db || db->count) return; QTime t; t.start();#ifndef QT_NO_FONTCONFIG loadFontConfig(); FD_DEBUG("QFontDatabase: loaded FontConfig: %d ms", t.elapsed());#endif t.start();#ifndef QT_NO_FONTCONFIG for (int i = 0; i < db->count; i++) { for (int j = 0; j < db->families[i]->count; ++j) { // each foundry QtFontFoundry *foundry = db->families[i]->foundries[j]; for (int k = 0; k < foundry->count; ++k) { QtFontStyle *style = foundry->styles[k]; if (style->key.style != QFont::StyleNormal) continue; QtFontSize *size = style->pixelSize(SMOOTH_SCALABLE); if (! size) continue; // should not happen QtFontEncoding *enc = size->encodingID(-1, 0, 0, 0, 0, true); if (! enc) continue; // should not happen either QtFontStyle::Key key = style->key; // does this style have an italic equivalent? key.style = QFont::StyleItalic; QtFontStyle *equiv = foundry->style(key); if (equiv) continue; // does this style have an oblique equivalent? key.style = QFont::StyleOblique; equiv = foundry->style(key); if (equiv) continue; // let's fake one... equiv = foundry->style(key, true); equiv->smoothScalable = true; QtFontSize *equiv_size = equiv->pixelSize(SMOOTH_SCALABLE, true); QtFontEncoding *equiv_enc = equiv_size->encodingID(-1, 0, 0, 0, 0, true); // keep the same pitch equiv_enc->pitch = enc->pitch; } } }#endif#ifdef QFONTDATABASE_DEBUG#ifndef QT_NO_FONTCONFIG if (!X11->has_fontconfig)#endif // load everything at startup in debug mode. loadXlfds(0, -1); // print the database for (int f = 0; f < db->count; f++) { QtFontFamily *family = db->families[f]; FD_DEBUG("'%s' %s hasFT=%s", family->name.latin1(), (family->fixedPitch ? "fixed" : ""), (family->hasFT ? "yes" : "no")); for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i); FD_DEBUG("\t%s: %s", QFontDatabase::writingSystemName(ws).toLatin1().constData(), ((family->writingSystems[i] & QtFontFamily::Supported) ? "Supported" : (family->writingSystems[i] & QtFontFamily::Unsupported) == QtFontFamily::Unsupported ? "Unsupported" : "Unknown")); } for (int fd = 0; fd < family->count; fd++) { QtFontFoundry *foundry = family->foundries[fd]; FD_DEBUG("\t\t'%s'", foundry->name.latin1()); for (int s = 0; s < foundry->count; s++) { QtFontStyle *style = foundry->styles[s]; FD_DEBUG("\t\t\tstyle: style=%d weight=%d (%s)\n" "\t\t\tstretch=%d (%s)", style->key.style, style->key.weight, style->weightName, style->key.stretch, style->setwidthName ? style->setwidthName : "nil"); if (style->smoothScalable) FD_DEBUG("\t\t\t\tsmooth scalable"); else if (style->bitmapScalable) FD_DEBUG("\t\t\t\tbitmap scalable"); if (style->pixelSizes) { qDebug("\t\t\t\t%d pixel sizes", style->count); for (int z = 0; z < style->count; ++z) { QtFontSize *size = style->pixelSizes + z; for (int e = 0; e < size->count; ++e) { FD_DEBUG("\t\t\t\t size %5d pitch %c encoding %s", size->pixelSize, size->encodings[e].pitch, xlfd_for_id(size->encodings[e].encoding)); } } } } } }#endif // QFONTDATABASE_DEBUG}// --------------------------------------------------------------------------------------// font loader// --------------------------------------------------------------------------------------static const char *styleHint(const QFontDef &request){ const char *stylehint = 0; switch (request.styleHint) { case QFont::SansSerif: stylehint = "sans-serif"; break; case QFont::Serif: stylehint = "serif"; break; case QFont::TypeWriter: stylehint = "monospace"; break; default: if (request.fixedPitch) stylehint = "monospace"; break; } return stylehint;}#ifndef QT_NO_FONTCONFIGstatic void addPatternProps(FcPattern *pattern, const QFontPrivate *fp, int script, const QFontDef &request){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -