Started converting the code in Core Text itself that determines what weight a font has into pseudocode.
This commit is contained in:
parent
4d57a12dbc
commit
9f1e1b25be
|
@ -0,0 +1,218 @@
|
|||
// pseudo-go
|
||||
|
||||
func (f *CTFont) IsRegistered() bool {
|
||||
n := f.Attribute(kCTFontRegistrationScopeAttribute)
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
return n.(*CFNumber).Uint32Value() == kCTFontManagerScopeNone
|
||||
}
|
||||
|
||||
// based on libFontRegistry.dylib's __ZN11TFontTraitsC2EP6CGFontRK13TFontMetadata — TFontTraits::TFontTraits(CGFont*, TFontMetadata const&)
|
||||
func (f *Font) WeightFromFontRegistry32() float32 {
|
||||
var weight float32
|
||||
|
||||
cgfont := f.CGFont()
|
||||
}
|
||||
|
||||
// because Core Text gets registry traits as a CFDictionary, convert the float to a double with CFNumber as that is what actually would be done
|
||||
func (f *Font) WeightFromFontRegistry() float64 {
|
||||
return CFNumberWithFloat32(f.WeightFromFontRegistry32()).Float64Value()
|
||||
}
|
||||
|
||||
// based on CoreText dylib's __Z13WeightOfClasst — WeightOfClass(unsigned short)
|
||||
func CoreText_WeightOfClass(usWeightClass uint16) float64 {
|
||||
if usWeightClass >= 11 {
|
||||
// do nothing; we are preserving the original asm comparisons
|
||||
} else {
|
||||
usWeightClass *= 100
|
||||
}
|
||||
|
||||
// figure out what two floats our weight will be between
|
||||
i := usWeightClass / 100
|
||||
j := i + 1
|
||||
if j > 10 {
|
||||
j = 10
|
||||
}
|
||||
b := float64(i * 100)
|
||||
c := float64(j * 100)
|
||||
|
||||
a := float64(0)
|
||||
if b != c {
|
||||
a = float64(usWeightClass)
|
||||
a -= b
|
||||
c -= b
|
||||
a /= c
|
||||
}
|
||||
scales := []float32{
|
||||
float32as(-1.000000, 0xbf800000),
|
||||
float32as(-0.700000, 0xbf333333),
|
||||
float32as(-0.500000, 0xbf000000),
|
||||
float32as(-0.230000, 0xbe6b851f),
|
||||
float32as(0.000000, 0x0),
|
||||
float32as(0.200000, 0x3e4ccccd),
|
||||
float32as(0.300000, 0x3e99999a),
|
||||
float32as(0.400000, 0x3ecccccd),
|
||||
float32as(0.600000, 0x3f19999a),
|
||||
float32as(0.800000, 0x3f4ccccd),
|
||||
float32as(1.000000, 0x3f800000),
|
||||
}
|
||||
c = float64(scale[i])
|
||||
b = float64[scale[j])
|
||||
return fma(a, b, c)
|
||||
}
|
||||
|
||||
// based on CoreText dylib's __ZL33CreateTraitsByStyleGlossaryStringPK10__CFString — CreateTraitsByStyleGlossaryString(__CFString const*)
|
||||
func CoreText_WeightByStyleGlossaryString(str string) (weight float64, ok bool) {
|
||||
str.Fold(kCFCompareCaseInsensitive, nil)
|
||||
|
||||
var weightNameMap = []struct {
|
||||
key string
|
||||
val float32
|
||||
}{
|
||||
{ "ultra light", float32as(-0.800000, 0xbf4ccccd) },
|
||||
{ "ultra black", float32as(0.750000, 0x3f400000) },
|
||||
{ "extra light", float32as(-0.500000, 0xbf000000) },
|
||||
{ "ultralight", float32as(-0.800000, 0xbf4ccccd) },
|
||||
{ "ultrablack", float32as(0.750000, 0x3f400000) },
|
||||
{ "extrablack", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "extralight", float32as(-0.500000, 0xbf000000) }
|
||||
{ "heavy face", float32as(0.560000, 0x3f0f5c29) },
|
||||
{ "semi light", float32as(-0.200000, 0xbe4ccccd) },
|
||||
{ "extra bold", float32as(0.500000, 0x3f000000) },
|
||||
{ "ultra bold", float32as(0.700000, 0x3f333333) },
|
||||
{ "heavyface", float32as(0.560000, 0x3f0f5c29) },
|
||||
{ "extrabold", float32as(0.500000, 0x3f000000) },
|
||||
{ "ultrabold", float32as(0.700000, 0x3f333333) },
|
||||
{ "semilight", float32as(-0.200000, 0xbe4ccccd) },
|
||||
{ "demi bold", float32as(0.250000, 0x3e800000) },
|
||||
{ "semi bold", float32as(0.300000, 0x3e99999a) },
|
||||
{ "demibold", float32as(0.250000, 0x3e800000) },
|
||||
{ "semibold", float32as(0.300000, 0x3e99999a) },
|
||||
{ "hairline", float32as(-0.700000, 0xbf333333) },
|
||||
{ "medium", float32as(0.230000, 0x3e6b851f) },
|
||||
{ "poster", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "light", float32as(-0.400000, 0xbecccccd) },
|
||||
{ "heavy", float32as(0.560000, 0x3f0f5c29) },
|
||||
{ "extra", float32as(0.500000, 0x3f000000) },
|
||||
{ "black", float32as(0.620000, 0x3f1eb852) },
|
||||
{ "super", float32as(0.620000, 0x3f1eb852) },
|
||||
{ "obese", float32as(0.850000, 0x3f59999a) },
|
||||
{ "lite", float32as(-0.400000, 0xbecccccd) },
|
||||
{ "book", float32as(-0.230000, 0xbe6b851f) },
|
||||
{ "demi", float32as(0.250000, 0x3e800000) },
|
||||
{ "semi", float32as(0.300000, 0x3e99999a) },
|
||||
{ "thin", float32as(-0.500000, 0xbf000000) },
|
||||
{ "bold", float32as(0.400000, 0x3ecccccd) },
|
||||
{ "nord", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "fat", float32as(0.750000, 0x3f400000) },
|
||||
{ "w1", float32as(-0.700000, 0xbf333333) },
|
||||
{ "w2", float32as(-0.500000, 0xbf000000) },
|
||||
{ "w3", float32as(-0.230000, 0xbe6b851f) },
|
||||
{ "w4", float32as(0.000000, 0x0) },
|
||||
{ "w5", float32as(0.230000, 0x3e6b851f) },
|
||||
{ "w6", float32as(0.300000, 0x3e99999a) },
|
||||
{ "w7", float32as(0.440000, 0x3ee147ae) },
|
||||
{ "w8", float32as(0.540000, 0x3f0a3d71) },
|
||||
{ "w9", float32as(0.620000, 0x3f1eb852) },
|
||||
}
|
||||
for _, m := range weightNameMap {
|
||||
if strstr(str, m.key) != nil {
|
||||
val := CFNumberWithFloat32(m.val)
|
||||
return val.Float64Value(), true
|
||||
}
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// based on CoreText dylib's __ZNK9TBaseFont29CreateTraitsValuesPerFontInfoEP12MetadataFlag — TBaseFont::CreateTraitsValuesPerFontInfo(MetadataFlag*) const
|
||||
func (f *CTFont) Weight() float64 {
|
||||
if f.IsRegistered() {
|
||||
return f.WeightFromFontRegistry()
|
||||
}
|
||||
|
||||
weight := float64as(2.0, 0x4000000000000000)
|
||||
ebx := -1
|
||||
hasWeight := false
|
||||
|
||||
name := f.Name(kCTFontPostScriptNameKey)
|
||||
if name != nil {
|
||||
switch *name {
|
||||
case "LucidaGrande":
|
||||
weight = float64as(0.000000, 0x0)
|
||||
hasWeight = true
|
||||
case ".LucidaGrandeUI":
|
||||
weight = float64as(0.000000, 0x0)
|
||||
hasWeight = true
|
||||
case "STHeiti":
|
||||
weight = float64as(0.240000, 0x3fceb851eb851eb8)
|
||||
hasWeight = true
|
||||
case "STXihei":
|
||||
weight = float64as(-0.100000, 0xbfb999999999999a)
|
||||
hasWeight = true
|
||||
case "TimesNewRomanPSMT":
|
||||
weight = float64as(0.000000, 0x0)
|
||||
hasWeight = true
|
||||
// there is one more hardcoded case, for "Times-Roman", but that will only set the class style, not the weight
|
||||
}
|
||||
}
|
||||
|
||||
os2table := f.Table('OS/2')
|
||||
if os2table != nil {
|
||||
if !hasWeight {
|
||||
var usWeightClass uint16
|
||||
|
||||
valid := false
|
||||
if os2table.Len() > 77 {
|
||||
b := os2table.Bytes()
|
||||
usWeightClass = uint16be(b[4:6])
|
||||
if usWeightClass > 1000 {
|
||||
weight = 0
|
||||
hasWeight = false
|
||||
} else {
|
||||
valid = true
|
||||
}
|
||||
} else {
|
||||
usWeightClass = 0
|
||||
valid = true
|
||||
}
|
||||
if valid {
|
||||
weight = CoreText_WeightOfClass(usWeightClass)
|
||||
hasWeight = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
styleGlossaryNames := []string{
|
||||
kCTFontSubFamilyNameKey,
|
||||
kCTFontFullNameKey,
|
||||
kCTFontFamilyNameKey,
|
||||
}
|
||||
for _, key := range styleGlossaryNames {
|
||||
name := f.Name(key)
|
||||
if name == nil {
|
||||
continue
|
||||
}
|
||||
candidate, ok := CoreText_WeightByStyleGlossaryString(*name)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if !hasWeight {
|
||||
weight = candidate
|
||||
hasWeight = true
|
||||
}
|
||||
}
|
||||
|
||||
if hasWeight {
|
||||
return weight
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (f *Font) ShouldEnableBoldSymbolicTrait() bool {
|
||||
if f.IsRegistered() {
|
||||
return f.ShouldEnableBoldSymbolicTraitFromRegistry()
|
||||
}
|
||||
no := f.Weight() <= float64as(0.239000, 0x3fce978d4fdf3b64)
|
||||
return !no
|
||||
}
|
Loading…
Reference in New Issue