font/sfnt: support fonts with "true" apple version tag
OpenType specification mentions that fonts might contain Apple version tag that is equal to "true" (see note in [1]). Currently, the library returns a parsing error for those fonts. CL adds Apple this version tag to the validation code and allows fonts to omit OS/2 table, as mentioned in the TrueType spec [2]. [1] https://docs.microsoft.com/en-us/typography/opentype/spec/otff#organization-of-an-opentype-font [2] https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6OS2.html Change-Id: I13406fe97b091f24aaabf9b477df9c8fc8df883c Reviewed-on: https://go-review.googlesource.com/c/146078 Reviewed-by: Nigel Tao <nigeltao@golang.org>
This commit is contained in:
parent
d9c2484c48
commit
dd492a22e4
|
@ -333,7 +333,7 @@ func (c *Collection) initialize() error {
|
||||||
return errInvalidFontCollection
|
return errInvalidFontCollection
|
||||||
case dfontResourceDataOffset:
|
case dfontResourceDataOffset:
|
||||||
return c.parseDfont(buf, u32(buf[4:]), u32(buf[12:]))
|
return c.parseDfont(buf, u32(buf[4:]), u32(buf[12:]))
|
||||||
case 0x00010000, 0x4f54544f:
|
case 0x00010000, 0x4f54544f, 0x74727565: // 0x10000, "OTTO", "true"
|
||||||
// Try parsing it as a single font instead of a collection.
|
// Try parsing it as a single font instead of a collection.
|
||||||
c.offsets = []uint32{0}
|
c.offsets = []uint32{0}
|
||||||
case 0x74746366: // "ttcf".
|
case 0x74746366: // "ttcf".
|
||||||
|
@ -637,7 +637,7 @@ func (f *Font) initialize(offset int, isDfont bool) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
buf, os2Vers, xHeight, capHeight, err := f.parseOS2(buf)
|
buf, hasXHeightCapHeight, xHeight, capHeight, err := f.parseOS2(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -664,7 +664,7 @@ func (f *Font) initialize(offset int, isDfont bool) error {
|
||||||
f.cached.unitsPerEm = unitsPerEm
|
f.cached.unitsPerEm = unitsPerEm
|
||||||
f.cached.xHeight = xHeight
|
f.cached.xHeight = xHeight
|
||||||
|
|
||||||
if os2Vers <= 1 {
|
if !hasXHeightCapHeight {
|
||||||
xh, ch, err := f.initOS2Version1()
|
xh, ch, err := f.initOS2Version1()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -695,6 +695,8 @@ func (f *Font) initializeTables(offset int, isDfont bool) (buf1 []byte, isPostSc
|
||||||
// No-op.
|
// No-op.
|
||||||
case 0x4f54544f: // "OTTO".
|
case 0x4f54544f: // "OTTO".
|
||||||
isPostScript = true
|
isPostScript = true
|
||||||
|
case 0x74727565: // "true"
|
||||||
|
// No-op.
|
||||||
case 0x74746366: // "ttcf".
|
case 0x74746366: // "ttcf".
|
||||||
return nil, false, errInvalidSingleFont
|
return nil, false, errInvalidSingleFont
|
||||||
}
|
}
|
||||||
|
@ -1121,36 +1123,40 @@ func (f *Font) initOS2Version1() (xHeight, capHeight int32, err error) {
|
||||||
return int32(xh), int32(ch), nil
|
return int32(xh), int32(ch), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Font) parseOS2(buf []byte) (buf1 []byte, version uint16, xHeight, capHeight int32, err error) {
|
func (f *Font) parseOS2(buf []byte) (buf1 []byte, hasXHeightCapHeight bool, xHeight, capHeight int32, err error) {
|
||||||
// https://docs.microsoft.com/da-dk/typography/opentype/spec/os2
|
// https://docs.microsoft.com/da-dk/typography/opentype/spec/os2
|
||||||
if f.os2.length < 2 {
|
|
||||||
return nil, 0, 0, 0, errInvalidOS2Table
|
if f.os2.length == 0 {
|
||||||
|
// Apple TrueType fonts might omit the OS/2 table.
|
||||||
|
return buf, false, 0, 0, nil
|
||||||
|
} else if f.os2.length < 2 {
|
||||||
|
return nil, false, 0, 0, errInvalidOS2Table
|
||||||
}
|
}
|
||||||
vers, err := f.src.u16(buf, f.os2, 0)
|
vers, err := f.src.u16(buf, f.os2, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, 0, err
|
return nil, false, 0, 0, err
|
||||||
}
|
}
|
||||||
if vers <= 1 {
|
if vers <= 1 {
|
||||||
const headerSize = 86
|
const headerSize = 86
|
||||||
if f.os2.length < headerSize {
|
if f.os2.length < headerSize {
|
||||||
return nil, 0, 0, 0, errInvalidOS2Table
|
return nil, false, 0, 0, errInvalidOS2Table
|
||||||
}
|
}
|
||||||
// Will resolve xHeight and capHeight later, see initOS2Version1.
|
// Will resolve xHeight and capHeight later, see initOS2Version1.
|
||||||
return buf, vers, 0, 0, nil
|
return buf, false, 0, 0, nil
|
||||||
}
|
}
|
||||||
const headerSize = 96
|
const headerSize = 96
|
||||||
if f.os2.length < headerSize {
|
if f.os2.length < headerSize {
|
||||||
return nil, 0, 0, 0, errInvalidOS2Table
|
return nil, false, 0, 0, errInvalidOS2Table
|
||||||
}
|
}
|
||||||
xh, err := f.src.u16(buf, f.os2, 86)
|
xh, err := f.src.u16(buf, f.os2, 86)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, 0, err
|
return nil, false, 0, 0, err
|
||||||
}
|
}
|
||||||
ch, err := f.src.u16(buf, f.os2, 88)
|
ch, err := f.src.u16(buf, f.os2, 88)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, 0, 0, 0, err
|
return nil, false, 0, 0, err
|
||||||
}
|
}
|
||||||
return buf, vers, int32(int16(xh)), int32(int16(ch)), nil
|
return buf, true, int32(int16(xh)), int32(int16(ch)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PostTable represents an information stored in the PostScript font section.
|
// PostTable represents an information stored in the PostScript font section.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user