luaotfload
luaotfload copied to clipboard
Allow creation of small caps font variant
It would be very nice to be able to create a small caps font (variant) from a font that doesn't have one.
Feature request posted here as suggested by @u-fischer.
This is hard to do right. There are multiple ways this could be implemented:
- Use virtual fonts to replace the glyphs without telling the shaper what is going on. Probably would work ok for ligatures, kerning would be weird. Maybe we would have to disable positioning which would break all kinds of things.
- Use virtual fonts and adjust the fontloader tables -- Would break isolation and don't work with HarfBuzz. (Probably less of a problem because scripts which really need HarfBuzz don't have the concept of small capitals) HarfBuzz support could be added by adding it directly to the
harfcode, but that would be ugly. - Do something similar to the multiscript code and actually replace lower-case letter with small upper-case letters before shaping. Probably works best, but it is slow. Especially it would affect the performance even for paragraphs which do not even use the functionality.
- Convert everything to upper-case, track which characters used to be lower case, identify them post-shaping and make them smaller. Probably breaks if a big and a small character would otherwise form a ligature. Might be doable by inserting ZWNJs at appropriate locations.
I think I prefer the last option.
Further remarks:
- What do we do if people insert characters which behave oddly in this context? E.g. the specific title case codepoints.
- This uses case mapping. ~~> Coordinate with expl3? We probably need a Lua implementation though.
Nothing sounds very convincing (and I wouldn't give this a high priority ;-)).
I wouldn't try to get it working in harf mode, I don't think that it is relevant there.
I don't think converting to uppercase would be good: Font \scshape{Font} should copy & paste as Font Font, not Font FONT. But I think one could get it working for short words if one had a virtual font where the lower case glyphs are replaced by upper case glyphs (along this line https://tex.stackexchange.com/q/370799/2388, but this also change copy&paste). Then one could either with macros or with combofont make the uppercase letters larger.
IMHO, the best way to do fake small-caps should be in a layer above luaotfload i.e. in fontspec itself, by converting text to upper case (which is language-sensitive) then scale the glyphs down and may be slightly embolden and widen them. This breaks text copying, but one could use a better font with real small-caps instead of faking them (or fontspec could tag the text).
Luaotfload is simply too low level for this kind of business.
Admittedly my original goal was for fontspec to have a FakeSmallCaps property, like they have for FakeBold and FakeSlanted. I thought this was the right place though.
Will open the suggestion there then.
Admittedly my original goal was for fontspec to have a
FakeSmallCapsproperty, like they have forFakeBoldandFakeSlanted. I thought this was the right place though.Will open the suggestion there then.
There is an issue for that at https://github.com/wspr/fontspec/issues/379. I don't believe fontspec is the right place though, especially the whole text conversion stuff has to happen on a much lower level than fontspec. I think luaotfload is a good place for that or a separate package could be used.
@BrainStone I don't think either that fontspec is the right place. Basically it should be either luaotfload having some low-level support (which fontspec then can use) or a macro solution which does something like this:
\documentclass{article}
\usepackage{fontspec}
\setmainfont{Arial}
\newfontfamily\smallerArial{Arial}[Scale=0.8,FakeBold=1.2]
\begin{document}
\ExplSyntaxOn
G{\smallerArial\tl_upper_case:n {rüße~an~die}}~
W{\smallerArial\tl_upper_case:n {elt}}
\ExplSyntaxOff
\end{document}

This very example shows why fontspec is the more ideal place :)
If such a macro solution were used I agree that this might belong into fontspec and certainly not into luaotfload, but I think the entire point behind these requests (correct me if I'm wrong @BrainStone) is that people want an interface which behaves like a real small caps font, while such a macro solution will behave quite differently, probably relying on expandable arguments, not integrating with NFSS, etc.