219 lines
6.3 KiB
Plaintext
219 lines
6.3 KiB
Plaintext
|
// 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
|
||
|
}
|