cancel
Showing results for 
Search instead for 
Did you mean: 

Digit alignment not optimal because "FIGURE SPACE" not used (feature request)

unsigned_char_array
Senior III

I want to align digits without prepending with 0. So %3d instead of %03d.

 

000:00
100:00
 10:00
  1:00

 

With non-monospaced fonts, such as verdana this doesn't work due to the space character not having the same width as digits. I don't care about the width of punctuation. All digits do have the same width in most non-monospaced fonts, but the space differs.

Unicode has different space types. Such as U+2007 "FIGURE SPACE" (https://jkorpela.fi/chars/spaces.html). This character should be a space character with the same width as a digit. Not all fonts support this character(https://www.fileformat.info/info/unicode/char/2007/fontsupport.htm). Arial is non-monospaced, but supports this character.
Below is a demonstration with ARIAL with regular space and "FIGURE SPACE"

WWW:WW
lll:ll
000:00
100:00
 10:00
  1:00

WWW:WW
lll:ll
000:00
100:00
 10:00
  1:00

As you can see (if the forum renders this correctly) the width of characters differs, but digits have the same width. And the "FIGURE SPACE" is the same width as the digits. So that's good.

But if I try this in TouchGFX it doesn't work as regular spaces are used. I wrote some code to add this, but ideally this should be implemented inside TouchGFX snprintf method:

 

textArea1.setLinespacing(-5); // alignment is easier to see this way
textArea1.invalidateContent();
Unicode::snprintf(textArea1Buffer, TEXTAREA1_SIZE, "WWW\nlll\n%3d\n%3d\n%3d\n", 100,10,1);
textArea1.resizeToCurrentText();
textArea1.invalidateContent();

textArea2.setLinespacing(-5);// alignment is easier to see this way
textArea2.invalidateContent();
Unicode::snprintf(textArea2Buffer, TEXTAREA2_SIZE, "WWW\nlll\n%3d\n%3d\n%3d\n", 100,10,1);
bool typographySupportsFigureSpace = true;// TODO: how to detect this?
if (typographySupportsFigureSpace)
{
	auto len = Unicode::strlen(textArea2Buffer);
	for(auto i = 0; i < len; ++i)
	{
		if (textArea2Buffer[i] == 0x0020)
		{
			textArea2Buffer[i] = 0x2007; // "FIGURE SPACE"
		}
	}
}
textArea2.resizeToCurrentText();
textArea2.invalidateContent();

 

Result (when using ARIAL and adding the needed characters to the typography):

unsigned_char_array_0-1718798876186.png

So it works. But I would have to implement this for every single aligned text field. And I cannot simply replace all spaces since some of them should be normal spaces. In my opinion aligning digits is a huge aesthetic improvement over having them jump around and it doesn't add much CPU overhead. I was able to succesfully modify an existing font that lacked "FIGURE SPACE" and didn't have monospaced digits using fontforge. I made all digits equal width, centered them and added the "FIGURE SPACE" character. This worked. So adding support for "FIGURE SPACE" in an snprintf variant is a huge benefit since you can make it work with all fonts if you are willing to edit them.

My questions are:

  1. Can ST implement the use of figure space inside a variant of snprintf when using width specification (such as %3d)?
  2. If not, how would I implement it? (I would need a way to overload snprintf and also a way to detect if the character is supported by the current typography, because I rather have a regular space than the fallback character and I think most users would too, so then I would need to overload the text render functions too to not insert a fallback character for the "FIGURE SPACE" but a regular space.)
  3. How do I add invisible typography wildcard characters in unicode format instead of pasting them in the field and not seeing them in the field. In other words: the field in TouchGFX Designer doesn't show the invisible characters, but they are there. I add them in the middle of the list of wildcard characters so you can see there are white space characters in there.
Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.
6 REPLIES 6
GaetanGodart
ST Employee

Hello @unsigned_char_array ,

 

Can't this be achieve by aligning the text to the right?

1) If there is a workaround (aligning text to the right for instance), this won't be a priority.

2) Instead of overwriting the touchgfx_printf function, can't you create a my_printf function, that does exactly what you want it do do?
You would probably have to split the string with '\n' to get each line, then check if the line is only number and then try replacing the spaces for that string with the figure space. Maybe wrap the whole thing in a try or implement another safety mecanism.

3) I am often lazy and simple add "0x00-0xff" as wildcard character when simulating. I assume you can just add it with "0x2007".

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)

@GaetanGodart wrote:

Can't this be achieve by aligning the text to the right?


Only if the string has just a number in it. I have a few fields that are only digits, so I will definitely use it in those situations! But I mostly use textArea with wildcard:(.
For instance "Sensor value: <%3d>" and that would have the text at the beginning of the string jump back and forth depending on the sensor value if I align it to the right since you can only set the alignment for the whole string, not just the wildcard part.
I cannot split the text into a fixed and a variable string since the beginning part of the string varies in width depending on the selected language.

 


@GaetanGodart wrote:

2) Instead of overwriting the touchgfx_printf function, can't you create a my_printf function, that does exactly what you want it do do?


I can write my own snprintf function for unicode but I don't want to rewrite the entire formatting functionality. I only want to rewrite the spacing part. I assume that part is closed source in the library (touchgfx::Unicode::composeString?).
I could write a function that first processes the formatting and then passes it to TouchGFX snprintf (either by multiple calls or by modifying the arguments and using vsnprintf, but that would take more stack). But that might not be as elegant. I would have to think about it. It might be too much work without having that part of the source code. If you can help me save work that would be great.

 


@GaetanGodart wrote:

3) I am often lazy and simple add "0x00-0xff" as wildcard character when simulating. I assume you can just add it with "0x2007".


That works! I can just add an individual character in wildcard ranges e.g. "0-9,A-Z,a-z,0x2007". Thanks!

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

1)

I think it would work by using 2 strings: 1 for "Sensor : " and 1 for the value.
You align the value to the right.
When using various languages, just align the "Sensor :" textArea to the right too and make it too big.
Sounds like it would work. I know it's a workaround but that sounds easier than making your own print function.

Another workaround would be to use a monospaced font.
I always use Consolas now when I can. I can also use Inconsolata which free to use.

 

2)

I have looked and yes it seems to be close source.
I can help you but my knowledge is limited.

I looked at the snprintf function and asked chatGPT how to create a custom print function and I understand the steps but I have never done it from scratch and also I don't how you plan on modifying the arguments or doing multiple calls.

 

3)

Great!

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)
unsigned_char_array
Senior III

Aligning text to the right in a text area with wildcard doesn't work in a container. It always centers the text.
I print minutes and seconds.

It kind of looks like this (if the forum renders it correctly):

100:00
 10:00
  0:00

I've set the alignment to the right, but I don't see a difference with left or center alignment.

I tried upgrading to TouchGFX 4.24.0 but the problem persists.

How can this be?

"FIGURE SPACE"  still seems the best solution at the moment for non-monospaced fonts. I will implement my own printf function.

I have one more question: why is there a separate float print function in TouchGFX?

 

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.

Hello @unsigned_char_array ,

 

I was able to put a textArea inside a custom container, align that textArea to the right:

GaetanGodart_2-1719238388240.png

GaetanGodart_3-1719238411124.png

Can you share a project where the alignment misbehave, this sound like a bug.

 

The separate float print function have for description : "Variant of snprintf for floats only. The format supports several \%f with flags/modifiers".
I assume it is optimized.

 

Regards,

Gaetan Godart
Software engineer at ST (TouchGFX)

I created a new project from scratch in TouchGFX 4.24.0 and replicated the result. I used Arial and right align a field, but it clearly aligns left.

I think it's due to resizeToCurrentText. I think that doesn't take alignment into account. Resizing should move the left border of the text box, not the right border if it is right aligned.

I found the solution while typing this post: Using resizeToCurrentTextWithAlignment() instead solved the problem.

 

Kudo posts if you have the same problem and kudo replies if the solution works.
Click "Accept as Solution" if a reply solved your problem. If no solution was posted please answer with your own.