Search Unity

Load font from mobile device and assign as fallback TMP_FontAsset

Discussion in 'Unity UI (uGUI) & TextMesh Pro' started by Alexfedel, Apr 6, 2019.

  1. Alexfedel

    Alexfedel

    Joined:
    Sep 25, 2015
    Posts:
    13
    I'm working on a mobile app with multi-language support, including Japanese. I do not want to include the Japanese font in the app, but I also want to use TextMesh Pro.
    The font should be loaded from the device and assigned as a fallback TMP_FontAsset to my standard TMP_FontAsset.
    I know unitys ui text-component is using this kind of system to make all characters of all languages available.

    I´m using Unity 2018.3.11f1 and TextMesh Pro 1.4.0 with Dynamic SDF.

    This is my code, but it is not working as expected. Does anyone know what I'm making wrong or is it not possible how I try?

    Code (CSharp):
    1.     public TMP_FontAsset defaultFontAsset;
    2.     public TextMeshProUGUI testLabel;
    3.    
    4.     private void AssignFallbackFont(){
    5.  
    6.         string[] fonts = Font.GetOSInstalledFontNames();
    7.  
    8.         for(int i = 0; i < fonts.Length; i++){
    9.            
    10.             /*
    11.             I know my android device has this font
    12.             and it should have all japanese characters
    13.             */
    14.             if(  fonts[i] == "Noto Sans CJK JP" ){
    15.                
    16.                 Font font = Font.CreateDynamicFontFromOSFont(fonts[i], 12);
    17.                
    18.                 // some japanese characters to test
    19.                 font.RequestCharactersInTexture("テスト");
    20.                
    21.                 TMP_FontAsset fontAsset = TMP_FontAsset.CreateFontAsset(font, 44, 5,  GlyphRenderMode.SDFAA, 512, 512, AtlasPopulationMode.Dynamic);
    22.                
    23.                 // this is not working it returns false
    24.                 bool success = fontAsset.TryAddCharacters("テスト");
    25.                 print(success);
    26.                
    27.                 defaultFontAsset.fallbackFontAssetTable.Add(fontAsset);
    28.                
    29.                 // I just see squares
    30.                 testLabel.text = "テスト";
    31.             }
    32.         }
    33.     }
     
  2. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    3,314
    This is not working because the font created by using CreateDynamicFontFromOSFont does not have a reference to the font file / font data unlike font files imported in the project with the Include Font Data property set to true.

    The FontEngine used by TMP, can create font assets from the file path of any given font. So if you have the path of this OS font files, then adding a new overload for the CreateFontAsset that would take this path could be added in TMP.

    Alternatively, I would need to make changes to Unity to either force the fontData to be referenced by Fonts created using CreateDynamicFontFromOSFont or modify the Font class to expose a reference to the file path for the font. Both of these options, are problematic only because they would require back porting the changes.
     
  3. Alexfedel

    Alexfedel

    Joined:
    Sep 25, 2015
    Posts:
    13
    I understand. I think it would be nice if TMP could create a FontAsset from a given font file path.
    However, I have to find a way to get the OS font file paths. It´s a bit unfortunate that Unity has a function "GetOSInstalledFontNames", but you only get the font names and not the absolute file path.

    It think TMP Pro is almost perfect with the new Dynamic SDF support. If sometime there would be a more or less simple solution to automatically get the OS fonts as fallback like unitys Text-Component does, so we wouldn't get any problems with different languages, I would be very grateful.

    Thank you for the great work!
     
    habitoti and MingweiWang like this.
  4. habitoti

    habitoti

    Joined:
    Feb 28, 2013
    Posts:
    96
    Absolutely agree! Mobile devices have at least one almost complete or very comprehensive Unicode font on board that would allow you to dynamically create whatever you haven't pre-rendered as font asset. Plus you'd instantly get a full set of Emojiis, not just a very limited subset.
     
  5. mdsitton

    mdsitton

    Joined:
    Jan 27, 2018
    Posts:
    35
    100% agree that this should be fixed. We're already having to ship cjk fonts with our game to be able to use TMP.
     
  6. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    3,314
    I am adding a new function called GetPathsToOSFonts() which will retrieve the paths to fonts installed on local devices.

    I am also modifying the Font constructor to allow users to pass a path to a local on device font retrieved with the previous new function. This newly created font will include the Font Data needed for TMP to create TMP_FontAssets at runtime from these fonts.

    This new functionality will be included in a future release of Unity 2018.4 and 2019.x. This will also require an updated version of the TMP package.

    See the following post.
     
    Last edited: Jun 16, 2019
  7. habitoti

    habitoti

    Joined:
    Feb 28, 2013
    Posts:
    96
    This sounds like an awesome and incredibly useful feature that could solve the font issues once and for all! Do you have a some more specific ETA?
     
  8. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    3,314
    Hopefully within the next 2 - 3 weeks.
     
  9. Alexfedel

    Alexfedel

    Joined:
    Sep 25, 2015
    Posts:
    13
    Thank you, it is working on Android. The android phones I tested all have "/system/fonts/NotoSansCJK-Regular.ttc", which I can use to create the TMP_FontAsset for japanese characters. I also search for some fallback font names if "NotoSansCJK-Regular" not exists.
    Unfortunately it is not working on iOS; GetPathsToOSFonts doesn't return any font paths. Probably you can't access iOS fonts? Although unitys Text component is able to load japanese fonts and GetOSInstalledFontNames() also returns valid japanese font names.
     
  10. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    3,314
    Prior to the inclusion of this feature, I did test GetPathsToOSFonts() on iOS so that should be working. I'll try taking another look over the next few days.
     
  11. Alexfedel

    Alexfedel

    Joined:
    Sep 25, 2015
    Posts:
    13
    I tested it on 3 different iOS devices and did not get any font paths. All devices have iOS 12. I use Unity 2019.2.4.
     
  12. Stephan_B

    Stephan_B

    Unity Technologies

    Joined:
    Feb 26, 2017
    Posts:
    3,314
    There is indeed an issue on iOS with getting the paths to OS fonts.

    I'll try looking into this over the weekend / early next week. I will provide an update as soon as I have more information.