textWidth() issues

Hi there.
I’m using textWidth() to fit texts horizontaly in a fixed width.
Doing so works great, I check for the textWidth() of my text in size 100, then I calculate in which size it would perfectly fit my fixed width and I draw it accordingly.

But whith some apparently random chains the textWidth() is not accurate.
For exemple “TOROTOTO” is ok, but not “TARATATA” (the “TA” chain is what causes the problem).

I guess it may be a misinterpretation of the font I use, because it works fineif I don’t use any font.
but as anyone an idea about it ?

Or maybe another way of checking the width of a text which would be more accurate ?

1 Like

Here is a test code I’m using to find a solution :


var texte = "taRATA";
texte = texte.toUpperCase();

var my_font;
function preload(){
	my_font = loadFont('../madgen-assets/fonts/FredokaOne-Regular.ttf');
}
function setup(){
	var c = createCanvas(600, 600); 
	// c.parent(self.select.canvas_container);

	textFont(my_font);
	textAlign(CENTER, CENTER);
	rectMode(CENTER);
	imageMode(CENTER);
}
function draw(){

	fill(0);
	textSize(100);
	text(texte, width/2, 60);

	var w = textWidth(texte);
	var h = textAscent();
	noFill();
	rect(width/2, 60, w, h);

	noLoop();
}

and 2 results, a good and a bad one :
Annotation-2019-09-26-164056b

Well, I managed to get the real width of the text by looking at the pixel matrix, searching for the farest not-empty pixel on screen…
It was a bit tricky but works fine.

function realTextWidth(texte){
	clear();

	// écrit le texte
	textAlign(LEFT, TOP);
	fill(255,0,0);
	textSize(100);
	text(texte, 0, 0);

	// ok la zone ou chercher un point noir
	var _x = Math.ceil(textWidth(texte));
	var _y = 0;
	var w = 300; // arbitraire
	var h = Math.floor(textAscent(texte));

	loadPixels(); 
	var max_x = _x; // coord du point non-blanc le plus éloigné

	for (var x = _x; x < _x+w; x++) {
		for (var y = _y; y < _y+h; y++) {

			var k = 4* (x + y*width); // le rang du lot de valeurs rgba

			if(pixels[k]>0){
				max_x = Math.max(x, max_x);
			}
		}
	}
	console.log(texte+' : '+i+ " itérations... "+_x+' / '+max_x);

	// si on cleare tout de suite on n'a même pas le temps de voir quoi que ce soit...
	clear();

	return max_x;

}

It works fine and fast, too.
I started with the get() function but it was really slow (like 8 or 9 seconds ).
With loadPixels() it takes no time.

It solved my issue and I learned some stuff !

2 Likes

Nice workaround!

I am not a font expert, but it looks as if your specific font has broken kerning – that is, it is reporting textwidth as if there is kerning around T – but doesn’t actually do it.

Typographically, that second T in TARATA looks … really bad. Each “A” ought to be closer to the T in ATA… As they are in this forum text.

Oh you’re right !
I just tested with another font and had no problem at all…
I should have consider it sooner : it’s just a font issue.
Thanks for the observation.