godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.16k stars 97 forks source link

Implement a backend for `TextServer` using the `CanvasRenderingContext2D` web API #5741

Open dkaste opened 2 years ago

dkaste commented 2 years ago

Describe the project you are working on

A game that will be exported for the web and will require runtime text rendering/shaping.

Describe the problem or limitation you are having in your project

Large export sizes, particularly with the engine wasm blob.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Web browsers already contain full-featured text rendering and shaping functionality. These features are mostly accessible to JavaScript (and thereby Godot) via CanvasRenderingContext2D. By using the web API, we can remove the dependencies on FreeType and HarfBuzz.

It would probably be useful to profile the engine wasm to determine just how much of the size is due to FreeType+HarfBuzz. I tried to use twiggy to do so, but it doesn't support multi-threaded wasm yet.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

Implement the TextServer interface using the CanvasRenderingContext2D web API.

There are currently some unfortunate limitations on the web API, however. Most notably, TextMetrics lacks the ability to accurately get the "line height" on Firefox. Firefox has an experimental implementation of the missing features that will hopefully be enabled by default soon. A temporary workaround could be to use the width of the letter "M" as the line height. I believe all major browsers including Firefox now support the required TextMetrics APIs.

Another concern is that text could look different on different browsers. For this reason I believe this feature should be an option in projects' export settings.

If this enhancement will not be used often, can it be worked around with a few lines of script?

No

Is there a reason why this should be core and not an add-on in the asset library?

I believe this option should be available by default for all web exports. Using a GDExtension plugin instead would add an unnecessary dependency on GDExtension to the web export for those who use it.

Calinou commented 2 years ago

It's an interesting idea, but it comes with a lot of potential limitations. It may still be good enough for 2D and simple 3D projects though.

I assume a web-based font renderer will not support MSDF fonts either, which is unfortunate for 3D games as they can benefit from arbitrary font size drawing quite a lot in Label3D (without requiring re-rasterization for every size).

Zireael07 commented 2 years ago

I strongly suspect this is meant for 2D games mostly.

dkaste commented 10 months ago

This would also provide a solution for https://github.com/godotengine/godot/issues/78921. System fallback fonts are automatically handled by the browser canvas.