Is there a way to get the related position rect of each letter in the label control?

It’s not possible to get that information directly from a Label but you can use the TextServer directly to calculate it. It’s a low-level system but there’s some abstraction classes to handle the setup like TextParagraph and TextLine

Here is an example that renders a paragraph and draws a rectangle surrounding each glyph:

extends Control

var paragraph = TextParagraph.new()

@export var font:Font

var text = "Hello world!\nAnother line.\nAnd another one that's long so it breaks whenever it needs to."

func _ready() -> void:
	# Add the text to the paragraph with the loaded font and with font size 32
	paragraph.add_string(text, font, 32)
	# Set the max width to 300
	paragraph.width = 300


func _draw() -> void:
	# Get the primary text server
	var text_server = TextServerManager.get_primary_interface()
	var x = 0.0
	var y = 0.0
	var ascent = 0.0
	var descent = 0.0
	# for each line
	for i in paragraph.get_line_count():
		# reset x
		x = 0.0
		# get the ascent and descent of the line
		ascent = paragraph.get_line_ascent(i)
		descent = paragraph.get_line_descent(i)

		# get the rid of the line
		var line_rid = paragraph.get_line_rid(i)
		# get all the glyphs that compose the line
		var glyphs = text_server.shaped_text_get_glyphs(line_rid)

		# for each glyph
		for glyph in glyphs:
			# get the advance (how much the we need to move x)
			var advance = glyph.get("advance", 0)
			# get the offset, I'm not sure what this does but it may be needed
			var offset = glyph.get("offset", Vector2.ZERO)
			# draw a red rect surrounding the glyph
			draw_rect(Rect2(Vector2(x, y), Vector2(advance, ascent + descent)), Color.RED, false)
			# add the advance to x
			x += advance

		# update y with the ascent and descent of the line
		y += ascent + descent

	# draw the paragraph to this canvas item
	paragraph.draw(get_canvas_item(), Vector2.ZERO)

Result:

2 Likes