📄 qfontdatabase_x11.cpp
字号:
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 (QX11Info::appDepth(fp->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(); FcPatternAddWeak(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); addPatternProps(pattern, fp, 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); // this small hack changes all weak bindings into strong ones FcPattern *p = FcPatternDuplicate(pattern); FcPatternDestroy(pattern); return p;}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 *loadFc(const QFontPrivate *fp, int script, const QFontDef &request){ FM_DEBUG("===================== loadFc: script=%d family='%s'\n", script, request.family.toLatin1().data()); FcPattern *pattern = getFcPattern(fp, script, request); FcBool forceScalable = request.styleStrategy & QFont::ForceOutline;#ifdef FONT_MATCH_DEBUG FM_DEBUG("\n\nfinal FcPattern contains:\n"); FcPatternPrint(pattern);#endif FcResult result; FcFontSet *fs = FcFontSort(0, pattern, FcTrue, 0, &result);#ifdef FONT_MATCH_DEBUG FM_DEBUG("first font in fontset:\n"); FcPatternPrint(fs->fonts[0]);#endif FcPatternDestroy(pattern); if (!fs) return 0; // remove fonts if they are not scalable (and should be) if (forceScalable) { for (int i = 0; i < fs->nfont; ++i) { FcPattern *font = fs->fonts[i]; FcResult res; FcBool scalable; res = FcPatternGetBool(font, FC_SCALABLE, 0, &scalable); if (res != FcResultMatch || !scalable) { FcFontSetRemove(fs, i);#ifdef FONT_MATCH_DEBUG FM_DEBUG("removing pattern:"); FcPatternPrint(font);#endif --i; // go back one } } } FM_DEBUG("final pattern contains %d fonts\n", fs->nfont); QFontEngine *fe = 0; if (script != QUnicodeTables::Common) { // load a single font for the script for (int i = 0; !fe && i < fs->nfont; ++i) { FcChar8 *fam; FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, &fam); FM_DEBUG("==== trying %s\n", fam); // skip font if it doesn't support the language we want if (specialChars[script]) { // need to check the charset, as the langset doesn't work for these scripts FcCharSet *cs; if (FcPatternGetCharSet(fs->fonts[i], FC_CHARSET, 0, &cs) != FcResultMatch) continue; if (!FcCharSetHasChar(cs, specialChars[script])) continue; } else { FcLangSet *langSet = 0; if (FcPatternGetLangSet(fs->fonts[i], FC_LANG, 0, &langSet) != FcResultMatch) continue; if (FcLangSetHasLang(langSet, (const FcChar8*)specialLanguages[script]) != FcLangEqual) continue; } FM_DEBUG("passes charset test\n"); FcPattern *pattern = FcPatternDuplicate(fs->fonts[i]); // add properties back in as the font selected from the // list doesn't contain them. addPatternProps(pattern, fp, script, request); FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult res; FcPattern *match = FcFontMatch(0, pattern, &res); QFontEngineFT *engine = new QFontEngineFT(match, qt_FcPatternToQFontDef(match, request), fp->screen); if (engine->invalid()) { FM_DEBUG(" --> invalid!\n"); delete engine; } else if (scriptRequiresOpenType(script)) { QOpenType *ot = engine->openType(); if (!ot || !ot->supportsScript(script)) { FM_DEBUG(" OpenType support missing for script\n"); delete engine; } else { fe = engine; } } else { fe = engine; } } FM_DEBUG("engine for script %d is %s\n", script, fe ? fe->fontDef.family.toLatin1().data(): "(null)"); } else if (fs->nfont) { // create a multi engine for the fontset fontconfig gave us FcFontSet *fontSet = FcFontSetCreate(); for (int i = 0; i < fs->nfont; ++i) { FcPattern *pattern = FcPatternDuplicate(fs->fonts[i]); // add properties back in as the font selected from the // list doesn't contain them. addPatternProps(pattern, fp, script, request); FcFontSetAdd(fontSet, pattern); } fe = new QFontEngineMultiFT(fontSet, fp->screen, request); } FcFontSetDestroy(fs); return fe;}#endif // QT_NO_FONTCONFIGstatic QFontEngine *loadRaw(const QFontPrivate *fp, const QFontDef &request){ Q_ASSERT(fp && fp->rawMode); QByteArray xlfd = request.family.toLatin1(); FM_DEBUG("Loading XLFD (rawmode) '%s'", xlfd.data()); QFontEngine *fe; XFontStruct *xfs; if (!(xfs = XLoadQueryFont(QX11Info::display(), xlfd.data()))) return 0; fe = new QFontEngineXLFD(xfs, xlfd, 0); if (! qt_fillFontDef(xfs, &fe->fontDef, fp->dpi) && ! qt_fillFontDef(xlfd, &fe->fontDef, fp->dpi)) fe->fontDef = QFontDef(); return fe;}QFontEngine *QFontDatabase::loadXlfd(int screen, int script, const QFontDef &request, int force_encoding_id){ QtFontDesc desc; FM_DEBUG() << "---> loadXlfd: request is" << request.family; QStringList families_and_foundries = ::familyList(request); const char *stylehint = styleHint(request); if (stylehint) families_and_foundries << QString::fromLatin1(stylehint); families_and_foundries << QString(); FM_DEBUG() << "loadXlfd: list is" << families_and_foundries; for (int i = 0; i < families_and_foundries.size(); ++i) { QString family, foundry; ::parseFontName(families_and_foundries.at(i), foundry, family); FM_DEBUG("loadXlfd: >>>>>>>>>>>>>>trying to match '%s' encoding=%d", family.toLatin1().data(), force_encoding_id); ::match(script, request, family, foundry, force_encoding_id, &desc); if (desc.family) break; } QFontEngine *fe = 0; if (force_encoding_id != -1 || script != QUnicodeTables::Common) { if (desc.family) { int px = desc.size->pixelSize; if (desc.style->smoothScalable && px == SMOOTH_SCALABLE) px = request.pixelSize; else if (desc.style->bitmapScalable && px == 0) px = request.pixelSize; QByteArray xlfd("-"); xlfd += desc.foundry->name.isEmpty() ? QByteArray("*") : desc.foundry->name.toLatin1(); xlfd += "-"; xlfd += desc.family->name.isEmpty() ? QByteArray("*") : desc.family->name.toLatin1(); xlfd += "-"; xlfd += desc.style->weightName ? desc.style->weightName : "*"; xlfd += "-"; xlfd += (desc.style->key.style == QFont::StyleItalic ? "i" : (desc.style->key.style == QFont::StyleOblique ? "o" : "r")); xlfd += "-"; xlfd += desc.style->setwidthName ? desc.style->setwidthName : "*"; // ### handle add-style xlfd += "-*-"; xlfd += QByteArray::number(px); xlfd += "-"; xlfd += QByteArray::number(desc.encoding->xpoint); xlfd += "-"; xlfd += QByteArray::number(desc.encoding->xres); xlfd += "-"; xlfd += QByteArray::number(desc.encoding->yres); xlfd += "-"; xlfd += desc.encoding->pitch; xlfd += "-"; xlfd += QByteArray::number(desc.encoding->avgwidth); xlfd += "-"; xlfd += xlfd_for_id(desc.encoding->encoding); FM_DEBUG(" using XLFD: %s\n", xlfd.data()); const int mib = xlfd_encoding[desc.encoding->encoding].mib; XFontStruct *xfs; if ((xfs = XLoadQueryFont(QX11Info::display(), xlfd))) { fe = new QFontEngineXLFD(xfs, xlfd, mib); const int dpi = QX11Info::appDpiY(); if (!qt_fillFontDef(xfs, &fe->fontDef, dpi) && !qt_fillFontDef(xlfd, &fe->fontDef, dpi)) { initFontDef(desc, request, &fe->fontDef); } } } if (!fe) { fe = new QFontEngineBox(request.pixelSize); fe->fontDef = QFontDef(); } } else { QList<int> encodings; if (desc.encoding) encodings.append(int(desc.encoding->encoding)); if (desc.size) { // append all other encodings for the matched font for (int i = 0; i < desc.size->count; ++i) { QtFontEncoding *e = desc.size->encodings + i; if (e == desc.encoding) continue; encodings.append(int(e->encoding)); } } // fill in the missing encodings const XlfdEncoding *enc = xlfd_encoding; for (; enc->name; ++enc) { if (!encodings.contains(enc->id)) encodings.append(enc->id); }#if defined(FONT_MATCH_DEBUG) FM_DEBUG(" using MultiXLFD, encodings:"); for (int i = 0; i < encodings.size(); ++i) { const int id = encodings.at(i); FM_DEBUG(" %2d: %s", xlfd_encoding[id].id, xlfd_encoding[id].name); }#endif fe = new QFontEngineMultiXLFD(request, encodings, screen); } return fe;}/*! \internal Loads a QFontEngine for the specified \a script that matches the QFontDef \e request member variable.*/void QFontDatabase::load(const QFontPrivate *d, int script){ Q_ASSERT(script >= 0 && script < QUnicodeTables::ScriptCount); if (!privateDb()->count) initializeDb(); // normalize the request to get better caching QFontDef req = d->request; if (req.pixelSize <= 0) req.pixelSize = qRound(qt_pixelSize(req.pointSize, d->dpi)); req.pointSize = 0; if (req.weight == 0) req.weight = QFont::Normal; if (req.stretch == 0) req.stretch = 100; QFontCache::Key key(req, d->rawMode ? QUnicodeTables::Common : script, d->screen); if (!d->engineData) getEngineData(d, key); // the cached engineData could have already loaded the engine we want if (d->engineData->engines[script]) return; // set it to the actual pointsize, so QFontInfo will do the right thing req.pointSize = qt_pointSize(req.pixelSize, d->dpi); QFontEngine *fe = QFontCache::instance->findEngine(key); if (!fe) { if (qt_enable_test_font && req.family == QLatin1String("__Qt__Box__Engine__")) { fe = new QTestFontEngine(req.pixelSize); fe->fontDef = req; } else if (d->rawMode) { fe = loadRaw(d, req); } else#ifndef QT_NO_FONTCONFIG if (X11->has_fontconfig) { fe = loadFc(d, script, req); } else#endif { fe = loadXlfd(d->screen, script, req); } if (!fe) { fe = new QFontEngineBox(req.pixelSize); fe->fontDef = QFontDef(); } } d->engineData->engines[script] = fe; fe->ref.ref(); QFontCache::instance->insertEngine(key, fe);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -