void tst_QFontMetrics::inFontUcs4() { int id = QFontDatabase::addApplicationFont(":/fonts/ucs4font.ttf"); QVERIFY(id >= 0); QFont font("QtTestUcs4"); { QFontMetrics fm(font); QVERIFY(fm.inFontUcs4(0x1D7FF)); } { QFontMetricsF fm(font); QVERIFY(fm.inFontUcs4(0x1D7FF)); } { QFontEngine *engine = QFontPrivate::get(font)->engineForScript(QChar::Script_Common); QGlyphLayout glyphs; glyphs.numGlyphs = 3; uint buf[3]; glyphs.glyphs = buf; QString string; { string.append(QChar::highSurrogate(0x1D7FF)); string.append(QChar::lowSurrogate(0x1D7FF)); glyphs.numGlyphs = 3; glyphs.glyphs[0] = 0; QVERIFY(engine->stringToCMap(string.constData(), string.size(), &glyphs, &glyphs.numGlyphs, QFontEngine::GlyphIndicesOnly)); QCOMPARE(glyphs.numGlyphs, 1); QCOMPARE(glyphs.glyphs[0], uint(1)); } { string.clear(); string.append(QChar::ObjectReplacementCharacter); glyphs.numGlyphs = 3; glyphs.glyphs[0] = 0; QVERIFY(engine->stringToCMap(string.constData(), string.size(), &glyphs, &glyphs.numGlyphs, QFontEngine::GlyphIndicesOnly)); QVERIFY(glyphs.glyphs[0] != 1); } } QFontDatabase::removeApplicationFont(id); }
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; }
static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft) { QFontEngine *fe = (QFontEngine *)font->userData; QVarLengthGlyphLayoutArray qglyphs(*numGlyphs); QTextEngine::ShaperFlags shaperFlags(QTextEngine::GlyphIndicesOnly); if (rightToLeft) shaperFlags |= QTextEngine::RightToLeft; int nGlyphs = *numGlyphs; bool result = fe->stringToCMap(reinterpret_cast<const QChar *>(string), length, &qglyphs, &nGlyphs, shaperFlags); *numGlyphs = nGlyphs; if (!result) return false; for (hb_uint32 i = 0; i < *numGlyphs; ++i) glyphs[i] = qglyphs.glyphs[i]; return true; }