10-20-2019, 02:43 AM
Post: #1
 DrDarius Junior Member Posts: 41 Joined: Oct 2019
This is a question from a HP Prime newbie (I bought HP Prime G2 two weeks ago).

Is there a way to center a string given as a variable displayed on the screen with TEXTOUT (or ..._P) command?
I could not find any command which would return the length of the string in pixels. Hp Prime is using proportional font, so DIM() command is not of much help.

I did not browse though the history of this forum thoroughly, so, in case if this issue has been already addressed in the past, I apologize for bringing it up again.

Darius
10-20-2019, 04:13 PM
Post: #2
 Wes Loewer Senior Member Posts: 413 Joined: Jan 2014
(10-20-2019 02:43 AM)DrDarius Wrote:  Is there a way to center a string given as a variable displayed on the screen with TEXTOUT (or ..._P) command?
I could not find any command which would return the length of the string in pixels.

The TEXTOUT_P help screen says
Quote:Returns the X coordinate at which the next character of the string should be drawn if the string had more characters

from which the width could be derived. For example:

Code:
#pragma mode( separator(.,;) integer(h64) ) EXPORT CENTERTEXT_P() BEGIN   LOCAL w,str1,str2;     str1:="uncentered text";    str2:="horizontally centered text";   RECT_P();   TEXTOUT_P(str1,160,0);   PIXON_P(160,20);   DIMGROB_P(G1,320,240);   w:=TEXTOUT_P(str2,G1,0,0);   TEXTOUT_P(str2,160-w/2,20);   WAIT();   RETURN w; END;
10-20-2019, 05:17 PM
Post: #3
 DrDarius Junior Member Posts: 41 Joined: Oct 2019
Clever. I did not think of using a graphic variable as a buffer. It clearly indicates that I need more practice to start "feeling" the calculator's architecture.

Thank you!

Darius
10-20-2019, 05:48 PM
Post: #4
 Wes Loewer Senior Member Posts: 413 Joined: Jan 2014
Note that if you are using TEXTOUT() instead of TEXTOUT_P(), the returned value is still in pixel coordinates, not in the Cartesian coordinates as one might expect.

I'm sure there was a logical reason for this, though I can't think of what it might have been. :-)
10-21-2019, 12:35 AM
Post: #5
 Tim Wessman Senior Member Posts: 2,281 Joined: Dec 2013
I am pretty sure because we could not think of a possible reason having the length in cartestian would be helpful...

TW

Although I work for HP, the views and opinions I post here are my own.
10-21-2019, 12:37 AM
Post: #6
 Tim Wessman Senior Member Posts: 2,281 Joined: Dec 2013
(10-20-2019 05:17 PM)DrDarius Wrote:  Clever. I did not think of using a graphic variable as a buffer. It clearly indicates that I need more practice to start "feeling" the calculator's architecture.

Thank you!

Darius

The issue is that you do not have a fixed font anymore. You have a TTF font, with 30K+ characters, and flags to render in different forms. The only way to really determine what the display size will be is to do it basically!

TW

Although I work for HP, the views and opinions I post here are my own.
10-21-2019, 04:29 AM
Post: #7
 Wes Loewer Senior Member Posts: 413 Joined: Jan 2014
In my example, I wrote

Code:
DIMGROB_P(G1,320,240);        // is this line really necessary? w:=TEXTOUT_P(str2,G1,0,0);

but the program works the same without the DIMGROB_P() function. Since the text being written to G1 wasn't going to be displayed, is it necessary to use a DIMGROB before writing/drawing something to G1? Is there any danger in writing outside the dimensions? Or are things outside the boundaries safely ignored?
10-21-2019, 04:59 AM (This post was last modified: 10-21-2019 05:07 AM by Wes Loewer.)
Post: #8
 Wes Loewer Senior Member Posts: 413 Joined: Jan 2014
(10-21-2019 12:35 AM)Tim Wessman Wrote:  I am pretty sure because we could not think of a possible reason having the length in cartestian would be helpful...

Since the returned value of TEXTOUT is not the length but the X coordinate of where the next character would go, I figured the main purpose of the return value was to indicate where the next TEXTOUT should be placed so that the output would flow.

Code:
#pragma mode( separator(.,;) integer(h32) ) EXPORT TEXTOUT_Px3() BEGIN LOCAL a,b,c; RECT(); a:=TEXTOUT_P("ABC",100,50); b:=TEXTOUT_P("DEF",a,50); c:=TEXTOUT_P("GHI",b,50); WAIT(); RETURN {a,b,c}; END;

If these had been TEXTOUT() instead of TEXTOUT_P(), then the returned values would need to be converted back to Cartesian values for the next call. I suppose subsequent calls could be made with TEXTOUT_P(), but then the Y value would have to be converted.

I don't think I've ever used the TEXTOUT functions in my programming, so I may be way off base here.
10-21-2019, 06:49 PM
Post: #9
 DrDarius Junior Member Posts: 41 Joined: Oct 2019
Quote:The issue is that you do not have a fixed font anymore. You have a TTF font, with 30K+ characters, and flags to render in different forms. The only way to really determine what the display size will be is to do it basically!
Given what the HPP command set is, yes.
That said, the method used to center a string is a work around. It has two disadvantages:
1. It calls for allocating memory taking it from available memory pool.
2. It goes through the extra printing process, which takes time.
On the OS level getting the width of the glyph (regardless whether it's a rater, vector, or true type font) is a simple process. A function which would get the widths of the glyphs in the string, add them up, and return the result is way faster than printing the string, and calls for no memory allocation.
All I am stating is that there should be such a function available in the HPP command set. Such a function is very common in other language implementations.
To back my statement with an example and at the same time remain withing the realm of calculator world: A FontLib font library for CE C for TI84+CE provides a few variants of such a function.
Of course you may say that HPP G2 with its half a gigahertz of clock speed and a quarter of gigabyte of RAM can handle such a work around easily, and this is not a statement without merit. But I believe that every engineer during designing a product should optimize it for best performance within input requirements, and I am not seeing it in the context of this example.

Darius
10-21-2019, 06:58 PM
Post: #10
 DrDarius Junior Member Posts: 41 Joined: Oct 2019
(10-21-2019 04:29 AM)Wes Loewer Wrote:  In my example, I wrote

Code:
DIMGROB_P(G1,320,240);        // is this line really necessary? w:=TEXTOUT_P(str2,G1,0,0);

but the program works the same without the DIMGROB_P() function.

My guess would be that if you don't declare a GROB, its initial dimensions are set to zero. TEXTOUT (..._P) must have built-in protection mechanisms against overwriting RAM outside predeclared bounds, so nothing bad happens (processor does not perform erroneous write), but the procedure keeps being executed until the last glyph is processed. And since you don't see what's printed in the GROB, the issue goes unnoticed.
This would explain why you get the right result. TEXTOUT (..._P) simply returns coordinates of where the end of the string would be if it were printed.
(I did not test it, so I may be wrong. My guess is based on the HPP behavior: if a string longer than the remaining space is printed, it's simply truncated.)

Darius
10-22-2019, 04:51 AM
Post: #11
 cyrille de brébisson Senior Member Posts: 1,047 Joined: Dec 2013
Hello,

TEXTOUT is definitely clipped correctly, this means that there will not be memory write where it should not...

However, what I do not remember is if the returned value of TEXTOUT will be the last chr that would have been written OF THE STRING, or IN THE GROB....

but it should be easy enough to test using a very long string...

Cyrille

Although I work for the HP calculator group, the views and opinions I post here are my own. I do not speak for HP.
10-22-2019, 07:39 PM
Post: #12
 Wes Loewer Senior Member Posts: 413 Joined: Jan 2014
(10-22-2019 04:51 AM)cyrille de brébisson Wrote:  However, what I do not remember is if the returned value of TEXTOUT will be the last chr that would have been written OF THE STRING, or IN THE GROB....

but it should be easy enough to test using a very long string...

Must be STRING as TEXTOUT_P returns the same value, even when the GROBW_P is zero.

TEXTOUT_P("12345678901234567890123456789012345678901234567890",0,0) returns 400
10-23-2019, 01:07 AM
Post: #13
 DrDarius Junior Member Posts: 41 Joined: Oct 2019
I decided to explore this issue a little more, and wrote a small program testing time of the timing of center string workaround. This is a quick and dirty test routine, no fanciness involved.
(This is the first time I am trying to post the code, so, if I mess something up, my apologies.)
PHP Code:
EXPORT CENTER_TEST()BEGIN  LOCAL nCounter,nBuffer,i,nX;  LOCAL sString:="Mary had a little lamb, whose fleece was white as snow.";   PRINT();  PRINT(sString);  nCounter:=TICKS();  FOR i FROM 0 TO 10000 DO    DIMGROB_P(G1,320,240);    // TEXTOUT_P(sString,G1,0,0);  END;  nCounter:=TICKS()-nCounter;  nX:=TEXTOUT_P(sString,G1,0,0);  nBuffer:=nCounter;  PRINT("\nGROB full screen\nTime: "+nCounter+", X coord.: "+nX);  nCounter:=TICKS();  FOR i FROM 0 TO 10000 DO    DIMGROB_P(G1,1,1);    // TEXTOUT_P(sString,G1,0,0);  END;  nCounter:=TICKS()-nCounter;  nX:=TEXTOUT_P(sString,G1,0,0);  PRINT("\nGROB one px.:\nTime: "+nCounter+", X coord.: "+nX);  PRINT("\nRatio: "+nBuffer/nCounter);END;
I ran this program on real G2, not the virtual calculator.

The results slightly varied from run to run. (Is it true that HPP OS is RTOS based? That would explain it. Or is it just an effect of executing ISRs of interrupts coming to CPU during program execution?)
Regardless, my typical results were as follows:
1. For the program with printing statements disabled, allocating GROB1 full screen only was 9656 ms, while allocating GROB1 one px. was 105 ms (each 10,000 times).
2. For the program with printing statements enabled, allocating GROB1 full screen and printing the string was 13096 ms, while allocating GROB1 one px. and printing the string was 1594 ms (each 10,000 times).
Thus, if you subtract those numbers (respectively), you should get time that takes to print the string in GROB1 10,000 times. If you do it, you will see that the time of printing the screen depends on the size of the GROB.

Note: Initially I tried to allocate the GROB of (0,0). When I did it, I was occasionally getting wrong X coordinates. I did not explore it further, but there is apparently a not handled situation in the code when the area of the GROB is zero.

My conclusions:
1. The smaller the GROB, the shorter its allocation time. I am assuming this is because of GROB initialization during allocation (rather obvious conclusion...).
2. A process of printing to the undefined section of the GROB is faster than a process of printing to the defined section of the GROB.

Darius
10-23-2019, 04:11 PM
Post: #14
 Jacob Wall Member Posts: 157 Joined: Dec 2013
StringHalfWidth(); EXPORT CENTER_TEST() BEGIN   LOCAL nCounter,i,nX;   LOCAL sString:="Some string less than 320px wide";    PRINT();   PRINT(sString);   DIMGROB(G9,320,30,#FFFFFFh);   nCounter:=TICKS();   FOR i FROM 0 TO 10000 DO     nX:=StringHalfWidth(sString,3);   END;   nCounter:=TICKS()-nCounter;   PRINT("\nTime: "+nCounter+", Half Width: "+nX); END; StringHalfWidth(text,txtsz) BEGIN   RETURN IP(TEXTOUT_P(text,G9,0,0,txtsz,#000000h,320)/2); END;