📄 qfontdatabase.cpp
字号:
int best = 0; int dist = 0xffff; for ( int i = 0; i < foundry->count; i++ ) { QtFontStyle *style = foundry->styles[i]; int d = qAbs( styleKey.weight - style->key.weight ); if ( styleKey.stretch != 0 && style->key.stretch != 0 ) { d += qAbs( styleKey.stretch - style->key.stretch ); } if (styleKey.style != style->key.style) { if (styleKey.style != QFont::StyleNormal && style->key.style != QFont::StyleNormal) // one is italic, the other oblique d += 0x0001; else d += 0x1000; } if ( d < dist ) { best = i; dist = d; } } FM_DEBUG( " best style has distance 0x%x", dist ); return foundry->styles[best];}#if defined(Q_WS_X11)static QtFontEncoding *findEncoding(int script, int styleStrategy, QtFontSize *size, int force_encoding_id){ QtFontEncoding *encoding = 0; if (force_encoding_id >= 0) { encoding = size->encodingID(force_encoding_id); if (!encoding) FM_DEBUG(" required encoding_id not available"); return encoding; } if (styleStrategy & (QFont::OpenGLCompatible | QFont::PreferBitmap)) { FM_DEBUG(" PreferBitmap and/or OpenGL set, skipping Freetype"); } else { encoding = size->encodingID(-1); // -1 == prefer Freetype if (encoding) return encoding; } // FT not available, find an XLFD font, trying the default encoding first encoding = size->encodingID(QFontPrivate::defaultEncodingID); if (encoding) { // does it support the requested script? bool supportsScript = false; for (int ws = 1; !supportsScript && ws < QFontDatabase::WritingSystemsCount; ++ws) { if (scriptForWritingSystem[ws] != script) continue; supportsScript = writingSystems_for_xlfd_encoding[encoding->encoding][ws]; } if (!supportsScript) encoding = 0; } // find the first encoding that supports the requested script for (int ws = 1; !encoding && ws < QFontDatabase::WritingSystemsCount; ++ws) { if (scriptForWritingSystem[ws] != script) continue; for (int x = 0; !encoding && x < size->count; ++x) { const int enc = size->encodings[x].encoding; if (writingSystems_for_xlfd_encoding[enc][ws]) encoding = size->encodings + x; } } return encoding;}#endif // Q_WS_X11#if !defined(Q_WS_MAC)staticunsigned int bestFoundry(int script, unsigned int score, int styleStrategy, const QtFontFamily *family, const QString &foundry_name, QtFontStyle::Key styleKey, int pixelSize, char pitch, QtFontDesc *desc, int force_encoding_id){ Q_UNUSED(force_encoding_id); Q_UNUSED(script); Q_UNUSED(pitch); desc->foundry = 0; desc->style = 0; desc->size = 0; desc->encoding = 0; FM_DEBUG(" REMARK: looking for best foundry for family '%s' [%d]", family->name.toLatin1().constData(), family->count); for (int x = 0; x < family->count; ++x) { QtFontFoundry *foundry = family->foundries[x]; if (!foundry_name.isEmpty() && foundry->name.compare(foundry_name, Qt::CaseInsensitive) != 0) continue; FM_DEBUG(" looking for matching style in foundry '%s' %d", foundry->name.isEmpty() ? "-- none --" : foundry->name.toLatin1().constData(), foundry->count); QtFontStyle *style = bestStyle(foundry, styleKey); if (!style->smoothScalable && (styleStrategy & QFont::ForceOutline)) { FM_DEBUG(" ForceOutline set, but not smoothly scalable"); continue; } int px = -1; QtFontSize *size = 0; // 1. see if we have an exact matching size if (!(styleStrategy & QFont::ForceOutline)) { size = style->pixelSize(pixelSize); if (size) { FM_DEBUG(" found exact size match (%d pixels)", size->pixelSize); px = size->pixelSize; } } // 2. see if we have a smoothly scalable font if (!size && style->smoothScalable && ! (styleStrategy & QFont::PreferBitmap)) { size = style->pixelSize(SMOOTH_SCALABLE); if (size) { FM_DEBUG(" found smoothly scalable font (%d pixels)", pixelSize); px = pixelSize; } } // 3. see if we have a bitmap scalable font if (!size && style->bitmapScalable && (styleStrategy & QFont::PreferMatch)) { size = style->pixelSize(0); if (size) { FM_DEBUG(" found bitmap scalable font (%d pixels)", pixelSize); px = pixelSize; } }#ifdef Q_WS_X11 QtFontEncoding *encoding = 0;#endif // 4. find closest size match if (! size) { unsigned int distance = ~0u; for (int x = 0; x < style->count; ++x) {#ifdef Q_WS_X11 encoding = findEncoding(script, styleStrategy, style->pixelSizes + x, force_encoding_id); if (!encoding) { FM_DEBUG(" size %3d does not support the script we want", style->pixelSizes[x].pixelSize); continue; }#endif unsigned int d; if (style->pixelSizes[x].pixelSize < pixelSize) { // penalize sizes that are smaller than the // requested size, due to truncation from floating // point to integer conversions d = pixelSize - style->pixelSizes[x].pixelSize + 1; } else { d = style->pixelSizes[x].pixelSize - pixelSize; } if (d < distance) { distance = d; size = style->pixelSizes + x; FM_DEBUG(" best size so far: %3d (%d)", size->pixelSize, pixelSize); } } if (!size) { FM_DEBUG(" no size supports the script we want"); continue; } if (style->bitmapScalable && ! (styleStrategy & QFont::PreferQuality) && (distance * 10 / pixelSize) >= 2) { // the closest size is not close enough, go ahead and // use a bitmap scaled font size = style->pixelSize(0); px = pixelSize; } else { px = size->pixelSize; } }#ifdef Q_WS_X11 if (size) { encoding = findEncoding(script, styleStrategy, size, force_encoding_id); if (!encoding) size = 0; } if (! encoding) { FM_DEBUG(" foundry doesn't support the script we want"); continue; }#endif // Q_WS_X11 unsigned int this_score = 0x0000; enum { PitchMismatch = 0x4000, StyleMismatch = 0x2000, BitmapScaledPenalty = 0x1000, EncodingMismatch = 0x0002, XLFDPenalty = 0x0001 };#ifdef Q_WS_X11 if (encoding->encoding != -1) { this_score += XLFDPenalty; if (encoding->encoding != QFontPrivate::defaultEncodingID) this_score += EncodingMismatch; } if (pitch != '*') { if (!(pitch == 'm' && encoding->pitch == 'c') && pitch != encoding->pitch) this_score += PitchMismatch; }#else if (pitch != '*') {#if !defined(QWS) && defined(Q_OS_MAC) qt_mac_get_fixed_pitch(const_cast<QtFontFamily*>(family));#endif if ((pitch == 'm' && !family->fixedPitch) || (pitch == 'p' && family->fixedPitch)) this_score += PitchMismatch; }#endif if (styleKey != style->key) this_score += StyleMismatch; if (!style->smoothScalable && px != size->pixelSize) // bitmap scaled this_score += BitmapScaledPenalty; if (px != pixelSize) // close, but not exact, size match this_score += qAbs(px - pixelSize); if (this_score < score) { FM_DEBUG(" found a match: score %x best score so far %x", this_score, score); score = this_score; desc->foundry = foundry; desc->style = style; desc->size = size;#ifdef Q_WS_X11 desc->encoding = encoding;#endif // Q_WS_X11 } else { FM_DEBUG(" score %x no better than best %x", this_score, score); } } return score;}#endif#if !defined(Q_WS_MAC)/*! \internal Tries to find the best match for a given request and family/foundry*/static void match(int script, const QFontDef &request, const QString &family_name, const QString &foundry_name, int force_encoding_id, QtFontDesc *desc){ Q_UNUSED(force_encoding_id); QtFontStyle::Key styleKey; styleKey.style = request.style; styleKey.weight = request.weight; styleKey.stretch = request.stretch; char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p'; FM_DEBUG("QFontDatabase::match\n" " request:\n" " family: %s [%s], script: %d\n" " weight: %d, style: %d\n" " stretch: %d\n" " pixelSize: %d\n" " pitch: %c", family_name.isEmpty() ? "-- first in script --" : family_name.toLatin1().constData(), foundry_name.isEmpty() ? "-- any --" : foundry_name.toLatin1().constData(), script, request.weight, request.style, request.stretch, request.pixelSize, pitch);#if defined(FONT_MATCH_DEBUG) && defined(Q_WS_X11) if (force_encoding_id >= 0) { FM_DEBUG(" required encoding: %d", force_encoding_id); }#endif desc->family = 0; desc->foundry = 0; desc->style = 0; desc->size = 0; desc->encoding = 0; unsigned int score = ~0u; ::load(family_name, script); QFontDatabasePrivate *db = privateDb(); for (int x = 0; x < db->count; ++x) { QtFontDesc test; test.family = db->families[x]; if (!family_name.isEmpty() && test.family->name.compare(family_name, Qt::CaseInsensitive) != 0#ifdef Q_WS_WIN && test.family->english_name.compare(family_name, Qt::CaseInsensitive) != 0#endif ) continue; if (family_name.isEmpty()) ::load(test.family->name, script); uint score_adjust = 0; bool supported = (script == QUnicodeTables::Common); for (int ws = 1; !supported && ws < QFontDatabase::WritingSystemsCount; ++ws) { if (scriptForWritingSystem[ws] != script) continue; if (test.family->writingSystems[ws] & QtFontFamily::Supported) supported = true; } if (!supported) { // family not supported in the script we want continue; } // as we know the script is supported, we can be sure // to find a matching font here. unsigned int newscore = bestFoundry(script, score, request.styleStrategy, test.family, foundry_name, styleKey, request.pixelSize, pitch, &test, force_encoding_id); if (test.foundry == 0) { // the specific foundry was not found, so look for // any foundry matching our requirements newscore = bestFoundry(script, score, request.styleStrategy, test.family, QString(), styleKey, request.pixelSize, pitch, &test, force_encoding_id); } newscore += score_adjust; if (newscore < score) { score = newscore; *desc = test; } if (newscore < 10) // xlfd instead of FT... just accept it break; }}#endifstatic QString styleString(int weight, QFont::Style style){ QString result; if (weight >= QFont::Black) result = qApp->translate("QFontDatabase", "Black"); else if (weight >= QFont::Bold) result = qApp->translate("QFontDatabase", "Bold"); else if (weight >= QFont::DemiBold) result = qApp->translate("QFontDatabase", "Demi Bold"); else if (weight < QFont::Normal) result = qApp->translate("QFontDatabase", "Light"); if (style == QFont::StyleItalic) result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Italic"); else if (style == QFont::StyleOblique) result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Oblique"); if (result.isEmpty()) result = qApp->translate("QFontDatabase", "Normal"); return result.simplified();}/*! Returns a string that describes the style of the \a font. For example, "Bold Italic", "Bold", "Italic" or "Normal". An empty string may be returned.*/QString QFontDatabase::styleString(const QFont &font){ return ::styleString(font.weight(), font.style());}/*! Returns a string that describes the style of the \a fontInfo. For example, "Bold Italic", "Bold", "Italic" or "Normal". An empty string may be returned.*/QString QFontDatabase::styleString(const QFontInfo &fontInfo){ return ::styleString(fontInfo.weight(), fontInfo.style());}/*! \class QFontDatabase \brief The QFontDatabase class provides information about the fonts available in the underlying window system. \ingroup environment \ingroup multimedia \ingroup text The most common uses of this class are to query the database for the list of font families() and for the pointSizes() and styles() that are available for each family. An alternative to pointSizes() is smoothSizes() which returns the sizes at which a given family and style will look attractive. If the font family is available from two or more foundries the foundry name is included in the family name, e.g. "Helvetica [Adobe]" and "Helvetica [Cronyx]". When you specify a family you can either use the old hyphenated Qt 2.x "foundry-family" format, e.g. "Cronyx-Helvetica", or the new bracketed Qt 3.x "family [foundry]" format e.g. "Helvetica [Cronyx]". If the family has a foundry it is always returned, e.g. by families(), using the bracketed format. The font() function returns a QFont given a family, style and point size. A family and style combination can be checked to see if it is italic() or bold(), and to retrieve its weight(). Similarly we can call isBitmapScalable(), isSmoothlyScalable(), isScalable() and isFixedPitch(). Use the styleString() to obtain a text version of a style. The QFontDatabase class also supports some static functions, for example, standardSizes(). You can retrieve the description of a writing system using writingSystemName(), and a sample of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -