openfl / lime

A foundational Haxe framework for cross-platform development
https://lime.openfl.org/
MIT License
749 stars 362 forks source link

Multiple font assets specified using <font> tag aren't preloaded by lime.utils.Preloader #1758

Closed mallyskies closed 5 months ago

mallyskies commented 5 months ago

Declaring multiple fonts in a Lime project.xml file using the assets snippet below don't preload on HTML5 builds:

<assets path="/usr/local/lib/haxe/lib/openfl/9,3,2/assets/fonts"
        rename="fonts">
    <font path="fonts/NotoSans-Regular.ttf"/>
    <font path="fonts/NotoSerif-Regular.ttf"/>
    <font path="fonts/NotoMono-Regular.ttf"/>
</assets>

You can see this by creating a simple project, such as the AddingText sample project, adding the above to the project.xml file (using your own path to the TTF files), and running it with the verbose flag to enable verbose logging by Lime (e.g. openfl -verbose -debug test html5), which should produce this output:

[Log] [lime.utils.Preloader] Preloading asset library (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: assets/KatamotzIkasi.woff [BINARY] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: assets/KatamotzIkasi.svg [TEXT] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: assets/KatamotzIkasi.eot [BINARY] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: assets/KatamotzIkasi.ttf [FONT] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset:  [FONT] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: assets/KatamotzIkasi.woff [BINARY] (1/5) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: assets/KatamotzIkasi.eot [BINARY] (2/5) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: assets/KatamotzIkasi.svg [TEXT] (3/5) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: assets/KatamotzIkasi.ttf [FONT] (4/5) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset:  [FONT] (5/5) (AddingText.js, line 24958)
[Log] [lime.utils.Preloader] Loaded asset library [1/1] (AddingText.js, line 24958)
[Log] [lime.utils.Preloader] Preload complete (AddingText.js, line 24958)

The assets included by the sample project's existing <assets> tag are all loaded, but the three fonts added by the new tag are not mentioned, though there is a line stating "Loaded asset: [FONT] (5/5)" without any asset name. The explanation for that console output is due to how lime.utils.AssetLibrary.__fromManifest() processes the asset. On this statement, the id is assigned:

id = Reflect.hasField(asset, "id") ? asset.id : asset.path;

However, for the fonts using the <font> tag, they have no asset id at all and the path is the empty string "", which is why the output for [FONT] (5/5) doesn't show a path like the other assets. And since id is used as the key in a StringMap, only one font asset ends up being added to the map instead of three.

A fairly simple workaround is to include all the assets in a specified folder, or a subset using <assets include="..."/> or <assets exclude="..."/>. That's what the sample project does, and why its fonts do preload. Another workaround is to specify each font as a separate asset, like this:

<assets rename="fonts/NotoSans-Regular.ttf"
        path="/usr/local/lib/haxe/lib/openfl/9,3,2/assets/fonts/NotoSans-Regular.ttf"/>
<assets rename="fonts/NotoSerif-Regular.ttf"
        path="/usr/local/lib/haxe/lib/openfl/9,3,2/assets/fonts/NotoSerif-Regular.ttf"/>
<assets rename="fonts/NotoMono-Regular.ttf"
        path="/usr/local/lib/haxe/lib/openfl/9,3,2/assets/fonts/NotoMono-Regular.ttf"/>

Using this syntax, the verbose console output looks correct:

[Log] [lime.utils.Preloader] Preloading asset library (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: assets/KatamotzIkasi.woff [BINARY] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: assets/KatamotzIkasi.svg [TEXT] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: assets/KatamotzIkasi.eot [BINARY] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: assets/KatamotzIkasi.ttf [FONT] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: fonts/NotoSans-Regular.ttf [FONT] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: fonts/NotoSerif-Regular.ttf [FONT] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Preloading asset: fonts/NotoMono-Regular.ttf [FONT] (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: assets/KatamotzIkasi.woff [BINARY] (1/7) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: assets/KatamotzIkasi.eot [BINARY] (2/7) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: assets/KatamotzIkasi.svg [TEXT] (3/7) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: assets/KatamotzIkasi.ttf [FONT] (4/7) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: fonts/NotoSans-Regular.ttf [FONT] (5/7) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: fonts/NotoSerif-Regular.ttf [FONT] (6/7) (AddingText.js, line 24958)
[Log] [lime.utils.AssetLibrary] Loaded asset: fonts/NotoMono-Regular.ttf [FONT] (7/7) (AddingText.js, line 24958)
[Log] [lime.utils.Preloader] Loaded asset library [1/1] (AddingText.js, line 24958)

Since the workaround is fairly straightforward, I don't think this issue is particularly important to fix. But I wanted it documented for others since it isn't clear how to successfully preload fonts for HTML5 targets in OpenFL. I tested this using OpenFL 9.3.2 and Lime 8.0.2, but I suspect it's been this way a long time.

player-03 commented 5 months ago
<assets path="/usr/local/lib/haxe/lib/openfl/9,3,2/assets/fonts"
        rename="fonts">
    <font path="fonts/NotoSans-Regular.ttf"/>
    <font path="fonts/NotoSerif-Regular.ttf"/>
    <font path="fonts/NotoMono-Regular.ttf"/>
</assets>

I assume this was a typo? Because that would produce "/usr/local/lib/haxe/lib/openfl/9,3,2/assets/fonts/fonts/NotoSans-Regular.ttf", which shouldn't exist.

There were a couple other bits I couldn't reproduce either, but it all ended up being close enough. Your insight about the id being an empty string was correct, and that saved me a bunch of time tracking down the source. So, thanks for the detailed report!

mallyskies commented 5 months ago

Yep, that was a typo from copy-pasting my example code's paths incorrectly. The paths should just be the filename of the fonts, not including the prefix "fonts/".

Glad to hear it was easy to fix! It was a bit tricky to find the bug, but fortunately I had another project that worked using the alternate assets definition so I was able to narrow in on it by seeing where the behavior diverged.


From: player-03 @.> Sent: Sunday, February 11, 2024 7:33 PM To: openfl/lime @.> Cc: mallyskies @.>; Author @.> Subject: Re: [openfl/lime] Multiple font assets specified using tag aren't preloaded by lime.utils.Preloader (Issue #1758)

<assets path="/usr/local/lib/haxe/lib/openfl/9,3,2/assets/fonts" rename="fonts">

I assume this was a typo? Because that would produce "/usr/local/lib/haxe/lib/openfl/9,3,2/assets/fonts/fonts/NotoSans-Regular.ttf", which shouldn't exist.

There were a couple other bits I couldn't reproduce either, but it all ended up being close enough. Your insight about the id being an empty string was correct, and that saved me a bunch of time tracking down the source. So, thanks for the detailed report!

— Reply to this email directly, view it on GitHubhttps://github.com/openfl/lime/issues/1758#issuecomment-1937995183, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AADEWLZCY2D2F3VYLOKENFTYTF5OTAVCNFSM6AAAAABC6M75I2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZXHE4TKMJYGM. You are receiving this because you authored the thread.Message ID: @.***>