void SFontPool::SetDefaultFont(LPCTSTR lpszFaceName, LONG lSize,BYTE byCharset/*=DEFAULT_CHARSET*/) { SASSERT(GetCount()==1);//初始化前才可以调用该接口 RemoveKeyObject(FontKey(0)); _tcscpy_s(m_lfDefault.lfFaceName,_countof(m_lfDefault.lfFaceName),lpszFaceName); m_lfDefault.lfHeight = -abs(lSize); if(byCharset!=DEFAULT_CHARSET) m_lfDefault.lfCharSet = byCharset; SetKeyObject(FontKey(0),_CreateFont(m_lfDefault)); }
FMeasureCache* FSlateFontMeasure::FindOrAddMeasureCache( const FSlateFontInfo& InFontInfo, const float InFontScale ) const { #if USE_MEASURE_CACHING FSlateFontKey FontKey(InFontInfo, InFontScale); const FCompositeFont* const CompositeFont = InFontInfo.GetCompositeFont(); TSharedPtr< FSlateFontMeasureCache > FoundMeasureCache = FontToMeasureCache.FindRef( FontKey ); if( FoundMeasureCache.IsValid() ) { // Clear out this entry if it's stale so that we make a new one if( FoundMeasureCache->IsStale( CompositeFont ) ) { FoundMeasureCache.Reset(); FontToMeasureCache.Remove( FontKey ); } else { return &FoundMeasureCache->MeasureCache; } } FoundMeasureCache = MakeShareable( new FSlateFontMeasureCache( CompositeFont ) ); FontToMeasureCache.Add( FontKey, FoundMeasureCache ); return &FoundMeasureCache->MeasureCache; #endif return nullptr; }
SFontPool::SFontPool(IRenderFactory *pRendFactory) :m_RenderFactory(pRendFactory) { ::GetObjectA(::GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &m_lfDefault); m_lfDefault.lfHeight = -12; m_lfDefault.lfQuality = CLEARTYPE_QUALITY; _tcscpy(m_lfDefault.lfFaceName,_T("宋体")); m_pFunOnKeyRemoved=OnKeyRemoved; SetKeyObject(FontKey(0,m_lfDefault.lfFaceName),_CreateFont(m_lfDefault)); }
FVector2D FSlateFontMeasure::MeasureStringInternal( const FString& Text, int32 StartIndex, int32 EndIndex, const FSlateFontInfo& InFontInfo, bool IncludeKerningWithPrecedingChar, float FontScale, int32 StopAfterHorizontalOffset, ELastCharacterIndexFormat CharIndexFormat, int32& OutLastCharacterIndex ) const { SCOPE_CYCLE_COUNTER(STAT_SlateMeasureStringTime); FCharacterList& CharacterList = FontCache->GetCharacterList( InFontInfo, FontScale ); const uint16 MaxHeight = CharacterList.GetMaxHeight(); const bool DoesStartAtBeginning = StartIndex == 0; const bool DoesFinishAtEnd = EndIndex == Text.Len(); const int32 TextRangeLength = EndIndex - StartIndex; if ( EndIndex - StartIndex <= 0 || EndIndex <= 0 || StartIndex < 0 || EndIndex <= StartIndex ) { return FVector2D( 0, MaxHeight ); } #define USE_MEASURE_CACHING 1 #if USE_MEASURE_CACHING TSharedPtr< FMeasureCache > CurrentMeasureCache = NULL; // Do not cache strings which have small sizes or which have complicated measure requirements if( DoesStartAtBeginning && DoesFinishAtEnd && !IncludeKerningWithPrecedingChar && TextRangeLength > 5 && StopAfterHorizontalOffset == INDEX_NONE ) { FSlateFontKey FontKey(InFontInfo,FontScale); TSharedPtr< FMeasureCache > FoundMeasureCache = FontToMeasureCache.FindRef( FontKey ); if ( FoundMeasureCache.IsValid() ) { CurrentMeasureCache = FoundMeasureCache; const FVector2D* CachedMeasurement = CurrentMeasureCache->AccessItem( Text ); if( CachedMeasurement ) { return *CachedMeasurement; } } else { CurrentMeasureCache = MakeShareable( new FMeasureCache( FontMeasureConstants::MeasureCacheSize ) ); FontToMeasureCache.Add( FontKey, CurrentMeasureCache ); } } #endif // The size of the string FVector2D Size(0,0); // Widest line encountered while drawing this text. int32 MaxLineWidth = 0; // The width of the current line so far. int32 CurrentX = 0; // Accumulated height of this block of text int32 StringSizeY = MaxHeight; // The previous char (for kerning) TCHAR PreviousChar = 0; //If we are measuring a range then we should take into account the kerning with the character before the start of the range if ( !DoesStartAtBeginning && IncludeKerningWithPrecedingChar ) { PreviousChar = Text[ StartIndex - 1 ]; } int32 FinalPosX = 0; int32 CharIndex; for( CharIndex = StartIndex; CharIndex < EndIndex; ++CharIndex ) { TCHAR CurrentChar = Text[CharIndex]; const bool IsNewline = (CurrentChar == '\n'); if (IsNewline) { // New line means // 1) we accumulate total height StringSizeY += MaxHeight; // 2) update the longest line we've encountered MaxLineWidth = FMath::Max(CurrentX, MaxLineWidth); // 3) the next line starts at the beginning CurrentX = 0; } else { const FCharacterEntry& Entry = CharacterList[CurrentChar]; int32 Kerning = 0; if( CharIndex > 0 ) { Kerning = CharacterList.GetKerning( PreviousChar, CurrentChar ); } const int32 TotalCharSpacing = Kerning + Entry.HorizontalOffset + // Width is any kerning plus how much to advance the position when drawing a new character Entry.XAdvance; // How far we advance PreviousChar = CurrentChar; CurrentX += Kerning + Entry.XAdvance; // Were we asked to stop measuring after the specified horizontal offset in pixels? if( StopAfterHorizontalOffset != INDEX_NONE ) { if( CharIndexFormat == ELastCharacterIndexFormat::CharacterAtOffset ) { // Round our test toward the character's center position if( StopAfterHorizontalOffset < CurrentX - TotalCharSpacing / 2 ) { // We've reached the stopping point, so bail break; } } else if( CharIndexFormat == ELastCharacterIndexFormat::LastWholeCharacterBeforeOffset ) { if( StopAfterHorizontalOffset < CurrentX ) { --CharIndex; if ( CharIndex < StartIndex ) { CharIndex = INDEX_NONE; } // We've reached the stopping point, so bail break; } } } } } // We just finished a line, so need to update the longest line encountered. MaxLineWidth = FMath::Max(CurrentX, MaxLineWidth); Size.X = MaxLineWidth; Size.Y = StringSizeY; OutLastCharacterIndex = CharIndex; #if USE_MEASURE_CACHING if( StopAfterHorizontalOffset == INDEX_NONE && CurrentMeasureCache.IsValid() ) { CurrentMeasureCache->Add( Text, Size ); } #endif return Size; }