fontdb icon indicating copy to clipboard operation
fontdb copied to clipboard

CSS queries by full name rather than family name

Open CryZe opened this issue 4 years ago • 7 comments

I'm currently looking to somewhat replicating the font lookup a browser does, and I stumbled upon this crate. However it seems to only be able to match against the family name rather than the full name. Is this something that you would consider adding, or that I could do a Pull Request for?

CryZe avatar Jan 04 '21 14:01 CryZe

What do you mean by full name? A font can have a family name, subfamily name, typographic family name and typographic subfamily name. There are also special name generation algorithms like this one.

So the problem is not to change the current logic, but to understand what result we actually need.

RazrFalcon avatar Jan 04 '21 15:01 RazrFalcon

I believe I've seen it be referred to that in Firefox's source code? I'm not even sure anymore, I'm so confused at this point. Basically browsers can match on "family name + typographic subfamily" or alternatively "family name + font variation instance" (Firefox doesn't support the latter). I'd like to match against both possibilities. Though at this point I also found the spec mention that font-family should only refer to the actual font family, not the font face, so I guess browsers just do it anyway? I'm not even sure if I want to support it then.

However this is also what most Windows application choose fonts by, such as mspaint:

https://i.imgur.com/eNLleUk.png

This is also this "full name", with the Light in Calibri referring to a typographic subfamily and the Light in Bahnschrift referring to a named variation instance.

CryZe avatar Jan 04 '21 15:01 CryZe

However this is also what most Windows application choose fonts by

Yes, but this is not the only way. fontdb works with font family name (id1). Basically, to get the output you see on your screenshot, you have to generate it manually on your side and then deconstruct it for frondb. Because Cascadia Mono Light is not a family-name, Cascadia Mono is. And you can match it just fine with fontdb.

The problem is that font's creator can set font family to any value. So for example, NotoSansDevanagari-CondensedMedium.ttf contains:

Family Noto Sans Devanagari Cn Md
Subfamily Regular
Typographic Family Noto Sans Devanagari
Typographic Subfamily Condensed Medium
PostScript NotoSansDevanagari-CondensedMedium

Which one do you need and in what combination?

PS: ideally, we should use Typographic Family, but it's often missing and/or contains unexpected data.

RazrFalcon avatar Jan 04 '21 16:01 RazrFalcon

Basically I'm getting my font names from more or less basically the same list as Paint. Which seems to always be (after having looked at it a lot more now) "Family" + "variation instance name", so I'd need to somehow take this string and find the correct font to load for it. I'm guessing it might make sense if I just pop off pieces at the end of the font until I hit a font family that exists and then look for a named variation instance with the rest? (+ maybe a PR to ttf-parser to query for the named variation instances)

CryZe avatar Jan 04 '21 16:01 CryZe

Yes, I think this should be handled by the caller. Nothing we can do on the fontdb side.

maybe a PR to ttf-parser to query for the named variation instances

You mean STAT?

RazrFalcon avatar Jan 04 '21 16:01 RazrFalcon

fvar: https://docs.microsoft.com/en-us/typography/opentype/spec/fvar

There's a named instance array at the end

CryZe avatar Jan 04 '21 17:01 CryZe

Oh right, they store the same value.

RazrFalcon avatar Jan 04 '21 18:01 RazrFalcon

Seems like this is agains the CSS spec, so we would not support it either. A fontdb::Family is strictly a Font Family (ID 1).

RazrFalcon avatar Dec 25 '22 08:12 RazrFalcon

Mmh sounds like the spec needs to be updated to reflect reality then. I wonder how easy it is to get that change in.

CryZe avatar Dec 25 '22 16:12 CryZe

By the CSS, you're suppose to use font-weight and font-style instead. CSS doesn't care about full typographic family names.

I'm not sure about origin of family names, but this is definitely a huge mess. There are so many ways to define and combine them that this is not even a joke.

RazrFalcon avatar Dec 25 '22 16:12 RazrFalcon

Wait, are you even sure that this "is against the CSS spec"?

Note: The precise way a set of fonts are grouped into font families varies depending upon the platform font management APIs.

On various platforms, different names are used to search for a font. For example, with the Windows GDI CreateIndirectFont API, either a family or fullname can be used to lookup a face, while on Mac OS X the CTFontCreateWithName API call is used to lookup a given face using the fullname and Postscript name. Under Linux, the fontconfig API allows fonts to be searched using any of these names. In situations where platform API’s automatically substitute other font choices, it may be necessary to verify a returned font matches a given name.

So not only does the spec seem to mention that full names and co. are usually used for the family names, but also all the OS APIs and browsers do it that way. So only supporting ID 1 isn't going to be a great user experience even if it was in the spec like that, which apparently it isn't even? (Or maybe I'm missing something)

Anyways, I'm not sure to what degree I'm still even affected by this issue. I solved part of it and I'm planning to use cosmic-text rather than fontdb directly, so they might be using a different matching algorithm anyway.

CryZe avatar Dec 25 '22 16:12 CryZe

I did some tests on macos and Chrome and Firefox ignored family names with Regular, Bold, Light suffixes. Safari didn't mind. This is the web inconsistency for you.

There are actually two issues here. First, I'm not sure if this is allowed by the spec to begin with. It's not really clear. And second, getting/generating those names are far from trivial and error-prone.

Here are my results for:

<text id="text1" x="32" y="100" font-family="Arial Bold" font-size="64">Text</text>
<text id="text2" x="32" y="150" font-family="Arial" font-weight="bold" font-size="64">Text</text>

light-font

As you can see, only Safari is able to detect both. And since fondb is web-first library, I must obey the Chrome.

Also, Arial Bold is not even a family. It's a full name.

RazrFalcon avatar Dec 25 '22 16:12 RazrFalcon

That's... surprising. I'll look into it more later. Also Merry Christmas :)

CryZe avatar Dec 25 '22 17:12 CryZe

Thanks! 😃 You too.

RazrFalcon avatar Dec 25 '22 17:12 RazrFalcon

Not sure if this is necessarily the original problem, but it seems like the problem is rather opposite in that Arial Black, Calibri Light and co. are not considered to be part of Arial, Calibri and co. respectively.

https://i.imgur.com/yTyPYBv.png

I also tried it with cosmic-text and it absolutely runs into this problem and can't handle these fonts (because it apparently just uses the font names as provided by fontdb).

As a whole Chrome seems to be able to roughly match against:

  1. Typographic Family (e.g. specifying "Calibri" can end up using "Calibri Light")
  2. Typographic Family + Typographic Subfamily (e.g. specifying "Calibri Light" ends up using "Calibri Light")
  3. Family (only if Typographic ones don't exist) (e.g. specifying "Arial Bold" doesn't end up using "Arial Bold" as it doesn't have typographic names and the family doesn't match)

So to me it seems pretty clear that typographic family names should be preferred over the normal ones (as is also documented by Microsoft), at which point 1. and 3. would be supported. Whether 2. necessarily needs to be supported is less clear.

CryZe avatar Dec 25 '22 22:12 CryZe

Strange. I will check Windows later, but macos fonts do not include Typographic Family. But they do have Full Name sometimes. This is one giant mess.

RazrFalcon avatar Dec 26 '22 07:12 RazrFalcon

Just compare MS docs about Typographic Family ID 16 and Apple one.

MS:

16: Typographic Family name: The typographic family grouping doesn’t impose any constraints on the number of faces within it, in contrast with the 4-style family grouping (ID 1), which is present both for historical reasons and to express style linking groups. If name ID 16 is absent, then name ID 1 is considered to be the typographic family name. (In earlier versions of the specification, name ID 16 was known as “Preferred Family”.)

Apple:

16: Preferred Family. In Windows, the Family name is displayed in the font menu, and the Subfamily name is presented as the Style name. For historical reasons, font families have contained a maximum of four styles, but font designers may group more than four fonts to a single family. The Preferred Family and Preferred Subfamily IDs allow font designers to include the preferred family/subfamily groupings. These IDs are only present if they are different from IDs 1 and 2.

Not only Apple calls it differently, but also Apple's name makes more sense. If it's preferred, then we should prefer it. The issue is that it will not fix your issue anyway, because it's still not a Full Name.

RazrFalcon avatar Dec 26 '22 07:12 RazrFalcon

Yet another example: /System/Library/Fonts/MuktaMahee.ttc

  • Family: MuktaMahee Regular
  • Full Name: MuktaMahee Regular
  • Typographic Family: Mukta Mahee

FontBook shows it as Mukta Mahee. So #35

RazrFalcon avatar Dec 26 '22 07:12 RazrFalcon

The issue is that it will not fix your issue anyway, because it's still not a Full Name.

As shown here, I don't think Full Name is used by Chrome anymore and it's these three instead: image

I'm fine with only the first and third being supported I think, so #35 would do it.

CryZe avatar Dec 26 '22 07:12 CryZe

Family + Subfamily = Full Name. Not sure if chrome generates one automatically or gets one from the file. Will have to dive into its source code to find out.

Using Typographic Name as preferred is an easy fix, but I'm not sure it will improve the situation much. Unless the Windows Calibri font has "Calibri Light" Typographic Name.

RazrFalcon avatar Dec 26 '22 07:12 RazrFalcon