Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Gum] Cannot specify color for Text outline #107

Open
Arcnor opened this issue Oct 7, 2023 · 4 comments
Open

[Gum] Cannot specify color for Text outline #107

Arcnor opened this issue Oct 7, 2023 · 4 comments

Comments

@Arcnor
Copy link
Collaborator

Arcnor commented Oct 7, 2023

When using Outline Thickness on the Text component, a black outline appears but there doesn't seem to be a way of modifying said color.

@Arcnor
Copy link
Collaborator Author

Arcnor commented Oct 8, 2023

If #93 gets accepted, there is a SecondaryColor on the picker already that could be used to set the color using the same control (then maybe modifying the displayed color in the properties panel a bit so it shows both).

@vchelaru
Copy link
Owner

vchelaru commented Oct 8, 2023

Summary Recommendation

Specifying a custom secondary color may be difficult to do through Gum itself. As a workaround, you may want to investigate custom fonts using the Bitmap Font Generator. Information about referencing custom fonts can be found here:

https://flatredball.gitbook.io/gum/gum-elements/text/use-custom-font

The tool that Gum uses internally is the same as the one that can be used to create custom fonts: http://www.angelcode.com/products/bmfont/

Unfortunately it looks like the BMFont tool does not support generating fonts using non-black outlines. There seem to be some options on how the ARGB values are set but nothing as straight forward as picking a color for black outlines. Therefore, it may be that the color on the fonts may need to be modified in a paint program by opening the PNGs and modifying the PNGs.

Please let me know if this workaround is suitable. For reference I will provide some technical information below about how fonts are generated, just in case you are curious or in case it gives you any ideas for workarounds or solutions that I haven't considered.

Technical Details

When a font is generated by Gum using BMFont.exe, the font is generated as white. The color values for the Text object are "multiplied" by the white to produce the final color. For example, the following shows a Text object with a green color.

image

In this case, the green color is multiplied across all pixels on Text object. The white part of the font becomes green. Darker parts of the font (such as the area between the outline and inner part of the lettering) also get multiplied by this value. Prior to multiplication the values would be gray, so when multiplied by green, they become a darker green.

image

For this rendering approach to work, the font must be grayscale. If the font had a non-black outline, then the outline would get multiplied by the text color as well. Since the outline and inner part of the fonts are just one PNG, there is no way to independently multiply the inner part of the text by one color and the outer part of the text by another color. To achieve different colors for inside and outside, those colors must be baked in to the PNG, which is why I recommend modifying the source PNG.

Alternative - Skia Text

Gum supports the addition of Skia objects for rendering

image

Currently these skia objects are used for rounded rectangles, filled circles, arcs, SVGs, and Lottie animations. However, Skia supports a far more powerful text rendering system than native Gum. Furthermore, using Skia enables the use of additional libraries such as the RichTextKit: https://github.com/toptensoftware/RichTextKit

Since Gum already has Skia rendering support, the foundation for adding a Skia-based Text rendering system is already in place. A proper SkiaText object has not (yet) been added to Gum because the existing Text object was enough for most projects.

I haven't investigated whether outline rendering is possible to do, but I'd expect that Skia supports this. If so, we could look at incorporating a SkiaText object as part of the Skia plugin. If this works out, then there would be no need to create or modify custom fonts and PNGs.

@Arcnor
Copy link
Collaborator Author

Arcnor commented Oct 8, 2023

Thanks for the very detailed explanation, as usual.

First, a possible alternative to fix the issue, which is disabling BMFont border generation and do it manually using the same algorithm (I think) BMFont uses: render the text in 4 or 8 directions offset behind the original, then cache the result.

That said:

From my point of view (non-FRB user), my thinking was that the renderer is the one taking care of the issue, meaning: There is a property "Color" of the Text, as well as "Font". How this text is rendered should not be Gum's problem, but that should be part of the renderer to decide. If a new property "Border Color" is added, then the renderer should be taking care of it as well not Gum (from what I thought, Gum's output is just a "preview" that might not match 100% what's on the "backend" of your game, but maybe my premise is already wrong).

In this case, I guess the issue is that Gum's "consumers" are expected to use BMFont to render the font, but IMHO that seems to get too much into "implementation details". I understand that if a consumer renders fonts differently that rendering might not match Gum's rendition, but as stated above, my impression is that Gum was "just" previewing your changes, not dictating how they should 100% appear in-game.

Maybe the proper solution will be as you say, using SkiaText to replace the Text object, but again, the separation between layouting and rendering should be left to the engine you use to consume Gum, IMHO, so even if this is done, what the consumers should get is "text T with properties X, Y and Z" instead of anything related to Skia at all.

I haven't investigated whether outline rendering is possible to do, but I'd expect that Skia supports this.

Even if it didn't, for the Gum preview (if you accept my premise that Gum should only care about previewing and not be a performant pixel-perfect rendering of your UI, which might not be true at all) the same "fix" as I present above will probably work for Skia as well, but as you say it might not be needed.

TL;DR; I guess this is a bigger ask than expected, and maybe not worth it if nobody else has this issue. Locally I can just add a "Border Color" property to my Gum fork that can be set, but not previewed, then my engine will do the right thing.

@vchelaru
Copy link
Owner

vchelaru commented Oct 9, 2023

Okay that makes sense, you're thinking about Gum as an end-user, the same way you might think about Figma. You aren't thinking about the runtime, the way a FRB user might think about it.

I will keep this open for a while and work on the other issues that you've posted. Once those are finished, if this becomes high priority I can look at how to solve this, possibly by using Skia as a rendering engine for Text.

@vchelaru vchelaru transferred this issue from vchelaru/FlatRedBall Oct 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants