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>
diff --git a/font/sfnt/sfnt.go b/font/sfnt/sfnt.go
index d57200c..0eb5cd5 100644
--- a/font/sfnt/sfnt.go
+++ b/font/sfnt/sfnt.go
@@ -333,7 +333,7 @@
 		return errInvalidFontCollection
 	case dfontResourceDataOffset:
 		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.
 		c.offsets = []uint32{0}
 	case 0x74746366: // "ttcf".
@@ -637,7 +637,7 @@
 	if err != nil {
 		return err
 	}
-	buf, os2Vers, xHeight, capHeight, err := f.parseOS2(buf)
+	buf, hasXHeightCapHeight, xHeight, capHeight, err := f.parseOS2(buf)
 	if err != nil {
 		return err
 	}
@@ -664,7 +664,7 @@
 	f.cached.unitsPerEm = unitsPerEm
 	f.cached.xHeight = xHeight
 
-	if os2Vers <= 1 {
+	if !hasXHeightCapHeight {
 		xh, ch, err := f.initOS2Version1()
 		if err != nil {
 			return err
@@ -695,6 +695,8 @@
 		// No-op.
 	case 0x4f54544f: // "OTTO".
 		isPostScript = true
+	case 0x74727565: // "true"
+		// No-op.
 	case 0x74746366: // "ttcf".
 		return nil, false, errInvalidSingleFont
 	}
@@ -1121,36 +1123,40 @@
 	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
-	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)
 	if err != nil {
-		return nil, 0, 0, 0, err
+		return nil, false, 0, 0, err
 	}
 	if vers <= 1 {
 		const headerSize = 86
 		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.
-		return buf, vers, 0, 0, nil
+		return buf, false, 0, 0, nil
 	}
 	const headerSize = 96
 	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)
 	if err != nil {
-		return nil, 0, 0, 0, err
+		return nil, false, 0, 0, err
 	}
 	ch, err := f.src.u16(buf, f.os2, 88)
 	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.