I have enough datapoints to report some findings from my comparison of the
appearance of fonts across platforms, in particular on the length of strings in
fields and text baselines, and to correct some of my previous statements. My
intention is to compile a database for some 7000+ fonts in 7 different font
sizes ranging from 9pt to 18pt on Mac Windows and Linux system; but for now
(for reasons given below) I looked at four basic fonts in common use: Arial,
Times New Roman, Noto Sans and Noto Serif.
The good news is that the horrible problem of different strings lengths is no
longer a problem, as long as your target platforms are just Mac or Windows 10.
For each of these four fonts, strings in (right or left justified) fields have
the same rendered length (they differ between fonts of course). I would be
confident that holds for all TrueType fonts installed on these platforms,
starting from the advent of Windows 10. My former claim about a difference
between High Sierra and Monterey on the Mac is incorrect, the result of a
coding error. Of course the field or stack must have a font assigned: leaving
the font to empty will result in the system using its own font, which will be
consistent with the look-and-feel of the platform/system version, but which
will certainly be quite different between platforms.
On LInux (Ubuntu 18.x) however, string lengths for all the fonts in all sizes
are quite different, sometimes longer and sometimes shorter than on the other
platforms. The biggest difference was for Noto Sans 9pt, the sample Linux
string being 14% longer; this was an outlier, mostly the Linux strings were
less than 8% longer. In the other directions was Arial 15pt, where Linux was 5%
shorter. So if Linux is a target platform, allow some extra length for your
fields (on the right for a left justified field, on the left for a right
justified label).
A more difficult problem is the vertical placement of text. With the default
settings for fields, strings in Windows will typically appear 2 or 3 pixels
lower than on a Mac, which can mess with your layout — text carefully
positioned on one platform will appear too close to nearby objects on the
other, or will not align with text in adjacent fields. This can be fixed by
adjusting the topMargin of the field, but the details are not straightforward..
The baseline for rendered strings is determined by the font metrics and the
font size; unfortunately Mac Windows and Linux all use different metrics from
each other. It would be nice if LC had a function which returned the baseline
for the rendered string, but I couldn’t find such a function. The closest
formula I can get is (for text using the textFont and textSize of the owner
field, and consigning to oblivion the formula I had previously proposed which
was caused by the aforementioned error plus a glitch in the data processing
unit, ie my brain.)
first baseline relative to the top of the field = the topMargin of the
field + fontAscent - 6
where
fontAscent = - (item 2 of measureText(fld <fldname>,fld <fldname>,”bounds”)
Why the magic number -6? It seems this places text in a common font such as
Time New Roman or Arial in medium range textSizes such as 11 to 15 so that the
top of the lower case character “x” is at ...approximately... the topMargin of
the field. This would be the ideal placement for text at all fonts and sizes,
but of course in general 6 is nothing like the difference between the
fontAscent (the height of the capital “A” above the baseline) and the height of
“x”, and anyway the fontAscent is not the actual height of the font, so for
other sizes and fonts the placement is wildly different from the ideal. The
simplification is probably a legacy of a decision originally made for speed
given the complications of dealing with different font formats; a correction
now would break all existing stacks.
Actually while my formula fits precisely most of the time, it occasionally is
out by 1 pixel. And that precision holds for all fonts I have looked at, even
for the gorgeously extravagant Zapfino at 64pt. So the discrepancy is probably
some floating point rounding from the correct formula. If anyone (LC
engineer’s?) can provide the correct formula that would be nice, but I have the
feeling it may involve a font metric not directly exposed by the LC api.
The formula can be used to adjust the topMargin so that the baseline is fixed,
to within 1 pixel anyway The adjustment would have to be done at runtime, or
applied to a stack before building a standalone for a particular platform,
using a pre-cooked fontAscent. Hence my database project. Just at the moment
this has hit a bit of snag: as far as I can see, fonts have to be added to
Windows 10 one at a time -- on a Mac you just dump a folder of fonts onto Font
Book. Does anyone know how to do this in Windows and Linux? If necessary,
following Ralph’s post I believe I could work out where the Mac and Windows 10
systems pick up their ascent parameters by parsing the ttf metadata (horrors!),
but the Linux values are another mystery.
The apparently obvious solution to the problem is to set fixedLineHeight to
true, but unfortunately this does not work. The bottom of each character glyph
will I guess be placed on a fixed line independently of the font, size or
platform, but that is not the baseline, which will still be dependent on font
metrics. The result is that even with fixedLineHeight true baselines are
different for different sizes of a given font, and for different fonts for a
given size even on the same platform (so adjacent fields with different fonts
or sizes will not align baselines), and also different for a given font and
size on different platforms so the layout looks sloppy.
My formula for the first baseline for a field with fixed line height is
baseline = the topMargin of the field + the textHeight of the field -
item 2 of measureText(the field,the text,"size”) + fontAscent - 7
which again seems to be accurate except for a few (different!) cases where it
is 1 pixel out. Again, if anyone knows the exact formula I would be grateful to
hear it.
Possibly an enhancement to LC could provide a fixedBaseline,baseline pair of
properties for fields, which would set the first baseline at a user value,
bleeding the text into the top margin, thus eliminating this problem.
Neville
_______________________________________________
use-livecode mailing list
[email protected]
Please visit this url to subscribe, unsubscribe and manage your subscription
preferences:
http://lists.runrev.com/mailman/listinfo/use-livecode