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"

How do you dynamically create a UFont at Runtime in c++?

How do you dynamically create a UFont object at runtime from a .ttf font in c++? Assuming I can get the .ttf font into memory as bytes, TArray, how can I create UFontFace from that and plug it into a UFont?

I want my users to be able to upload custom .ttf fonts in addition to the ones that I provide for maximum customization.

Product Version: UE 4.17
Tags:
more ▼

asked Sep 28 '17 at 09:54 AM in C++ Programming

avatar image

DanimalsOnParade
68 4 11 14

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

1 answer: sort voted first

It's simpler if you can write the font to disk and avoid dealing with UFontFace.

FLegacySlateFontInfoCache::GetSystemFont provides an example of this, and you'd want to do something similar but populate the CompositeFont inside your UFont (you'd also need to make sure that FontCacheType is set to EFontCacheType::Runtime on your UFont).

If you do want to use a UFontFace then you'd need to populate its FontFaceData via a call to FFontFaceData::MakeFontFaceData passing in your raw TTF data (you'd also need to make sure that LoadingPolicy is set to EFontLoadingPolicy::Inline on your UFontFace). It's then just a case of using that UFontFace as the asset on the FFontData for the CompositeFont inside your UFont.

more ▼

answered Sep 28 '17 at 01:54 PM

avatar image

Jamie Dale STAFF
7.4k 176 66 304

avatar image DanimalsOnParade Sep 29 '17 at 01:47 AM

Thanks for your reply!

I'm working with the HTML5 platform, so I don't think writing to disk is an option here.

My understanding of what you suggested for the raw TTF data is -

  1. Create an FFontFaceData struct using FFontFaceData::MakeFontFaceData( .ttf file as bytes TArray ). Will I need to strip any headers or anything out of the .ttf file as bytes?

  2. Create an FFontFaceDataRef using the FFontFaceData from step 1.

  3. Create a new UFontFace object and set it's public member variable FontFaceData to the FFontFaceDataRef from step 2.

From here I'm unsure on how you would make an FCompositeFont from the UFontFace. How do you do that?

Once I have the FCompositeFont, then I can just create a new UFont object and set the UFont's CompositeFont to the newly created FCompositeFont? Then the UFont will be ready to use in UMG and such?

avatar image Jamie Dale STAFF Sep 29 '17 at 01:33 PM
 UFontFace* FontFace = NewObject<UFontFace>(...);
 FontFace->LoadingPolicy = EFontLoadingPolicy::Inline;
 FontFace->FontFaceData = FFontFaceData::MakeFontFaceData(...);
 
 UFont* Font = NewObject<UFont>(...);
 Font->FontCacheType = EFontCacheType::Runtime;
 FTypefaceEntry& TypefaceEntry = Font->CompositeFont.DefaultTypeface.Fonts[Font->CompositeFont.DefaultTypeface.Fonts.AddDefaulted()];
 TypefaceEntry.Font = FFontData(FontFace);

Something like that. Note that at that point in time nothing is keeping your font from being GC'd, but if you use it with a UMG widget then the widget will keep it alive (there are also other ways to keep an object alive).

Also note that MakeFontFaceData takes an r-value reference, so you'll either need to MoveTemp or CopyTemp your data into it (depending on whether you still need your source array afterwards).

Will I need to strip any headers or anything out of the .ttf file as bytes?

No, it's just raw TTF/OTF payload data. FreeType is what actually makes use of the data.

avatar image DanimalsOnParade Sep 30 '17 at 05:30 AM

This worked! Thank you so much!!

avatar image MichaelWion Feb 24 '19 at 04:48 AM

For anyone running into GC issues, try this:

 // After making the font
 FontFace->AddToRoot();
 Font->AddToRoot();
 
 ...
 
 // Later on, when exiting your game or releasing resources
 FontFace->RemoveFromRoot();
 FontFace->ConditionalBeginDestroy();
 Font->RemoveFromRoot();
 Font->ConditionalBeginDestroy();
(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