📄 qfontdatabase_x11.cpp
字号:
// add properties back in as the font selected from the // list doesn't contain them. qt_addPatternProps(pattern, screen, script, request); FcConfigSubstitute(0, pattern, FcMatchPattern); FcDefaultSubstitute(pattern); FcResult res; FcPattern *match = FcFontMatch(0, pattern, &res); QFontEngineX11FT *engine = 0; if (script != QUnicodeTables::Common) { // 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(match, FC_CHARSET, 0, &cs) != FcResultMatch) goto done; if (!FcCharSetHasChar(cs, specialChars[script])) goto done; } else { FcLangSet *langSet = 0; if (FcPatternGetLangSet(match, FC_LANG, 0, &langSet) != FcResultMatch) goto done; if (FcLangSetHasLang(langSet, (const FcChar8*)specialLanguages[script]) != FcLangEqual) goto done; } } // enforce non-antialiasing if requested. the ft font engine looks at this property. if (request.styleStrategy & QFont::NoAntialias) { FcPatternDel(match, FC_ANTIALIAS); FcPatternAddBool(match, FC_ANTIALIAS, false); } engine = new QFontEngineX11FT(match, qt_FcPatternToQFontDef(match, request), screen); if (engine->invalid()) { FM_DEBUG(" --> invalid!\n"); delete engine; engine = 0; } else if (scriptRequiresOpenType(script)) { QOpenType *ot = engine->openType(); if (!ot || !ot->supportsScript(script)) { FM_DEBUG(" OpenType support missing for script\n"); delete engine; engine = 0; } }done: FcPatternDestroy(pattern); return engine;}FcFontSet *qt_fontSetForPattern(FcPattern *pattern, const QFontDef &request){ 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 FcBool forceScalable = request.styleStrategy & QFont::ForceOutline; // 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); return fs;}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);#ifdef FONT_MATCH_DEBUG FM_DEBUG("\n\nfinal FcPattern contains:\n"); FcPatternPrint(pattern);#endif QFontEngine *fe = 0; fe = tryPatternLoad(pattern, fp->screen, request, script); if (!fe) { FcFontSet *fs = qt_fontSetForPattern(pattern, request); for (int i = 0; !fe && i < fs->nfont; ++i) fe = tryPatternLoad(fs->fonts[i], fp->screen, request, script); FcFontSetDestroy(fs); FM_DEBUG("engine for script %d is %s\n", script, fe ? fe->fontDef.family.toLatin1().data(): "(null)"); } if (fe && script == QUnicodeTables::Common && !(request.styleStrategy & QFont::NoFontMerging) && !fe->symbol) { fe = new QFontEngineMultiFT(fe, pattern, fp->screen, request); } else { FcPatternDestroy(pattern); } return fe;}static FcPattern *queryFont(const FcChar8 *file, const QByteArray &data, int id, FcBlanks *blanks, int *count){#if FC_VERSION < 20402 Q_UNUSED(data) return FcFreeTypeQuery(file, id, blanks, count);#else if (data.isEmpty()) return FcFreeTypeQuery(file, id, blanks, count); extern FT_Library qt_getFreetype(); FT_Library lib = qt_getFreetype(); FcPattern *pattern = 0; FT_Face face; if (!FT_New_Memory_Face(lib, (const FT_Byte *)data.constData(), data.size(), id, &face)) { *count = face->num_faces; pattern = FcFreeTypeQueryFace(face, file, id, blanks); FT_Done_Face(face); } return pattern;#endif}#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()))) if (!(xfs = XLoadQueryFont(QX11Info::display(), "fixed"))) 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 || (request.styleStrategy & QFont::NoFontMerging) || (desc.family && desc.family->writingSystems[QFontDatabase::Symbol] & QtFontFamily::Supported)) { 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);#ifndef QT_NO_FONTCONFIG } else if (X11->has_fontconfig) { fe = loadFc(d, script, req);#endif } else { fe = loadXlfd(d->screen, script, req); } if (!fe) { fe = new QFontEngineBox(req.pixelSize); fe->fontDef = QFontDef(); } } if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) { for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) { if (!d->engineData->engines[i]) { d->engineData->engines[i] = fe; fe->ref.ref(); } } } else { d->engineData->engines[script] = fe; fe->ref.ref(); } QFontCache::instance->insertEngine(key, fe);}static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt){#if defined(QT_NO_FONTCONFIG) return;#else if (!X11->has_fontconfig) return; FcConfig *config = FcConfigGetCurrent(); if (!config) return; FcFontSet *set = FcConfigGetFonts(config, FcSetApplication); if (!set) { FcConfigAppFontAddFile(config, (const FcChar8 *)":/non-existant"); set = FcConfigGetFonts(config, FcSetApplication); // try again if (!set) return; } QString fileNameForQuery = fnt->fileName;#if FC_VERSION < 20402 QTemporaryFile tmp; if (!fnt->data.isEmpty()) { if (!tmp.open()) return; tmp.write(fnt->data); tmp.flush(); fileNameForQuery = tmp.fileName(); }#endif int id = 0; FcBlanks *blanks = FcConfigGetBlanks(0); int count = 0; QStringList families; FcPattern *pattern = 0; do { pattern = queryFont((const FcChar8 *)QFile::encodeName(fileNameForQuery).constData(), fnt->data, id, blanks, &count); if (!pattern) return; FcPatternDel(pattern, FC_FILE); FcPatternAddString(pattern, FC_FILE, (const FcChar8 *)fnt->fileName.toUtf8().constData()); FcChar8 *fam = 0; if (FcPatternGetString(pattern, FC_FAMILY, 0, &fam) == FcResultMatch) { QString family = QString::fromUtf8(reinterpret_cast<const char *>(fam)); family.replace(QLatin1Char('-'), QLatin1Char(' ')); family.remove(QLatin1Char('/')); families << family; } if (!FcFontSetAdd(se
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -