Standardize Font Appearance
neville.smythe at optusnet.com.au
Thu Sep 15 22:27:23 EDT 2022
Thanks Richard for your comments. Interesting to see comments about font drift in a general context
The problems is however not fixed if you add Google fonts to your standalone. The problem could probably be fixed (on Mac and Windows anyway) by hacking the fonts to change their metadata tables but that is getting into really deep water, and may even violate copyright.
The core of the issue is what I think is a design flaw in the way LC places text when it asks the platform OS to render the string.
Experiment 1: Create a standard field. Set the properties to non-3d, draw borders with thickness 1 so we can judge the vertical placement. Type the text “A standard label”. Set the field font to Arial so we can compare the results on Mac and Windows.
Result: On the Mac and Windows we get subtly different results. On Windows the capital “A" appears centered in the box; on the Mac the lower case letters “san" appear centered. Which means the Windows string is lower than the Mac string. As an initialisation of the new field it looks OK on both IDEs. But as we have seen we get into trouble when the text uses other fonts or sizes or if it interacts visually with nearby objects.
Experiment 2: Now change the font size to 64pt.
Result: The text disappears. It is now placed way below the bounding box, and it is a bit of a hassle to get it back into view. That is a terrible user interface.
The nicest user experience would be if the newly sized string appeared with the same baseline as the initial string, and that would certainly make alignment of text easier. However, that model wouldn’t quite fit the LC field model with a user-settable top margin, as it would necessitate overriding the top margin. If the top margin is to be honoured, the two obvious choices are to place the text so the top of the capital A appears at the bottom of the top margin (perhaps the Windows viewpoint?) or if the top of the lowercase letters appear at the top margin, allowing cap letters and risers such as h to bleed into the top margin (let us call this the Mac viewpoint). But neither of these two are what actually happens.
I can confirm that LC actually places the text (the first line, for a field with fixedLineHeight false - that is another story) so that the baseline is set
top margin of the field + fontAscent of the font - 6
pixels below the top of the field. This formula holds precisely over all the fonts and sizes I have tested and on all 3 platforms.
It appears what was intended, probably way back in Hypercard when fonts were bitmaps, was to drop the string below the top margin by the height of capitals (the ascent) and then pull back by 6 pixels so that the top of the lowercase x is at the top margin (the Mac viewpoint). It works well enough on the common initial fonts and sizes for fields because 6 is about the difference in letter heights at these sizes.
However the fontAscent returned by measureText is quite evidently not the height of the letter A above the baseline, it is more like the maximum font height above the baseline, so the string disappears in Experiment 2. And the two platforms return different values for fontAscent anyway, leading to the alignment problems in Experiment 1. Furthermore that constant 6 is of course grossly wrong for other font sizes. What was meant surely was
top margin + x-ascent of the font
(Which was possibly computational more expensive bearing in mind various font formats?)
It would now be impossible for LC to change how it places text in fields, to either the Mac or Windows viewpoint, because that would break every stack having a text field!
What could be done however would be to add a couple of field properties which would enable baselines to be aligned, as I suggested in a previous post.
More information about the use-livecode