First Commit
This commit is contained in:
commit
ae0fab9400
424 files changed
+71006
No files matched your search
@@ -0,0 +1,5 @@
|
||||
font features are not provided by the collection and have to be added when asking for a font
|
||||
it does preserve when going from CTFont to CTFontDescriptor
|
||||
feature 17 has no flags in the header but can also hold small caps info
|
||||
if a feature is present, it is ignored; other features will still show up
|
||||
at least in the case of kLetterCaseTrait and kLowerCaseTrait
|
||||
@@ -0,0 +1,750 @@
|
||||
// pseudo-go
|
||||
|
||||
func (f *CTFont) IsRegistered() bool {
|
||||
n := f.Attribute(kCTFontRegistrationScopeAttribute)
|
||||
if n == nil {
|
||||
return false
|
||||
}
|
||||
return n.(*CFNumber).Uint32Value() == kCTFontManagerScopeNone
|
||||
}
|
||||
|
||||
// this type is in libFontRegistry.dylib; functions like x_list.Prepend() are called things like x_list_prepend() there
|
||||
type x_list struct {
|
||||
Data interface{}
|
||||
Next *x_list
|
||||
}
|
||||
|
||||
func (x *x_list) Prepend(data interface{}) *x_list {
|
||||
y := malloc(sizeof (x_list))
|
||||
if y != nil {
|
||||
y.data = data
|
||||
y.next = x
|
||||
return y
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func (x *x_list) Reverse() *x_list {
|
||||
if x == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var old, next *x_list
|
||||
|
||||
next = nil
|
||||
for {
|
||||
old = x
|
||||
x = old.next
|
||||
old.next = next
|
||||
next = old
|
||||
if x == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return old
|
||||
}
|
||||
|
||||
func (x *x_list) Concat(y *x_list) *x_list {
|
||||
if x == nil {
|
||||
return y
|
||||
}
|
||||
start := x
|
||||
z := x
|
||||
for {
|
||||
x = z
|
||||
z = z.next
|
||||
if z == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
x.next = y
|
||||
return start
|
||||
}
|
||||
|
||||
// based on CoreGraphics dylib's _CGFontCopyName
|
||||
// note that this is different from the public API function CGFontCopyPostScriptName() (which is font type-independent)
|
||||
// also note that in reality these keys are strings but the implementation of the function turns them into ints and only uses them as such
|
||||
const (
|
||||
kCGFontNameKeyPostScriptName = 0x6
|
||||
kCGFontNameKeyPreferredSubfamily = 0x11
|
||||
kCGFontNameKeyFontSubfamily = 0x2
|
||||
kCGFontNameKeyFullName = 0x4
|
||||
kCGFontNameKeyPreferredFamily = 0x10
|
||||
kCGFontNameKeyFontFamily = 0x1
|
||||
)
|
||||
func (f *CGFont) CopyName(key int) (string, bool) {
|
||||
table := f.TableForTag('name')
|
||||
b := table.Bytes()
|
||||
n := table.Len()
|
||||
|
||||
// this code looks weird, but we're imitating the assembly, or the effective effects thereof
|
||||
offCount := uint16(0)
|
||||
offStringOffset := uint16(2)
|
||||
if n > 1 {
|
||||
offCount = 2
|
||||
offStringOffset = 4
|
||||
}
|
||||
|
||||
count := uint16(0)
|
||||
if int(offCount) <= n {
|
||||
count = uint16be(b[offCount:offCount + 2])
|
||||
}
|
||||
|
||||
offNameRecord := offStringOffset + 2
|
||||
stringOffset := uint16(0)
|
||||
if int(offNameRecord) <= n {
|
||||
stringOffset = uint16be(b[offStringOffset:offStringOffset + 2])
|
||||
}
|
||||
|
||||
type NameRecord struct {
|
||||
PlatformID uint16
|
||||
PlatformSpecificID uint16
|
||||
LanguageID uint16
|
||||
NameID uint16
|
||||
Length uint16
|
||||
Offset uint16
|
||||
}
|
||||
|
||||
var nameList *x_list
|
||||
|
||||
addrStrings := offNameRecords + (12 * count)
|
||||
if addrStrings != stringOffset {
|
||||
goto hasLanguageTags
|
||||
}
|
||||
pos := offNameRecords
|
||||
if count == 0 {
|
||||
// TODO note assembly logic here
|
||||
} else {
|
||||
for {
|
||||
var nr NameRecord
|
||||
|
||||
nr.PlatformID = 0
|
||||
next := pos + 2
|
||||
if int(next) <= n {
|
||||
nr.PlatformID = uint16be(b[pos:pos + 2])
|
||||
pos = next
|
||||
}
|
||||
|
||||
nr.PlatformSpecificID = 0
|
||||
next = pos + 2
|
||||
if int(next) <= n {
|
||||
nr.PlatformSpecificID = uint16be(b[pos:pos + 2])
|
||||
pos = next
|
||||
}
|
||||
|
||||
nr.LanguageID = 0
|
||||
next = pos + 2
|
||||
if int(next) <= n {
|
||||
nr.LanguageID = uint16be(b[pos:pos + 2])
|
||||
pos = next
|
||||
}
|
||||
|
||||
nr.NameID = 0
|
||||
next = pos + 2
|
||||
if int(next) <= n {
|
||||
nr.NameID = uint16be(b[pos:pos + 2])
|
||||
pos = next
|
||||
}
|
||||
|
||||
nr.Length = 0
|
||||
next = pos + 2
|
||||
if int(next) <= n {
|
||||
nr.Length = uint16be(b[pos:pos + 2])
|
||||
pos = next
|
||||
}
|
||||
|
||||
nr.Offset = 0
|
||||
next = pos + 2
|
||||
if int(next) <= n {
|
||||
nr.Offset = uint16be(b[pos:pos + 2])
|
||||
pos = next
|
||||
}
|
||||
|
||||
strpos := stringOffset + nr.Offset
|
||||
if strpos >= n {
|
||||
// TODO put comment about imitating the assembly comparisons here
|
||||
} else {
|
||||
realLen := nr.Length
|
||||
strend = strpos + nr.Length
|
||||
if strend > n {
|
||||
realLen = nr.Length - strpos
|
||||
strend = strpos + realLen
|
||||
}
|
||||
b := malloc(12 + realLen + 1)
|
||||
if b != nil {
|
||||
name := (*sfnt_name_t)(b)
|
||||
name.PlatformID = nr.PlatformID
|
||||
name.PlatformSpecificID = nr.PlatformSpecificID
|
||||
name.LanguageID = nr.LanguageID
|
||||
name.NameID = nr.NameID
|
||||
name.Length = realLen
|
||||
memcpy(&(name.Name), b[strpos:strend], realLen)
|
||||
name.Name[realLen] = 0
|
||||
nameList = nameList.Prepend(name)
|
||||
}
|
||||
}
|
||||
count--
|
||||
if count == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
nameList = nameList.Reverse()
|
||||
|
||||
hasLanguageTags:
|
||||
add_localized_names := func(platformID uint16, platformSpecificID uint16, to *x_list) *x_list {
|
||||
out := (*x_list)(nil)
|
||||
if nameList == nil {
|
||||
xx TODO logic verbatim etc.
|
||||
} else {
|
||||
x := nameList
|
||||
for {
|
||||
name := (*sfnt_name_t)(x.data)
|
||||
if name.PlatformID != platformID {
|
||||
xx TODO
|
||||
} else {
|
||||
if platformSpecificID == 0xFFFF || name.PlatformSpecificID == platformSpecificID {
|
||||
out = out.Prepend(name)
|
||||
}
|
||||
}
|
||||
x = x.next
|
||||
if x == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
out = out.Reverse()
|
||||
return to.Concat(out)
|
||||
}
|
||||
localized := (*x_list)(nil)
|
||||
localized = add_localized_names(0x1, 0xFFFF, localized)
|
||||
localized = add_localized_names(0, 0xFFFF, localized)
|
||||
localized = add_localized_names(0x3, 0xFFFF, localized)
|
||||
localized = add_localized_names(0x1, 0, localized)
|
||||
localized = add_localized_names(0x3, 0x9, localized)
|
||||
localized = add_localized_names(0x3, 0x409, localized)
|
||||
|
||||
sysLocale := CFLocaleGetSystem()
|
||||
|
||||
}
|
||||
|
||||
// based on libFontRegistry.dylib's __ZNK8OS2Table15DetermineWeightERf — OS2Table::DetermineWeight(float&) const
|
||||
func RegistryDetermineOS2Weight(table *CFData) (float32, bool) {
|
||||
if table == nil {
|
||||
return 0, false
|
||||
}
|
||||
if table.Len() < 78 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
b := table.Bytes()
|
||||
usWeightClass := uint16be(b[4:6])
|
||||
if usWeightClass >= 10 {
|
||||
// do nothing; we are preserving the original asm comparisons
|
||||
} else {
|
||||
usWeightClass *= 100
|
||||
}
|
||||
/* TODO:
|
||||
000000000000b37e mov dx, word [rax+4]
|
||||
000000000000b382 mov cx, dx
|
||||
000000000000b385 rol cx, 0x8
|
||||
000000000000b389 movzx esi, cx
|
||||
000000000000b38c imul ecx, ecx, 100
|
||||
000000000000b38f cmp esi, 10
|
||||
000000000000b392 cmovae cx, si
|
||||
000000000000b396 test dx, dx
|
||||
000000000000b399 cmove cx, si
|
||||
what's the function of the last two instructions? */
|
||||
|
||||
// note that this is an unsigned comparison, so underflow will result in a number > 998
|
||||
// the effect is the same as (usWeightClass == 0) || (usWeightClass >= 1000)
|
||||
if (usWeightClass - 1) > 998 {
|
||||
// note the - 2 here; the switch cases below reflect that!
|
||||
// also note that b[0x22] and panose will be unsigned, so underflow will result in a number > 9
|
||||
panose := b[0x22] - 2
|
||||
if panose > 9 {
|
||||
return 0, false
|
||||
}
|
||||
switch panose {
|
||||
case 0:
|
||||
return float32as(-0.500000, 0xbf000000), true
|
||||
case 1:
|
||||
return float32as(-0.400000, 0xbecccccd), true
|
||||
case 2:
|
||||
// yes, this returns false; I don't know why
|
||||
return float32as(-0.300000, 0xbe99999a), false
|
||||
case 3:
|
||||
return float32as(-0.230000, 0xbe6b851f), true
|
||||
case 4:
|
||||
return float32as(0.230000, 0x3e6b851f), true
|
||||
case 5:
|
||||
return float32as(0.250000, 0x3e800000), true
|
||||
case 6:
|
||||
return float32as(0.400000, 0x3ecccccd), true
|
||||
case 7:
|
||||
return float32as(0.560000, 0x3f0f5c29), true
|
||||
case 8:
|
||||
return float32as(0.620000, 0x3f1eb852), true
|
||||
case 9:
|
||||
return float32as(0.800000, 0x3f4ccccd), true
|
||||
}
|
||||
// should not reach here
|
||||
}
|
||||
|
||||
// let's mimic the assembly here too
|
||||
// the gotos avoid the massive if nesting
|
||||
// also note I'm using Go idioms and not saying "else return", imagine those if you must
|
||||
if usWeightClass > 100 {
|
||||
if usWeightClass > 200 {
|
||||
goto do201AndUp
|
||||
}
|
||||
return float32as(-0.500000, 0xbf000000), true
|
||||
}
|
||||
return float32as(-0.800000, 0xbf4ccccd), true
|
||||
|
||||
do201AndUp:
|
||||
if usWeightClass > 300 {
|
||||
if usWeightClass > 400 {
|
||||
goto do401AndUp
|
||||
}
|
||||
return float32as(0.000000, 0x0), true
|
||||
}
|
||||
return float32as(-0.400000, 0xbecccccd), true
|
||||
|
||||
do401AndUp:
|
||||
if usWeightClass > 500 {
|
||||
if usWeightClass > 600 {
|
||||
goto do601AndUp
|
||||
}
|
||||
return float32as(0.250000, 0x3e800000), true
|
||||
}
|
||||
return float32as(0.230000, 0x3e6b851f), true
|
||||
|
||||
do601AndUp:
|
||||
if usWeightClass > 700 {
|
||||
if usWeightClass > 800 {
|
||||
goto do801AndUp
|
||||
}
|
||||
return float32as(0.500000, 0x3f000000), true
|
||||
}
|
||||
return float32as(0.400000, 0x3ecccccd), true
|
||||
|
||||
do801AndUp:
|
||||
if usWeightClass > 900 {
|
||||
if usWeightClass > 950 {
|
||||
return float32(0.800000, 0x3f4ccccd), true
|
||||
}
|
||||
return float32(0.750000, 0x3f400000), true
|
||||
}
|
||||
return float32as(0.620000, 0x3f1eb852), true
|
||||
}
|
||||
|
||||
// based on libFontRegistry.dylib's __ZN11TFontTraitsC2EP6CGFontRK13TFontMetadata — TFontTraits::TFontTraits(CGFont*, TFontMetadata const&)
|
||||
func (f *Font) WeightFromFontRegistry32() float32 {
|
||||
var weight float32
|
||||
var hasWeight bool = false
|
||||
|
||||
cgfont := f.CGFont()
|
||||
if f.RegistryHasMetadata() {
|
||||
wv := f.RegistryMetadataValueForKey("MTD_Typeface_Weight_VisualDescriptor")
|
||||
if wv != nil {
|
||||
if wn, ok := wv.(string); ok {
|
||||
// note: uses CFStringCompare(0)
|
||||
switch wn {
|
||||
case "reg":
|
||||
weight = float32as(0.000000, 0x0)
|
||||
hasWeight = true
|
||||
case "semi":
|
||||
weight = float32as(0.300000, 0x3e99999a)
|
||||
hasWeight = true
|
||||
case "bold":
|
||||
weight = float32as(0.400000, 0x3ecccccd)
|
||||
hasWeight = true
|
||||
case "light":
|
||||
weight = float32as(-0.400000, 0xbecccccd)
|
||||
hasWeight = true
|
||||
case "med":
|
||||
weight = float32as(0.230000, 0x3e6b851f)
|
||||
hasWeight = true
|
||||
case "heavy":
|
||||
weight = float32as(0.560000, 0x3f0f5c29)
|
||||
hasWeight = true
|
||||
case "black":
|
||||
weight = float32as(0.620000, 0x3f1eb852)
|
||||
hasWeight = true
|
||||
case "thin":
|
||||
weight = float32as(-0.600000, 0xbf19999a)
|
||||
hasWeight = true
|
||||
case "ulight":
|
||||
weight = float32as(-0.800000, 0xbf4ccccd)
|
||||
hasWeight = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cgpsname, ok := cgfont.CopyName(kCGFontNameKeyPostScriptName)
|
||||
if ok {
|
||||
// note: uses CFStringCompare(0)
|
||||
switch cgpsname {
|
||||
case "LucidaGrande",
|
||||
".LucidaGrandeUI",
|
||||
".Keyboard":
|
||||
weight = float32as(0.000000, 0x0)
|
||||
hasWeight = true
|
||||
case "STHeiti":
|
||||
weight = float32as(0.240000, 0x3e75c28f)
|
||||
hasWeight = true
|
||||
case "STXihei":
|
||||
weight = float32as(-0.100000, 0xbdcccccd)
|
||||
hasWeight = true
|
||||
case "TimesNewRomanPSMT":
|
||||
weight = float32as(0.000000, 0x0)
|
||||
hasWeight = true
|
||||
}
|
||||
}
|
||||
|
||||
styleGlossaryStrings := []int{
|
||||
kCGFontNameKeyPreferredSubfamily,
|
||||
kCGFontNameKeyFontSubfamily,
|
||||
kCGFontNameKeyFullName,
|
||||
kCGFontNameKeyPreferredFamily,
|
||||
kCGFontNameKeyFontFamily,
|
||||
}
|
||||
weightNameMap := []struct {
|
||||
key string
|
||||
val float32
|
||||
}{
|
||||
{ "Ultra Light", float32as(-0.800000f, 0xbf4ccccd) },
|
||||
{ "Ultra Black", float32as(0.750000f, 0x3f400000) },
|
||||
{ "Extra Light", float32as(-0.500000f, 0xbf000000) },
|
||||
{ "UltraBlack", float32as(0.750000f, 0x3f400000) },
|
||||
{ "ExtraBlack", float32as(0.800000f, 0x3f4ccccd) },
|
||||
{ "UltraLight", float32as(-0.800000f, 0xbf4ccccd) },
|
||||
{ "ExtraLight", float32as(-0.500000f, 0xbf000000) },
|
||||
{ "Ultra Thin", float32as(-0.800000f, 0xbf4ccccd) },
|
||||
{ "Extra Thin", float32as(-0.800000f, 0xbf4ccccd) },
|
||||
{ "Heavy Face", float32as(0.560000f, 0x3f0f5c29) },
|
||||
{ "Semi Light", float32as(-0.200000f, 0xbe4ccccd) },
|
||||
{ "Extra Bold", float32as(0.500000f, 0x3f000000) },
|
||||
{ "Ultra Bold", float32as(0.700000f, 0x3f333333) },
|
||||
{ "HeavyFace", float32as(0.560000f, 0x3f0f5c29) },
|
||||
{ "ExtraBold", float32as(0.500000f, 0x3f000000) },
|
||||
{ "UltraBold", float32as(0.700000f, 0x3f333333) },
|
||||
{ "Ext Black", float32as(0.800000f, 0x3f4ccccd) },
|
||||
{ "SemiLight", float32as(-0.200000f, 0xbe4ccccd) },
|
||||
{ "Demi Bold", float32as(0.250000f, 0x3e800000) },
|
||||
{ "Semi Bold", float32as(0.300000f, 0x3e99999a) },
|
||||
{ "Ext Light", float32as(-0.500000f, 0xbf000000) },
|
||||
{ "Ext Bold", float32as(0.500000f, 0x3f000000) },
|
||||
{ "DemiBold", float32as(0.250000f, 0x3e800000) },
|
||||
{ "SemiBold", float32as(0.300000f, 0x3e99999a) },
|
||||
{ "HairLine", float32as(-0.800000f, 0xbf4ccccd) },
|
||||
{ "Ext Thin", float32as(-0.800000f, 0xbf4ccccd) },
|
||||
{ "Medium", float32as(0.230000f, 0x3e6b851f) },
|
||||
{ "Poster", float32as(0.800000f, 0x3f4ccccd) },
|
||||
{ "Light", float32as(-0.400000f, 0xbecccccd) },
|
||||
{ "Ultra", float32as(0.500000f, 0x3f000000) },
|
||||
{ "Heavy", float32as(0.560000f, 0x3f0f5c29) },
|
||||
{ "Extra", float32as(0.500000f, 0x3f000000) },
|
||||
{ "Black", float32as(0.620000f, 0x3f1eb852) },
|
||||
{ "Super", float32as(0.620000f, 0x3f1eb852) },
|
||||
{ "Obese", float32as(0.850000f, 0x3f59999a) },
|
||||
{ "Lite", float32as(-0.400000f, 0xbecccccd) },
|
||||
{ "Book", float32as(-0.230000f, 0xbe6b851f) },
|
||||
{ "Demi", float32as(0.250000f, 0x3e800000) },
|
||||
{ "Semi", float32as(0.300000f, 0x3e99999a) },
|
||||
{ "Thin", float32as(-0.500000f, 0xbf000000) },
|
||||
{ "Bold", float32as(0.400000f, 0x3ecccccd) },
|
||||
{ "Nord", float32as(0.800000f, 0x3f4ccccd) },
|
||||
{ "Fat", float32as(0.750000f, 0x3f400000) },
|
||||
{ "W1", float32as(-0.230000f, 0xbe6b851f) },
|
||||
{ "W2", float32as(-0.500000f, 0xbf000000) },
|
||||
{ "W3", float32as(-0.230000f, 0xbe6b851f) },
|
||||
{ "W4", float32as(0.000000f, 0x0) },
|
||||
{ "W5", float32as(0.230000f, 0x3e6b851f) },
|
||||
{ "W6", float32as(0.300000f, 0x3e99999a) },
|
||||
{ "W7", float32as(0.440000f, 0x3ee147ae) },
|
||||
{ "W8", float32as(0.540000f, 0x3f0a3d71) },
|
||||
{ "W9", float32as(0.620000f, 0x3f1eb852) },
|
||||
}
|
||||
for _, key := range styleGlossaryStrings {
|
||||
if hasWeight {
|
||||
break
|
||||
}
|
||||
str, ok := cgfont.CopyName(key)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, m := range weightNameMap {
|
||||
if str.FindWithOptions(m.key, CFRangeMake(0, str.CFStringLength()), kCFCompareCaseInsensitive | kCFCompareBackwards | kCFCompareNonliteral, nil) {
|
||||
weight = m.val
|
||||
hasWeight = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !hasWeight {
|
||||
os2table := cgfont.TableForTag('OS/2')
|
||||
weight, hasWeight = RegistryDetermineOS2Weight(os2table)
|
||||
}
|
||||
|
||||
if !hasWeight {
|
||||
headtable := cgfont.TableForTag('head')
|
||||
if headtable != nil {
|
||||
if headtable.Len() >= 54 {
|
||||
b := headtable.Bytes()
|
||||
if (b[0x2d] & 1) != 0 {
|
||||
weight = float32as(0.400000, 0x3ecccccd)
|
||||
hasWeight = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
styleGlossaryAbbreviationKeys := []int{
|
||||
kCGFontNameKeyPreferredSubfamily,
|
||||
kCGFontNameKeyFontSubfamily,
|
||||
}
|
||||
abbreviatedWeightNameMap := []struct {
|
||||
key string
|
||||
val float32
|
||||
}{
|
||||
{ "EL", float32as(-0.200000, 0xbe4ccccd) },
|
||||
{ "EB", float32as(0.500000, 0x3f000000) },
|
||||
{ "SB", float32as(0.300000, 0x3e99999a) },
|
||||
{ "UH", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "U", float32as(0.700000, 0x3f333333) },
|
||||
{ "L", float32as(-0.400000, 0xbecccccd) },
|
||||
{ "H", float32as(0.560000, 0x3f0f5c29) },
|
||||
{ "B", float32as(0.400000, 0x3ecccccd) },
|
||||
{ "M", float32as(0.230000, 0x3e6b851f) },
|
||||
{ "R", float32as(0.000000, 0x0) },
|
||||
}
|
||||
if !hasWeight {
|
||||
for _, key := range styleGlossaryAbbreviationStrings {
|
||||
str, ok := cgfont.CopyName(key)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, m := range abbreviatedWeightNameMap {
|
||||
if str.Compare(m.key, kCFCompareCaseInsensitive) == kCFCompareEqualTo {
|
||||
weight = m.val
|
||||
hasWeight = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if hasWeight {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !hasWeight {
|
||||
return float32as(0.000000, 0x0)
|
||||
}
|
||||
return weight
|
||||
}
|
||||
|
||||
// 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
|
||||
// and yes, this one is 11, but the one above is 10
|
||||
} 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)
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
-0.100000 0xbdcccccd registered postscript name "STXihei"
|
||||
-0.100000 0xbfb999999999999a unregistered postscript name "STXihei"
|
||||
-0.200000 0xbe4ccccd registered subfamily abbr "EL"
|
||||
-0.200000 0xbe4ccccd "Semi Light"
|
||||
-0.200000 0xbe4ccccd "SemiLight"
|
||||
-0.200000 0xbe4ccccd "semi light"
|
||||
-0.200000 0xbe4ccccd "semilight"
|
||||
-0.230000 0xbe6b851f "Book"
|
||||
-0.230000 0xbe6b851f "W1"
|
||||
-0.230000 0xbe6b851f "W3"
|
||||
-0.230000 0xbe6b851f "book"
|
||||
-0.230000 0xbe6b851f "w3"
|
||||
-0.230000 0xbe6b851f panose 5
|
||||
-0.400000 0xbecccccd registered subfamily abbr "L"
|
||||
-0.400000 0xbecccccd "Light"
|
||||
-0.400000 0xbecccccd "Lite"
|
||||
-0.400000 0xbecccccd "light"
|
||||
-0.400000 0xbecccccd "light"
|
||||
-0.400000 0xbecccccd "lite"
|
||||
-0.400000 0xbecccccd registered OS2 weights 3, 201 - 300
|
||||
-0.400000 0xbecccccd panose 3
|
||||
-0.500000 0xbf000000 "Ext Light"
|
||||
-0.500000 0xbf000000 "Extra Light"
|
||||
-0.500000 0xbf000000 "ExtraLight"
|
||||
-0.500000 0xbf000000 "Thin"
|
||||
-0.500000 0xbf000000 "W2"
|
||||
-0.500000 0xbf000000 "extra light"
|
||||
-0.500000 0xbf000000 "extralight"
|
||||
-0.500000 0xbf000000 "thin"
|
||||
-0.500000 0xbf000000 "w2"
|
||||
-0.500000 0xbf000000 registered OS2 weights 2, 101 - 200
|
||||
-0.500000 0xbf000000 panose 2
|
||||
-0.600000 0xbf19999a "thin"
|
||||
-0.700000 0xbf333333 "hairline"
|
||||
-0.700000 0xbf333333 "w1"
|
||||
-0.800000 0xbf4ccccd "Ext Thin"
|
||||
-0.800000 0xbf4ccccd "Extra Thin"
|
||||
-0.800000 0xbf4ccccd "HairLine"
|
||||
-0.800000 0xbf4ccccd "Ultra Light"
|
||||
-0.800000 0xbf4ccccd "Ultra Thin"
|
||||
-0.800000 0xbf4ccccd "UltraLight"
|
||||
-0.800000 0xbf4ccccd "ulight"
|
||||
-0.800000 0xbf4ccccd "ultra light"
|
||||
-0.800000 0xbf4ccccd "ultralight"
|
||||
-0.800000 0xbf4ccccd registered OS2 weights 1, 10 - 100
|
||||
0.000000 0x0 registered postscript name ".Keyboard"
|
||||
0.000000 0x0 registered postscript name ".LucidaGrandeUI"
|
||||
0.000000 0x0 unregistered postscript name ".LucidaGrandeUI"
|
||||
0.000000 0x0 registered postscript name "LucidaGrande"
|
||||
0.000000 0x0 unregistered postscript name "LucidaGrande"
|
||||
0.000000 0x0 registered subfamily abbr "R"
|
||||
0.000000 0x0 registered postscript name "TimesNewRomanPSMT"
|
||||
0.000000 0x0 unregistered postscript name "TimesNewRomanPSMT"
|
||||
0.000000 0x0 "W4"
|
||||
0.000000 0x0 "reg"
|
||||
0.000000 0x0 "w4"
|
||||
0.000000 0x0 registered OS2 weights 4, 301 - 400
|
||||
0.000000 0x0 default
|
||||
0.230000 0x3e6b851f registered OS2 weights 5, 401 - 500
|
||||
0.230000 0x3e6b851f registered subfamily abbr "M"
|
||||
0.230000 0x3e6b851f "Medium"
|
||||
0.230000 0x3e6b851f "W5"
|
||||
0.230000 0x3e6b851f "med"
|
||||
0.230000 0x3e6b851f "medium"
|
||||
0.230000 0x3e6b851f "w5"
|
||||
0.230000 0x3e6b851f panose 6
|
||||
0.240000 0x3e75c28f registered postscript name "STHeiti"
|
||||
0.240000 0x3fceb851eb851eb8 unregistered postscript name "STHeiti"
|
||||
0.250000 0x3e800000 "Demi Bold"
|
||||
0.250000 0x3e800000 "Demi"
|
||||
0.250000 0x3e800000 "DemiBold"
|
||||
0.250000 0x3e800000 "demi bold"
|
||||
0.250000 0x3e800000 "demi"
|
||||
0.250000 0x3e800000 "demibold"
|
||||
0.250000 0x3e800000 registered OS2 weights 6, 501 - 600
|
||||
0.250000 0x3e800000 panose 7
|
||||
0.300000 0x3e99999a registered subfamily abbr "SB"
|
||||
0.300000 0x3e99999a "Semi Bold"
|
||||
0.300000 0x3e99999a "Semi"
|
||||
0.300000 0x3e99999a "SemiBold"
|
||||
0.300000 0x3e99999a "W6"
|
||||
0.300000 0x3e99999a "semi bold"
|
||||
0.300000 0x3e99999a "semi"
|
||||
0.300000 0x3e99999a "semi"
|
||||
0.300000 0x3e99999a "semibold"
|
||||
0.300000 0x3e99999a "w6"
|
||||
0.400000 0x3ecccccd registered subfamily abbr "B"
|
||||
0.400000 0x3ecccccd "Bold"
|
||||
0.400000 0x3ecccccd "bold"
|
||||
0.400000 0x3ecccccd "bold"
|
||||
0.400000 0x3ecccccd 'head'[0x2D] & 1
|
||||
0.400000 0x3ecccccd registered OS2 weights 7, 601 - 700
|
||||
0.400000 0x3ecccccd panose 8
|
||||
0.440000 0x3ee147ae "W7"
|
||||
0.440000 0x3ee147ae "w7"
|
||||
0.500000 0x3f000000 registered subfamily abbr "EB"
|
||||
0.500000 0x3f000000 "Ext Bold"
|
||||
0.500000 0x3f000000 "Extra Bold"
|
||||
0.500000 0x3f000000 "Extra"
|
||||
0.500000 0x3f000000 "ExtraBold"
|
||||
0.500000 0x3f000000 "Ultra"
|
||||
0.500000 0x3f000000 "extra bold"
|
||||
0.500000 0x3f000000 "extra"
|
||||
0.500000 0x3f000000 "extrabold"
|
||||
0.500000 0x3f000000 registered OS2 weights 8, 701 - 800
|
||||
0.540000 0x3f0a3d71 "W8"
|
||||
0.540000 0x3f0a3d71 "w8"
|
||||
0.560000 0x3f0f5c29 registered subfamily abbr "H"
|
||||
0.560000 0x3f0f5c29 "Heavy Face"
|
||||
0.560000 0x3f0f5c29 "Heavy"
|
||||
0.560000 0x3f0f5c29 "HeavyFace"
|
||||
0.560000 0x3f0f5c29 "heavy face"
|
||||
0.560000 0x3f0f5c29 "heavy"
|
||||
0.560000 0x3f0f5c29 "heavy"
|
||||
0.560000 0x3f0f5c29 "heavyface"
|
||||
0.560000 0x3f0f5c29 panose 9
|
||||
0.620000 0x3f1eb852 "Black"
|
||||
0.620000 0x3f1eb852 "Super"
|
||||
0.620000 0x3f1eb852 "W9"
|
||||
0.620000 0x3f1eb852 "black"
|
||||
0.620000 0x3f1eb852 "black"
|
||||
0.620000 0x3f1eb852 "super"
|
||||
0.620000 0x3f1eb852 "w9"
|
||||
0.620000 0x3f1eb852 registered OS2 weights 9, 801 - 900
|
||||
0.620000 0x3f1eb852 panose 10
|
||||
0.700000 0x3f333333 registered subfamily abbr "U"
|
||||
0.700000 0x3f333333 "Ultra Bold"
|
||||
0.700000 0x3f333333 "UltraBold"
|
||||
0.700000 0x3f333333 "ultra bold"
|
||||
0.700000 0x3f333333 "ultrabold"
|
||||
0.750000 0x3f400000 "Fat"
|
||||
0.750000 0x3f400000 "Ultra Black"
|
||||
0.750000 0x3f400000 "UltraBlack"
|
||||
0.750000 0x3f400000 "fat"
|
||||
0.750000 0x3f400000 "ultra black"
|
||||
0.750000 0x3f400000 "ultrablack"
|
||||
0.750000 0x3f400000 registered OS2 weights 901 - 950
|
||||
0.800000 0x3f4ccccd "Ext Black"
|
||||
0.800000 0x3f4ccccd "ExtraBlack"
|
||||
0.800000 0x3f4ccccd "Nord"
|
||||
0.800000 0x3f4ccccd "Poster"
|
||||
0.800000 0x3f4ccccd registered subfamily abbr "UH"
|
||||
0.800000 0x3f4ccccd "extrablack"
|
||||
0.800000 0x3f4ccccd "nord"
|
||||
0.800000 0x3f4ccccd "poster"
|
||||
0.800000 0x3f4ccccd registered OS2 weights 951 - 999
|
||||
0.800000 0x3f4ccccd panose 11
|
||||
0.850000 0x3f59999a "Obese"
|
||||
0.850000 0x3f59999a "obese"
|
||||
@@ -0,0 +1,146 @@
|
||||
-0.100000
|
||||
postscript name "STXihei" (which, according to http://www.typophile.com/node/93813, means "ST Hei Light", and so we can assume it's the Light version of STHeiti, which I think is Medium though is given Regular status below because meh)
|
||||
|
||||
-0.200000
|
||||
subfamily abbreviation "EL" (???????????)
|
||||
style string contains "Semi Light"
|
||||
style string contains "SemiLight"
|
||||
|
||||
-0.230000
|
||||
style string contains "Book"
|
||||
style string contains "W1" (registered fonts only; probably a typo and -0.7 was expected instead)
|
||||
style string contains "W3"
|
||||
panose 5
|
||||
|
||||
-0.400000
|
||||
subfamily abbreviation "L"
|
||||
style string contains "Light"
|
||||
style string contains "Lite"
|
||||
ATSD style "light"
|
||||
OS2 weights 3, 201 - 300
|
||||
panose 3
|
||||
|
||||
-0.500000
|
||||
style string contains "Ext Light"
|
||||
style string contains "Extra Light"
|
||||
style string contains "ExtraLight"
|
||||
style string contains "Thin"
|
||||
style string contains "W2"
|
||||
OS2 weights 2, 101 - 200
|
||||
panose 2
|
||||
|
||||
-0.600000
|
||||
ATSD style "thin"
|
||||
|
||||
-0.700000
|
||||
style string contains "hairline"
|
||||
style string contains "w1"
|
||||
|
||||
-0.800000
|
||||
style string contains "Ext Thin"
|
||||
style string contains "Extra Thin"
|
||||
style string contains "HairLine"
|
||||
style string contains "Ultra Light"
|
||||
style string contains "Ultra Thin"
|
||||
style string contains "UltraLight"
|
||||
ATSD style "ulight"
|
||||
OS2 weights 1, 10 - 100
|
||||
|
||||
0.000000
|
||||
ostscript name ".Keyboard"
|
||||
postscript name ".LucidaGrandeUI"
|
||||
postscript name "LucidaGrande"
|
||||
subfamily abbreviation "R"
|
||||
postscript name "TimesNewRomanPSMT"
|
||||
style string contains "W4"
|
||||
ATSD style "reg"
|
||||
OS2 weights 4, 301 - 400
|
||||
default
|
||||
|
||||
0.230000
|
||||
OS2 weights 5, 401 - 500
|
||||
subfamily abbreviation "M"
|
||||
style string contains "Medium"
|
||||
style string contains "W5"
|
||||
ATSD style "med"
|
||||
panose 6
|
||||
|
||||
0.240000
|
||||
postscript name "STHeiti"
|
||||
|
||||
0.250000
|
||||
style string contains "Demi Bold"
|
||||
style string contains "Demi"
|
||||
style string contains "DemiBold"
|
||||
OS2 weights 6, 501 - 600
|
||||
panose 7
|
||||
|
||||
0.300000
|
||||
subfamily abbreviation "SB"
|
||||
style string contains "Semi Bold"
|
||||
style string contains "Semi"
|
||||
style string contains "SemiBold"
|
||||
style string contains "W6"
|
||||
ATSD style "semi"
|
||||
|
||||
0.400000
|
||||
subfamily abbreviation "B"
|
||||
style string contains "Bold"
|
||||
ATSD style "bold"
|
||||
('head' table byte 0x2D) & 1 != 0
|
||||
OS2 weights 7, 601 - 700
|
||||
panose 8
|
||||
|
||||
0.440000
|
||||
style string contains "W7"
|
||||
|
||||
0.500000
|
||||
subfamily abbreviation "EB"
|
||||
style string contains "Ext Bold"
|
||||
style string contains "Extra Bold"
|
||||
style string contains "Extra"
|
||||
style string contains "ExtraBold"
|
||||
style string contains "Ultra"
|
||||
OS2 weights 8, 701 - 800
|
||||
|
||||
0.540000
|
||||
style string contains "W8"
|
||||
|
||||
0.560000
|
||||
subfamily abbreviation "H"
|
||||
style string contains "Heavy Face"
|
||||
style string contains "Heavy"
|
||||
style string contains "HeavyFace"
|
||||
ATSD style "heavy"
|
||||
panose 9
|
||||
|
||||
0.620000
|
||||
style string contains "Black"
|
||||
style string contains "Super"
|
||||
style string contains "W9"
|
||||
ATSD style "black"
|
||||
OS2 weights 9, 801 - 900
|
||||
panose 10
|
||||
|
||||
0.700000
|
||||
subfamily abbreviation "U"
|
||||
style string contains "Ultra Bold"
|
||||
style string contains "UltraBold"
|
||||
|
||||
0.750000
|
||||
style string contains "Fat"
|
||||
style string contains "Ultra Black"
|
||||
style string contains "UltraBlack"
|
||||
OS2 weights 901 - 950
|
||||
|
||||
0.800000
|
||||
style string contains "Ext Black"
|
||||
style string contains "ExtraBlack"
|
||||
style string contains "Nord"
|
||||
style string contains "Poster"
|
||||
subfamily abbreviation "UH"
|
||||
OS2 weights 951 - 999
|
||||
panose 11
|
||||
|
||||
0.850000
|
||||
style string contains "Obese"
|
||||
@@ -0,0 +1,149 @@
|
||||
-0.100000 0xbdcccccd "STXihei"
|
||||
-0.100000 0xbfb999999999999a "STXihei"
|
||||
-0.200000 0xbe4ccccd "EL"
|
||||
-0.200000 0xbe4ccccd "Semi Light"
|
||||
-0.200000 0xbe4ccccd "SemiLight"
|
||||
-0.200000 0xbe4ccccd "semi light"
|
||||
-0.200000 0xbe4ccccd "semilight"
|
||||
-0.230000 0xbe6b851f "Book"
|
||||
-0.230000 0xbe6b851f "W1"
|
||||
-0.230000 0xbe6b851f "W3"
|
||||
-0.230000 0xbe6b851f "book"
|
||||
-0.230000 0xbe6b851f "w3"
|
||||
-0.230000 0xbe6b851f panose 5
|
||||
-0.400000 0xbecccccd "L"
|
||||
-0.400000 0xbecccccd "Light"
|
||||
-0.400000 0xbecccccd "Lite"
|
||||
-0.400000 0xbecccccd "light"
|
||||
-0.400000 0xbecccccd "light"
|
||||
-0.400000 0xbecccccd "lite"
|
||||
-0.400000 0xbecccccd 3, 201 - 300
|
||||
-0.400000 0xbecccccd panose 3
|
||||
-0.500000 0xbf000000 "Ext Light"
|
||||
-0.500000 0xbf000000 "Extra Light"
|
||||
-0.500000 0xbf000000 "ExtraLight"
|
||||
-0.500000 0xbf000000 "Thin"
|
||||
-0.500000 0xbf000000 "W2"
|
||||
-0.500000 0xbf000000 "extra light"
|
||||
-0.500000 0xbf000000 "extralight"
|
||||
-0.500000 0xbf000000 "thin"
|
||||
-0.500000 0xbf000000 "w2"
|
||||
-0.500000 0xbf000000 2, 101 - 200
|
||||
-0.500000 0xbf000000 panose 2
|
||||
-0.600000 0xbf19999a "thin"
|
||||
-0.700000 0xbf333333 "hairline"
|
||||
-0.700000 0xbf333333 "w1"
|
||||
-0.800000 0xbf4ccccd "Ext Thin"
|
||||
-0.800000 0xbf4ccccd "Extra Thin"
|
||||
-0.800000 0xbf4ccccd "HairLine"
|
||||
-0.800000 0xbf4ccccd "Ultra Light"
|
||||
-0.800000 0xbf4ccccd "Ultra Thin"
|
||||
-0.800000 0xbf4ccccd "UltraLight"
|
||||
-0.800000 0xbf4ccccd "ulight"
|
||||
-0.800000 0xbf4ccccd "ultra light"
|
||||
-0.800000 0xbf4ccccd "ultralight"
|
||||
-0.800000 0xbf4ccccd 1, 10 - 100
|
||||
0.000000 0x0 ".Keyboard"
|
||||
0.000000 0x0 ".LucidaGrandeUI"
|
||||
0.000000 0x0 ".LucidaGrandeUI"
|
||||
0.000000 0x0 "LucidaGrande"
|
||||
0.000000 0x0 "LucidaGrande"
|
||||
0.000000 0x0 "R"
|
||||
0.000000 0x0 "TimesNewRomanPSMT"
|
||||
0.000000 0x0 "TimesNewRomanPSMT"
|
||||
0.000000 0x0 "W4"
|
||||
0.000000 0x0 "reg"
|
||||
0.000000 0x0 "w4"
|
||||
0.000000 0x0 4, 301 - 400
|
||||
0.000000 0x0 default
|
||||
0.230000 0x3e6b851f 5, 401 - 500
|
||||
0.230000 0x3e6b851f "M"
|
||||
0.230000 0x3e6b851f "Medium"
|
||||
0.230000 0x3e6b851f "W5"
|
||||
0.230000 0x3e6b851f "med"
|
||||
0.230000 0x3e6b851f "medium"
|
||||
0.230000 0x3e6b851f "w5"
|
||||
0.230000 0x3e6b851f panose 6
|
||||
0.240000 0x3e75c28f "STHeiti"
|
||||
0.240000 0x3fceb851eb851eb8 "STHeiti"
|
||||
0.250000 0x3e800000 "Demi Bold"
|
||||
0.250000 0x3e800000 "Demi"
|
||||
0.250000 0x3e800000 "DemiBold"
|
||||
0.250000 0x3e800000 "demi bold"
|
||||
0.250000 0x3e800000 "demi"
|
||||
0.250000 0x3e800000 "demibold"
|
||||
0.250000 0x3e800000 6, 501 - 600
|
||||
0.250000 0x3e800000 panose 7
|
||||
0.300000 0x3e99999a "SB"
|
||||
0.300000 0x3e99999a "Semi Bold"
|
||||
0.300000 0x3e99999a "Semi"
|
||||
0.300000 0x3e99999a "SemiBold"
|
||||
0.300000 0x3e99999a "W6"
|
||||
0.300000 0x3e99999a "semi bold"
|
||||
0.300000 0x3e99999a "semi"
|
||||
0.300000 0x3e99999a "semi"
|
||||
0.300000 0x3e99999a "semibold"
|
||||
0.300000 0x3e99999a "w6"
|
||||
0.400000 0x3ecccccd "B"
|
||||
0.400000 0x3ecccccd "Bold"
|
||||
0.400000 0x3ecccccd "bold"
|
||||
0.400000 0x3ecccccd "bold"
|
||||
0.400000 0x3ecccccd 'head'[0x2D] & 1
|
||||
0.400000 0x3ecccccd 7, 601 - 700
|
||||
0.400000 0x3ecccccd panose 8
|
||||
0.440000 0x3ee147ae "W7"
|
||||
0.440000 0x3ee147ae "w7"
|
||||
0.500000 0x3f000000 "EB"
|
||||
0.500000 0x3f000000 "Ext Bold"
|
||||
0.500000 0x3f000000 "Extra Bold"
|
||||
0.500000 0x3f000000 "Extra"
|
||||
0.500000 0x3f000000 "ExtraBold"
|
||||
0.500000 0x3f000000 "Ultra"
|
||||
0.500000 0x3f000000 "extra bold"
|
||||
0.500000 0x3f000000 "extra"
|
||||
0.500000 0x3f000000 "extrabold"
|
||||
0.500000 0x3f000000 8, 701 - 800
|
||||
0.540000 0x3f0a3d71 "W8"
|
||||
0.540000 0x3f0a3d71 "w8"
|
||||
0.560000 0x3f0f5c29 "H"
|
||||
0.560000 0x3f0f5c29 "Heavy Face"
|
||||
0.560000 0x3f0f5c29 "Heavy"
|
||||
0.560000 0x3f0f5c29 "HeavyFace"
|
||||
0.560000 0x3f0f5c29 "heavy face"
|
||||
0.560000 0x3f0f5c29 "heavy"
|
||||
0.560000 0x3f0f5c29 "heavy"
|
||||
0.560000 0x3f0f5c29 "heavyface"
|
||||
0.560000 0x3f0f5c29 panose 9
|
||||
0.620000 0x3f1eb852 "Black"
|
||||
0.620000 0x3f1eb852 "Super"
|
||||
0.620000 0x3f1eb852 "W9"
|
||||
0.620000 0x3f1eb852 "black"
|
||||
0.620000 0x3f1eb852 "black"
|
||||
0.620000 0x3f1eb852 "super"
|
||||
0.620000 0x3f1eb852 "w9"
|
||||
0.620000 0x3f1eb852 9, 801 - 900
|
||||
0.620000 0x3f1eb852 panose 10
|
||||
0.700000 0x3f333333 "U"
|
||||
0.700000 0x3f333333 "Ultra Bold"
|
||||
0.700000 0x3f333333 "UltraBold"
|
||||
0.700000 0x3f333333 "ultra bold"
|
||||
0.700000 0x3f333333 "ultrabold"
|
||||
0.750000 0x3f400000 "Fat"
|
||||
0.750000 0x3f400000 "Ultra Black"
|
||||
0.750000 0x3f400000 "UltraBlack"
|
||||
0.750000 0x3f400000 "fat"
|
||||
0.750000 0x3f400000 "ultra black"
|
||||
0.750000 0x3f400000 "ultrablack"
|
||||
0.750000 0x3f400000 901 - 950
|
||||
0.800000 0x3f4ccccd "Ext Black"
|
||||
0.800000 0x3f4ccccd "ExtraBlack"
|
||||
0.800000 0x3f4ccccd "Nord"
|
||||
0.800000 0x3f4ccccd "Poster"
|
||||
0.800000 0x3f4ccccd "UH"
|
||||
0.800000 0x3f4ccccd "extrablack"
|
||||
0.800000 0x3f4ccccd "nord"
|
||||
0.800000 0x3f4ccccd "poster"
|
||||
0.800000 0x3f4ccccd 951 - 999
|
||||
0.800000 0x3f4ccccd panose 11
|
||||
0.850000 0x3f59999a "Obese"
|
||||
0.850000 0x3f59999a "obese"
|
||||
@@ -0,0 +1,149 @@
|
||||
0.000000 0x0 "reg"
|
||||
0.300000 0x3e99999a "semi"
|
||||
0.400000 0x3ecccccd "bold"
|
||||
-0.400000 0xbecccccd "light"
|
||||
0.230000 0x3e6b851f "med"
|
||||
0.560000 0x3f0f5c29 "heavy"
|
||||
0.620000 0x3f1eb852 "black"
|
||||
-0.600000 0xbf19999a "thin"
|
||||
-0.800000 0xbf4ccccd "ulight"
|
||||
0.000000 0x0 "LucidaGrande"
|
||||
0.000000 0x0 ".LucidaGrandeUI"
|
||||
0.000000 0x0 ".Keyboard"
|
||||
0.240000 0x3e75c28f "STHeiti"
|
||||
-0.100000 0xbdcccccd "STXihei"
|
||||
0.000000 0x0 "TimesNewRomanPSMT"
|
||||
-0.800000 0xbf4ccccd "Ultra Light"
|
||||
0.750000 0x3f400000 "Ultra Black"
|
||||
-0.500000 0xbf000000 "Extra Light"
|
||||
0.750000 0x3f400000 "UltraBlack"
|
||||
0.800000 0x3f4ccccd "ExtraBlack"
|
||||
-0.800000 0xbf4ccccd "UltraLight"
|
||||
-0.500000 0xbf000000 "ExtraLight"
|
||||
-0.800000 0xbf4ccccd "Ultra Thin"
|
||||
-0.800000 0xbf4ccccd "Extra Thin"
|
||||
0.560000 0x3f0f5c29 "Heavy Face"
|
||||
-0.200000 0xbe4ccccd "Semi Light"
|
||||
0.500000 0x3f000000 "Extra Bold"
|
||||
0.700000 0x3f333333 "Ultra Bold"
|
||||
0.560000 0x3f0f5c29 "HeavyFace"
|
||||
0.500000 0x3f000000 "ExtraBold"
|
||||
0.700000 0x3f333333 "UltraBold"
|
||||
0.800000 0x3f4ccccd "Ext Black"
|
||||
-0.200000 0xbe4ccccd "SemiLight"
|
||||
0.250000 0x3e800000 "Demi Bold"
|
||||
0.300000 0x3e99999a "Semi Bold"
|
||||
-0.500000 0xbf000000 "Ext Light"
|
||||
0.500000 0x3f000000 "Ext Bold"
|
||||
0.250000 0x3e800000 "DemiBold"
|
||||
0.300000 0x3e99999a "SemiBold"
|
||||
-0.800000 0xbf4ccccd "HairLine"
|
||||
-0.800000 0xbf4ccccd "Ext Thin"
|
||||
0.230000 0x3e6b851f "Medium"
|
||||
0.800000 0x3f4ccccd "Poster"
|
||||
-0.400000 0xbecccccd "Light"
|
||||
0.500000 0x3f000000 "Ultra"
|
||||
0.560000 0x3f0f5c29 "Heavy"
|
||||
0.500000 0x3f000000 "Extra"
|
||||
0.620000 0x3f1eb852 "Black"
|
||||
0.620000 0x3f1eb852 "Super"
|
||||
0.850000 0x3f59999a "Obese"
|
||||
-0.400000 0xbecccccd "Lite"
|
||||
-0.230000 0xbe6b851f "Book"
|
||||
0.250000 0x3e800000 "Demi"
|
||||
0.300000 0x3e99999a "Semi"
|
||||
-0.500000 0xbf000000 "Thin"
|
||||
0.400000 0x3ecccccd "Bold"
|
||||
0.800000 0x3f4ccccd "Nord"
|
||||
0.750000 0x3f400000 "Fat"
|
||||
-0.230000 0xbe6b851f "W1"
|
||||
-0.500000 0xbf000000 "W2"
|
||||
-0.230000 0xbe6b851f "W3"
|
||||
0.000000 0x0 "W4"
|
||||
0.230000 0x3e6b851f "W5"
|
||||
0.300000 0x3e99999a "W6"
|
||||
0.440000 0x3ee147ae "W7"
|
||||
0.540000 0x3f0a3d71 "W8"
|
||||
0.620000 0x3f1eb852 "W9"
|
||||
-0.800000 0xbf4ccccd 1, 10 - 100
|
||||
-0.500000 0xbf000000 2, 101 - 200
|
||||
-0.400000 0xbecccccd 3, 201 - 300
|
||||
0.000000 0x0 4, 301 - 400
|
||||
0.230000 0x3e6b851f 5, 401 - 500
|
||||
0.250000 0x3e800000 6, 501 - 600
|
||||
0.400000 0x3ecccccd 7, 601 - 700
|
||||
0.500000 0x3f000000 8, 701 - 800
|
||||
0.620000 0x3f1eb852 9, 801 - 900
|
||||
0.750000 0x3f400000 901 - 950
|
||||
0.800000 0x3f4ccccd 951 - 999
|
||||
-0.500000 0xbf000000 panose 2
|
||||
-0.400000 0xbecccccd panose 3
|
||||
-0.230000 0xbe6b851f panose 5
|
||||
0.230000 0x3e6b851f panose 6
|
||||
0.250000 0x3e800000 panose 7
|
||||
0.400000 0x3ecccccd panose 8
|
||||
0.560000 0x3f0f5c29 panose 9
|
||||
0.620000 0x3f1eb852 panose 10
|
||||
0.800000 0x3f4ccccd panose 11
|
||||
0.400000 0x3ecccccd 'head'[0x2D] & 1
|
||||
-0.200000 0xbe4ccccd "EL"
|
||||
0.500000 0x3f000000 "EB"
|
||||
0.300000 0x3e99999a "SB"
|
||||
0.800000 0x3f4ccccd "UH"
|
||||
0.700000 0x3f333333 "U"
|
||||
-0.400000 0xbecccccd "L"
|
||||
0.560000 0x3f0f5c29 "H"
|
||||
0.400000 0x3ecccccd "B"
|
||||
0.230000 0x3e6b851f "M"
|
||||
0.000000 0x0 "R"
|
||||
0.000000 0x0 default
|
||||
0.000000 0x0 "LucidaGrande"
|
||||
0.000000 0x0 ".LucidaGrandeUI"
|
||||
0.240000 0x3fceb851eb851eb8 "STHeiti"
|
||||
-0.100000 0xbfb999999999999a "STXihei"
|
||||
0.000000 0x0 "TimesNewRomanPSMT"
|
||||
-0.800000 0xbf4ccccd "ultra light"
|
||||
0.750000 0x3f400000 "ultra black"
|
||||
-0.500000 0xbf000000 "extra light"
|
||||
-0.800000 0xbf4ccccd "ultralight"
|
||||
0.750000 0x3f400000 "ultrablack"
|
||||
0.800000 0x3f4ccccd "extrablack"
|
||||
-0.500000 0xbf000000 "extralight"
|
||||
0.560000 0x3f0f5c29 "heavy face"
|
||||
-0.200000 0xbe4ccccd "semi light"
|
||||
0.500000 0x3f000000 "extra bold"
|
||||
0.700000 0x3f333333 "ultra bold"
|
||||
0.560000 0x3f0f5c29 "heavyface"
|
||||
0.500000 0x3f000000 "extrabold"
|
||||
0.700000 0x3f333333 "ultrabold"
|
||||
-0.200000 0xbe4ccccd "semilight"
|
||||
0.250000 0x3e800000 "demi bold"
|
||||
0.300000 0x3e99999a "semi bold"
|
||||
0.250000 0x3e800000 "demibold"
|
||||
0.300000 0x3e99999a "semibold"
|
||||
-0.700000 0xbf333333 "hairline"
|
||||
0.230000 0x3e6b851f "medium"
|
||||
0.800000 0x3f4ccccd "poster"
|
||||
-0.400000 0xbecccccd "light"
|
||||
0.560000 0x3f0f5c29 "heavy"
|
||||
0.500000 0x3f000000 "extra"
|
||||
0.620000 0x3f1eb852 "black"
|
||||
0.620000 0x3f1eb852 "super"
|
||||
0.850000 0x3f59999a "obese"
|
||||
-0.400000 0xbecccccd "lite"
|
||||
-0.230000 0xbe6b851f "book"
|
||||
0.250000 0x3e800000 "demi"
|
||||
0.300000 0x3e99999a "semi"
|
||||
-0.500000 0xbf000000 "thin"
|
||||
0.400000 0x3ecccccd "bold"
|
||||
0.800000 0x3f4ccccd "nord"
|
||||
0.750000 0x3f400000 "fat"
|
||||
-0.700000 0xbf333333 "w1"
|
||||
-0.500000 0xbf000000 "w2"
|
||||
-0.230000 0xbe6b851f "w3"
|
||||
0.000000 0x0 "w4"
|
||||
0.230000 0x3e6b851f "w5"
|
||||
0.300000 0x3e99999a "w6"
|
||||
0.440000 0x3ee147ae "w7"
|
||||
0.540000 0x3f0a3d71 "w8"
|
||||
0.620000 0x3f1eb852 "w9"
|
||||
@@ -0,0 +1,247 @@
|
||||
registered font, preexisting metadata weight
|
||||
"reg": float32as(0.000000, 0x0)
|
||||
"semi": float32as(0.300000, 0x3e99999a)
|
||||
"bold": float32as(0.400000, 0x3ecccccd)
|
||||
"light": float32as(-0.400000, 0xbecccccd)
|
||||
"med": float32as(0.230000, 0x3e6b851f)
|
||||
"heavy": float32as(0.560000, 0x3f0f5c29)
|
||||
"black": float32as(0.620000, 0x3f1eb852)
|
||||
"thin": float32as(-0.600000, 0xbf19999a)
|
||||
"ulight": float32as(-0.800000, 0xbf4ccccd)
|
||||
|
||||
registered font, postscript name (probably only for TrueType and OpenType) special cases, overrides the above
|
||||
"LucidaGrande": float32as(0.000000, 0x0)
|
||||
".LucidaGrandeUI": float32as(0.000000, 0x0)
|
||||
".Keyboard": float32as(0.000000, 0x0)
|
||||
"STHeiti": float32as(0.240000, 0x3e75c28f)
|
||||
"STXihei": float32as(-0.100000, 0xbdcccccd)
|
||||
"TimesNewRomanPSMT": float32as(0.000000, 0x0)
|
||||
|
||||
registered font, style glossary strings, tried in this order (possibly TrueType and OpenType only): preferred subfamily, subfamily, full name, preferred family, family; case-insensitive search, reverse search, "nonliteral" (kCFCompareNonliteral)
|
||||
"Ultra Light": float32as(-0.800000, 0xbf4ccccd)
|
||||
"Ultra Black": float32as(0.750000, 0x3f400000)
|
||||
"Extra Light": float32as(-0.500000, 0xbf000000)
|
||||
"UltraBlack": float32as(0.750000, 0x3f400000)
|
||||
"ExtraBlack": float32as(0.800000, 0x3f4ccccd)
|
||||
"UltraLight": float32as(-0.800000, 0xbf4ccccd)
|
||||
"ExtraLight": float32as(-0.500000, 0xbf000000)
|
||||
"Ultra Thin": float32as(-0.800000, 0xbf4ccccd)
|
||||
"Extra Thin": float32as(-0.800000, 0xbf4ccccd)
|
||||
"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)
|
||||
"Ext Black": float32as(0.800000, 0x3f4ccccd)
|
||||
"SemiLight": float32as(-0.200000, 0xbe4ccccd)
|
||||
"Demi Bold": float32as(0.250000, 0x3e800000)
|
||||
"Semi Bold": float32as(0.300000, 0x3e99999a)
|
||||
"Ext Light": float32as(-0.500000, 0xbf000000)
|
||||
"Ext Bold": float32as(0.500000, 0x3f000000)
|
||||
"DemiBold": float32as(0.250000, 0x3e800000)
|
||||
"SemiBold": float32as(0.300000, 0x3e99999a)
|
||||
"HairLine": float32as(-0.800000, 0xbf4ccccd)
|
||||
"Ext Thin": float32as(-0.800000, 0xbf4ccccd)
|
||||
"Medium": float32as(0.230000, 0x3e6b851f)
|
||||
"Poster": float32as(0.800000, 0x3f4ccccd)
|
||||
"Light": float32as(-0.400000, 0xbecccccd)
|
||||
"Ultra": float32as(0.500000, 0x3f000000)
|
||||
"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.230000, 0xbe6b851f)
|
||||
"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)
|
||||
|
||||
registered font, OS2 weights; table length >= 78
|
||||
1, 10 - 100: float32as(-0.800000, 0xbf4ccccd)
|
||||
2, 101 - 200: float32as(-0.500000, 0xbf000000)
|
||||
3, 201 - 300: float32as(-0.400000, 0xbecccccd)
|
||||
4, 301 - 400: float32as(0.000000, 0x0)
|
||||
5, 401 - 500: float32as(0.230000, 0x3e6b851f)
|
||||
6, 501 - 600: float32as(0.250000, 0x3e800000)
|
||||
7, 601 - 700: float32as(0.400000, 0x3ecccccd)
|
||||
8, 701 - 800: float32as(0.500000, 0x3f000000)
|
||||
9, 801 - 900: float32as(0.620000, 0x3f1eb852)
|
||||
901 - 950: float32as(0.750000, 0x3f400000)
|
||||
951 - 999: float32as(0.800000, 0x3f4ccccd)
|
||||
0, 1000: panose
|
||||
panose 2: float32as(-0.500000, 0xbf000000)
|
||||
panose 3: float32as(-0.400000, 0xbecccccd)
|
||||
panose 4: !!!! see note should be float32as(-0.300000, 0xbe99999a) but is treated as invalid instead due to returning false instead of true
|
||||
panose 5: float32as(-0.230000, 0xbe6b851f)
|
||||
panose 6: float32as(0.230000, 0x3e6b851f)
|
||||
panose 7: float32as(0.250000, 0x3e800000)
|
||||
panose 8: float32as(0.400000, 0x3ecccccd)
|
||||
panose 9: float32as(0.560000, 0x3f0f5c29)
|
||||
panose 10: float32as(0.620000, 0x3f1eb852)
|
||||
panose 11: float32as(0.800000, 0x3f4ccccd)
|
||||
|
||||
registered font, head table, low bit of byte 0x2D
|
||||
'head'[0x2D] & 1: float32as(0.400000, 0x3ecccccd)
|
||||
|
||||
registered font, abbreviated weight glossary, checks for (possibly in TrueType and OpenType only) in order: preferred subfamily, family; case-insensitive strict comparison
|
||||
"EL": float32as(-0.200000, 0xbe4ccccd)
|
||||
"EB": float32as(0.500000, 0x3f000000)
|
||||
"SB": float32as(0.300000, 0x3e99999a)
|
||||
"UH": float32as(0.800000, 0x3f4ccccd)
|
||||
"U": float32as(0.700000, 0x3f333333)
|
||||
"L": float32as(-0.400000, 0xbecccccd)
|
||||
"H": float32as(0.560000, 0x3f0f5c29)
|
||||
"B": float32as(0.400000, 0x3ecccccd)
|
||||
"M": float32as(0.230000, 0x3e6b851f)
|
||||
"R": float32as(0.000000, 0x0)
|
||||
|
||||
registered font
|
||||
default: float32as(0.000000, 0x0)
|
||||
|
||||
// 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
|
||||
// and yes, this one is 11, but the one above is 10
|
||||
} 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)
|
||||
}
|
||||
|
||||
unregistered font: kCTFontPostScriptNameKey defaults
|
||||
"LucidaGrande": float64as(0.000000, 0x0)
|
||||
".LucidaGrandeUI": float64as(0.000000, 0x0)
|
||||
"STHeiti": float64as(0.240000, 0x3fceb851eb851eb8)
|
||||
"STXihei": float64as(-0.100000, 0xbfb999999999999a)
|
||||
"TimesNewRomanPSMT": float64as(0.000000, 0x0)
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unregistered font, style glossary, checks against kCTFontSubFamilyNameKey, kCTFontFullNameKey, kCTFontFamilyNameKey; case-insensitive (folded by Unicode rules) strstr()
|
||||
"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)
|
||||
|
||||
func (f *Font) ShouldEnableBoldSymbolicTrait() bool {
|
||||
if f.IsRegistered() {
|
||||
return f.ShouldEnableBoldSymbolicTraitFromRegistry()
|
||||
}
|
||||
no := f.Weight() <= float64as(0.239000, 0x3fce978d4fdf3b64)
|
||||
return !no
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
xx pseudo-go
|
||||
|
||||
func (f *CTFont) RegistryWidth32() float32 {
|
||||
metadata visual descriptors
|
||||
{ "med", float32as(0.000000, 0x0) },
|
||||
{ "cond", float32as(-0.200000, 0xbe4ccccd) },
|
||||
{ "ext", float32as(0.200000, 0x3e4ccccd) },
|
||||
|
||||
style dictionary
|
||||
{ "Extra Compressed", float32as(-0.700000, 0xbf333333) },
|
||||
{ "Ultra Compressed", float32as(-0.700000, 0xbf333333) },
|
||||
{ "Ultra Condensed", float32as(-0.700000, 0xbf333333) },
|
||||
{ "Extra Condensed", float32as(-0.500000, 0xbf000000) },
|
||||
{ "Extra Extended", float32as(0.400000, 0x3ecccccd) },
|
||||
{ "Ext Compressed", float32as(-0.700000, 0xbf333333) },
|
||||
{ "Ultra Expanded", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "Ultra Extended", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "Extra Expanded", float32as(0.400000, 0x3ecccccd) },
|
||||
xx TODO this is weird, but correct...
|
||||
{ "Semi Condensed", float32as(-0.700000, 0xbf333333) },
|
||||
{ "Semi Condensed", float32as(-0.100000, 0xbdcccccd) },
|
||||
xx end TODO
|
||||
{ "Ext Condensed", float32as(-0.500000, 0xbf000000) },
|
||||
{ "SemiCondensed", float32as(-0.100000, 0xbdcccccd) },
|
||||
{ "ExtraExpanded", float32as(0.400000, 0x3ecccccd) },
|
||||
{ "Semi Expanded", float32as(0.100000, 0x3dcccccd) },
|
||||
{ "Semi Extended", float32as(0.100000, 0x3dcccccd) },
|
||||
{ "Ext Expanded", float32as(0.400000, 0x3ecccccd) },
|
||||
{ "Ext Extended", float32as(0.400000, 0x3ecccccd) },
|
||||
{ "SemiExpanded", float32as(0.100000, 0x3dcccccd) },
|
||||
{ "Extra Narrow", float32as(-0.500000, 0xbf000000) },
|
||||
{ "ExtraNarrow", float32as(-0.500000, 0xbf000000) },
|
||||
{ "Extra Wide", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "Ultra Cond", float32as(-0.700000, 0xbf333333) },
|
||||
{ "Compressed", float32as(-0.500000, 0xbf000000) },
|
||||
{ "Extra Cond", float32as(-0.500000, 0xbf000000) },
|
||||
{ "Semi Cond", float32as(-0.100000, 0xbdcccccd) },
|
||||
{ "Condensed", float32as(-0.200000, 0xbe4ccccd) },
|
||||
{ "ExtraWide", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "Extended", float32as(0.200000, 0x3e4ccccd) },
|
||||
{ "Expanded", float32as(0.200000, 0x3e4ccccd) },
|
||||
{ "Ext Cond", float32as(-0.500000, 0xbf000000) },
|
||||
{ "Narrow", float32as(-0.400000 , 0xbecccccd) },
|
||||
{ "Compact", float32as(-0.400000, 0xbecccccd) },
|
||||
{ "Cond", float32as(-0.200000, 0xbe4ccccd) },
|
||||
{ "Wide", float32as(0.600000, 0x3f19999a) },
|
||||
{ "Thin", float32as(-0.700000, 0xbf333333) },
|
||||
|
||||
get os2 table
|
||||
if os2table.Len() >= 78 {
|
||||
usWidthClass := uint16be(b[6:8]) - 1
|
||||
xx this handles the case where the original usWidthClass == 0
|
||||
if usWidthClass > 8 {
|
||||
panose := b[0x23] - 2
|
||||
if panose > 6 {
|
||||
xx TODO
|
||||
} else {
|
||||
switch panose {
|
||||
case 0, 1, 2:
|
||||
width = float32as(0.000000, 0x0)
|
||||
case 3:
|
||||
width = float32as(0.200000, 0x3e4ccccd)
|
||||
case 4:
|
||||
width = float32as(-0.200000, 0xbe4ccccd)
|
||||
case 5:
|
||||
width = float32as(0.400000, 0x3ecccccd)
|
||||
case 6:
|
||||
width = float32as(-0.400000, 0xbecccccd)
|
||||
}
|
||||
}
|
||||
}
|
||||
switch usWidthClass {
|
||||
case 0:
|
||||
width = float32as(-0.700000, 0xbf333333)
|
||||
case 1:
|
||||
width = float32as(-0.500000, 0xbf000000)
|
||||
case 2:
|
||||
width = float32as(-0.200000, 0xbe4ccccd)
|
||||
case 3:
|
||||
width = float32as(-0.100000, 0xbdcccccd)
|
||||
case 4:
|
||||
width = float32as(0.000000, 0x0)
|
||||
case 5:
|
||||
width = float32as(0.100000, 0x3dcccccd)
|
||||
case 6:
|
||||
width = float32as(0.400000, 0x3ecccccd)
|
||||
case 7:
|
||||
width = float32as(0.600000, 0x3f19999a)
|
||||
case 8:
|
||||
width = float32as(0.800000, 0x3f4ccccd)
|
||||
}
|
||||
}
|
||||
|
||||
headtable := f.CopyTable('head')
|
||||
if headtable != nil {
|
||||
if headtable.Len() >= 54 {
|
||||
x := b[0x2d]
|
||||
if (x & 0x20) != 0 {
|
||||
width = float32as(-0.200000, 0xbe4ccccd)
|
||||
} else if (x & 0x40) != 0 {
|
||||
width = float32as(0.200000, 0x3e4ccccd)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
xx and if all else fails
|
||||
return float32as(0.000000, 0x0)
|
||||
}
|
||||
|
||||
func (f *CTFont) Width() float64 {
|
||||
if f.IsRegistered() {
|
||||
return f.RegistryWidth()
|
||||
}
|
||||
|
||||
width := 0.0
|
||||
hasWidth := false
|
||||
|
||||
if there is an OS2 table {
|
||||
var usWidthClass uint16
|
||||
|
||||
valid := false
|
||||
if it's 78 bytes or more {
|
||||
usWidthClass = uint16be(table[6:8])
|
||||
if usWeightClass <= 10 {
|
||||
valid = true
|
||||
} else {
|
||||
valid = false
|
||||
}
|
||||
} else {
|
||||
usWidthClass = 0
|
||||
valid = true
|
||||
}
|
||||
if valid {
|
||||
ten := float64as(10.000000, 0x4024000000000000)
|
||||
negPointFive := float64as(-0.500000, 0xbfe0000000000000)
|
||||
width = (float64(usWidthClass) div ten) + negPointFive
|
||||
hasWidth = true
|
||||
}
|
||||
}
|
||||
|
||||
then there's the style glossary strings comparison:
|
||||
{ "semi condensed", float32as(-0.100000, 0xbdcccccd) },
|
||||
{ "extra expanded", float32as(0.400000, 0x3ecccccd) },
|
||||
{ "semicondensed", float32as(-0.100000, 0xbdcccccd) },
|
||||
{ "extraexpanded", float32as(0.400000, 0x3ecccccd) },
|
||||
{ "semi expanded", float32as(0.100000, 0x3dcccccd) },
|
||||
{ "semiexpanded", float32as(0.100000, 0x3dcccccd) },
|
||||
{ "extra narrow", float32as(-0.500000, 0xbf000000) },
|
||||
{ "extranarrow", float32as(-0.500000, 0xbf000000) },
|
||||
{ "extra wide", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "condensed", float32as(-0.200000, 0xbe4ccccd) },
|
||||
{ "extrawide", float32as(0.800000, 0x3f4ccccd) },
|
||||
{ "extended", float32as(0.200000, 0x3e4ccccd) },
|
||||
{ "expanded", float32as(0.200000, 0x3e4ccccd) },
|
||||
{ "narrow", float32as(-0.400000, 0xbecccccd) },
|
||||
{ "wide", float32as(0.600000, 0x3f19999a) },
|
||||
{ "thin", float32as(-0.700000, 0xbf333333) },
|
||||
|
||||
otherwise just return float64as(0.000000, 0x0)
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
-0.100000
|
||||
style string contains "Semi Cond"
|
||||
style string contains "Semi Condensed"; unregistered fonts only (see below)
|
||||
style string contains "SemiCondensed"
|
||||
OS2 width 4
|
||||
|
||||
-0.200000
|
||||
('head' table byte 0x2d) & 0x20 != 0
|
||||
ATSD style "cond"
|
||||
panose 6
|
||||
style string contains "Cond"
|
||||
style string contains "Condensed"
|
||||
OS2 width 3
|
||||
|
||||
-0.400000
|
||||
panose 8
|
||||
style string contains "Compact"
|
||||
style string contains "Narrow"
|
||||
|
||||
-0.500000
|
||||
style string contains "Compressed"
|
||||
style string contains "Ext Cond"
|
||||
style string contains "Ext Condensed"
|
||||
style string contains "Extra Cond"
|
||||
style string contains "Extra Condensed"
|
||||
style string contains "Extra Narrow"
|
||||
style string contains "ExtraNarrow"
|
||||
OS2 width 2
|
||||
|
||||
-0.700000
|
||||
style string contains "Ext Compressed"
|
||||
style string contains "Extra Compressed"
|
||||
style string contains "Semi Condensed" (this is probably a typo, since another "Semi Condensed" with a value of -0.1 follows this in the table it comes from); registered fonts only
|
||||
style string contains "Thin"
|
||||
style string contains "Ultra Compressed"
|
||||
style string contains "Ultra Cond"
|
||||
style string contains "Ultra Condensed"
|
||||
OS2 width 1
|
||||
|
||||
0.000000
|
||||
default
|
||||
ATSD style "med"
|
||||
panose 2, 3, 4
|
||||
OS2 width 5
|
||||
|
||||
0.100000
|
||||
style string contains "Semi Expanded"
|
||||
style string contains "Semi Extended"
|
||||
style string contains "SemiExpanded"
|
||||
OS2 width 6
|
||||
|
||||
0.200000
|
||||
('head' table byte 0x2d) & 0x40 != 0
|
||||
ATSD style "ext"
|
||||
panose 5
|
||||
style string contains "Expanded"
|
||||
style string contains "Extended"
|
||||
|
||||
0.400000
|
||||
panose 7
|
||||
style string contains "Ext Expanded"
|
||||
style string contains "Ext Extended"
|
||||
style string contains "Extra Expanded"
|
||||
style string contains "Extra Extended"
|
||||
style string contains "ExtraExpanded"
|
||||
OS2 width 7
|
||||
|
||||
0.600000
|
||||
style string contains "Wide"
|
||||
OS2 width 8
|
||||
|
||||
0.800000
|
||||
style string contains "Extra Wide"
|
||||
style string contains "ExtraWide"
|
||||
style string contains "Ultra Expanded"
|
||||
style string contains "Ultra Extended"
|
||||
OS2 width 9
|
||||
@@ -0,0 +1,73 @@
|
||||
-0.100000 0xbdcccccd registered "Semi Cond"
|
||||
-0.100000 0xbdcccccd registered "Semi Condensed"
|
||||
-0.100000 0xbdcccccd registered "SemiCondensed"
|
||||
-0.100000 0xbdcccccd registered OS2 4
|
||||
-0.100000 0xbdcccccd unregistered "semi condensed"
|
||||
-0.100000 0xbdcccccd unregistered "semicondensed"
|
||||
-0.200000 0xbe4ccccd head[0x2d] & 0x20
|
||||
-0.200000 0xbe4ccccd metadata "cond"
|
||||
-0.200000 0xbe4ccccd panose 6
|
||||
-0.200000 0xbe4ccccd registered "Cond"
|
||||
-0.200000 0xbe4ccccd registered "Condensed"
|
||||
-0.200000 0xbe4ccccd registered OS2 3
|
||||
-0.200000 0xbe4ccccd unregistered "condensed"
|
||||
-0.400000 0xbecccccd panose 8
|
||||
-0.400000 0xbecccccd registered "Compact"
|
||||
-0.400000 0xbecccccd registered "Narrow"
|
||||
-0.400000 0xbecccccd unregistered "narrow"
|
||||
-0.500000 0xbf000000 registered "Compressed"
|
||||
-0.500000 0xbf000000 registered "Ext Cond"
|
||||
-0.500000 0xbf000000 registered "Ext Condensed"
|
||||
-0.500000 0xbf000000 registered "Extra Cond"
|
||||
-0.500000 0xbf000000 registered "Extra Condensed"
|
||||
-0.500000 0xbf000000 registered "Extra Narrow"
|
||||
-0.500000 0xbf000000 registered "ExtraNarrow"
|
||||
-0.500000 0xbf000000 registered OS2 2
|
||||
-0.500000 0xbf000000 unregistered "extra narrow"
|
||||
-0.500000 0xbf000000 unregistered "extranarrow"
|
||||
-0.700000 0xbf333333 registered "Ext Compressed"
|
||||
-0.700000 0xbf333333 registered "Extra Compressed"
|
||||
-0.700000 0xbf333333 registered "Semi Condensed"
|
||||
-0.700000 0xbf333333 registered "Thin"
|
||||
-0.700000 0xbf333333 registered "Ultra Compressed"
|
||||
-0.700000 0xbf333333 registered "Ultra Cond"
|
||||
-0.700000 0xbf333333 registered "Ultra Condensed"
|
||||
-0.700000 0xbf333333 registered OS2 1
|
||||
-0.700000 0xbf333333 unregistered "thin"
|
||||
0.000000 0x0 default
|
||||
0.000000 0x0 metadata "med"
|
||||
0.000000 0x0 panose 2, 3, 4
|
||||
0.000000 0x0 registered OS2 5
|
||||
0.000000 0x0 registered default
|
||||
0.100000 0x3dcccccd registered "Semi Expanded"
|
||||
0.100000 0x3dcccccd registered "Semi Extended"
|
||||
0.100000 0x3dcccccd registered "SemiExpanded"
|
||||
0.100000 0x3dcccccd registered OS2 6
|
||||
0.100000 0x3dcccccd unregistered "semi expanded"
|
||||
0.100000 0x3dcccccd unregistered "semiexpanded"
|
||||
0.200000 0x3e4ccccd head[0x2d] & 0x40
|
||||
0.200000 0x3e4ccccd metadata "ext"
|
||||
0.200000 0x3e4ccccd panose 5
|
||||
0.200000 0x3e4ccccd registered "Expanded"
|
||||
0.200000 0x3e4ccccd registered "Extended"
|
||||
0.200000 0x3e4ccccd unregistered "expanded"
|
||||
0.200000 0x3e4ccccd unregistered "extended"
|
||||
0.400000 0x3ecccccd panose 7
|
||||
0.400000 0x3ecccccd registered "Ext Expanded"
|
||||
0.400000 0x3ecccccd registered "Ext Extended"
|
||||
0.400000 0x3ecccccd registered "Extra Expanded"
|
||||
0.400000 0x3ecccccd registered "Extra Extended"
|
||||
0.400000 0x3ecccccd registered "ExtraExpanded"
|
||||
0.400000 0x3ecccccd registered OS2 7
|
||||
0.400000 0x3ecccccd unregistered "extra expanded"
|
||||
0.400000 0x3ecccccd unregistered "extraexpanded"
|
||||
0.600000 0x3f19999a registered "Wide"
|
||||
0.600000 0x3f19999a registered OS2 8
|
||||
0.600000 0x3f19999a unregistered "wide"
|
||||
0.800000 0x3f4ccccd registered "Extra Wide"
|
||||
0.800000 0x3f4ccccd registered "ExtraWide"
|
||||
0.800000 0x3f4ccccd registered "Ultra Expanded"
|
||||
0.800000 0x3f4ccccd registered "Ultra Extended"
|
||||
0.800000 0x3f4ccccd registered OS2 9
|
||||
0.800000 0x3f4ccccd unregistered "extra wide"
|
||||
0.800000 0x3f4ccccd unregistered "extrawide"
|
||||
@@ -0,0 +1,112 @@
|
||||
metadata "med": float32as(0.000000, 0x0)
|
||||
metadata "cond": float32as(-0.200000, 0xbe4ccccd)
|
||||
metadata "ext": float32as(0.200000, 0x3e4ccccd)
|
||||
|
||||
registered "Extra Compressed": float32as(-0.700000, 0xbf333333)
|
||||
registered "Ultra Compressed": float32as(-0.700000, 0xbf333333)
|
||||
registered "Ultra Condensed": float32as(-0.700000, 0xbf333333)
|
||||
registered "Extra Condensed": float32as(-0.500000, 0xbf000000)
|
||||
registered "Extra Extended": float32as(0.400000, 0x3ecccccd)
|
||||
registered "Ext Compressed": float32as(-0.700000, 0xbf333333)
|
||||
registered "Ultra Expanded": float32as(0.800000, 0x3f4ccccd)
|
||||
registered "Ultra Extended": float32as(0.800000, 0x3f4ccccd)
|
||||
registered "Extra Expanded": float32as(0.400000, 0x3ecccccd)
|
||||
registered "Semi Condensed": float32as(-0.700000, 0xbf333333)
|
||||
registered "Semi Condensed": float32as(-0.100000, 0xbdcccccd)
|
||||
registered "Ext Condensed": float32as(-0.500000, 0xbf000000)
|
||||
registered "SemiCondensed": float32as(-0.100000, 0xbdcccccd)
|
||||
registered "ExtraExpanded": float32as(0.400000, 0x3ecccccd)
|
||||
registered "Semi Expanded": float32as(0.100000, 0x3dcccccd)
|
||||
registered "Semi Extended": float32as(0.100000, 0x3dcccccd)
|
||||
registered "Ext Expanded": float32as(0.400000, 0x3ecccccd)
|
||||
registered "Ext Extended": float32as(0.400000, 0x3ecccccd)
|
||||
registered "SemiExpanded": float32as(0.100000, 0x3dcccccd)
|
||||
registered "Extra Narrow": float32as(-0.500000, 0xbf000000)
|
||||
registered "ExtraNarrow": float32as(-0.500000, 0xbf000000)
|
||||
registered "Extra Wide": float32as(0.800000, 0x3f4ccccd)
|
||||
registered "Ultra Cond": float32as(-0.700000, 0xbf333333)
|
||||
registered "Compressed": float32as(-0.500000, 0xbf000000)
|
||||
registered "Extra Cond": float32as(-0.500000, 0xbf000000)
|
||||
registered "Semi Cond": float32as(-0.100000, 0xbdcccccd)
|
||||
registered "Condensed": float32as(-0.200000, 0xbe4ccccd)
|
||||
registered "ExtraWide": float32as(0.800000, 0x3f4ccccd)
|
||||
registered "Extended": float32as(0.200000, 0x3e4ccccd)
|
||||
registered "Expanded": float32as(0.200000, 0x3e4ccccd)
|
||||
registered "Ext Cond": float32as(-0.500000, 0xbf000000)
|
||||
registered "Narrow": float32as(-0.400000 , 0xbecccccd)
|
||||
registered "Compact": float32as(-0.400000, 0xbecccccd)
|
||||
registered "Cond": float32as(-0.200000, 0xbe4ccccd)
|
||||
registered "Wide": float32as(0.600000, 0x3f19999a)
|
||||
registered "Thin": float32as(-0.700000, 0xbf333333)
|
||||
|
||||
panose 2, 3, 4: float32as(0.000000, 0x0)
|
||||
panose 5: float32as(0.200000, 0x3e4ccccd)
|
||||
panose 6: float32as(-0.200000, 0xbe4ccccd)
|
||||
panose 7: float32as(0.400000, 0x3ecccccd)
|
||||
panose 8: float32as(-0.400000, 0xbecccccd)
|
||||
|
||||
registered OS2 1: float32as(-0.700000, 0xbf333333)
|
||||
registered OS2 2: float32as(-0.500000, 0xbf000000)
|
||||
registered OS2 3: float32as(-0.200000, 0xbe4ccccd)
|
||||
registered OS2 4: float32as(-0.100000, 0xbdcccccd)
|
||||
registered OS2 5: float32as(0.000000, 0x0)
|
||||
registered OS2 6: float32as(0.100000, 0x3dcccccd)
|
||||
registered OS2 7: float32as(0.400000, 0x3ecccccd)
|
||||
registered OS2 8: float32as(0.600000, 0x3f19999a)
|
||||
registered OS2 9: float32as(0.800000, 0x3f4ccccd)
|
||||
|
||||
head[0x2d] & 0x20: float32as(-0.200000, 0xbe4ccccd)
|
||||
head[0x2d] & 0x40: float32as(0.200000, 0x3e4ccccd)
|
||||
|
||||
registered default: float32as(0.000000, 0x0)
|
||||
|
||||
func (f *CTFont) Width() float64 {
|
||||
if f.IsRegistered() {
|
||||
return f.RegistryWidth()
|
||||
}
|
||||
|
||||
width := 0.0
|
||||
hasWidth := false
|
||||
|
||||
if there is an OS2 table {
|
||||
var usWidthClass uint16
|
||||
|
||||
valid := false
|
||||
if it's 78 bytes or more {
|
||||
usWidthClass = uint16be(table[6:8])
|
||||
if usWeightClass <= 10 {
|
||||
valid = true
|
||||
} else {
|
||||
valid = false
|
||||
}
|
||||
} else {
|
||||
usWidthClass = 0
|
||||
valid = true
|
||||
}
|
||||
if valid {
|
||||
ten := float64as(10.000000, 0x4024000000000000)
|
||||
negPointFive := float64as(-0.500000, 0xbfe0000000000000)
|
||||
width = (float64(usWidthClass) div ten) + negPointFive
|
||||
hasWidth = true
|
||||
}
|
||||
}
|
||||
|
||||
then there's the style glossary strings comparison:
|
||||
unregistered "semi condensed": float32as(-0.100000, 0xbdcccccd)
|
||||
unregistered "extra expanded": float32as(0.400000, 0x3ecccccd)
|
||||
unregistered "semicondensed": float32as(-0.100000, 0xbdcccccd)
|
||||
unregistered "extraexpanded": float32as(0.400000, 0x3ecccccd)
|
||||
unregistered "semi expanded": float32as(0.100000, 0x3dcccccd)
|
||||
unregistered "semiexpanded": float32as(0.100000, 0x3dcccccd)
|
||||
unregistered "extra narrow": float32as(-0.500000, 0xbf000000)
|
||||
unregistered "extranarrow": float32as(-0.500000, 0xbf000000)
|
||||
unregistered "extra wide": float32as(0.800000, 0x3f4ccccd)
|
||||
unregistered "condensed": float32as(-0.200000, 0xbe4ccccd)
|
||||
unregistered "extrawide": float32as(0.800000, 0x3f4ccccd)
|
||||
unregistered "extended": float32as(0.200000, 0x3e4ccccd)
|
||||
unregistered "expanded": float32as(0.200000, 0x3e4ccccd)
|
||||
unregistered "narrow": float32as(-0.400000, 0xbecccccd)
|
||||
unregistered "wide": float32as(0.600000, 0x3f19999a)
|
||||
unregistered "thin": float32as(-0.700000, 0xbf333333)
|
||||
|
||||
default: float64as(0.000000, 0x0)
|
||||
@@ -0,0 +1,73 @@
|
||||
// 2 november 2017
|
||||
import Cocoa
|
||||
import CoreText
|
||||
|
||||
func fourccString(_ k: FourCharCode) -> String {
|
||||
var c: [UInt8] = [0, 0, 0, 0]
|
||||
c[0] = UInt8((k >> 24) & 0xFF)
|
||||
c[1] = UInt8((k >> 16) & 0xFF)
|
||||
c[2] = UInt8((k >> 8) & 0xFF)
|
||||
c[3] = UInt8(k & 0xFF)
|
||||
return String(bytes: c, encoding: .utf8)!
|
||||
}
|
||||
|
||||
var weightMin: Double = 0
|
||||
var weightMax: Double = 0
|
||||
var weightDef: Double = 0
|
||||
var weightVals: [String: Double] = [:]
|
||||
|
||||
let attrs: [String: String] = [
|
||||
kCTFontFamilyNameAttribute as String: "Skia",
|
||||
]
|
||||
let bd = CTFontDescriptorCreateWithAttributes(attrs as CFDictionary)
|
||||
let matches = CTFontDescriptorCreateMatchingFontDescriptors(bd, nil) as! [CTFontDescriptor]
|
||||
let mfont = CTFontCreateWithFontDescriptor(matches[0], 0.0, nil)
|
||||
let master = CTFontCopyVariationAxes(mfont) as! [NSDictionary]
|
||||
master.forEach { d in
|
||||
print("axis {")
|
||||
d.forEach { k, v in
|
||||
if (k as! String) == (kCTFontVariationAxisIdentifierKey as String) {
|
||||
let c = v as! FourCharCode
|
||||
print("\t\(k) \(fourccString(c))")
|
||||
} else {
|
||||
print("\t\(k) \(v)")
|
||||
}
|
||||
}
|
||||
print("}")
|
||||
if (d[kCTFontVariationAxisNameKey] as! String) == "Weight" {
|
||||
weightMin = d[kCTFontVariationAxisMinimumValueKey] as! Double
|
||||
weightMax = d[kCTFontVariationAxisMaximumValueKey] as! Double
|
||||
weightDef = d[kCTFontVariationAxisDefaultValueKey] as! Double
|
||||
}
|
||||
}
|
||||
print("")
|
||||
matches.forEach { d in
|
||||
let f = CTFontDescriptorCopyAttribute(d, kCTFontVariationAttribute) as! [FourCharCode: Double]
|
||||
let n = CTFontDescriptorCopyAttribute(d, kCTFontStyleNameAttribute) as! String
|
||||
print("\(n) {")
|
||||
f.forEach { k, v in
|
||||
print("\t\(fourccString(k)) \(v)")
|
||||
}
|
||||
print("}")
|
||||
weightVals[n] = weightDef
|
||||
if let v = f[2003265652] {
|
||||
weightVals[n] = v
|
||||
}
|
||||
}
|
||||
print("")
|
||||
weightVals.forEach { k, v in
|
||||
let basicScaled = (v - weightMin) / (weightMax - weightMin)
|
||||
print("\(k) basic scaled = \(basicScaled) (OS2 \(UInt16(basicScaled * 1000)))")
|
||||
// https://www.microsoft.com/typography/otspec/otvaroverview.htm#CSN
|
||||
var opentypeScaled: Double = 0
|
||||
if v < weightDef {
|
||||
opentypeScaled = -((weightDef - v) / (weightDef - weightMin))
|
||||
} else if v > weightDef {
|
||||
opentypeScaled = (v - weightDef) / (weightMax - weightDef)
|
||||
}
|
||||
print("\(k) opentype scaled = \(opentypeScaled)")
|
||||
}
|
||||
print("")
|
||||
print("\(String(describing: CTFontDescriptorCreateMatchingFontDescriptors(CTFontDescriptorCreateCopyWithVariation(matches[0], FourCharCode(2003265652) as CFNumber, CGFloat(weightMax)), Set([kCTFontVariationAttribute as String]) as CFSet)))")
|
||||
print("")
|
||||
print("\(CTFontCopyTable(mfont, CTFontTableTag(kCTFontTableAvar), []) != nil)")
|
||||
@@ -0,0 +1,58 @@
|
||||
// 2 november 2017
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type fixed1616 uint32
|
||||
type fixed214 uint16
|
||||
|
||||
func fixed1616To214(f fixed1616) fixed214 {
|
||||
f += 0x00000002
|
||||
g := int32(f) >> 2
|
||||
return fixed214(uint32(g) & 0xFFFF)
|
||||
}
|
||||
|
||||
func (f fixed1616) In214Range() bool {
|
||||
base := int16((f >> 16) & 0xFFFF)
|
||||
return base >= -2 && base < 2
|
||||
}
|
||||
|
||||
func (f fixed1616) String() string {
|
||||
base := int16((f >> 16) & 0xFFFF)
|
||||
frac := float64(f & 0xFFFF) / 65536
|
||||
res := float64(base) + frac
|
||||
return fmt.Sprintf("%f 0x%08X", res, uint32(f))
|
||||
}
|
||||
|
||||
func (f fixed214) String() string {
|
||||
base := []int16{
|
||||
0,
|
||||
1,
|
||||
-2,
|
||||
-1,
|
||||
}[(f & 0xC000) >> 14]
|
||||
frac := float64(f & 0x3FFF) / 16384
|
||||
res := float64(base) + frac
|
||||
return fmt.Sprintf("%f 0x%04X", res, uint16(f))
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(fixed214(0x7fff))
|
||||
fmt.Println(fixed214(0x8000))
|
||||
fmt.Println(fixed214(0x4000))
|
||||
fmt.Println(fixed214(0xc000))
|
||||
fmt.Println(fixed214(0x7000))
|
||||
fmt.Println(fixed214(0x0000))
|
||||
fmt.Println(fixed214(0x0001))
|
||||
fmt.Println(fixed214(0xffff))
|
||||
|
||||
fmt.Println()
|
||||
|
||||
for i := uint64(0x00000000); i <= 0xFFFFFFFF; i++ {
|
||||
j := fixed1616(i)
|
||||
if !j.In214Range() { continue }
|
||||
fmt.Println(j, "->", fixed1616To214(j))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
# 21 october 2017
|
||||
gawk '
|
||||
BEGIN { FS = "\t+" }
|
||||
!/float..as/ { next }
|
||||
{ i = 0; if ($1 == "") i++ }
|
||||
(NF-i) != 2 { next }
|
||||
{ print }
|
||||
' "$@"
|
||||
@@ -0,0 +1,10 @@
|
||||
# 21 october 2017
|
||||
gawk '
|
||||
{
|
||||
gsub(/float..as\(/, "")
|
||||
gsub(/,/, "", $(NF - 1))
|
||||
gsub(/\)$/, "")
|
||||
split($0, parts, /:/)
|
||||
print $(NF - 1) "\t" $NF "\t" parts[1]
|
||||
}
|
||||
' "$@"
|
||||
@@ -0,0 +1,3 @@
|
||||
# 21 october 2017
|
||||
sort -t$'\t' -k1,1 -k2,2 "$@" |
|
||||
column -t -s$'\t'
|
||||
@@ -0,0 +1,3 @@
|
||||
// 22 october 2017
|
||||
extern int realMain(void);
|
||||
int main(void) { return realMain(); }
|
||||
@@ -0,0 +1,11 @@
|
||||
unregistered OS2 0: float64as(-0.5, 0xbfe0000000000000)
|
||||
unregistered OS2 1: float64as(-0.4, 0xbfd999999999999a)
|
||||
unregistered OS2 2: float64as(-0.3, 0xbfd3333333333333)
|
||||
unregistered OS2 3: float64as(-0.2, 0xbfc999999999999a)
|
||||
unregistered OS2 4: float64as(-0.1, 0xbfb9999999999998)
|
||||
unregistered OS2 5: float64as(0, 0x0000000000000000)
|
||||
unregistered OS2 6: float64as(0.1, 0x3fb9999999999998)
|
||||
unregistered OS2 7: float64as(0.2, 0x3fc9999999999998)
|
||||
unregistered OS2 8: float64as(0.3, 0x3fd3333333333334)
|
||||
unregistered OS2 9: float64as(0.4, 0x3fd999999999999a)
|
||||
unregistered OS2 10: float64as(0.5, 0x3fe0000000000000)
|
||||
@@ -0,0 +1,11 @@
|
||||
-0.1 0xbfb9999999999998 unregistered OS2 4
|
||||
-0.2 0xbfc999999999999a unregistered OS2 3
|
||||
-0.3 0xbfd3333333333333 unregistered OS2 2
|
||||
-0.4 0xbfd999999999999a unregistered OS2 1
|
||||
-0.5 0xbfe0000000000000 unregistered OS2 0
|
||||
0 0x0000000000000000 unregistered OS2 5
|
||||
0.1 0x3fb9999999999998 unregistered OS2 6
|
||||
0.2 0x3fc9999999999998 unregistered OS2 7
|
||||
0.3 0x3fd3333333333334 unregistered OS2 8
|
||||
0.4 0x3fd999999999999a unregistered OS2 9
|
||||
0.5 0x3fe0000000000000 unregistered OS2 10
|
||||
@@ -0,0 +1,51 @@
|
||||
# 22 october 2017
|
||||
# clang -o writewidths writewidths.c writewidths.s -g -Wall -Wextra -pedantic -g
|
||||
# thanks to:
|
||||
# - http://www.idryman.org/blog/2014/12/02/writing-64-bit-assembly-on-mac-os-x/
|
||||
# - https://developer.apple.com/library/content/documentation/DeveloperTools/Reference/Assembler/060-i386_Addressing_Modes_and_Assembler_Instructions/i386_intructions.html#//apple_ref/doc/uid/TP30000825-TPXREF101
|
||||
# - https://stackoverflow.com/questions/46309041/trivial-macos-assembly-64-bit-program-has-incorrect-stack-alignment
|
||||
# - https://www.google.com/search?q=macos+implement+main+in+assembly+-nasm&oq=macos+implement+main+in+assembly+-nasm&gs_l=psy-ab.3...12877.13839.0.13988.6.6.0.0.0.0.117.407.4j1.5.0....0...1.1.64.psy-ab..1.0.0....0.et6MkokjvwA
|
||||
# - https://stackoverflow.com/questions/2529185/what-are-cfi-directives-in-gnu-assembler-gas-used-for
|
||||
|
||||
.section __DATA,__data
|
||||
|
||||
double10:
|
||||
.quad 0x4024000000000000
|
||||
doubleNeg05:
|
||||
.quad 0xbfe0000000000000
|
||||
|
||||
fmt:
|
||||
.asciz "unregistered OS2 %ld:\tfloat64as(%g, 0x%016lx)\n"
|
||||
|
||||
.section __TEXT,__text
|
||||
.globl _realMain
|
||||
_realMain:
|
||||
pushq %rbp
|
||||
movq %rsp, %rbp
|
||||
addq $8, %rsp
|
||||
|
||||
xorq %rcx, %rcx
|
||||
loop:
|
||||
pushq %rcx
|
||||
# the code from core text
|
||||
movzwl %cx, %ecx
|
||||
xorps %xmm0, %xmm0
|
||||
cvtsi2sdl %ecx, %xmm0
|
||||
divsd double10(%rip), %xmm0
|
||||
addsd doubleNeg05(%rip), %xmm0
|
||||
# end core text code
|
||||
popq %rcx
|
||||
pushq %rcx
|
||||
movd %xmm0, %rdx
|
||||
movzwq %cx, %rsi
|
||||
leaq fmt(%rip), %rdi
|
||||
callq _printf
|
||||
popq %rcx
|
||||
incw %cx
|
||||
cmpw $10, %cx
|
||||
jbe loop
|
||||
|
||||
xorq %rax, %rax
|
||||
subq $8, %rsp
|
||||
popq %rbp
|
||||
ret
|
||||
Reference in new issue
Block a user