📄 qfontdatabase_x11.cpp
字号:
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 initializeDb();static void load(const QString &family = QString(), int script = -1){ if (X11->has_fontconfig) { initializeDb(); 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 checkSymbolFont(QtFontFamily *family){ if (!family || family->symbol_checked || family->fontFilename.isEmpty()) return;// qDebug() << "checking " << family->rawName; family->symbol_checked = true; QFontEngine::FaceId id; id.filename = family->fontFilename; id.index = family->fontFileIndex; QFreetypeFace *f = QFreetypeFace::getFace(id); if (!f) { qWarning("checkSymbolFonts: Couldn't open face %s (%s/%d)", qPrintable(family->rawName), family->fontFilename.data(), family->fontFileIndex); return; } for (int i = 0; i < f->face->num_charmaps; ++i) { FT_CharMap cm = f->face->charmaps[i]; if (cm->encoding == ft_encoding_adobe_custom || cm->encoding == ft_encoding_symbol) { for (int x = QFontDatabase::Latin; x < QFontDatabase::Other; ++x) family->writingSystems[x] = QtFontFamily::Unsupported; family->writingSystems[QFontDatabase::Other] = QtFontFamily::Supported; break; } } f->release(id);}static void checkSymbolFonts(const QString &family = QString()){#ifndef QT_NO_FONTCONFIG QFontDatabasePrivate *d = privateDb(); if (family.isEmpty()) { for (int i = 0; i < d->count; ++i) checkSymbolFont(d->families[i]); } else { checkSymbolFont(d->family(family)); }#endif}static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt);static void initializeDb(){ QFontDatabasePrivate *db = privateDb(); if (!db || db->count) return; QTime t; t.start();#ifndef QT_NO_FONTCONFIG if (db->reregisterAppFonts) { db->reregisterAppFonts = false; for (int i = 0; i < db->applicationFonts.count(); ++i) if (!db->applicationFonts.at(i).families.isEmpty()) { registerFont(&db->applicationFonts[i]); } } 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 fixed=%s", family->name.latin1(), (family->fixedPitch ? "fixed" : ""), (family->fixedPitch ? "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_FONTCONFIGvoid qt_addPatternProps(FcPattern *pattern, int screen, int script, const QFontDef &request){ int weight_value = FC_WEIGHT_BLACK; if (request.weight == 0) weight_value = FC_WEIGHT_MEDIUM; else if (request.weight < (QFont::Light + QFont::Normal) / 2) weight_value = FC_WEIGHT_LIGHT; else if (request.weight < (QFont::Normal + QFont::DemiBold) / 2) weight_value = FC_WEIGHT_MEDIUM; else if (request.weight < (QFont::DemiBold + QFont::Bold) / 2) weight_value = FC_WEIGHT_DEMIBOLD; else if (request.weight < (QFont::Bold + QFont::Black) / 2) weight_value = FC_WEIGHT_BOLD; FcPatternAddInteger(pattern, FC_WEIGHT, weight_value); int slant_value = FC_SLANT_ROMAN; if (request.style == QFont::StyleItalic) slant_value = FC_SLANT_ITALIC; else if (request.style == QFont::StyleOblique) slant_value = FC_SLANT_OBLIQUE; FcPatternAddInteger(pattern, FC_SLANT, slant_value); double size_value = request.pixelSize; FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size_value); int stretch = request.stretch; if (!stretch) stretch = 100; FcPatternAddInteger(pattern, FC_WIDTH, stretch); if (X11->display && QX11Info::appDepth(screen) <= 8) { // can't do antialiasing on 8bpp FcPatternAddBool(pattern, FC_ANTIALIAS, false); } else if (request.styleStrategy & (QFont::PreferAntialias|QFont::NoAntialias)) { FcPatternAddBool(pattern, FC_ANTIALIAS, !(request.styleStrategy & QFont::NoAntialias)); } if (script != QUnicodeTables::Common) { Q_ASSERT(script < QUnicodeTables::ScriptCount); FcLangSet *ls = FcLangSetCreate(); FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); FcPatternAddLangSet(pattern, FC_LANG, ls); FcLangSetDestroy(ls); }}static bool preferScalable(const QFontDef &request){ return request.styleStrategy & (QFont::PreferOutline|QFont::ForceOutline|QFont::PreferQuality|QFont::PreferAntialias);}static FcPattern *getFcPattern(const QFontPrivate *fp, int script, const QFontDef &request){ if (!X11->has_fontconfig) return 0; FcPattern *pattern = FcPatternCreate(); if (!pattern) return 0; FcValue value; value.type = FcTypeString; QtFontDesc desc; QStringList families_and_foundries = familyList(request); for (int i = 0; i < families_and_foundries.size(); ++i) { QString family, foundry; parseFontName(families_and_foundries.at(i), foundry, family); if (!family.isEmpty()) { QByteArray cs = family.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAdd(pattern, FC_FAMILY, value, FcTrue); } if (i == 0) { ::match(script, request, family, foundry, -1, &desc); if (!foundry.isEmpty()) { QByteArray cs = foundry.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAddWeak(pattern, FC_FOUNDRY, value, FcTrue); } } } const char *stylehint = styleHint(request); if (stylehint) { value.u.s = (const FcChar8 *)stylehint; FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); } if (!request.ignorePitch) { char pitch_value = FC_PROPORTIONAL; if (request.fixedPitch || (desc.family && desc.family->fixedPitch)) pitch_value = FC_MONO; FcPatternAddInteger(pattern, FC_SPACING, pitch_value); } FcPatternAddBool(pattern, FC_OUTLINE, !(request.styleStrategy & QFont::PreferBitmap)); if (::preferScalable(request) || (desc.style && desc.style->smoothScalable)) FcPatternAddBool(pattern, FC_SCALABLE, true); qt_addPatternProps(pattern, fp->screen, script, request); FcDefaultSubstitute(pattern); FcConfigSubstitute(0, pattern, FcMatchPattern); FcConfigSubstitute(0, pattern, FcMatchFont); // these should only get added to the pattern _after_ substitution // append the default fallback font for the specified script extern QString qt_fallback_font_family(int); QString fallback = qt_fallback_font_family(script); if (!fallback.isEmpty()) { QByteArray cs = fallback.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); } // add the default family QString defaultFamily = QApplication::font().family(); QByteArray cs = defaultFamily.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); // add QFont::defaultFamily() to the list, for compatibility with // previous versions defaultFamily = QApplication::font().defaultFamily(); cs = defaultFamily.toUtf8(); value.u.s = (const FcChar8 *)cs.data(); FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); return pattern;}static void FcFontSetRemove(FcFontSet *fs, int at){ Q_ASSERT(at < fs->nfont); FcPatternDestroy(fs->fonts[at]); int len = (--fs->nfont - at) * sizeof(FcPattern *);; if (len > 0) memmove(fs->fonts + at, fs->fonts + at + 1, len);}static QFontEngine *tryPatternLoad(FcPattern *p, int screen, const QFontDef &request, int script){#ifdef FONT_MATCH_DEBUG FcChar8 *fam; FcPatternGetString(p, FC_FAMILY, 0, &fam); FM_DEBUG("==== trying %s\n", fam);#endif FM_DEBUG("passes charset test\n"); FcPattern *pattern = FcPatternDuplicate(p);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -