int QFontMetrics::width( QChar ch ) const { unsigned short uc = ch.unicode(); if ( uc < QFontEngineData::widthCacheSize && d->engineData && d->engineData->widthCache[ uc ] ) return d->engineData->widthCache[ uc ]; if ( ::category( ch ) == QChar::Mark_NonSpacing || qIsZeroWidthChar(ch.unicode())) return 0; QFont::Script script; SCRIPT_FOR_CHAR( script, ch ); QFontEngine *engine = d->engineForScript( script ); #ifdef QT_CHECK_STATE Q_ASSERT( engine != 0 ); #endif // QT_CHECK_STATE glyph_t glyphs[8]; advance_t advances[8]; int nglyphs = 7; engine->stringToCMap( &ch, 1, glyphs, advances, &nglyphs, FALSE ); // ### can nglyphs != 1 happen at all? Not currently I think if ( uc < QFontEngineData::widthCacheSize && advances[0] > 0 && advances[0] < 0x100 ) d->engineData->widthCache[ uc ] = advances[0]; return advances[0]; }
int QFontMetrics::charWidth( const QString &str, int pos ) const { if ( pos < 0 || pos > (int)str.length() ) return 0; const QChar &ch = str.unicode()[ pos ]; if ( ch.unicode() < QFontEngineData::widthCacheSize && d->engineData && d->engineData->widthCache[ ch.unicode() ] ) return (d->engineData->widthCache[ ch.unicode() ]*d->engineData->engine->scale)>>8; QFont::Script script; SCRIPT_FOR_CHAR( script, ch ); int width; if ( script >= QFont::Arabic && script <= QFont::Khmer ) { // complex script shaping. Have to do some hard work int from = QMAX( 0, pos - 8 ); int to = QMIN( (int)str.length(), pos + 8 ); QConstString cstr( str.unicode()+from, to-from); QTextEngine layout( cstr.string(), d ); layout.itemize( QTextEngine::WidthOnly ); width = layout.width( pos-from, 1 ); } else if ( ::category( ch ) == QChar::Mark_NonSpacing || qIsZeroWidthChar(ch.unicode())) { width = 0; } else { QFontEngine *engine = d->engineForScript( script ); #ifdef QT_CHECK_STATE Q_ASSERT( engine != 0 ); #endif // QT_CHECK_STATE glyph_t glyphs[8]; advance_t advances[8]; int nglyphs = 7; engine->stringToCMap( &ch, 1, glyphs, advances, &nglyphs, FALSE ); width = advances[0]; } if ( ch.unicode() < QFontEngineData::widthCacheSize && width > 0 && width < 0x100 ) d->engineData->widthCache[ ch.unicode() ] = width; return width; }
/*! Internal function that initializes the font system. \internal The font cache and font dict do not alloc the keys. The key is a QString which is shared between QFontPrivate and QXFontName. */ void QFont::initialize() { // create global font cache if ( ! QFontCache::instance ) (void) new QFontCache; #ifndef QT_NO_CODECS #ifndef QT_NO_BIG_CODECS static bool codecs_once = FALSE; if ( ! codecs_once ) { (void) new QFontJis0201Codec; (void) new QFontJis0208Codec; (void) new QFontKsc5601Codec; (void) new QFontGb2312Codec; (void) new QFontGbkCodec; (void) new QFontGb18030_0Codec; (void) new QFontBig5Codec; (void) new QFontBig5hkscsCodec; (void) new QFontLaoCodec; codecs_once = TRUE; } #endif // QT_NO_BIG_CODECS #endif // QT_NO_CODECS extern int qt_encoding_id_for_mib( int mib ); // from qfontdatabase_x11.cpp QTextCodec *codec = QTextCodec::codecForLocale(); // determine the default encoding id using the locale, otherwise // fallback to latin1 ( mib == 4 ) int mib = codec ? codec->mibEnum() : 4; // for asian locales, use the mib for the font codec instead of the locale codec switch (mib) { case 38: // eucKR mib = 36; break; case 2025: // GB2312 mib = 57; break; case 113: // GBK mib = -113; break; case 114: // GB18030 mib = -114; break; case 2026: // Big5 mib = -2026; break; case 2101: // Big5-HKSCS mib = -2101; break; case 16: // JIS7 mib = 15; break; case 17: // SJIS case 18: // eucJP mib = 63; break; } // get the default encoding id for the locale encoding... QFontPrivate::defaultEncodingID = qt_encoding_id_for_mib( mib ); // get some sample text based on the users locale. we use this to determine the // default script for the font system QCString oldlctime = setlocale(LC_TIME, 0); QCString lctime = setlocale(LC_TIME, ""); time_t ttmp = time(0); struct tm *tt = 0; char samp[64]; QString sample; if ( ttmp != -1 ) { #if defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) // use the reentrant versions of localtime() where available tm res; tt = localtime_r( &ttmp, &res ); #else tt = localtime( &ttmp ); #endif // QT_THREAD_SUPPORT && _POSIX_THREAD_SAFE_FUNCTIONS if ( tt != 0 && strftime( samp, 64, "%A%B", tt ) > 0 ) if ( codec ) sample = codec->toUnicode( samp ); } if ( ! sample.isNull() && ! sample.isEmpty() ) { QFont::Script cs = QFont::NoScript, tmp; const QChar *uc = sample.unicode(); QFontPrivate *priv = new QFontPrivate; for ( uint i = 0; i < sample.length(); i++ ) { SCRIPT_FOR_CHAR( tmp, *uc ); uc++; if ( tmp != cs && tmp != QFont::UnknownScript ) { cs = tmp; break; } } delete priv; if ( cs != QFont::UnknownScript ) QFontPrivate::defaultScript = cs; } setlocale( LC_TIME, oldlctime.data() ); }