diff --git a/doc/export/fontmatch.m b/doc/export/fontmatch.m index abd38c32..fe2dceae 100644 --- a/doc/export/fontmatch.m +++ b/doc/export/fontmatch.m @@ -1,13 +1,29 @@ // 3 january 2017 #import "uipriv_darwin.h" -// Stupidity: Core Text requires an **exact match for the entire traits dictionary**, otherwise it will **drop ALL the traits**. -// This seems to be true for every function in Core Text that advertises that it performs font matching; I can confirm at the time of writing this is the case for -// - CTFontDescriptorCreateMatchingFontDescriptors() (though the conditions here seem odd) -// - CTFontCreateWithFontDescriptor() -// - CTFontCreateCopyWithAttributes() -// We have to implement the closest match ourselves. -// This needs to be done early in the matching process; in particular, we have to do this before adding any features (such as small caps), because the matching descriptors won't have those. +// Core Text exposes font style info in two forms: +// - Fonts with a QuickDraw GX font variation (fvar) table, a feature +// adopted by OpenType, expose variations directly. +// - All other fonts have Core Text normalize the font style info +// into a traits dictionary. +// Of course this setup doesn't come without its hiccups and +// glitches. In particular, not only are the exact rules not well +// defined, but also font matching doesn't work as we want it to +// (exactly how varies based on the way the style info is exposed). +// So we'll have to implement style matching ourselves. +// We can use Core Text's matching to get a complete list of +// *possible* matches, and then we can filter out the ones we don't +// want ourselves. +// +// To make things easier for us, we'll match by converting Core +// Text's values back into libui values. This allows us to also use the +// normalization code for filling in uiDrawFontDescriptors from +// Core Text fonts and font descriptors. +// +// Style matching needs to be done early in the font loading process; +// in particular, we have to do this before adding any features, +// because the descriptors returned by Core Text's own font +// matching won't have any. struct closeness { CFIndex index; diff --git a/doc/export/fonttraits.m b/doc/export/fonttraits.m index 10aa45ea..0c57b9d4 100644 --- a/doc/export/fonttraits.m +++ b/doc/export/fonttraits.m @@ -1,6 +1,23 @@ // 1 november 2017 #import "uipriv_darwin.h" +// This is the part of the font style matching and normalization code +// that handles fonts that use a traits dictionary. +// +// Matching stupidity: Core Text requires an **exact match for the +// entire traits dictionary**, otherwise it will **drop ALL the traits**. +// +// Normalization stupidity: Core Text uses its own scaled values for +// weight and width, but the values are different if the font is not +// registered and if said font is TrueType or OpenType. The values +// for all other cases do have some named constants starting with +// OS X 10.11, but even these aren't very consistent in practice. +// +// Of course, none of this is documented anywhere, so I had to do +// both trial-and-error AND reverse engineering to figure out what's +// what. We'll just convert Core Text's values into libui constants +// and use those for matching. + static BOOL fontRegistered(CTFontDescriptorRef desc) { CFNumberRef scope; diff --git a/doc/export/fontvariation.m b/doc/export/fontvariation.m index d97a6158..79236613 100644 --- a/doc/export/fontvariation.m +++ b/doc/export/fontvariation.m @@ -1,7 +1,25 @@ // 2 november 2017 #import "uipriv_darwin.h" -// references: +// This is the part of the font style matching and normalization code +// that handles fonts that use the fvar table. +// +// Matching stupidity: Core Text **doesn't even bother** matching +// these, even if you tell it to do so explicitly. It'll always return +// all variations for a given font. +// +// Normalization stupidity: Core Text doesn't normalize the fvar +// table values for us, so we'll have to do it ourselves. Furthermore, +// Core Text doesn't provide an API for accessing the avar table, if +// any, so we must do so ourselves. (TODO does Core Text even +// follow the avar table if a font has it?) +// +// Thankfully, normalization is well-defined in both TrueType and +// OpenType and seems identical in both, so we can just normalize +// the values and then convert them linearly to libui values for +// matching. +// +// References: // - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fvar.html // - https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6avar.html // - https://www.microsoft.com/typography/otspec/fvar.htm