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

Font.get_char_size() documentation is either incorrect or very confusing #88348

Closed
DaltonSW opened this issue Feb 14, 2024 · 5 comments · Fixed by #88444
Closed

Font.get_char_size() documentation is either incorrect or very confusing #88348

DaltonSW opened this issue Feb 14, 2024 · 5 comments · Fixed by #88444

Comments

@DaltonSW
Copy link
Contributor

Tested versions

Documentation related. Using Godot 4.2

System information

Windows 11, Godot 4.2

Issue description

The docs, located here, indicate that there is a way to pass in the following character to account for kerning. That doesn't seem to be the case based on the underlying code or the param indications.

Steps to reproduce

Read the docs here

Minimal reproduction project (MRP)

Hopefully not necessary, just documentation related

@bruvzg
Copy link
Member

bruvzg commented Feb 15, 2024

This is an outdated description from 3.x. Kerning is controlled automatically when using draw_string and get_string_size, and char functions were modified to prevent their misuse (should be used only to draw a single independent character).

@DaltonSW
Copy link
Contributor Author

Totally understand that that is the use case, but it still sounds like it would be very useful in my situation. I want to fade in a word character by character, so I use draw_string to draw the visible substring and then draw_char to fade in the next character

By not being able to account for kerning of the next character, it causes some jittering as the substring goes from x characters to x+1 characters, as that most recent character might have kerning applied and sneak in a bit

How else can this be achieved if get_char_size doesn't account for kerning?

@bruvzg
Copy link
Member

bruvzg commented Feb 15, 2024

I want to fade in a word character by character, so I use draw_string to draw the visible substring and then draw_char to fade in the next character

That's pretty much a type of misuse it's trying to prevent, since it won't work with complex scripts. The next character in the string is not necessary the next visible character, and adding a character to the string might change the look of the whole string.

A proper way to implement it would be using TextLine/TextParagraph and TextServer directly. Something like:

extends Control

var glyphs = []

func _ready() -> void:
	var font = get_theme_font("font")
	var font_size = 16

	# Prerpcessing
	var text_line = TextLine.new()
	text_line.add_string("text", font, font_size) # You can add multiple spans of text with different font and size.

	var ts = TextServerManager.get_primary_interface()
	glyphs = ts.shaped_text_get_glyphs(text_line.get_rid()) # Store "glyphs" for actual rendering

func _draw() -> void:
	var color = Color(1, 0, 0)
	var position = Vector2(100, 100)
	var ci = get_canvas_item()

	var ts = TextServerManager.get_primary_interface()
	# Draw shaped glyphs left-to-right.
	for gl in glyphs:
		if gl["font_rid"].is_valid():
			ts.font_draw_glyph(gl["font_rid"], ci, gl["font_size"], position + gl["offset"], gl["index"], color) # Do your custom drawing, you can check which part of original string glyph correspong to by checeking gl["start"] and gl["end"]
		else:
			ts.draw_hex_code_box(ci, gl["font_size"], position + gl["offset"], gl["index"], color) # Glyph not found in the font.

		position.x = position.x + gl["advance"]

@DaltonSW
Copy link
Contributor Author

Thank you very much for the code example! Are there any references for this other than the TextServer<Whatever> doc pages? Fonts has a whole section with some more examples and details in the overall UI section, which might've been why I was drawn to that instead of the TextServer stuff.

Like the docs, and your example, show TextServerManager.get_primary_interface(), but I don't see any documentation on what exactly an interface is. Node type? Abstract concept? Something I've never heard of? It just gets a little confusing. I think some additional and adjusted information on some of these functions/classes would be extraordinarily helpful.

@DaltonSW
Copy link
Contributor Author

Or even just a high level "Hey here's what you should know about drawing text to the screen from code". I imagine this would be a fairly common issue. I almost just decided to use a monospace font to not deal with it since it seemed like these functions were being used as intended, and the TextServer stuff seemed more complicated than what I needed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants