📄 qfont.cpp
字号:
{ QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); Q_ASSERT(engine != 0); return engine->fontDef.style != QFont::StyleNormal;}/*! Returns the style value of the matched window system font. \sa QFont::style()*/QFont::Style QFontInfo::style() const{ QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); Q_ASSERT(engine != 0); return (QFont::Style)engine->fontDef.style;}/*! Returns the weight of the matched window system font. \sa QFont::weight(), bold()*/int QFontInfo::weight() const{ QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); Q_ASSERT(engine != 0); return engine->fontDef.weight;}/*! \fn bool QFontInfo::bold() const Returns true if weight() would return a value greater than QFont::Normal; otherwise returns false. \sa weight(), QFont::bold()*//*! Returns the underline value of the matched window system font. \sa QFont::underline() \internal Here we read the underline flag directly from the QFont. This is OK for X11 and for Windows because we always get what we want.*/bool QFontInfo::underline() const{ return d->underline;}/*! Returns the overline value of the matched window system font. \sa QFont::overline() \internal Here we read the overline flag directly from the QFont. This is OK for X11 and for Windows because we always get what we want.*/bool QFontInfo::overline() const{ return d->overline;}/*! Returns the strikeout value of the matched window system font. \sa QFont::strikeOut() \internal Here we read the strikeOut flag directly from the QFont. This is OK for X11 and for Windows because we always get what we want.*/bool QFontInfo::strikeOut() const{ return d->strikeOut;}/*! Returns the fixed pitch value of the matched window system font. \sa QFont::fixedPitch()*/bool QFontInfo::fixedPitch() const{ QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); Q_ASSERT(engine != 0);#ifdef Q_OS_MAC if (!engine->fontDef.fixedPitchComputed) { QChar ch[2] = { QChar('i'), QChar('m') }; QGlyphLayout g[2]; int l = 2; engine->stringToCMap(ch, 2, g, &l, 0); engine->fontDef.fixedPitch = g[0].advance.x == g[1].advance.x; engine->fontDef.fixedPitchComputed = true; }#endif return engine->fontDef.fixedPitch;}/*! Returns the style of the matched window system font. Currently only returns the style hint set in QFont. \sa QFont::styleHint() QFont::StyleHint*/QFont::StyleHint QFontInfo::styleHint() const{ QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); Q_ASSERT(engine != 0); return (QFont::StyleHint) engine->fontDef.styleHint;}/*! Returns true if the font is a raw mode font; otherwise returns false. If it is a raw mode font, all other functions in QFontInfo will return the same values set in the QFont, regardless of the font actually used. \sa QFont::rawMode()*/bool QFontInfo::rawMode() const{ return d->rawMode;}/*! Returns true if the matched window system font is exactly the same as the one specified by the font; otherwise returns false. \sa QFont::exactMatch()*/bool QFontInfo::exactMatch() const{ QFontEngine *engine = d->engineForScript(QUnicodeTables::Common); Q_ASSERT(engine != 0); return (d->rawMode ? engine->type() != QFontEngine::Box : d->request.exactMatch(engine->fontDef));}// **********************************************************************// QFontCache// **********************************************************************#ifdef QFONTCACHE_DEBUG// fast timeouts for debuggingstatic const int fast_timeout = 1000; // 1sstatic const int slow_timeout = 5000; // 5s#elsestatic const int fast_timeout = 10000; // 10sstatic const int slow_timeout = 300000; // 5m#endif // QFONTCACHE_DEBUGQFontCache *QFontCache::instance = 0;const uint QFontCache::min_cost = 4*1024; // 4mbQFontCache::QFontCache() : QObject(qApp), total_cost(0), max_cost(min_cost), current_timestamp(0), fast(false), timer_id(-1){ Q_ASSERT(instance == 0); instance = this;}QFontCache::~QFontCache(){ { EngineDataCache::Iterator it = engineDataCache.begin(), end = engineDataCache.end(); while (it != end) { if (it.value()->ref == 0) delete it.value(); else FC_DEBUG("QFontCache::~QFontCache: engineData %p still has refcount %d", it.value(), it.value()->ref.atomic); ++it; } } EngineCache::Iterator it = engineCache.begin(), end = engineCache.end(); while (it != end) { if (--it.value().data->cache_count == 0) { if (it.value().data->ref == 0) { FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %g %d %d %d %d)", it.value().data, it.key().script, it.key().def.pointSize, it.key().def.pixelSize, it.key().def.weight, it.key().def.style, it.key().def.fixedPitch); delete it.value().data; } else { FC_DEBUG("QFontCache::~QFontCache: engine = %p still has refcount %d", it.value().data, it.value().data->ref.atomic); } } ++it; } instance = 0;}#ifdef Q_WS_QWSvoid QFontCache::clear(){ { EngineDataCache::Iterator it = engineDataCache.begin(), end = engineDataCache.end(); while (it != end) { QFontEngineData *data = it.value(); if (data->engine) data->engine->ref.deref(); data->engine = 0; ++it; } } EngineCache::Iterator it = engineCache.begin(), end = engineCache.end(); while (it != end) { if (--it.value().data->cache_count == 0) { if (it.value().data->ref == 0) { FC_DEBUG("QFontCache::~QFontCache: deleting engine %p key=(%d / %g %d %d %d %d)", it.value().data, it.key().script, it.key().def.pointSize, it.key().def.pixelSize, it.key().def.weight, it.key().def.style, it.key().def.fixedPitch); delete it.value().data; } else { FC_DEBUG("QFontCache::~QFontCache: engine = %p still has refcount %d", it.value().data, it.value().data->ref.atomic); } } ++it; }}#endifQFontEngineData *QFontCache::findEngineData(const Key &key) const{ EngineDataCache::ConstIterator it = engineDataCache.find(key), end = engineDataCache.end(); if (it == end) return 0; // found return it.value();}void QFontCache::insertEngineData(const Key &key, QFontEngineData *engineData){ FC_DEBUG("QFontCache: inserting new engine data %p", engineData); engineDataCache.insert(key, engineData); increaseCost(sizeof(QFontEngineData));}QFontEngine *QFontCache::findEngine(const Key &key){ EngineCache::Iterator it = engineCache.find(key), end = engineCache.end(); if (it == end) return 0; // found... update the hitcount and timestamp it.value().hits++; it.value().timestamp = ++current_timestamp; FC_DEBUG("QFontCache: found font engine\n" " %p: timestamp %4u hits %3u ref %2d/%2d, type '%s'", it.value().data, it.value().timestamp, it.value().hits, it.value().data->ref.atomic, it.value().data->cache_count, it.value().data->name()); return it.value().data;}void QFontCache::insertEngine(const Key &key, QFontEngine *engine){ FC_DEBUG("QFontCache: inserting new engine %p", engine); Engine data(engine); data.timestamp = ++current_timestamp; engineCache.insert(key, data); // only increase the cost if this is the first time we insert the engine if (engine->cache_count == 0) increaseCost(engine->cache_cost); ++engine->cache_count;}void QFontCache::increaseCost(uint cost){ cost = (cost + 512) / 1024; // store cost in kb cost = cost > 0 ? cost : 1; total_cost += cost; FC_DEBUG(" COST: increased %u kb, total_cost %u kb, max_cost %u kb", cost, total_cost, max_cost); if (total_cost > max_cost) { max_cost = total_cost; if (timer_id == -1 || ! fast) { FC_DEBUG(" TIMER: starting fast timer (%d ms)", fast_timeout); if (timer_id != -1) killTimer(timer_id); timer_id = startTimer(fast_timeout); fast = true; } }}void QFontCache::decreaseCost(uint cost){ cost = (cost + 512) / 1024; // cost is stored in kb cost = cost > 0 ? cost : 1; Q_ASSERT(cost <= total_cost); total_cost -= cost; FC_DEBUG(" COST: decreased %u kb, total_cost %u kb, max_cost %u kb", cost, total_cost, max_cost);}#if defined(Q_WS_WIN) || defined (Q_WS_QWS)void QFontCache::cleanupPrinterFonts(){ FC_DEBUG("QFontCache::cleanupPrinterFonts"); { FC_DEBUG(" CLEAN engine data:"); // clean out all unused engine datas EngineDataCache::Iterator it = engineDataCache.begin(), end = engineDataCache.end(); while (it != end) { if (it.key().screen == 0) { ++it; continue; } if(it.value()->ref != 0) {#ifdef Q_WS_WIN for(int i = 0; i < QUnicodeTables::ScriptCount; ++i) { if(it.value()->engines[i]) { it.value()->engines[i]->ref.deref(); it.value()->engines[i] = 0; } }#else if (it.value()->engine) { it.value()->engine->ref.deref(); it.value()->engine = 0; }#endif ++it; } else { EngineDataCache::Iterator rem = it++; decreaseCost(sizeof(QFontEngineData)); FC_DEBUG(" %p", rem.value()); delete rem.value(); engineDataCache.erase(rem); } } } EngineCache::Iterator it = engineCache.begin(), end = engineCache.end(); while(it != end) { if (it.value().data->ref != 0 || it.key().screen == 0) { ++it; continue; } FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, type '%s'", it.value().data, it.value().timestamp, it.value().hits, it.value().data->ref.atomic, it.value().data->cache_count, it.value().data->name()); if (--it.value().data->cache_count == 0) { FC_DEBUG(" DELETE: last occurence in cache"); decreaseCost(it.value().data->cache_cost); delete it.value().data; } engineCache.erase(it++); }}#endifvoid QFontCache::timerEvent(QTimerEvent *){ FC_DEBUG("QFontCache::timerEvent: performing cache maintenance (timestamp %u)", current_timestamp); if (total_cost <= max_cost && max_cost <= min_cost) { FC_DEBUG(" cache redused sufficiently, stopping timer"); killTimer(timer_id); timer_id = -1; fast = false; return; } // go through the cache and count up everything in use uint in_use_cost = 0; { FC_DEBUG(" SWEEP engine data:"); // make sure the cost of each engine data is at least 1kb const uint engine_data_cost = sizeof(QFontEngineData) > 1024 ? sizeof(QFontEngineData) : 1024; EngineDataCache::ConstIterator it = engineDataCache.begin(), end = engineDataCache.end(); for (; it != end; ++it) {#ifdef QFONTCACHE_DEBUG FC_DEBUG(" %p: ref %2d", it.value(), int(it.value()->ref));# if defined(Q_WS_X11) || defined(Q_WS_WIN) // print out all engines for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) { if (! it.value()->engines[i]) continue; FC_DEBUG(" contains %p", it.value()->engines[i]); }# endif // Q_WS_X11 || Q_WS_WIN#endif // QFONTCACHE_DEBUG if (it.value()->ref != 0) in_use_cost += engine_data_cost; } } { FC_DEBUG(" SWEEP engine:"); EngineCache::ConstIterator it = engineCache.begin(), end = engineCache.end(); for (; it != end; ++it) { FC_DEBUG(" %p: timestamp %4u hits %2u ref %2d/%2d, cost %u bytes", it.value().data, it.value().timestamp, it.value().hits, it.value().data->ref.atomic, it.value().data->cache_count, it.value().data->cache_cost); if (it.value().data->ref != 0) in_use_cost += it.value().data->cache_cost / it.value().data->cache_count; } // attempt to make up for rounding errors in_use_cost += engineCache.size(); } in_use_cost = (in_use_cost + 512) / 1024; // cost is stored in kb /* calculate the new maximum cost for the cache NOTE: in_use_cost is *not* correct due to rounding errors in the above algorithm. instead of worrying about getting the calculation correct, we are more interested in spe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -