Font kerning not working (and mouse cursor control)

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
qwdqwqwffqw
Prole
Posts: 21
Joined: Sat Jan 25, 2020 4:11 pm

Font kerning not working (and mouse cursor control)

Post by qwdqwqwffqw »

Hi.
I'm trying to make editable text box in LOVE. In order to place cursor and select texts with mouse, calculating which character x position of mouse cursor lays on is necessary. However, font:getKerning() function doesn't seem to be working. It always returns zero, even when font:getWidth() of two characters clearly returns value less than sum of two characters' width.
I have tested numbers of fonts including Noto Sans, Roboto, and other well known fonts but getKerning works with none of them. Example Code :

Code: Select all

font = love.graphics.newFont("notosans.otf", 1000)
print(font:getWidth("A"))
print(font:getWidth("V"))
print(font:getWidth("AV")) -- minus kerning
print(font:getKerning("A","V")) -- 0

print(font:getWidth("W"))
print(font:getWidth("a"))
print(font:getWidth("Wa")) -- minus kerning
print(font:getKerning("W","a")) -- 0

print(font:getWidth("X"))
print(font:getWidth("X"))
print(font:getWidth("XX")) -- 0 kerning
print(font:getKerning("X","X")) -- 0

for i=32, 126 do
	for j=32, 126 do
		if font:getKerning(i, j) ~= 0 then
			print(i, j) -- no kerning other than zero is printed
		end
	end
end
Is there anything I'm missing? Also, is there any neat&better way regarding text cursor control with mouse? Alternative way of using Font:getWidth() for whole line makes garbage strings in iteration :

Code: Select all

for i=1, #text do
	if font:getWidth(text:sub(1, i)) > x then
		-- ...
	end
end
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Font kerning not working (and mouse cursor control)

Post by pgimeno »

qwdqwqwffqw wrote: Fri May 26, 2023 9:55 am

Code: Select all

font = love.graphics.newFont("notosans.otf", 1000)
print(font:getWidth("A"))
print(font:getWidth("V"))
print(font:getWidth("AV")) -- minus kerning
print(font:getKerning("A","V")) -- 0
I don't get the same result as you. I've grabbed this font: https://github.com/notofonts/noto-fonts ... egular.otf and renamed it to notosans.otf to use your snippet.

And yes, I get a kerning of 0, but also, the width of "AV" is the same of the width of "A" plus the width of "V". So, it's not "minus kerning", it's exactly the sum of the previous two values. I've tried with love.graphics.print and the results are consistent with the returned widths.

With the built-in font, I do get a different kerning:

Code: Select all

font = love.graphics.newFont(30)
print(font:getWidth("A")) -- 21
print(font:getWidth("V")) -- 21
print(font:getWidth("AV")) -- 40
print(font:getKerning("A","V")) -- -2
and that's also consistent with what love.graphics.print() does.

qwdqwqwffqw wrote: Fri May 26, 2023 9:55 am Is there anything I'm missing? Also, is there any neat&better way regarding text cursor control with mouse? Alternative way of using Font:getWidth() for whole line makes garbage strings in iteration :

Code: Select all

for i=1, #text do
	if font:getWidth(text:sub(1, i)) > x then
		-- ...
	end
end
You can use a binary search, which should be faster and generate fewer strings; see ReFreezed's https://github.com/ReFreezed/InputField ... d.lua#L487. It would be nice if we had Font:getPositionFromWidth(text, pixels) but that's not the case. Using getKerning to precalculate tables could be fast but probably use quite some memory.
qwdqwqwffqw
Prole
Posts: 21
Joined: Sat Jan 25, 2020 4:11 pm

Re: Font kerning not working (and mouse cursor control)

Post by qwdqwqwffqw »

After still getting same result(kerning=0) with your suggested font file, I found out that it only happens in 12.0 version(in-development version). And yes, it works well in 11.4 released version.
Binary search would be definitely better option. Thanks for the help!
User avatar
slime
Solid Snayke
Posts: 3131
Joined: Mon Aug 23, 2010 6:45 am
Location: Nova Scotia, Canada
Contact:

Re: Font kerning not working (and mouse cursor control)

Post by slime »

love 12 has much better glyph/text positioning in love.graphics.print and friends than previous versions for a lot of fonts, since it uses Harfbuzz for text shaping. But that new text shaping doesn't really match with the concept of computing glyphs independently and adding together offsets and kerning - Font:getKerning isn't (and can't really be) aware of everything that Harfbuzz does to compute positions of sections of text.

So it's possible Font:getKerning and similar functions will be deprecated before love 12's release, if we make a new API that can use Harfbuzz' text shaping to compute the glyph positions of arbitrary input text or something.
qwdqwqwffqw
Prole
Posts: 21
Joined: Sat Jan 25, 2020 4:11 pm

Re: Font kerning not working (and mouse cursor control)

Post by qwdqwqwffqw »

slime wrote: Sun May 28, 2023 8:30 pm love 12 has much better glyph/text positioning in love.graphics.print and friends than previous versions for a lot of fonts, since it uses Harfbuzz for text shaping. But that new text shaping doesn't really match with the concept of computing glyphs independently and adding together offsets and kerning - Font:getKerning isn't (and can't really be) aware of everything that Harfbuzz does to compute positions of sections of text.
Now it makes sense. Well then I guess repetitive comparison of substrings' width with font:getWidth() is only valid option here, unless something like 'index = font:clip(string, limit)' is added in the future.

Thanks for the answer, it was really helpful.
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Bing [Bot] and 47 guests