x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

UCanvas::StrLen does not take kerning into account and returns a wrong size

I wanted to create a small Slate Widget that displays two pieces of text in diffrent font sizes directly next to each other. After rendering the first piece, and advancing my rendering position by the value UCanvas::StrLen( ... ) for it, I drew the second piece. The result was the following:

alt text

As you can see, the second piece is displaced. After tracing the problem through the sourcecode, I discovered that UCanvas::MeasureStringInternal used the Kerningvalues returned by UFont::GetCharKerning(...), and that these seem be 0 for all characters, which seems to be connected to the newer SlateFonts, whose Kerning values are stored in the FSlateFontCache. My solution to this problem was to write a new measuring method. Please keep in mind that this most likely does not cover all diffrent types of text formatting that can occur:

 FVector2D CalculateStringLength(FString String, FSlateFontInfo& FontInfo,float Scale)
 {
     //Emtpy string
     if (String.Len() == 0)
     {
         return FVector2D(0, 0);
     }
 
     //Characterlist from the SlateFontCache
     TSharedRef<FSlateFontCache> FontCache = FSlateApplication::Get().GetRenderer()->GetFontCache();
     FCharacterList& CharacterList = FontCache->GetCharacterList(FontInfo, Scale);
 
     const TCHAR* pCurrentPos;                        //where are we now in the string ?
     const TCHAR* pPrevPos = 0;                         //which was the last string ( needed to scaling )
     const TCHAR* pText = *String;                     //Chararray to be iterated
     const int32 TextLength = String.Len();           //Length of the String
     const int32 YIncrement = FontCache->GetMaxCharacterHeight(FontInfo, Scale);
 
     FVector2D Size = FVector2D(0, YIncrement);
     //While our pointer is valid and we are within the bounds of the chararray ...
     for (pCurrentPos = pText; *pCurrentPos && pCurrentPos < pText + TextLength; ++pCurrentPos)
     {
         TCHAR currentChar = *pCurrentPos;
         Size.X += CharacterList[currentChar].XAdvance; //Add the width of the current char to the counter
 
         if (currentChar == TEXT('\n') && pCurrentPos + 1 < pText + TextLength && pCurrentPos + 1)
         { // Char is a newline and string is not at end
             Size.Y += YIncrement;
             pPrevPos = 0; //No kerning when beginning a new line
         }
         else if (pPrevPos != 0)
         {
             //Do not forget to take Kerning into account
             Size.X += FontCache->GetKerning(FontCache->GetDefaultFontData(FontInfo), FontInfo.Size, *pPrevPos, currentChar, Scale);
         }
 
         //Cache last char
         pPrevPos = pCurrentPos;
     }
 
     return Size;
 }

These one uses the values provided by the SlateFontInfo and yields correct result:

alt text

Can anyone else confirm this problem ?

Product Version: Not Selected
Tags:
more ▼

asked Jan 23 '15 at 08:03 PM in Bug Reports

avatar image

Sebi330
1 1 3

(comments are locked)
10|2000 characters needed characters left
Viewable by all users

1 answer: sort voted first

Ah, despite the fact that Canvas accepts Slate font data, you're not actually using Slate here :)

UFont::GetCharKerning should be returning the correct kerning for your font, however Canvas text measuring can currently only work with the "legacy" font info from the UFont - see UFont::GetLegacySlateFontInfo() - so if you're passing a custom FSlateFontInfo when drawing your FCanvasTextItem, then your measuring may be off.

A better way to measure the text if you know you're dealing with a composite font (which you are) is to just use the Slate font measurer directly.

 const TSharedRef<FSlateFontMeasure> FontMeasure = FSlateApplication::Get().GetRenderer()->GetFontMeasureService();
  FontMeasure->Measure(YourText, YourFontInfo);

Alternatively, once you've called Draw on your FCanavsTextItem, its DrawnSize variable will be filled in with the size of the text that was just drawn.

Could you post the code used when setting up the FCanvasTextItem(s) that you draw with, and also a link to your font (if possible, I realise it may not be available publicly or freely).

more ▼

answered Jan 23 '15 at 08:28 PM

avatar image

Jamie Dale STAFF
7.4k 176 66 304

avatar image Sebi330 Jan 28 '15 at 05:24 PM

Thank you, your hint about the measuring system already helped ma a lot. Sorry for the late anwser ;(

(comments are locked)
10|2000 characters needed characters left
Viewable by all users
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question