Bug 95428

Summary: Subfamilies with different OpenType 'size' should not be merged
Product: fontconfig Reporter: gm
Component: fc-cacheAssignee: fontconfig-bugs
Status: RESOLVED MOVED QA Contact: Behdad Esfahbod <freedesktop>
Severity: normal    
Priority: medium CC: akira, freedesktop, lars+bug.freedesktop.org
Version: 2.11   
Hardware: Other   
OS: All   
Whiteboard:
i915 platform: i915 features:

Description gm 2016-05-16 14:43:56 UTC
When a font comes in several variants of different sizes, in the sense of the opentype 'size' feature, fontconfig has a hard time loading the proper one. For now, fontconfig does not implement the opentype 'size' feature and maybe this is complicated and has been already decided against; in any case, in the current state, fonts with 'size' variants are completely unusable since we cannot choose which variant is going to be selected, and it appears to be chosen at random (examples below).


== Fonts I used for the tests (output of fc-list): ==

'''
/home/user/.fonts/from adobe CS3/ArnoPro-Subhead.otf: Arno Pro,Arno Pro Subhead:style=Subhead,Regular
/home/user/.fonts/from adobe CS3/ArnoPro-Caption.otf: Arno Pro,Arno Pro Caption:style=Caption,Regular
/home/user/.fonts/from adobe CS3/ArnoPro-LightDisplay.otf: Arno Pro,Arno Pro Light Display:style=Light Display,Regular
/home/user/.fonts/from adobe CS3/ArnoPro-SmText.otf: Arno Pro,Arno Pro SmText:style=SmText,Regular
/home/user/.fonts/from adobe CS3/ArnoPro-Display.otf: Arno Pro,Arno Pro Display:style=Display,Regular
/home/user/.fonts/from adobe CS3/ArnoPro-Regular.otf: Arno Pro:style=Regular
'''

Contents of the 'size' feature:

'''
$ otfinfo -z /home/user/.fonts/from\ adobe\ CS3/ArnoPro-Caption.otf 
design size 8 pt, size range (5.9 pt, 8.5 pt], subfamily ID 1, subfamily name Regular
$ otfinfo -z /home/user/.fonts/from\ adobe\ CS3/ArnoPro-SmText.otf
design size 10 pt, size range (8.5 pt, 11 pt], subfamily ID 1, subfamily name Regular
$ otfinfo -z /home/user/.fonts/from\ adobe\ CS3/ArnoPro-Regular.otf 
design size 12 pt, size range (11 pt, 14 pt], subfamily ID 1, subfamily name Regular
$ otfinfo -z /home/user/.fonts/from\ adobe\ CS3/ArnoPro-Subhead.otf 
design size 18 pt, size range (14 pt, 21.5 pt], subfamily ID 1, subfamily name Regular
$ otfinfo -z /home/user/.fonts/from\ adobe\ CS3/ArnoPro-Display.otf 
design size 36 pt, size range (21.5 pt, 72 pt], subfamily ID 1, subfamily name Regular
$ otfinfo -z /home/user/.fonts/from\ adobe\ CS3/ArnoPro-LightDisplay.otf 
design size 36 pt, size range (21.5 pt, 72 pt], subfamily ID 4, subfamily name Light
'''

These fonts are not free but after writing the result of my tests I realised that all the problems below can be reproduced using the open source font EB Garamond (08 vs 12).


== Issues: ==

* The gnome font selector (for instance in the preferences of gedit) shows all the fonts, but they all display the same as Arno Pro Caption, i.e. if one chooses Arno Pro Regular one gets Arno Pro Caption instead.

* Inkscape only lists Arno Pro as a family. One can enter "Arno Pro Display" (and Caption, etc.) by hand, however this produces strange results: the metrics of Arno Pro Display are used, but the glyphs from the initial font are used. I noticed it used to work better in older versions of Inkscape (from Ubuntu 11.04, if my memory serves well).

* LyX 2.2dev (based on qt) only shows "Arno Pro" as a choice in the Dialog. Moreover requesting the font "Arno Pro" with qt5 (QFont class) with various weights seems to select the variant randomly (the weight is an integer between 0 and 99):
  0 (Ultra light): ArnoPro-Display.otf
  1-37 (Light): ArnoPro-LightDisplay.otf
  38-56 (Normal): ArnoPro-Display.otf
  57-69 (Demi bold): ArnoPro-SmbdSubhead.otf
  70-99 (Bold and black): ArnoPro-Bold.otf (i.e. the bold variant of size range (11 pt, 14 pt])

  Only the bold weight produces the expected font.

  This is the relevant fontconfig debug output when requesting "Arno Pro" in weight 50 with QFont in lyx:

'''
FC_DEBUG=3:
Match Pattern has 24 elts (size 32)
	family: "Arno Pro"(s) "DejaVu Sans"(w) "DejaVu LGC Sans"(w) "DejaVu LGC Sans"(w) "DejaVu Sans"(w) "Bitstream Vera Sans"(w) "Verdana"(w) "Arial"(w) "Albany AMT"(w) "Luxi Sans"(w) "Nimbus Sans L"(w) "Nimbus Sans"(w) "Helvetica"(w) "Lucida Sans Unicode"(w) "BPG Glaho International"(w) "Tahoma"(w) "Waree"(w) "Loma"(w) "Garuda"(w) "Umpush"(w) "Laksaman"(w) "Noto Sans CJK JP"(w) "Noto Sans CJK SC"(w) "Noto Sans CJK TC"(w) "Khmer OS"(w) "Nachlieli"(w) "Lucida Sans Unicode"(w) "Yudit Unicode"(w) "Kerkis"(w) "ArmNet Helvetica"(w) "Artsounk"(w) "BPG UTF8 M"(w) "Waree"(w) "Loma"(w) "Garuda"(w) "Umpush"(w) "Saysettha Unicode"(w) "JG Lao Old Arial"(w) "GF Zemen Unicode"(w) "Pigiarniq"(w) "B Davat"(w) "B Compset"(w) "Kacst-Qr"(w) "Urdu Nastaliq Unicode"(w) "Raghindi"(w) "Mukti Narrow"(w) "malayalam"(w) "Sampige"(w) "padmaa"(w) "Hapax Berbère"(w) "MS Gothic"(w) "UmePlus P Gothic"(w) "SimSun"(w) "PMingLiu"(w) "WenQuanYi Zen Hei"(w) "WenQuanYi Bitmap Song"(w) "AR PL ShanHeiSun Uni"(w) "AR PL New Sung"(w) "MgOpen Modata"(w) "VL Gothic"(w) "IPAMonaGothic"(w) "IPAGothic"(w) "Sazanami Gothic"(w) "Kochi Gothic"(w) "AR PL KaitiM GB"(w) "AR PL KaitiM Big5"(w) "AR PL ShanHeiSun Uni"(w) "AR PL SungtiL GB"(w) "AR PL Mingti2L Big5"(w) "MS ゴシック"(w) "ZYSong18030"(w) "TSCu_Paranar"(w) "NanumGothic"(w) "DejaVu Sans"(w) "UnDotum"(w) "Baekmuk Dotum"(w) "Baekmuk Gulim"(w) "KacstQura"(w) "Lohit Bengali"(w) "Lohit Gujarati"(w) "Lohit Hindi"(w) "Lohit Marathi"(w) "Lohit Maithili"(w) "Lohit Kashmiri"(w) "Lohit Konkani"(w) "Lohit Nepali"(w) "Lohit Sindhi"(w) "Lohit Punjabi"(w) "Lohit Tamil"(w) "Meera"(w) "Lohit Malayalam"(w) "Lohit Kannada"(w) "Lohit Telugu"(w) "Lohit Oriya"(w) "LKLUG"(w) "WenQuanYi Micro Hei"(w) "FreeSans"(w) "Arial Unicode MS"(w) "Arial Unicode"(w) "Code2000"(w) "Code2001"(w) "sans-serif"(w) "Roya"(w) "Koodak"(w) "Terafik"(w) "sans-serif"(w) "sans-serif"(w)
	familylang: "fr"(s) "en-us"(w)
	stylelang: "fr"(s) "en-us"(w)
	fullnamelang: "fr"(s) "en-us"(w)
	slant: 0(i)(s)
	weight: 80(i)(s)
	width: 100(i)(s)
	size: 25,92(f)(s)
	pixelsize: 27(f)(s)
	hintstyle: 3(i)(s)
	hinting: True(s)
	verticallayout: False(s)
	autohint: False(s)
	globaladvance: True(s)
	file: "/home/user/.fonts/from adobe CS3/ArnoPro-Display.otf"(s)
	index: 0(i)(s)
	lang: "fr"(w)
	fontversion: 2147483647(i)(s)
	embeddedbitmap: True(s)
	decorative: False(s)
	lcdfilter: 1(i)(w)
	namelang: "fr"(s)
	prgname: "part3"(s)
	symbol: False(s)
'''

This seems to be the only relevant font appearing in the debug output, so I conclude that the wrong choice is made by fontconfig and not qt.

Also, do not be fooled by the requested size above which appears to match the size range of Display. The selection does not depend on the size, asking for a smaller size still gives the Display variant. And in this particular case, even obeying the opentype 'size' specification would produce wrong results since it does not take the local dpi into account (here, for size 25.9 the regular variant would be desired).


== Expected behaviour: ==

* At the very least, the font selection should be consistent and preferably select the regular variant by default. However, it is hard to know for sure which one should be selected, because nothing in the opentype specification of the 'size' feature indicates that there must be a reference variant, such as Arno Pro Regular in the example of Arno Pro.

* Preferably, Arno Pro Caption, Arno Pro SmText, Arno Pro Regular, Arno Pro Subhead, and Arno Pro Display should be recognised as distinct font families such that user interfaces would let the user choose every variant, and this variant should be correctly selected when asked for. (In the case of Arno Pro, they all come with bold, semi-bold and italic variants.)

* Alternatively, the opentype 'size' feature should be implemented. However, the example of qt, above, where size 25.9 is requested while it looks like 12pt on screen shows that the 'size' feature is not viable without a way to fine-tune or disable the feature.

Implementing the opentype 'size' feature looks like a complicated enhancement. I think it is reasonable in the meanwhile to request a way to make fonts with 'size' variants at least usable.

I use the current Ubuntu 16.04 (fontconfig 2.11.94-0ubuntu1). Again, the bugs can be reproduced with EB Garamond 08 & 12 (in this case the qt (lyx 2.2dev) issue even worse, since EB Garamond Small Caps is rendered!).

Maybe related: bug #13416.
Comment 1 Akira TAGOH 2016-05-17 08:05:09 UTC
Hm, that sounds like a side-effect of the multiple family names in those fonts. strictly speaking, those fonts are recognized separately in fontconfig itself. but due to the unified family name for those, when applications queries it to fontconfig, fontconfig just returns the better font sets against the requested patterns. but if that pattern isn't enough, say, if asking for only family name once and reuse it for any size for rendering, it may not works as expected right.

(In reply to gm from comment #0)
> == Issues: ==
> 
> * The gnome font selector (for instance in the preferences of gedit) shows
> all the fonts, but they all display the same as Arno Pro Caption, i.e. if
> one chooses Arno Pro Regular one gets Arno Pro Caption instead.

I can't say off hand but if "fc-match 'Arno Pro Regular'" returns it as is, maybe fontconfig decided it isn't a best font for the certain pattern. I can't say more without logs containing what applications actually requested.

> * Inkscape only lists Arno Pro as a family. One can enter "Arno Pro Display"
> (and Caption, etc.) by hand, however this produces strange results: the
> metrics of Arno Pro Display are used, but the glyphs from the initial font
> are used. I noticed it used to work better in older versions of Inkscape
> (from Ubuntu 11.04, if my memory serves well).

That should be the inkscape issue.

>   This is the relevant fontconfig debug output when requesting "Arno Pro" in
> weight 50 with QFont in lyx:
> 
> '''
> FC_DEBUG=3:

Well, I can't figure out if that really explain what you say because FC_DEBUG=3 doesn't show the original request and hard to estimate it from the debugging log, but that looks like lyx doesn't request weight=50 really. try FC_DEBUG=4 or =7 instead.

> == Expected behaviour: ==
> 
> * At the very least, the font selection should be consistent and preferably
> select the regular variant by default. However, it is hard to know for sure
> which one should be selected, because nothing in the opentype specification
> of the 'size' feature indicates that there must be a reference variant, such
> as Arno Pro Regular in the example of Arno Pro.
> 
> * Preferably, Arno Pro Caption, Arno Pro SmText, Arno Pro Regular, Arno Pro
> Subhead, and Arno Pro Display should be recognised as distinct font families
> such that user interfaces would let the user choose every variant, and this
> variant should be correctly selected when asked for. (In the case of Arno
> Pro, they all come with bold, semi-bold and italic variants.)

For a workaround, you could get rid of "Arno Pro" from those fonts. for example:

<match target="scan">
  <test name="family">Arno Pro</test>
  <edit name="family" mode="delete"/>
</match>

Once add it into the config, run fc-cache -f.

> * Alternatively, the opentype 'size' feature should be implemented. However,
> the example of qt, above, where size 25.9 is requested while it looks like
> 12pt on screen shows that the 'size' feature is not viable without a way to
> fine-tune or disable the feature.
> 
> Implementing the opentype 'size' feature looks like a complicated
> enhancement. I think it is reasonable in the meanwhile to request a way to
> make fonts with 'size' variants at least usable.

That may needs to be discussed, including it should be dealt with fontconfig or upper layer.
Comment 2 gm 2016-05-20 02:51:48 UTC
> > == Issues: ==
> > 
> > * The gnome font selector (for instance in the preferences of gedit) shows
> > all the fonts, but they all display the same as Arno Pro Caption, i.e. if
> > one chooses Arno Pro Regular one gets Arno Pro Caption instead.
> 
> I can't say off hand but if "fc-match 'Arno Pro Regular'" returns it as is,
> maybe fontconfig decided it isn't a best font for the certain pattern. I
> can't say more without logs containing what applications actually requested.

I am also curious as to why it always selects the same font for a
given WWS. I tried to find the request with FC_DEBUG 4 & 7 but I get
80MB logs and I could not understand what was going on. What should I
look for?


> 
> > * Inkscape only lists Arno Pro as a family. One can enter "Arno Pro Display"
> > (and Caption, etc.) by hand, however this produces strange results: the
> > metrics of Arno Pro Display are used, but the glyphs from the initial font
> > are used. I noticed it used to work better in older versions of Inkscape
> > (from Ubuntu 11.04, if my memory serves well).
> 
> That should be the inkscape issue.

From fontconfig's point of view, inkscape should list "Bold Caption",
etc. as subfamilies? (for now it only lists WWS subfamilies: "Bold",
"Semibold", "Italic"...)


> 
> >   This is the relevant fontconfig debug output when requesting "Arno Pro" in
> > weight 50 with QFont in lyx:
> > 
> > '''
> > FC_DEBUG=3:
> 
> Well, I can't figure out if that really explain what you say because
> FC_DEBUG=3 doesn't show the original request and hard to estimate it from
> the debugging log, but that looks like lyx doesn't request weight=50 really.
> try FC_DEBUG=4 or =7 instead.

I should have mentioned that the weight in Qt is between 0 and 99 and
50 corresponds (correctly) to 80 in fontconfig. How do I figure out
what is the original request using FC_DEBUG 4 or 7?
Comment 3 gm 2016-05-20 03:07:10 UTC
(In reply to Akira TAGOH from comment #1)
> Hm, that sounds like a side-effect of the multiple family names in those
> fonts. strictly speaking, those fonts are recognized separately in
> fontconfig itself. but due to the unified family name for those, when
> applications queries it to fontconfig, fontconfig just returns the better
> font sets against the requested patterns. but if that pattern isn't enough,
> say, if asking for only family name once and reuse it for any size for
> rendering, it may not works as expected right.
>

Thank you for your reply. I have learnt much in the process and I now
have a workaround thanks to you, and a proposed solution at the end of
this message.

It is definitely due to having fonts with very similar
patterns. First, fontconfig itself seems unable to select Arno Pro
Regular:

$ fc-match "Arno Pro" # expected: ArnoPro-Regular.otf
ArnoPro-Caption.otf: "Arno Pro" "Caption"
$ fc-match "Arno Pro" # expected: ArnoPro-Regular.otf
ArnoPro-Caption.otf: "Arno Pro" "Caption"
$ fc-match "Arno Pro-12" # expected: ArnoPro-Regular.otf
ArnoPro-Caption.otf: "Arno Pro" "Caption"
$ fc-match "Arno Pro Regular"
DejaVuSans.ttf: "DejaVu Sans" "Book"
$ fc-match "Arno Pro:style=Regular" # expected: ArnoPro-Regular.otf
ArnoPro-Caption.otf: "Arno Pro" "Caption"
$ fc-match "Arno Pro:size=12" # expected: ArnoPro-Regular.otf
ArnoPro-Caption.otf: "Arno Pro" "Caption"
$ fc-match "ArnoPro-Regular" # expected: ArnoPro-Regular.otf
ArnoPro-Caption.otf: "Arno Pro" "Caption"


Fontconfig mixes the subfamily (name ID 2) with the typographic family
(name ID 16), thus "Arno Pro Caption" is recognised as "Arno Pro"
"Regular":

$ fc-list | grep "ArnoPro-Caption.otf\\|ArnoPro-Regular.otf"
DIR/ArnoPro-Caption.otf: Arno Pro,Arno Pro Caption:style=Caption,Regular
DIR/ArnoPro-Regular.otf: Arno Pro:style=Regular

See the example of Minion Pro Opticals given at the end of
https://www.microsoft.com/typography/otspec/name.htm to see how the
names are set in an optical font family (but note that not all fonts
have name IDs 21 and 22: Arno Pro does not).

The confusion is probably due to the fact that they match on all criteria:

$ fc-query ArnoPro-Regular.otf 
Pattern has 23 elts (size 32)
	family: "Arno Pro"(s)
	familylang: "en"(s)
	style: "Regular"(s)
	stylelang: "en"(s)
	fullname: "ArnoPro-Regular"(s) "Arno Pro"(s)
	fullnamelang: "en"(s) "en"(s)
	slant: 0(i)(s)
	weight: 80(i)(s)
	width: 100(i)(s)
	foundry: "ADBE"(s)
	file: "ArnoPro-Regular.otf"(s)
	index: 0(i)(s)
	outline: True(s)
	scalable: True(s)
	charset: 
	0000: 00000000 ffffffff ffffffff 7fffffff 00000000 ffffffff ffffffff ffffffff
	0001: ffffffff ffffffff ffffffff ffffffff 80048000 00018003 00001ff0 fc0e0000
	0002: 3f000000 008c0000 02000000 00200000 00000000 08000000 3f0002c0 00000000
	0003: 0000000c 00000000 00000000 44300000 ffffd7f0 fffffffb 2ae27fff 00010002
	0004: ffffffff ffffffff ffffffff 003c000c 0ccf0000 0ccfc00c 03008001 0000c30c
	001e: 00000000 00000000 00000000 00000000 0000003f ffffffff ffffffff 03ffffff
	001f: 3f3fffff ffffffff aaff3f3f 3fffffff ffffffff ffdfffff efcfffdf 7fdcffff
	0020: 771d0080 060d0077 00000010 e3f10000 000063ff 0010189a 00000000 00000000
	0021: 00480000 00004044 78180000 00000000 00050000 00000000 00000000 00000000
	0022: 46268044 00000800 00000100 00000031 00000000 00000000 00000000 00000000
	0025: 00000000 00000000 00000000 00000000 00000000 00c00001 00000643 00000000
	0026: 00030000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
	0027: 00080000 00000000 00040000 00000000 00000000 00000000 00000000 00000000
	00fb: 0000007f 00000000 00000000 00000000 00000000 00000000 00000000 00000000
(s)
	lang: aa|af|av|ay|az-az|be|bg|bi|br|bs|bua|ca|ce|ch|co|cs|cy|da|de|el|en|eo|es|et|eu|fi|fj|fo|fr|fur|fy|gd|gl|gn|gv|haw|ho|hr|hu|ia|ig|id|ie|ik|io|is|it|kaa|ki|kk|kl|kum|kw|ky|la|lb|lez|lt|lv|mg|mh|mk|mo|mt|nb|nds|nl|nn|no|nr|nso|ny|oc|om|os|pl|pt|rm|ro|ru|se|sel|sk|sl|sm|sma|smj|smn|so|sq|sr|ss|st|sv|sw|tg|tk|tl|tn|to|tr|ts|tt|tyv|uk|uz|vo|vot|wa|wen|wo|xh|yap|zu|an|crh|csb|fil|hsb|ht|jv|kj|ku-tr|kwm|lg|li|mn-mn|ms|na|ng|pap-an|pap-aw|rn|rw|sc|sg|sn|su|za(s)
	fontversion: 66256(i)(s)
	capability: "otlayout:DFLT otlayout:cyrl otlayout:grek otlayout:latn"(s)
	fontformat: "CFF"(s)
	decorative: False(s)
	postscriptname: "ArnoPro-Regular"(s)
	color: False(s)
  symbol: False(s)

$ fc-query ArnoPro-Caption.otf 
Pattern has 23 elts (size 32)
	family: "Arno Pro"(s) "Arno Pro Caption"(s)
	familylang: "en"(s) "en"(s)
	style: "Caption"(s) "Regular"(s)
	stylelang: "en"(s) "en"(s)
	fullname: "ArnoPro-Caption"(s) "Arno Pro Caption"(s)
	fullnamelang: "en"(s) "en"(s)
	slant: 0(i)(s)
	weight: 80(i)(s)
	width: 100(i)(s)
	foundry: "ADBE"(s)
	file: "ArnoPro-Caption.otf"(s)
	index: 0(i)(s)
	outline: True(s)
	scalable: True(s)
	charset: 
	0000: 00000000 ffffffff ffffffff 7fffffff 00000000 ffffffff ffffffff ffffffff
	0001: ffffffff ffffffff ffffffff ffffffff 80048000 00018003 00001ff0 fc0e0000
	0002: 3f000000 008c0000 02000000 00200000 00000000 08000000 3f0002c0 00000000
	0003: 0000000c 00000000 00000000 44300000 ffffd7f0 fffffffb 2ae27fff 00010002
	0004: ffffffff ffffffff ffffffff 003c000c 0ccf0000 0ccfc00c 03008001 0000c30c
	001e: 00000000 00000000 00000000 00000000 0000003f ffffffff ffffffff 03ffffff
	001f: 3f3fffff ffffffff aaff3f3f 3fffffff ffffffff ffdfffff efcfffdf 7fdcffff
	0020: 771d0080 060d0077 00000010 e3f10000 000063ff 0010189a 00000000 00000000
	0021: 00480000 00004044 78180000 00000000 00050000 00000000 00000000 00000000
	0022: 46268044 00000800 00000100 00000031 00000000 00000000 00000000 00000000
	0025: 00000000 00000000 00000000 00000000 00000000 00c00001 00000643 00000000
	0026: 00030000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
	0027: 00080000 00000000 00040000 00000000 00000000 00000000 00000000 00000000
	00fb: 0000007f 00000000 00000000 00000000 00000000 00000000 00000000 00000000
(s)
	lang: aa|af|av|ay|az-az|be|bg|bi|br|bs|bua|ca|ce|ch|co|cs|cy|da|de|el|en|eo|es|et|eu|fi|fj|fo|fr|fur|fy|gd|gl|gn|gv|haw|ho|hr|hu|ia|ig|id|ie|ik|io|is|it|kaa|ki|kk|kl|kum|kw|ky|la|lb|lez|lt|lv|mg|mh|mk|mo|mt|nb|nds|nl|nn|no|nr|nso|ny|oc|om|os|pl|pt|rm|ro|ru|se|sel|sk|sl|sm|sma|smj|smn|so|sq|sr|ss|st|sv|sw|tg|tk|tl|tn|to|tr|ts|tt|tyv|uk|uz|vo|vot|wa|wen|wo|xh|yap|zu|an|crh|csb|fil|hsb|ht|jv|kj|ku-tr|kwm|lg|li|mn-mn|ms|na|ng|pap-an|pap-aw|rn|rw|sc|sg|sn|su|za(s)
	fontversion: 66256(i)(s)
	capability: "otlayout:DFLT otlayout:cyrl otlayout:grek otlayout:latn"(s)
	fontformat: "CFF"(s)
	decorative: False(s)
	postscriptname: "ArnoPro-Caption"(s)
	color: False(s)
	symbol: False(s)


Evidently, applications are confused at seeing multiple fonts
differing only by a subfamily name that they do not understand,
especially as fontconfig does not reflect the pairing between name IDs
1&2 and between name IDs 16&17 faithfully. Usually, when the latter
confusion happens, say in the case of semibolds, applications at least
have the weight for disambiguating.

As a conclusion, the Typographic Family (name ID 16) is not
appropriate when neither fontconfig nor the upper layer support the
opentype 'size' feature. (The bug report and the remainder of the
message essentially argue that it would be inappropriate even if
fontconfig supported the 'size' feature.)



> 
> > == Expected behaviour: ==
> > 
> > * Preferably, Arno Pro Caption, Arno Pro SmText, Arno Pro Regular, Arno Pro
> > Subhead, and Arno Pro Display should be recognised as distinct font families
> > such that user interfaces would let the user choose every variant, and this
> > variant should be correctly selected when asked for. (In the case of Arno
> > Pro, they all come with bold, semi-bold and italic variants.)
> 
> For a workaround, you could get rid of "Arno Pro" from those fonts. for
> example:
> 
> <match target="scan">
>   <test name="family">Arno Pro</test>
>   <edit name="family" mode="delete"/>
> </match>


Thanks. After adding the missing <string> and making sure that no font
ends up with zero family, I get the following which works:

<match target="scan">
  <test name="family"><string>Arno Pro</string></test>
  <test name="file" compare="not_contains"><string>ArnoPro-Regular.otf</string></test>
  <test name="file" compare="not_contains"><string>ArnoPro-Bold.otf</string></test>
  <test name="file" compare="not_contains"><string>ArnoPro-Italic.otf</string></test>
  <test name="file" compare="not_contains"><string>ArnoPro-BoldItalic.otf</string></test>
  <edit name="family" mode="delete"/>
</match>


But I need to add to it the following in order to get the complete
families:

<match target="scan">
  <test name="family"><string>Arno Pro Smbd Caption</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro Caption</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Smbd SmText</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro SmText</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Smbd</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Smbd Subhead</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro Subhead</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Smbd Display</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro Display</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Light Display</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro Display</string></edit>
</match>


Optionally one can get rid of the style mentioning te optical size:

<match target="scan">
  <test name="family" compare="eq"><string>Arno Pro Caption</string></test>
  <test name="style" compare="contains"><string>Caption</string></test>
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Arno Pro SmText</string></test>
  <test name="style" compare="contains"><string>SmText</string></test>
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Arno Pro Subhead</string></test>
  <test name="style" compare="contains"><string>Subhead</string></test>
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Arno Pro Display</string></test>
  <test name="style" compare="contains"><string>Display</string></test>
  <edit name="style" mode="delete"/>
</match>


This configuration fixes all the problems of font confusion and allows
me to select the various families in Inkscape and Qt, as desired.

Similarly, the following "fixes" EB Garamond:

<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond</string></test>
  <edit name="family" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond SC</string></test>
  <edit name="family" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond 08</string></test>
  <test name="style" compare="contains"><string>08</string></test>
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond 12</string></test>
  <test name="style" compare="contains"><string>12</string></test>
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond SC 08</string></test>
  <test name="style" compare="contains"><string>08</string></test>
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond SC 12</string></test>
  <test name="style" compare="contains"><string>12</string></test>
  <edit name="style" mode="delete"/>
</match>


(Strangely, when I tried to fix Latin Modern Roman it did not work:

<match target="scan">
  <test name="family" compare="eq"><string>Latin Modern Roman</string></test>
  <edit name="family" mode="delete"/>
</match>


With the above configuration, I still get the following:

$ fc-list | grep "lmroman7-regular.otf"
DIR/lmroman7-regular.otf: Latin Modern Roman,LM Roman 7:style=7 Regular,Regular
# expected: LM Roman 7:style=7 Regular,Regular


Do you have an Idea why? I noticed the same problem with EB
Garamond when I had multiple installations of it.)



Thanks you very much for your workaround. It works perfectly well especially in inkscape where being able to select the proper font is crucial. In addition one can see it as a proof of concept for the following implementation:

* References:
  https://www.microsoft.com/typography/otspec/name.htm
  https://www.microsoft.com/typography/otspec/features_pt.htm#size

* Goal: Implement the "UI suggestion" in the above reference to "allow
  the user to select non-default sizes", in particular for
  applications that are unaware of optical fonts, by separating the
  families as per the workaround configurations above.

* Rationale: handling optical fonts correctly requires the
  awareness of the upper layer, since:

  1. fonts differing only by their size range are
     undistinguishable by applications unaware of opentype 'size'.

  2. an unaware application might cache the font improperly and
     use it at different sizes, as you mentions.

  This implementation proposal makes optical fonts compatible with
  unaware applications, by having only WWS styles.

* Procedure: for any font with opentype 'size' feature and non-zero
  style ID (second value in the size table), or non-zero fields
  usLowerPointSize and usUpperPointSize in the OS/2 table. Examples:
  Microsoft Sitka, Arno Pro Opticals, Minion Pro Opticals, EB Garamond
  (I assume name IDs 1 & 2 have already been read and added)

  1. If the font has either name IDs 21 & 22, or OS/2 fsSelection bit
     8 is set: Then prepend name IDs 21 & 22 if available, and disregard
     name IDs 16 & 17 unless the fsSelection bit is set.
     Examples:
     "Sitka Small" "Bold Italic"
     "Minion Pro Caption" "Semibold Italic"

  2. Else, disregard name IDs 16 & 17, and if there is a 'size' table
     with non-zero third value, construct a WWS family as follows:

     * If the style name from the size table (name referenced to by
       the third value in the table) is one of Regular, Italic, Bold
       or Bold Italic: then we are happy with name ID 1 as
       family. Prepend the style name from the size table.
       Examples:
       "EB Garamond 12" "Italic"
       "Arno Pro Caption" "Bold"

     * Else, if the design point (first value) falls within the range
       of a font that has the same value for name ID 16 and whose
       style name from the size table is Regular, Italic, Bold or Bold
       Italic: prepend the name ID 1 from the latter font, and prepend
       the style name from the size table.
       Examples:
       "Arno Pro Caption" "Semibold"



> 
> > * Alternatively, the opentype 'size' feature should be implemented. However,
> > the example of qt, above, where size 25.9 is requested while it looks like
> > 12pt on screen shows that the 'size' feature is not viable without a way to
> > fine-tune or disable the feature.
> > 
> > Implementing the opentype 'size' feature looks like a complicated
> > enhancement. I think it is reasonable in the meanwhile to request a way to
> > make fonts with 'size' variants at least usable.
> 
> That may needs to be discussed, including it should be dealt with fontconfig
> or upper layer.



In light of all of the above, here's a suggestion if one wants to push
the previous implementation proposal further. Add a new element
'opticalfamily' which is set to name ID 16 whenever a font is optical
in the sense of the 'size' table or of the OS/2 table v5. Then, the
pattern "A:opticalfamily=B:size=C" preferably matches fonts with name
ID 16 matching B and size range matching C. Note that precedence
should be given to matching the size range: for instance, "Arno Pro
Light" does not exist, and ":opticalfamily=Arno Pro:size=12:weight=50"
should therefore be matched by Arno Pro Regular, and not by Arno Pro
Light Display.

Rationale: we have established that implementing optical font matching
properly requires the cooperation of the upper layer. Moreover, in
many situations it is desirable to disable optical font matching, or
to tweak the matching size according to a curve, as suggested in the
reference. The above proposal ensures that the application has
explicitly requested for fonts to be substituted according to the
'size' feature, and that the supplied size is the desired size to be
matched against in terms of optical font. This mean that we delegate
to the upper layer the responsibility of conforming to the
recommendation that "this feature should be active by default".

In addition, the range values from the 'size' table should be used as
a FC_SIZE range (unless the OS/2 table v5 already defines a size
range). Be careful though that with the 'size' table, the lower bound
is exclusive and the upper bound is inclusive, oposite to the OS/2
table.

Thank you again for reading up to there. I hope that I am not making
any big misunderstanding of fontconfig in my proposals above, and
that you find them worth of your time.


Sincerely
Comment 4 Akira TAGOH 2016-05-20 03:21:50 UTC
(In reply to gm from comment #2)
> I am also curious as to why it always selects the same font for a
> given WWS. I tried to find the request with FC_DEBUG 4 & 7 but I get
> 80MB logs and I could not understand what was going on. What should I
> look for?

You can figure out what the original request is from the logs before evaluating test/edit patterns like:
FcConfigSubstitute Pattern has 4 elts (size 16)
        family: "Arno Pro"(s)
        style: "Regular"(s)
        lang: "ja"(w)
        prgname: "fc-match"(s)

"(s)" means the strong binding which is explictly added into the pattern against the request except "prgname". "(w)" is the weak binding. it could be also added through API but usually that may means *here* it was added by fontconfig for the certain reason.
Anyway, please make sure it doesn't appear after "FcConfigSubstitute donePattern has..." line. otherwise that isn't the one what you are looking for.

> From fontconfig's point of view, inkscape should list "Bold Caption",
> etc. as subfamilies? (for now it only lists WWS subfamilies: "Bold",
> "Semibold", "Italic"...)

As long as they deal with it properly, no. otherwise yes. anyway, I meant how applications shows the information from fontconfig depends on their code. they just did so intentionally. it isn't fontconfig fault.
Comment 5 Akira TAGOH 2016-05-20 03:32:34 UTC
Sorry for the cherry-pick. will go back here for your suggestion later.

(In reply to gm from comment #3)
> (Strangely, when I tried to fix Latin Modern Roman it did not work:
> 
> <match target="scan">
>   <test name="family" compare="eq"><string>Latin Modern Roman</string></test>
>   <edit name="family" mode="delete"/>
> </match>
> 
> 
> With the above configuration, I still get the following:
> 
> $ fc-list | grep "lmroman7-regular.otf"
> DIR/lmroman7-regular.otf: Latin Modern Roman,LM Roman 7:style=7
> Regular,Regular
> # expected: LM Roman 7:style=7 Regular,Regular
> 
> 
> Do you have an Idea why? I noticed the same problem with EB
> Garamond when I had multiple installations of it.)

That may be a bug. need to investigate.
Comment 6 gm 2016-06-24 20:46:24 UTC
Hello, is there any update regarding my suggestion to disregard name IDs 16 & 17 when dealing with optical fonts? Thank you!
Comment 7 gm 2016-06-24 21:07:21 UTC
For reference, here's an updated proof-of-concept configuration that fixes some issues wrt my previous messages:


<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
<!-- Arno Pro -->
<!-- Disambiguate Arno Pro family -->
<match target="scan">
  <test name="family"><string>Arno Pro</string></test>
  <test name="file" compare="not_contains"><string>ArnoPro-Regular.otf</string></test>
  <test name="file" compare="not_contains"><string>ArnoPro-Bold.otf</string></test>
  <test name="file" compare="not_contains"><string>ArnoPro-Italic.otf</string></test>
  <test name="file" compare="not_contains"><string>ArnoPro-BoldItalic.otf</string></test>
  <edit name="family" mode="delete"/>
</match>
<!-- Fix semibolds and light -->
<match target="scan">
  <test name="family"><string>Arno Pro Smbd Caption</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro Caption</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Smbd SmText</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro SmText</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Smbd</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Smbd Subhead</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro Subhead</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Smbd Display</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro Display</string></edit>
</match>
<match target="scan">
  <test name="family"><string>Arno Pro Light Display</string></test>
  <edit name="family" mode="prepend"><string>Arno Pro Display</string></edit>
</match>
<!-- further fix semibolds and light -->
<match target="scan">
  <test name="family" compare="contains">
    <string>Arno Pro Smbd</string>
    <!-- Arno Pro Smbd SmText -->
  </test>
  <test name="style" compare="contains">
    <string>Semibold Italic</string>
    <!-- Semibold Italic SmText -->
  </test>
  <edit name="style" mode="delete"/>
  <edit name="style" mode="prepend_first">
    <string>Semibold Italic</string>
  </edit>
</match>
<match target="scan">
  <test name="family" compare="contains">
    <string>Arno Pro Smbd</string>
    <!-- Arno Pro Smbd SmText -->
  </test>
  <test name="style" compare="contains">
    <string>Semibold</string>
    <!-- Semibold SmText -->
  </test>
  <test name="style" compare="not_contains">
    <string>Italic</string>
  </test>
  <edit name="style" mode="delete"/>
  <edit name="style" mode="prepend_first">
    <string>Semibold</string>
  </edit>
</match>
<match target="scan">
  <test name="family" compare="contains">
    <string>Arno Pro Light</string>
    <!-- Arno Pro Light Display -->
  </test>
  <test name="style" compare="contains">
    <string>Light Italic</string>
    <!-- Light Italic Display -->
  </test>
  <edit name="style" mode="delete"/>
  <edit name="style" mode="prepend_first">
    <string>Light Italic</string>
  </edit>
</match>
<match target="scan">
  <test name="family" compare="contains">
    <string>Arno Pro Light</string>
    <!-- Arno Pro Light Display -->
  </test>
  <test name="style" compare="contains">
    <string>Light</string>
    <!-- Light Display -->
  </test>
  <test name="style" compare="not_contains">
    <string>Italic</string>
  </test>
  <edit name="style" mode="delete"/>
  <edit name="style" mode="prepend_first">
    <string>Light</string>
  </edit>
</match>
<!-- remove duplicate styles -->
<match target="scan">
  <test name="family" compare="eq"><string>Arno Pro Caption</string></test>
  <test name="style" compare="contains"><string>Caption</string></test>  
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Arno Pro SmText</string></test>
  <test name="style" compare="contains"><string>SmText</string></test>  
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Arno Pro Subhead</string></test>
  <test name="style" compare="contains"><string>Subhead</string></test>  
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Arno Pro Display</string></test>
  <test name="style" compare="contains"><string>Display</string></test>  
  <edit name="style" mode="delete"/>
</match>

<!-- disambiguate EB Garamond -->
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond</string></test>
  <edit name="family" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond 08</string></test>
  <test name="style" compare="contains"><string>08</string></test>  
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond 12</string></test>
  <test name="style" compare="contains"><string>12</string></test>  
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond SC</string></test>
  <edit name="family" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond SC 08</string></test>
  <test name="style" compare="contains"><string>08</string></test>  
  <edit name="style" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>EB Garamond SC 12</string></test>
  <test name="style" compare="contains"><string>12</string></test>  
  <edit name="style" mode="delete"/>
</match>
<!-- disambiguate Latin Modern -->
<!-- does not work -->
<match target="scan">
  <test name="family" compare="eq"><string>Latin Modern Roman</string></test>
  <edit name="family" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Latin Modern Sans</string></test>
  <edit name="family" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Latin Modern Roman Slanted</string></test>
  <edit name="family" mode="delete"/>
</match>
<match target="scan">
  <test name="family" compare="eq"><string>Latin Modern Mono</string></test>
  <edit name="family" mode="delete"/>
</match>
</fontconfig>
Comment 8 Akira TAGOH 2016-06-28 08:29:30 UTC
(In reply to gm from comment #6)
> Hello, is there any update regarding my suggestion to disregard name IDs 16
> & 17 when dealing with optical fonts? Thank you!

Sorry, still don't have a time to take a look carefully.
Though storing the optical font name into the new object may be an idea, but it comes to mind why font developers adds the same (sub-)family names to the different typefaces. I guess they expect to access them with it seamlessly. then it may be relevant to https://bugs.freedesktop.org/show_bug.cgi?id=13416. though your suggestions looks opposed to it.

For the functionality of fontconfig, to get much better fonts, more conditions needs to be given right. otherwise the result may be vague and not expected one for someone. in that sense, IMHO supporting the 'size' feature in OpenType may be a solution for this issue perhaps - of course applications needs to request the proper things to polish the result. otherwise it may not needs to be fontconfig. applications could read a font directly or the primitive way.

I'll revisit this issue once I have a time. but just for the record at this moment.
Comment 9 Behdad Esfahbod 2016-06-28 21:34:57 UTC
One way is to add a HarfBuzz dependency so we can read the GPOS size feature.
Comment 10 GitLab Migration User 2018-08-20 21:49:36 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to freedesktop.org's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.freedesktop.org/fontconfig/fontconfig/issues/70.

Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.