Font ScanString query
Martin Avison (27) 1494 posts |
I have a routine which uses Font_Paint to display some text. However, in some cases the text still will not fit, and my code truncates the last character. While investigating this I realised I do not understand some of the figures involved. Using Homerton.Medium at 12pt, then However, the returned r3 (end of string) is 30,024 The PRMs have not helped, but I would love to know why What am I missing? |
Colin (478) 2433 posts |
gives the the same as Font_StringWidth. Edit: I think the font bounding box is calculated from the rendering of the font and stringwidth uses the fonts character widths to work out the width. If you make the string just a space the bounding box left and right is 0 but the string width is 3336 |
Martin Avison (27) 1494 posts |
I did say that ScanString returns r3 with the same as StringWidth. |
Colin (478) 2433 posts |
Each character is drawn relative to an origin. Each character has a width specified in the font metrics and the sum of the widths of the characters in a string is the R3 value. The character widths are used to place the characters. The bounding box is the bounding box of the string converted into a path. So in your example the bounding box of “0000:” has a left value of 576mp. This means that when “0000:” is converted into a path the left hand edge of the first 0 is 576mp from the origin of the number 0 and the right hand edge of the : is 29256mp from the origin. So you have a string 30024 wide with a 576mp gap to the start of the 0 on the left and 30024-29256=768mp gap to the right of the : You can have bounding boxes with the left negative or the right wider than the character width (typically for italic fonts) and I think the bounding box takes into account the transformation matrix so if the string is plotted at 45 degrees the bounding box will be squarish. If kerning is used that affects character widths (R3 value) |
Martin Avison (27) 1494 posts |
Ahah! So the bounding box excludes the small space at the left of the 1st letter, and on the right of the last, but the r3 width includes them. Bloody subtle … and undocumented? I would have expected that kerning affected both measures? |
Colin (478) 2433 posts |
Sorry yes kerning does affect both values. If you are painting a line of text in several segments then you would use the R3 value to determine where each segment goes along the baseline – think of the R3 and R4 values as positions along a baseline. You need to paint segments of lines at mp positioning otherwise you see the join if you use os positioning. To determine the area to redraw you would use the string bounding box but note the mp values don’t take into account line widths so you need to expand the box a bit when converting to os units. This table illustrates the differences between bounding box areas and r3,r4
Note: I would have expected all leading and trailing spaces to be ignored and the bbox just covers the drawn text – but when it comes to the font manager don’t assume the obvious. 2) an underscore character is wider than than its baseline width. This is the program used for the table it helps make more sense of the title names
|
Chris Johnson (125) 825 posts |
Yes. That confused me when I was writing my !Text>Draw application. The string was painted in sections depending on changes in style, sub/super scripts etc, so sub strings often ended in a trailing space. |
Martin Avison (27) 1494 posts |
Thanks for that investigation, Colin. My understanding is now better! It seems that the r3 length should be used as the basis for calculations for Font_Paint, and the bounding box for redraw.
Very good advice! |
nemo (145) 2552 posts |
Advance width is not the same as bounding box. Full stops have a small bounding box and a wider width. Spaces usually have no bounding box. Items designed to join up horizontally, such as box drawing glyphs and underscores, have a bounding box wider than their advance width. Italics can overhang. Swatch capitals can overhang extravagantly. |
Colin (478) 2433 posts |
Nemo you may know. In a text editor for each line you effectively have a line of text in a box. For a 12pt font a line height is nominally 12pts high – I’ll ignore any leading between lines and the fact that 12pt text can be taller than 12pt. Is there a proper way to determine the baseline position for a font in the line rectangle? I’ve used several schemes over the years – non seem satisfactory. |
nemo (145) 2552 posts |
Everything is measured from the baseline. There are special rules for combining baselines from different writing systems, but that’s beyond RISC OS’s competence. So if formatting text to fit a rectangular frame, you start at the left margin, and leading for initial point size below the top (plus any rendering margin for ‘niceness’), then you use ScanString or equiv to fit text to the available width. That may result in other point sizes being included, which may require you to move the initial baseline down to fit. You render that line, then move down by the leading for the point size in effect at the end of the line, and off you go again. As for the convex hull of the bounding box, well that’s just the potato you were holding while doing the potato prints. It’s informational and is used, as you’ve said, for updating the screen efficiently. It’s not used for any calculations. So in conclusion: The baseline is king. Some fiddling is required when this is implied but not defined by an article frame. Feel free to implement whatever trickery makes your product better than all the other implementations. The only real rule is “does the result look beautiful”. Just be grateful you’re not setting Nasta’līq, where each word has its own sloping baseline, and the lower ends of all the word baselines have to line up. |